数字人离线合成openAPI

版本变更

版本

描述

时间

v0.6

提交数字人视频合成新增speed参数

SDK版本升级

2024-10-25

v0.5

提交数字人视频合成新增speechOpen参数,新增变音规则介绍,学术音标表

2024-09-29

v0.4

数字人视频合成支持自研数字人,新增素材音量调节字段,声音模板新增声音模板版本出参

SDK版本升级

2024-09-09

v0.3

新增批量查询数字人视频合成信息接口, sdk升级到2.3.0

2024-08-20

v0.2

提交数字人视频合成接口,新增透明背景

2024-07-31

v0.1

功能发布

2024-07-01

概览

交互示例

image

image

接入准备

  1. 需要接入方提前准备阿里云账号,并利用阿里云子账号生成对应的AK/SK;

  2. 阿里云主账号需要对生成AK/SK的子账号进行RAM授权;

  3. 使用阿里云主账号登录平台,签署相关法务协议。

API详情

1. 提交数字人视频合成任务

SubmitProjectTask

1.1. 入参

参数名

类型

是否必填

说明

scaleType

string

画面比例(9:16,16:9)

9:16 - 画面宽度:1080,高度:1920

16:9 - 画面宽度:1920,高度:1080

subtitleTag

int

是否开启字幕:1 - 是, 0 - 否,

自研数字人不支持字幕

transparentBackground

int

透明背景开关:1-开启 0-关闭, 默认0

开启透明背景不允许添加素材,自研数字人不支持透明背景,

开启透明背景主播的坐标位置默认居中,不支持调整

frames

List<OpenFrame>

视频画面(最多50个画面)

OpenFrame

参数名

类型

是否必填

说明

index

int

画面顺序,最小值为1。单次提交中每个画面顺序不可相同

layers

List<OpenLayer>

图层(一个画面最多10个图层)

videoScript

OpenVideoScript

脚本信息

subtitle

OpenSubtitle

开启字幕时必填

字幕设置

OpenVideoScript

参数名

类型

是否必填

说明

type

string

文本/音频:TEXT/AUDIO

audioUrl

string

音频类型必填

音频文件地址(最长十分钟)

textContent

string

文本类型必填

音频文本

voiceTemplateId

long

文本类型必填

声音模型id(需要跟主播匹配)

volume

int

文本类型必填

音量: 范围[0 到 100],推荐值50

speedRate

string

文本类型必填

语速倍数:范围[0.8 到 2.0] 正常语速1,仅支持一位小数

OpenLayer

参数名

类型

是否必填

说明

type

string

ANCHOR - 主播

BACKGROUND - 背景,透明背景开启时可不传背景

MATERIAL - 素材

material

OpenMaterial

图层素材

index

int

非背景必填

图层顺序 最小1,单次提交中每个画面中图层顺序不可相同,背景不填

positionX

int

非背景必填

图层X坐标,背景不填(详见坐标说明)

positionY

int

非背景必填

图层Y坐标,背景不填(详见坐标说明)

width

int

非背景必填

图层宽度,背景不填(不能超过画面高度)

height

int

非背景必填

图层高度,背景不填(不能超过画面宽度)

背景图层必须铺满整个画面,默认最底层

  • 背景图层的width,height默认等于画面的width,height

  • 背景图层的positionX,positionY默认等于0

OpenMaterial 主播/素材

参数名

类型

是否必填

说明

id

string

主播图层必填

主播id

url

string

非主播图层必填

素材url(http地址)

format

string

非主播图层必填

素材格式:video/mp4,image/png

image/jpg,image/jpeg

volume

int

视频音量: 范围[0 到 100],推荐值50 ,仅video/mp4格式支持

OpenSubtitle 字幕

参数名

类型

是否必填

说明

positionX

int

X坐标:详见字幕说明

positionY

int

Y坐标:详见字幕说明

font

string

字体,例如:SimSun ,详细见字体说明

fontSize

int

字号: 允许范围[32 - 160]

fontColor

string

文字的颜色,格式为#后跟16进制值。例如:#ffffff

alignment

string

对齐方式:

  • BottomLeft - 字幕框内左下角

  • BottomCenter - 字幕框内居中

  • BottomRight - 字幕框内右下角

backgroundColor

string

背景色,RGB颜色,格式为#后跟16进制值。例如:#ffffff。

maxCharLength

int

一行可显示最大字数,建议文本宽度/字体宽度

textWidth

int

文本宽度:详见字幕说明

textHeight

int

文本高度:详见字幕说明

1.1.1. 字体说明
  • Alibaba PuHuiTi - 阿里巴巴普惠体

  • FZKai-Z03S - 方正楷体简体

  • FZHei-B01S - 方正黑体简体

  • FZShuSong-Z01S - 方正书宋简体

  • FZFangSong-Z02S - 方正仿宋简体

  • SimSun - 宋体

  • WenQuanYi MicroHei - 文泉驿微米黑

  • WenQuanYi Zen Hei Mono - 文泉驿等宽正黑

  • WenQuanYi Zen Hei Sharp - 文泉驿点阵正黑

  • Microsoft YaHei - 微软雅黑

  • Yuanti SC - 圆体-简常规体

  • Roboto Bold - Google Robota字体,不支持中文

  • Roboto - Google Robota字体,不支持中文

  • KaiTi - 楷体

  • SiYuan Heiti - 思源黑体

  • SiYuan SimSun - 思源宋体

  • HappyZcool-2016 - 站酷快乐体

1.1.2. 坐标说明
  • 主播、素材、水印坐标参数均为画面左上角对接图片左上角的距离

  • 坐标如果存在小数,舍弃小数, 如下图:X=470, Y=700

image

1.1.3. 图层超出画面外
  • 超出画面的图片需要进行裁剪

  • 图片的宽高使用裁剪后的图片宽高

  • X,Y轴的坐标超出部分为0

原图:

1720689870780-9e3eebc9-6520-4a41-8e55-b27c061bec8e.png

裁剪后图片:

1720689913869-e20dd397-c543-4b60-9342-01c7f8da2757.png

画面内的效果:

image

1.1.4. 字幕说明

下图参数示例:

{
    "positionX": 68, // 字幕不允许超出画面外,最小0,最大不超过画面宽度
    "positionY": 392,// 字幕不允许超出画面外,最小0,最大不超过画面高度
    "maxCharLength": 7, // 一行可显示最大字数,建议文本宽度/字体宽度
    "textWidth": 800, // 文本宽度,文本框不能超出画面外
    "textHeight": 110, // 文本高度,必须大于字体大小
    "fontSize": 100, // 字体大小
    "font": "SiYuan SimSun",
    "fontColor": "#090707",
    "alignment": "BottomRight", // 右对齐
    "backgroundColor": "#fefefe"
}

image

1.1.5. 背景示例

背景图层提供的图片需要充满整个画布,无需传递坐标值,系统默认X=0, Y=0

image

1.1.6. 变音规则介绍

OpenVideoScript对象的类型为文本(TEXT)的时候可以支持变音配置,需要变音的时候OpenVideoScript的参数speechOpen需设置为true,textContent字段需要设置在变音标签下面,具体规则如下:

标签

说明

示例

tts版本支持情况

<speak>

根元素,不论使用哪个ssml标签,都要有<speak></speak>

<speak>这句话是没有任何SSML语法的效果。</speak>

0,2 支持

<break time="2.5s" />

在文本中插入停顿,time设置停顿时长,支持0s-10s

<speak> 今天天气<break time="2.5s" />很好 </speak>

0,2 支持

<word>

连读标签,指定的词组不被拆分,只能加在中文

<speak> 南京市<word>长江大桥</word></speak>

嵌套拼音标签示例:<speak><word>长江<phoneme alphabet="py" ph="da1">大</phoneme>桥</word></speak>

0 支持连读,但是不支持嵌套拼音标签,

2 支持

<phoneme alphabet="py" ph="xi1 xi1">

标签内的文本指定发音,只能加在中文

ph用于指定拼音,仅支持一个拼音。

  • 1~4 分别顺序对应汉语四个声调,5对应轻声。比如,词语“爸爸”,拼音应写为“ba4 ba5”

<speak> <phoneme alphabet="py" ph="xi1"></phoneme>公主 </speak>

0,2 支持

<phoneme alphabet="ipa" ph="æ">

通过国际音标指定英文发音,ph用于指定国际音标。

  • 标签内不限定字母是否为一个真正的单词,以“ph”的值为准。

  • 标签内不能有标点符号、空格等非英语字母内容。

<speak><phoneme alphabet="ipa" ph="æ">a</phoneme>,apple.是苹果的意思. </speak>

2 支持

<sub alias="文本替换">

内嵌文本替换为指定文本,目前暂时仅中文音色适用

<speak><sub alias="Speech Synthesis Markup Language">SSML</sub></speak>

0,2 支持

完整示例:

String textContent = "<speak> <sub alias="替换">我是文本替换</sub> <phoneme alphabet="ipa"ph="æ">a</phoneme>,apple.是苹果的意思<phoneme alphabet="py"ph="xi1"></phoneme>公主 , 南京市<word>长江大桥</word>。今天天气<break time="2.5s" />很好 </speak>"

1.1.7. 学术音标表

原词

学术IPA(本系统支持的)

教学IPA(市面常见的)

元音

i

ɪ

ɪ

ɛ

e

æ

æ

ɑ

ɔ

ɔː

ʊ

ʊ

u

ʌ

ʌ

ə

ə

ɚ

ər

ɝ

ɜːr

ɔɪ

ɔɪ

辅音

p

p

b

b

t

t

d

d

k

k

ɡ

g

dʒ或ʤ

f

f

v

v

θ

θ

ð

ð

s

s

z

z

ʃ

ʃ

ʒ

ʒ

h

h

m

m

n

n

ŋ

ŋ

j

j

w

w

ɹ

r

l

l

1.2. 出参

参数名

类型

说明

success

boolean

true 成功, false 失败

errorMessage

string

错误信息

errorCode

string

异常code

taskId

string

任务id

2. 查询数字人视频合成信息

GetProjectTask

2.1. 入参

参数名称

类型

是否必填

说明

taskId

String

任务id

2.2. 出参

参数名称

类型

说明

status

String

合成状态:IN_PROGRESS - 合成中, FAIL - 失败

SUCCESS - 成功, CANCEL - 已取消

errorMsg

String

合成失败原因

videoDuration

String

视频时长

videoUrl

String

视频地址

3. 批量查询数字人视频合成信息

BatchGetProjectTask

3.1. 入参

参数名称

类型

是否必填

说明

taskIdList

List<String>

任务id集合

3.2. 出参

参数名

类型

说明

resultList

List<Object>

视频信息

Object说明

status

String

合成状态:IN_PROGRESS - 合成中, FAIL - 失败

SUCCESS - 成功, CANCEL - 已取消

errorMsg

String

合成失败原因

videoDuration

String

视频时长

videoUrl

String

视频地址

4. 合成任务停止

StopProjectTask

4.1. 入参

参数名称

类型

是否必填

说明

taskId

String

任务id

4.2. 出参

参数名称

类型

说明

success

boolean

true-成功,false-失败(仅表示提交结果,任务是否真正停止需调用“查询数字人视频合成信息”接口根据任务状态判断)

errorCode

String

错误码

errorMsg

String

失败原因

5. 查询资源信息

5.1. 入参

5.2. 出参

参数名称

类型

说明

resourceInfoList

List<ResourceInfo>

资源剩余量信息

ResourceInfo

参数名称

类型

说明

resourceType

Integer

资源类型:2 - AI视频生成时长

remainCount

Integer

资源剩余量

unit

String

资源剩余量单位: second - 秒

lastExpire

Integer

资源过期剩余天数

6. 数字人形象模型查询

ListAnchor

6.1. 入参

参数名称

参数类型

是否必填

说明

coverRate

string

N

主播形象比例

9:16 竖版

16:9 横版

anchorType

string

N

主播类型:

PUBLIC_MODEL:公模

PRIVATE_MODEL:私模

digitalHumanType

string

N

主播类别:

dynamicReality 动态实景数字人(暂时不可使用);staticTransparency 静态数字人

useScene

string

Y

使用场景

offlineSynthesis 离线数字人;

pageSize

int

Y

每页大小

pageNumber

int

Y

页码

6.2. 出参

参数名

参数类型

参数说明

total

int

总数

list

array:AnchorResponse

主播形象obj array

success

Boolean

是否成功

errorMessage

String

异常信息

errorCode

String

异常错误码

AnchorResponse

参数名

参数类型

参数说明

anchoId

String

主播id

anchorMaterialName

String

主播名称

anchorType

String

主播类型:

PUBLIC_MODEL 公模

PRIVATE_MODEL 私模

coverUrl

String

模特封面图

coverThumbnailUrl

String

模特封面缩略图

coverWeight

int

封面图宽:像素值

coverHeight

int

封面图高:像素值

coverRate

String

封面比例

status

String

状态:

Usable 已上线

digitalHumanType

String

主播类别:

dynamicReality 动态实景数字人(暂时不可用);staticTransparency 静态数字人

useScene

String

使用场景

offlineSynthesis 离线数字人;

resourceTypeDesc

String

资源规格描述

gender

String

性别F/M(需要与声音模板性别保持一致)

7. 声音模板查询

ListVoiceModels

7.1. 入参

参数名

参数类型

是否必填

参数说明

voiceType

String

N

声音类型

PRIVATE_VOICE 私模声音;

PUBLIC_VOICE 公模声音;

useScene

string

Y

使用场景

offlineSynthesis 离线数字人

pageSize

int

Y

每页大小

pageNumber

int

Y

页码

7.2. 出参

参数名

参数类型

参数描述

total

int

总数

list

array:VoiceModelResult

音频脚本模板集合

success

Boolean

是否成功

errorMessage

String

异常信息

errorCode

String

异常错误码

VoiceModelResponse

参数名

参数类型

参数描述

voiceId

bigInt

声音模板id

voiceName

String

声音名称

voiceModel

String

声音模型(参数值)

voiceGender

String

男声M/女声F((需要与形象性别保持一致))

voiceUrl

String

试听音频url

voiceLanguage

String

zh/en

voiceDesc

String

声音模型描述

useScene

String

使用场景

offlineSynthesis 离线数字人

resourceTypeDesc

String

资源规格描述

ttsVersion

Integer

tts版本0,1,2 v0.4

对接详情

PHP

对接示例

require 'vendor/autoload.php';
use AlibabaCloud\SDK\Imarketing\V20220704\Models\GetOssUploadSignatureRequest;
use AlibabaCloud\SDK\IntelligentCreation\V20240313\IntelligentCreation;
use Darabonba\OpenApi\Models\Config as AlibabaConfig;

$config = new AlibabaConfig();
$config->accessKeyId = '****';
$config->accessKeySecret = '****';
$config->endpoint = "intelligentcreation.cn-zhangjiakou.aliyuncs.com";

$intelligentCreationClient = new IntelligentCreation($config);

$request = new GetProjectTaskRequest();
$request->taskId = '1111';
try {
  $response = $intelligentCreationClient->getProjectTask($request);
  var_dump($response->toMap());
} catch (TeaError $e) {
  Log::error($e);
}

2.6.0

u-2d06dbf9-cce5-4bcf-91b6-750b97fee3bf-composer-tea.zip

composer require alibabacloud/intelligentcreation-20240313 2.6.0

2.4.0

u-17374653-852f-4536-9c8f-61f96b9890ef-composer-tea.zip

composer require alibabacloud/intelligentcreation-20240313 2.4.0

Java

对接示例

package com.aliyun.intelligentcreation20240313;

import com.aliyun.intelligentcreation20240313.models.*;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.util.HashMap;
import java.util.Map;

/**
 * @author fangming.yu
 * @since 2024/7/5
 */
public class TestProjectTest {

    public static void main(String[] args) throws Exception {
        TestProjectTest testProjectTest = new TestProjectTest();

        try {
           String taskId = testProjectTest.submitProjectTaskRequest();
           testProjectTest.stopProjectTaskRequest(taskId);
           testProjectTest.getProjectTaskRequest(taskId);
           testProjectTest.selectResourceRequest(null);
            testProjectTest.listVoiceModelsRequest();
            System.out.println(taskId);
        } catch (TeaException e) {
            Gson gson = new Gson();
            System.out.println(e.getMessage());
            System.out.println(gson.toJson(e.getData()));
        } catch (Exception e) {

            e.printStackTrace();
        }


    }

    String url = "intelligentcreation.cn-zhangjiakou.aliyuncs.com";
    //初始化配置
    Config config = new Config().setAccessKeyId("**")
            .setAccessKeySecret("**")
            .setEndpoint(url);
    // 创建客户端
    Client client = new Client(config);

    public TestProjectTest() throws Exception {
    }


    String submitProjectTaskRequest() throws Exception {
        Gson gson = new Gson();
        String para = "{\"scaleType\":\"16:9\",\"subtitleTag\":1,\"frames\":[{\"index\":1,\"layers\":[{\"type\":\"BACKGROUND\",\"material\":{\"format\":\"image/png\",\"url\":\"https://yic-pre.oss-cn-hangzhou.aliyuncs.com/common/image/backgroundImage/shu/1.png\"}},{\"type\":\"MATERIAL\",\"material\":{\"format\":\"image/png\",\"url\":\"https://yic-pre.oss-cn-hangzhou.aliyuncs.com/1539704706413278/image/material/1716348615967-%E5%86%B0%E6%B7%87%E6%B7%8B.png\"},\"index\":2,\"positionX\":76,\"positionY\":1169,\"width\":549,\"height\":750},{\"type\":\"ANCHOR\",\"material\":{\"id\":\"759459670880206851\",\"url\":\"https://yic-pre.oss-cn-hangzhou.aliyuncs.com/1539704706413278/image/anchor/1715148681933-55254f81420c4c82954042414136e52d.png\"},\"index\":3,\"positionX\":0,\"positionY\":0,\"width\":1080,\"height\":1920},{\"type\":\"WATERMARK\",\"material\":{\"type\":\"WATERMARK\",\"format\":\"image/png\",\"url\":\"https://yic-pre.oss-cn-hangzhou.aliyuncs.com/common/image/material/%E6%B0%B4%E5%8D%B003%403x.png"},\"index\":4,\"positionX\":248,\"positionY\":280,\"width\":191,\"height\":195}],\"videoScript\":{\"textContent\":\"让我们一同投身于这场激动人心的呼吸之旅,共同见证科技与医学的完美融合,携手共进\",\"type\":\"TEXT\",\"voiceTemplateId\":82,\"volume\":50,\"speedRate\":1.5},\"subtitle\":{\"positionX\":0,\"positionY\":545,\"maxCharLength\":6,\"textWidth\":1080,\"fontSize\":60,\"font\":\"Microsoft YaHei\",\"fontColor\":\"#2a313d\",\"textHeight\":70,\"alignment\":\"BottomCenter\"}}]}";

        Map<String, Object> map = gson.fromJson(para, new TypeToken<Map<String, Object>>() {
        }.getType());

        SubmitProjectTaskRequest request = SubmitProjectTaskRequest.build(map);
        // 请求接口
        SubmitProjectTaskResponse response = client.submitProjectTask(request);

        System.out.println(gson.toJson(response));

        if (response.getStatusCode().equals(200)) {
            System.out.println("submitProjectTaskRequest 请求成功");
            return response.getBody().getTaskId();
        }
        return null;
    }

    void getProjectTaskRequest(String taskId) throws Exception {
        Gson gson = new Gson();

        Map<String, Object> map = new HashMap<>();
        map.put("taskId", taskId);

        GetProjectTaskRequest request = GetProjectTaskRequest.build(map);
        // 请求接口
        GetProjectTaskResponse response = client.getProjectTask(request);

        System.out.println(gson.toJson(response));

        if (response.getStatusCode().equals(200)) {
            System.out.println("getProjectTaskRequest 请求成功");
        }
    }

    void stopProjectTaskRequest(String taskId) throws Exception {
        Gson gson = new Gson();

        Map<String, Object> map = new HashMap<>();
        map.put("taskId", taskId);

        StopProjectTaskRequest request = StopProjectTaskRequest.build(map);
        // 请求接口
        StopProjectTaskResponse response = client.stopProjectTask(request);

        System.out.println(gson.toJson(response));

        if (response.getStatusCode().equals(200)) {
            System.out.println("stopProjectTaskRequest 请求成功");
        }
    }

    void selectResourceRequest(String projectId) throws Exception {
        Gson gson = new Gson();
        Map<String, Object> map = new HashMap<>();
        SelectResourceRequest request = SelectResourceRequest.build(map);
        SelectResourceResponse response = client.selectResource(request);

        System.out.println(gson.toJson(response));
        if (response.getStatusCode().equals(200)) {
            System.out.println("selectResourceRequest 请求成功");
        }
    }

    void listVoiceModelsRequest() throws Exception {
        Gson gson = new Gson();
        Map<String, Object> map = new HashMap<>();
        map.put("useScene", "offlineSynthesis");
        map.put("pageSize", 1);
        map.put("pageNumber", 10);
        ListVoiceModelsRequest request = ListVoiceModelsRequest.build(map);
        ListVoiceModelsResponse response = client.listVoiceModels(request);

        System.out.println(gson.toJson(response));
        if (response.getStatusCode().equals(200)) {
            System.out.println("listVoiceModelsRequest 请求成功");
        }
    }
}

2.6.0

u-2d06dbf9-cce5-4bcf-91b6-750b97fee3bf-java-tea.zip

<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>intelligentcreation20240313</artifactId>
  <version>2.6.0</version>
</dependency>

2.4.0

u-17374653-852f-4536-9c8f-61f96b9890ef-java-tea.zip

<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>intelligentcreation20240313</artifactId>
  <version>2.4.0</version>
</dependency>