功能简介
腾讯云媒体处理(MPS)AIGC 聚合平台提供 3D 大模型生成 服务,支持通过文字描述(文生 3D)、单张图片(图生 3D)或多视角图片(多视角图生 3D)生成高质量的 3D 模型资产。生成的 3D 模型包含几何体和纹理,支持输出 OBJ、GLB 等主流格式,可直接用于短剧、电商展示、AR/VR 等场景。开发者通过同一套 API 即可调用不同模型并获取生成结果。
计费说明
前置条件
1. 开通服务
1. 登录 腾讯云媒体处理控制台,按照引导开通 MPS 服务。
2. 获取 API 密钥:前往 API 密钥管理 获取 SecretId 和 SecretKey。
3. (可选)如需将生成结果存到 COS,还需开通对象存储 (COS) 并创建存储桶,授权 MPS_QcsRole 角色。可参考 账号授权相关 文档。
2. 安装依赖
本指南的代码示例使用 axios 作为 HTTP 客户端,但它不是必须的。您可以根据项目情况选择以下任一方式发送 HTTP 请求。
方案 | 是否需要安装 | 适用场景 |
axios(本文示例默认) | npm install axios | 已有项目在用 axios,或偏好其 API 风格。 |
Node.js 原生 fetch | 无需安装(Node.js ≥ 18 内置) | 零依赖、现代项目推荐。 |
Node.js 原生 https | 无需安装 | 兼容老版本 Node.js(< 18)。 |
如果您选择 axios:
npm install axios
如果您选择原生 fetch(Node.js ≥ 18,零依赖),将代码中的 axios.post(...) 替换为:
// 替换 axios.post 调用// 原: const resp = await axios.post(`https://${MPS_HOST}`, payload, { headers });// return resp.data;// 改为:const resp = await fetch(`https://${MPS_HOST}`, {method: 'POST',headers: headers,body: JSON.stringify(payload)});return await resp.json();
说明:
Node.js 内置的
crypto 模块即可完成签名,无需额外安装。签名部分无外部依赖。3. 密钥配置
{"tencentCloud": {"secretId": "您的 SecretId","secretKey": "您的 SecretKey","region": "ap-guangzhou"}}
注意:
安全提醒:密钥绝对不要硬编码到代码中或提交到 Git,建议使用环境变量或独立的配置文件(加入
.gitignore)。API 概览
说明:
通用信息:
请求域名:mps.tencentcloudapi.com
请求方式:POST(application/json)
API 版本:2019-06-12
签名方法:TC3-HMAC-SHA256
关键约束:
入参 Prompt / ImageUrl / MultiViewImages 三选一,必填其一,互斥,不可同时传入。
并发生成任务数默认为1并发/主账号。
MultiViewImages 至少2张(2~8 张),且必须包含 front 视角,同一 ViewType 不允许重复。
签名机制 (TC3-HMAC-SHA256)
腾讯云 API 3.0 使用 TC3-HMAC-SHA256 签名认证。签名过程如下:
1. 构建规范请求 (CanonicalRequest):拼接请求方法、URI、QueryString、Headers、Payload Hash。
2. 构建待签字符串 (StringToSign):拼接算法、时间戳、CredentialScope、CanonicalRequest Hash。
3. 计算签名 (Signature):用 SecretKey 逐级 HMAC 派生签名密钥,再对 StringToSign 签名。
4. 构建 Authorization Header:组装最终的认证头。
注意事项
1. 生成结果仅存储24小时
图片和视频的 URL 只有12小时有效期,务必在生成后及时下载或转存到自己的 COS/服务器。
2. 频率限制
几何(白模)生成:1并发
3D 模型(带纹理)生成:1并发
建议实现并发控制和请求队列,避免触发限流。
3. 图片输入要求
大小 ≤ 10MB,分辨率短边 ≥ 512、长边 ≤ 4096。
支持格式:JPG、JPEG、PNG、WEBP。
图片 URL 必须外网可访问。
4. Prompt 长度限制
字符限制:不超过 1024 utf-8 字符。
描述建议:使用具体、有画面感的描述(主体 + 风格 + 颜色 + 姿态),避免抽象概念与多主体。
5. COS 存储
使用 StoreCosParam 可将结果直接存到指定 COS 桶,需要:
开通 COS 服务。
创建存储桶。
授权 MPS_QcsRole 角色访问该桶。
核心代码实现
1. 签名工具 (tencent-sign.js)
/*** 腾讯云 API 签名工具 (TC3-HMAC-SHA256)*/const crypto = require('crypto');function sha256(message) {return crypto.createHash('sha256').update(message).digest('hex');}function hmac256(key, message) {return crypto.createHmac('sha256', key).update(message).digest();}/*** 生成腾讯云 API V3 签名* @param {string} secretId - 腾讯云 SecretId* @param {string} secretKey - 腾讯云 SecretKey* @param {string} service - 服务名,如 'mps'* @param {string} action - 接口名,如 'CreateAigcVideoTask'* @param {string} payload - 请求体 JSON 字符串* @param {string} region - 地域,如 'ap-guangzhou'* @param {string} [version] - API 版本号,默认 '2019-06-12'* @returns {{ headers: object }} - 包含完整签名的请求头*/function signRequest(secretId, secretKey, service, action, payload, region, version) {const timestamp = Math.floor(Date.now() / 1000);const date = new Date(timestamp * 1000).toISOString().split('T')[0];// ===== 步骤1: 拼接规范请求串 =====const httpRequestMethod = 'POST';const canonicalUri = '/';const canonicalQueryString = '';const contentType = 'application/json';const canonicalHeaders =`content-type:${contentType}\\n` +`host:${service}.tencentcloudapi.com\\n` +`x-tc-action:${action.toLowerCase()}\\n`;const signedHeaders = 'content-type;host;x-tc-action';const hashedRequestPayload = sha256(payload);const canonicalRequest =`${httpRequestMethod}\\n${canonicalUri}\\n${canonicalQueryString}\\n` +`${canonicalHeaders}\\n${signedHeaders}\\n${hashedRequestPayload}`;// ===== 步骤2: 拼接待签名字符串 =====const algorithm = 'TC3-HMAC-SHA256';const credentialScope = `${date}/${service}/tc3_request`;const hashedCanonicalRequest = sha256(canonicalRequest);const stringToSign =`${algorithm}\\n${timestamp}\\n${credentialScope}\\n${hashedCanonicalRequest}`;// ===== 步骤3: 计算签名 =====const secretDate = hmac256(`TC3${secretKey}`, date);const secretService = hmac256(secretDate, service);const secretSigning = hmac256(secretService, 'tc3_request');const signature = crypto.createHmac('sha256', secretSigning).update(stringToSign).digest('hex');// ===== 步骤4: 拼接 Authorization =====const authorization =`${algorithm} Credential=${secretId}/${credentialScope}, ` +`SignedHeaders=${signedHeaders}, Signature=${signature}`;return {headers: {'Authorization': authorization,'Content-Type': contentType,'Host': `${service}.tencentcloudapi.com`,'X-TC-Action': action,'X-TC-Timestamp': String(timestamp),'X-TC-Version': version || '2019-06-12','X-TC-Region': region || ''}};}module.exports = { signRequest };
2. MPS API 封装 (mps-api.js)
// mps-api.js — 混元 3D 生成 API 封装(Node.js ≥ 18,原生 fetch,零依赖)const { signRequest } = require('./sign');const SERVICE = 'mps';const VERSION = '2019-06-12';const REGION = 'ap-guangzhou';const ENDPOINT = 'mps.tencentcloudapi.com';const SECRET_ID = process.env.TENCENTCLOUD_SECRET_ID;const SECRET_KEY = process.env.TENCENTCLOUD_SECRET_KEY;/** 通用调用:签名 → 发请求 → 校验错误 → 返回 Response */async function callMpsApi(action, params) {const payload = params || {};const { authorization, timestamp } = signRequest({secretId: SECRET_ID,secretKey: SECRET_KEY,action,payload,});const res = await fetch('https://' + ENDPOINT + '/', {method: 'POST',headers: {Authorization: authorization,'Content-Type': 'application/json','X-TC-Action': action,'X-TC-Timestamp': String(timestamp),'X-TC-Version': VERSION,'X-TC-Region': REGION,},body: JSON.stringify(payload),});const data = await res.json();const r = data.Response || {};// 业务错误:先看标准错误信封 Error.Code,再看扁平 ErrorCode(如 ResourceNotFound.TaskId)if (r.Error || r.ErrorCode) {const code = (r.Error && r.Error.Code) || r.ErrorCode;const message = (r.Error && r.Error.Message) || r.ErrorMessage;throw new Error(`${action} failed: ${code} - ${message} (RequestId: ${r.RequestId})`);}return r;}/*** 提交 3D 生成任务(文生 / 图生 / 多视角图生,入参三选一,互斥)* @param {object} params* @param {string} [params.Prompt] 文生 3D 提示词,最长 1024 utf-8 字符* @param {string} [params.ImageUrl] 图生 3D 参考图 URL(jpg/jpeg/png/bmp/webp,* 短边 ≥ 512、长边 ≤ 4096、建议 ≤ 10MB,须公网可访问)* @param {Array<{ViewType: string, ViewImageUrl: string}>} [params.MultiViewImages]* 多视角图生 3D:2~8 张,必须包含 front 视角,ViewType 不可重复。* 可选值:front / back / left / right / top / bottom / left_front / right_front* @param {string} [params.GenerateType='Normal'] Normal:完整 3D 资产(几何+纹理);* Geometry:仅几何(更快,约 40s)* @param {boolean} [params.EnablePBR=false] 是否输出 PBR 材质* @param {number} [params.FaceCount=500000] 面片数,范围 [3000, 1500000]* @returns {Promise<{TaskId: string, RequestId: string}>}* TaskId:任务唯一 ID,用于后续查询;RequestId:请求追踪 ID,定位问题请提供此 ID*/async function submitHunyuan3DTask(params) {return callMpsApi('SubmitHunyuan3DTask', params);}/*** 查询 3D 生成任务* @param {string} taskId Submit 返回的任务 ID* @returns {Promise<{* Status: 'WAIT' | 'RUN' | 'DONE' | 'FAIL',* Progress: number,* ErrorCode?: string, // 仅 FAIL 时返回,如 InternalError.ModelInference* ErrorMessage?: string, // 仅 FAIL 时返回* ResultFile3Ds?: Array<{ // 仅 DONE 时返回* Type: 'OBJ' | 'GLB' | 'MTL' | 'OBJ_ZIP',* Url: string,* PreviewImageUrl?: string* }>,* RequestId: string* }>}* ⚠️ ResultFile3Ds 中的 Url 为临时签名 URL,有效期约 24 小时,请及时下载或转存。* 默认输出 OBJ + GLB 两种格式,其中 OBJ 同时提供单独文件和含 MTL+纹理的 ZIP 包。*/async function queryHunyuan3DTask(taskId) {return callMpsApi('QueryHunyuan3DTask', { TaskId: taskId });}module.exports = { submitHunyuan3DTask, queryHunyuan3DTask };
完整使用流程
本接口为异步任务模式,一次生成分两步:提交任务(Submit)→ 轮询查询(Query)。Status 状态流转为 WAIT → RUN → DONE / FAIL。
1. 文生 3D(根据 Prompt 生成带纹理的几何模型)
文字描述生成完整的 3D 模型(几何 + 纹理):
const { submitHunyuan3DTask, queryHunyuan3DTask } = require('./mps-api');async function main() {// ① 提交任务const submitResp = await submitHunyuan3DTask({Prompt: 'a cute cartoon dinosaur, green, small horns',FaceCount: 500000,});const taskId = submitResp.TaskId;console.log('TaskId:', taskId);// ② 每 8 秒轮询一次while (true) {const r = await queryHunyuan3DTask(taskId);console.log('Status:', r.Status, 'Progress:', r.Progress);if (r.Status === 'DONE') {// ⚠️ 以下 URL 为临时签名 URL,有效期约 24 小时,请尽快下载或转存for (const f of r.ResultFile3Ds) {console.log(f.Type, '->', f.Url);}break;}if (r.Status === 'FAIL') {console.error('FAIL:', r.ErrorCode, r.ErrorMessage);break;}await new Promise(resolve => setTimeout(resolve, 8000));}}main().catch(console.error);
2. 图生 3D(单图 / 多视角生成 3D 模型)
根据一张参考图生成完整 3D 模型,或多张不同角度的参考图获得最高还原度:
const { submitHunyuan3DTask } = require('./mps-api');// 场景 A:图生 3D(完整资产 + PBR)await submitHunyuan3DTask({ImageUrl: 'https://example.com/test.png',EnablePBR: true,});// 场景 B:图生 3D(仅几何,速度快)await submitHunyuan3DTask({ImageUrl: 'https://example.com/test.png',GenerateType: 'Geometry',FaceCount: 100000,});// 场景 C:多视角图生 3D(至少 2 张,必须包含 front 视角;质量要求高可追加 left / right)await submitHunyuan3DTask({MultiViewImages: [{ ViewType: 'front', ViewImageUrl: 'https://example.com/front.png' },{ ViewType: 'back', ViewImageUrl: 'https://example.com/back.png' },],EnablePBR: true,});// 场景 D:多视角图生几何await submitHunyuan3DTask({MultiViewImages: [{ ViewType: 'front', ViewImageUrl: 'https://example.com/front.png' },{ ViewType: 'back', ViewImageUrl: 'https://example.com/back.png' },],GenerateType: 'Geometry',});
3. 带任务队列的生产级用法
在实际项目中,建议实现任务队列控制并发数,避免超过 API 频率限制:
const { submitHunyuan3DTask, queryHunyuan3DTask } = require('./mps-api');/*** 通用轮询函数:带超时与间隔控制* @param {string} taskId 任务 ID* @param {object} [options]* @param {number} [options.timeoutMs=600000] 超时时间,默认 10 分钟* @param {number} [options.intervalMs=8000] 轮询间隔,默认 8 秒(不要低于 1 秒,会触发限频)* @returns {Promise<object>} DONE 状态的完整 Response*/async function pollTaskResult(taskId, options = {}) {const { timeoutMs = 10 * 60 * 1000, intervalMs = 8000 } = options;const deadline = Date.now() + timeoutMs;while (Date.now() < deadline) {const r = await queryHunyuan3DTask(taskId);if (r.Status === 'DONE') return r;if (r.Status === 'FAIL') {throw new Error(`task failed: ${r.ErrorCode} - ${r.ErrorMessage}`);}await new Promise(resolve => setTimeout(resolve, intervalMs));}throw new Error(`poll timeout after ${timeoutMs} ms, TaskId: ${taskId}`);}/*** 生产级工作流:先用 Geometry 模式快速验证骨架,满意后再生成完整资产* (仅几何约 40s,完整资产约 120s,P50 参考值)*/async function generateWithPreview(prompt) {// ① 先跑仅几何任务,快速评估模型骨架const geometryTask = await submitHunyuan3DTask({Prompt: prompt,GenerateType: 'Geometry',FaceCount: 200000,});const geometryResult = await pollTaskResult(geometryTask.TaskId);console.log('几何预览完成,文件数:', geometryResult.ResultFile3Ds.length);// ② 满意后再提交完整资产任务(几何 + 纹理 [+ PBR])const finalTask = await submitHunyuan3DTask({Prompt: prompt,GenerateType: 'Normal',FaceCount: 500000,EnablePBR: true,});const finalResult = await pollTaskResult(finalTask.TaskId);// ⚠️ 收到 DONE 后立即下载转存(URL 约 24 小时过期)return finalResult.ResultFile3Ds; // OBJ / GLB 文件列表}
配置文件参考
以下是一个完整的配置示例,涵盖图片和视频生成的所有可配置项:
{"tencentCloud": {"secretId": "TENCENTCLOUD_SECRET_ID","secretKey": "TENCENTCLOUD_SECRET_KEY","region": "ap-guangzhou"},"hunyuan3d": {"generateType": "Normal","enablePBR": false,"faceCount": 500000,"multiView": {"enabled": false,"minViews": 2,"maxViews": 8,"requiredViewType": "front"}},"concurrency": {"maxConcurrentTasks": 1,"pollIntervalSeconds": 8,"pollTimeoutMinutes": 10}}
常见问题
创建任务报 InvalidParameter 错误?
错误码 | 说明 |
InvalidParameter.NoInputSpecified | Prompt / ImageUrl / MultiViewImages 三者都未传。 |
InvalidParameter.PromptImageConflict | Prompt 与 ImageUrl / MultiViewImages 同时提供。 |
InvalidParameter.MultiInputConflict | ImageUrl 与 MultiViewImages 同时提供。 |
InvalidParameter.MissingFrontView | MultiViewImages 未包含 front 视角。 |
InvalidParameter.InsufficientViews | MultiViewImages 数量少于2。 |
InvalidParameter.DuplicateViewType | 出现重复的 ViewType。 |
InvalidParameter.FaceCountOutOfRange | FaceCount 不在 [3000, 1500000]。 |
InvalidParameter.PromptTooLong | Prompt 超过 1024 utf-8 字符。 |
创建任务报 AuthFailure 错误?
错误码 | 原因 |
AuthFailure.SignatureExpire | 本机时间与腾讯云服务器偏差 > 5 分钟,请校准 NTP。 |
AuthFailure.SecretIdNotFound | SecretId 不存在或已删除。 |
AuthFailure.UnauthorizedOperation / UnauthorizedOperation | 主账号 AppId 尚未在混元 3D 服务白名单内(联系商务开通),或子账号未绑定 CAM 策略 QcloudMPSFullAccess。 |
轮询一直返回 WAIT/RUN 状态?
完整 3D 资产(Normal)约180秒、仅几何(Geometry)约80秒(P50参考值),排队时间视平台负载而定,通常 < 10分钟。建议轮询超时设置为10分钟,间隔510秒;首次收到 Progress ≥ 90 后可加密到35秒,但不要低于1秒,会触发限频。
任务失败了会计费吗?
不会。仅 Query 首次返回 Status=DONE 时计费;未 DONE 的任务不计费,重复查询也不会重复计费。
Query 返回 ResourceNotFound.TaskId?
TaskId 在服务端保留7天,超期后自动清理。该错误走 HTTP 200,通过响应体的 ErrorCode / ErrorMessage 承载(响应中不含 Status 字段)。客户端判定顺序建议:先看 Response.ErrorCode 是否存在,存在即视为错误分支;否则再按 Response.Status 分派业务逻辑。
反馈问题需要提供什么?
RequestId(Submit 或 Query 响应里的 RequestId,非常关键)、TaskId(若有)、完整请求 Body(脱敏后)、期望结果 vs 实际结果的差异。
附录:HTTP 原始请求示例
如果您使用其他语言(Python / Go / Java 等),可以参考以下 HTTP 原始请求格式:
创建 3D 生成任务(文生 3D)
输入示例
curl -X POST https://mps.tencentcloudapi.com/ \\-H "Authorization: TC3-HMAC-SHA256 Credential=AKIDxxxxxxxx/2026-08-30/mps/tc3_request, SignedHeaders=content-type;host, Signature=fe5f6f..." \\-H "Content-Type: application/json" \\-H "X-TC-Action: SubmitHunyuan3DTask" \\-H "X-TC-Version: 2019-06-12" \\-H "X-TC-Timestamp: 1756543200" \\-H "X-TC-Region: ap-guangzhou" \\-d '{"Prompt": "a cute cartoon dinosaur, green, small horns","FaceCount": 500000}'
输出示例
{"Response": {"TaskId": "r_44504e4b9a3b11f186b56a073b12405b","RequestId": "d344d00c-b131-45ec-8de9-829e0c427dca"}}
查询 3D 生成任务
输入示例
POST / HTTP/1.1Host: mps.tencentcloudapi.comContent-Type: application/jsonX-TC-Action: QueryHunyuan3DTaskX-TC-Version: 2019-06-12{"TaskId": "r_44504e4b9a3b11f186b56a073b12405b"}
输出示例-已完成
{"Response": {"Status": "DONE","Progress": 100,"ResultFile3Ds": [{"Type": "GLB","Url": "https://hunyuan-3d-12583xxxx3.cos.ap-guangzhou.myqcloud.com/gen_tmp_test/<task_hash>/<file_hash>.glb?q-sign-algorithm=sha1&...","PreviewImageUrl": "https://hunyuan-base-prod-12583xxxx3.cos.ap-guangzhou.myqcloud.com/openapi/text2img/<preview_hash>.png?q-sign-algorithm=sha1&..."},{"Type": "OBJ","Url": "https://hunyuan-3d-12583xxxx3.cos.ap-guangzhou.myqcloud.com/gen_tmp_test/<task_hash>/<file_hash>.obj?q-sign-algorithm=sha1&..."},{"Type": "OBJ","Url": "https://hunyuan-3d-12583xxxx3.cos.ap-guangzhou.myqcloud.com/gen_tmp_test/<task_hash>/<file_hash>.zip?q-sign-algorithm=sha1&..."}],"RequestId": "8189fa91-1c54-499c-8ce3-e182ec9c19ce"}}
输出示例-执行中
{"Response": {"Status": "RUN","Progress": 0,"RequestId": "f3193547-4119-48d8-aa13-b27d29b49224"}}
输出示例-任务不存在或已过期
{"Response": {"ErrorCode": "ResourceNotFound.TaskId","ErrorMessage": "task not found or expired","RequestId": "0ba287dc-f6b3-4f93-bc3a-887e7f971f90"}}