Skip to content
On this page

Quickstart

5 分钟上手 Aholo 3D 生成/重建 API

前置准备

  1. 获取 API 访问权限

    • 注册酷家乐开放平台账号
    • 创建应用获取 appuid
    • 了解接口鉴权规则(签名认证)
  2. 基本概念

    • appuid: 第三方用户ID,所有接口必传
    • ousToken: 上传凭证,10分钟有效期
    • projectId: 项目唯一标识
    • taskId: 任务唯一标识

API 基础信息

Base URL: https://openapi.kujiale.com/v2/aholo
认证方式: appuid + 签名(详见官方文档)
响应格式: { "c": "0", "d": {...}, "m": null, "f": "" }
  • c: 状态码,"0" 表示成功
  • d: 返回数据
  • m: 消息(错误时)
  • f: 标志位

完整示例:从图片创建 3D 重建项目

python
import requests
import hashlib
import time

# ========== 配置 ==========
APPUID = "your_appuid"  # 替换为你的 appuid
BASE_URL = "https://openapi.kujiale.com/v2/aholo"

# ========== Step 1: 获取上传Token ==========

def get_upload_token():
    """获取上传凭证"""
    response = requests.get(
        f"{BASE_URL}/upload/token",
        params={"appuid": APPUID}
        # 注意:实际使用需添加签名认证
    )
    
    data = response.json()["d"]
    return {
        "ousToken": data["ousToken"],
        "globalDomain": data["globalDomain"],
        "blockSize": data["blockSize"]
    }

upload_info = get_upload_token()
print(f"✓ 获得 ousToken: {upload_info['ousToken'][:20]}...")
print(f"✓ 上传域名: {upload_info['globalDomain']}")

# ========== Step 2: 上传图片 ==========

def upload_image(file_path, upload_info):
    """上传单个图片文件"""
    
    # 计算 MD5
    with open(file_path, "rb") as f:
        file_data = f.read()
        md5 = hashlib.md5(file_data).hexdigest()
    
    # 上传
    response = requests.post(
        f"https://{upload_info['globalDomain']}/ous/api/v2/single/upload",
        headers={"ous-token-v2": upload_info["ousToken"]},
        files={"file": open(file_path, "rb")},
        data={"md5": md5}
    )
    
    task_id = response.json()["d"]["taskId"]
    
    # 轮询等待上传完成
    while True:
        status_response = requests.get(
            f"https://{upload_info['globalDomain']}/ous/api/v2/upload/status",
            headers={"ous-token-v2": upload_info["ousToken"]}
        )
        
        status_data = status_response.json()["d"]
        status = status_data["status"]
        
        if status == 5:  # 上传成功
            return status_data["url"]
        elif status in [6, 8]:  # 失败
            raise Exception(f"上传失败: status={status}")
        
        print(f"上传状态: {status}, 等待中...")
        time.sleep(0.5)

image_url = upload_image("/path/to/your/image.jpg", upload_info)
print(f"✓ 图片上传成功: {image_url}")

# ========== Step 3: 创建 3D 重建项目 ==========

def create_3d_recon_project(image_url, project_name):
    """创建3D重建项目"""
    
    payload = {
        "projectName": project_name,
        "cover": image_url,
        "scene": "model",  # model=物体, space=室内
        "taskQuality": "NORMAL",  # LOW/NORMAL/HIGH/ULTRA
        "accessLevel": 0,  # 0=公开, 1=私有
        "resources": [
            {
                "name": "input.jpg",
                "type": 0,  # 0=图片
                "url": image_url,
                "meta": {
                    "width": 1920,
                    "height": 1080,
                    "duration": None
                }
            }
        ],
        "uploadSog": False,
        "panorama": False
    }
    
    response = requests.post(
        f"{BASE_URL}/project/create-3d-recon",
        params={"appuid": APPUID},
        json=payload
    )
    
    return response.json()["d"]  # projectId

project_id = create_3d_recon_project(image_url, "我的3D模型")
print(f"✓ 项目创建成功: {project_id}")

# ========== Step 4: 查询任务状态 ==========

def wait_for_task(project_id, timeout=600):
    """等待任务完成"""
    
    start_time = time.time()
    
    while time.time() - start_time < timeout:
        response = requests.post(
            f"{BASE_URL}/project/task/list/by-ids",
            params={"appuid": APPUID},
            json=[project_id]
        )
        
        tasks = response.json()["d"]
        if tasks:
            task = tasks[0]
            status = task["status"]
            
            if status == 3:  # 成功
                return task["result"]
            elif status in [4, 5, 6, 7]:  # 失败/取消/超时/拒绝
                raise Exception(f"任务失败: status={status}")
            
            print(f"任务状态: {status}, 等待中...")
        
        time.sleep(5)
    
    raise Exception("超时")

result = wait_for_task(project_id)
print(f"✓ 任务完成!")

# ========== Step 5: 获取结果 ==========

print("\n📦 3D 资产:")
print(f"   PLY: {result['plyPath']}")
print(f"   SPZ: {result['spzPath']}")
print(f"   SOG: {result['sogPath']}")

# 或获取完整项目信息
project_info = requests.get(
    f"{BASE_URL}/project/info",
    params={"appuid": APPUID, "projectId": project_id}
).json()["d"]

print(f"\n项目名称: {project_info['name']}")
print(f"项目类型: {project_info['projectType']}")  # 0=重建, 1=生成

项目类型说明

类型接口说明
3D 重建create-3d-recon从图片/视频重建真实物体/空间
3D 生成create-3d-genAI 生成虚拟空间

任务状态枚举

Status含义是否终态
0排队中
1等待执行
2执行中
3成功✓ 是
4失败✓ 是
5取消✓ 是
6超时✓ 是
7被拒绝✓ 是
8预处理中

下一步: Media Assets - Prepare Upload

基于 Marble API 文档结构