You need to enable JavaScript to run this app.
导航
数字人服务API接口文档
最近更新时间:2023.09.25 19:29:06首次发布时间:2023.08.11 17:43:08
一、什么是TTA(Text To Animation)

文本转动画服务,支持输入文本,实时返回音视频&视频生产的功能,TTA服务与2D&3D服务间以websocket协议进行交互。
新增语音转动画功能,支持音频URL或音频流式输入,驱动数字人进行播报
新增推流至ByteRTC房间功能,实现1v1实时交互 ByteRTC介绍
新增推流至RTMP地址功能,实现数字人实时直播 视频云直播服务介绍

alt

二、数据格式

针对在控制台下单的数字人资产,在调用TTA接口时,

  • 数字分身、精品形象定制:形象id填入role
  • 形象租赁:在形象库中找到形象对应的role、clothes_type、pose_type
  • 声音复刻:声音id填入voice_type

2.1 Client-Side

格式类型描述备注

|CTL|00|

控制帧

开启session

控制帧后面追加json格式信息,例如uid、role等,开始session时支持对背景、logo、视频分辨率、横竖屏、主播相关配置(音色、姿态、服装、位置)设置
1.采用默认配置
|CTL|00|{"uid":"avatar_android", "role":"LiuXuan"}
2.自定义配置
|CTL|00{"uid":"avatar_android","background":"http://xxx.jpeg","logo":{"logo_url":"http://xxx..png","logo_top_offset":20,"logo_left_offset":20,"logo_width":50,"logo_height":50},"video":{"video_width":1080,"video_height":1920},"role":"LiuXuan","role_conf":{"voice_type":"BV009_DPE_ParaTaco","pose_type":"standing_fullbody","clothes_type":"uniform","role_width":400,"role_left_offset":500,"role_top_offset":500}}
各字段说明见下“自定义配置字段说明”
3.若是离线生产视频场景,需要额外追加编码格式的信息
|CTL|00|{"uid":"avatar_android", "role":"LiuXuan", "codec":" mp4 }

|CTL|01|控制帧关闭session

|CTL|02|

控制帧

发送chat命令

  • 文本驱动

  • 音频URL驱动

1.控制帧后面追加信息,支持文本驱动、音频驱动两种格式
文本驱动支持纯文本和ssml,示例(input_mode=text):
|CTL|02|今天天气不错
|CTL|02|今天天气不错
音频驱动示例(input_mode=audio):
|CTL|02|<audio url="http://xxx.pcm" format="pcm" sample_rate="48000" ac="1"/>
流式音频驱动示例(input_mode=audio)
|CTL|08|xxxx
xxxx表示一段时长的二进制音频片段,目前只支持16k单声道pcm输入
2.将支持的动作放入标签中,标签放到字的前面,会在播到相应字时做对应动作。支持的动作见下“动作库”
|CTL|02|<speak>今天<action type="OK"/>天气真不错</speak>
3.插入图片素材:图片相关配置放在image标签中,支持指定图片显示的开始/结束位置、大小、位置调整、前景后景切换
|CTL|02|<speak>今天<imageurl="http://xxx.png" left="250" top="500" width="500" height="500" level="1">天气真不错。</image>阳光很好</speak>
只在播到“天气真不错”时显示对应的图片,<image>标签中各字段说明见下“插入图片说明”
4.插入视频素材:支持在文本中指定视频显示的开始位置,视频播完自动不显示。视频在画面中的大小、位置支持调整、前景后景切换
|CTL|02|今天<video url="http://xxx.mp4" left="250" top="500" width="500" height="500" level="1"/>天气真不错。 阳光很好</speak>
标签中各字段含义同<image>

|CTL|03|控制帧打断数字人播报当前只有文本驱动下生效

|CTL|08|

控制帧

流式音频驱动

|CTL|08|xxxx
xxxx表示一段时长的二进制音频片段,建议1s为单位,当前不支持单次送入低于1s长度的音频数据,当前只支持16k单声道pcm数据

|CTL|09|

控制帧

流式音频驱动尾包

|CTL|09|xxxx
xxxx表示一段时长的二进制音频片段,尾包数据。若希望驱动完数字人之后,数字人输出静默的音视频流,需要设置尾包


2.1.1 自定义配置字段说明

字段含义层级类型是否必需备注

background

背景图片/视频url

1

string

非必需

可支持图片和视频作为背景,不设置或者为空时使用默认背景
视频格式:flv/mp4/mov/avi
图片格式:常见图片格式,如png/jpg/jpeg/bmp等

logologo配置相关1非必需如果logo字段存在,其他logo配置字段必须存在
logo_urllogo图url2string非必需为空时忽略其他logo配置
logo_top_offsetlogo上边距2unsigned int非必需可以为0
logo_left_offsetlogo左边距2unsigned int非必需可以为0
logo_heightlogo高度2unsigned int非必需logo字段不空时不可为0
logo_widthlogo宽度2unsigned int非必需logo字段不空时不可为0

video

视频配置相关

1

非必需

1.支持视频分辨率为1080p/720p/480p
2.横屏对应的宽高则反过来
3.默认配置为1080p竖屏

video_width

生成视频流宽

2

unsigned int

非必需

1.宽高都不设定时默认宽1080,高1920
2.指定高度,不指定宽度时,按照16:9竖屏计算宽度
3.指定宽度,不指定高度时,如果宽度>1080,按照16:9横屏计算高度,反之按照16:9竖屏计算
4.宽高范围:240<=值<=1920

video_height生成视频流高2unsigned int非必需

role

主播name

1

string

必需

目前支持多个主播形象,各个形象支持的姿态、服装、动作各不相同,具体见“动作库说明”。

  • 2D

GuoXiaoyuan(小源)
XiaoHuan(小焕)

  • 3D

COCO

role_conf主播配置相关1非必需

voice_type

主播声音

2

string

非必需

  • 女生音色:

BV405 (甜美小源)
BV418 (甜美小源-电商)
BV005_ParaTaco (活泼女声)
BV007_ParaTaco (亲切女声)
BV057_ParaTaco (活泼幼教)
BV009_DPE_ParaTaco(默认值 知性女声)
BV700 (灿灿)

  • 男生音色:

BV008_DPE_ParaTaco (知性男声)
BV419 (阳光男声)

如需试听音色,请前往语音合成产品能力体验

pose_type

主播姿态

2

string

非必需

合法值和主播形象相对应,详见“动作库说明”

clothes_type主播服装2string非必需

role_width

主播大小

2

unsigned int

非必需

100<=值<=video_width,有默认值,主播高度会自动推导,role_width过大,主播下半身可能会超出屏幕

role_left_offset

主播左边距

2

unsigned int

非必需

默认人物正中,值小于0或role_left_offset + role_width > video_width时,主播会左右超出屏幕

role_top_offset主播上边距2unsigned int非必需0 <= role_top_offset < video_height
speed调节数字人播报语速2float非必需[0.25,3],默认值1.0
pitch调节数字人播报语调2float非必需[0,10],默认值1.0
volume调节数字人播报音量2float非必需[0,3],默认值1.0

input_mode

设置引擎驱动模式

1

string

非必需

text:文本驱动模式,默认值
audio:音频驱动模式

codec

离线视频生产的格式

1

string

非必需

合法值为mp4/webm/mov
codec=webm/mov时离线视频为透明通道视频。
实时交互和实时直播场景不能传递该参数

appid账号ID1string必需授权下发,请联系对接人获取
rtcRTC相关配置1非必需
app_idRTC的app id2stringRTC场景下必需
roomRTC的房间号2stringRTC场景下必需
uidRTC的uid2stringRTC场景下必需
token根据RTC房间号和uid生成的token2stringRTC场景下必需生成token时可以指定有效期,需要确保在有效期内完成RTC交互
rtmpRTMP相关配置1非必需
addrRTMP推流地址2stringRTMP场景下必需
live_idRTMP的live id2stringRTMP场景下必需

2.1.2 动作库说明

  • 支持静默作为单个动作(例如3s)。支持<action type="LISTENING" time="3s" />或者<action type="LISTENING" time="3000ms" />两种格式,time最长为100s。使用该动作时time字段必填。(3D暂不支持)

  • 所有动作都支持:播放动作时不播报。支持通过<action type="OK" is_silence="true" />控制动作单独呈现,is_silence默认值为false,即默认边播报边做动作。(3D暂不支持)

形象
role

已支持姿态/服装组合

动作库

GuoXiaoyuan

pose2_clothes1
站姿全身_客服装

0 opening_wave_hand
2 指向前方 双手
3 指向前方 右手
4 指向前方 左手
5 指向侧上方 右手
6 指向侧上方 左手
7 指向侧下方 右手
8 指向侧下方 左手
9 指向斜前上方 右手
10 指向斜前上方 左手
11 指向斜前下方 右手
12 指向斜前下方 左手
13 鼓掌
15 ok
16 数字1
17 数字2
18 数字3
19 展示从外向内 右手
20 展示从外向内 左手
22 展示从内向外 右手
24 展示从内向外 左手
25 单手强调 右手
26 单手摊开 右手
28 单手摊开 左手
31 双手强调
32 双手摊开
33 双手点赞
34 右手 点赞
35 右手比心
36 结束动作 摆手

XiaoHuan

pose1_clothes1
站姿全身_客服装

OPENING_BOWING opening_bowing
3 指向前方(双手)
5 指向前方(右)
7 指向前方(左)
9 指向侧上方(右)
11 指向侧上方(左)
13 指向侧下方(右)
14 指向侧下方(左)
18 指向斜前上方(右)
20 指向斜前上方(左)
21 指向斜前下方(右)
24 指向斜前下方(左)
26 鼓掌
29 摆手
OK ok
34 数字1
35 数字2
37 数字3
39 打招呼
42 单手强调
46 单手摊开(右手)
49 单手摊开(左手)
IDLE idle
51 从外向内(右手)
54 从外向内(左手)
55 从内向外(右手)
57 从内向外(左手)
59 双手强调
61 双手摊开
63 双手比心
66 双手点赞
67 右手比心
69 右手点赞
ENDING_BOWING ending_bowing

COCO

pose_clothes2
站姿全身_客服装

coco_normal_01_ANI 自然站立 coco_hello_01_ANI 打招呼 coco_introduction_03_ANI 自我介绍 coco_selling_1_01_ANI 兴奋带货1 coco_selling_2_01_ANI 兴奋带货2 coco_selling_3_01_ANI 兴奋带货3 coco_selling_4_02_ANI 兴奋带货4 coco_talking_1_02_ANI 平静介绍商品1 coco_talking_2_01_ANI 平静介绍商品2 coco_talking_3_01_ANI 平静介绍商品3 coco_talking_4_01_Ani 平静介绍商品4 coco_talking_5_01_Ani 平静介绍商品5 coco_talking_6_01_Ani 平静介绍商品6 coco_talking_7_01_ANI 平静介绍商品7 coco_talking_8_01_ANI 平静介绍商品8 coco_talking_9_01_ANI 平静介绍商品4 coco_talking_10_01_ANI 平静介绍商品5 coco_upper_left_01_ANI 展示左上角 coco_upper_right_01_ANI 展示右上角 coco_buttom_left_02_ANI 展示左下角 coco_buttom_right_01_ANI 展示右下角 coco_left_01_ANI 展示左侧 coco_right_02_ANI 展示右侧 coco_front_02_ANI 展示身前 coco_heart_01_ANI 比心 coco_thumbup_01_2_ANI 点赞 coco_ok_03_ANI ok coco_no_01_2_ANI 不对 coco_sale_01_2_ANI 上链接 coco_order_06_2_ANI 逼单 coco_answer_1_01_ANI 回答商品问题1 coco_answer_2_02_ANI 回答商品问题2 coco_barrage_03_ANI 看弹幕 coco_refund_02_ANI 退款介绍 coco_soldout_05_ANI 卖光了 coco_bye_01_ANI 下播 coco_lookaround_01_ANI 四处观望 coco_yoga_02_2_ANI 做瑜伽 coco_laugh_1_02_ANI 捂嘴笑 coco_think_01_2_ANI 思考 coco_wave_04_2_ANI 晃动 coco_akimbo_01_ANI 叉腰 coco_nod_01_2_ANI 点头 coco_jidong_01_2_ANI 激动


2.1.3 插入图片/视频说明

标签类型标签说明示例

图片(image)

支持将文本放在<image></image>标签中,只在播报对应文本时显示图片。标签中对应字段设置图片大小、位置、前景后景

<speak><image url="https://b-ssl.duitang.com/uploads/item/201804/17/20180417143206_kdpwj.png" left="500" top="500" width="600" height="600" level="1">开始下一次测试。这是图片显示范围中的第一句话。显示结束了</image></speak>

支持多轨道:(3D暂不支持)
image mode字段说明:
opening:单张图片展示开始,标签为自闭合,支持重叠
closing:单张图片展示结束,标签为自闭合,支持重叠
default:通过指定文本范围显示单张图片,非自闭合,不支持重叠
说明: opening与closing根据track_id一一对应。同一时刻一个level最多支持出现一张图片,相邻图片的level不能相同

<speak>开始<image mode="opening" track_id="1" url="https://b-ssl.duitang.com/uploads/item/201804/17/20180417143206_kdpwj.png" left="200" top="200" width="600" height="600" level="0"/>下一次测试。3、2、1,开始。这是一个包含图片的文本,这是图片显示范围中的第一句话。<image mode="closing" track_id="1"/>这是图片显示范围中的第二句话。显示结束了!

支持多轨道示例如:

<speak>
    <image url='url_1' left='100' top='100' height='100' width='100' level='1'>
        这是图片内的文本
    </image>
</speak> <!-- 单张图片显示-->


<speak>
    <image mode='opening' track_id='1' url='url_1' left='100' top='100' height='100' width='100' level='1'/>
        这是图片内的文本
    <image mode='closing' track_id='1'/>
</speak> <!-- 效果等同于第一个-->


<speak>
    <image mode='opening' track_id='1' url='url_1' left='100' top='100' height='100' width='100' level='1'/>
    <image mode='opening' track_id='2' url='url_2' left='200' top='200' height='200' width='200' level='2'/>
        这是图片内的文本
    <image mode='closing' track_id='2'/>
    <image mode='closing' track_id='1'/>
</speak> <!-- 多张图片显示-->


<speak>
    <image mode='opening' track_id='2' url='url_2' left='200' top='200' height='200' width='200' level='2'/>
    <image url='url_1' left='100' top='100' height='100' width='100' level='1'>
        这是图片内的文本
    </image>
    <image mode='closing' track_id='2'/>
</speak> <!--混合使用-->

ps:非自闭合image(mode=default)中不可嵌套image标签,下述为错误示例

<speak>
    <image url='url_1' left='100' top='100' height='100' width='100' level='1'>
        <image mode='opening' track_id='2' url='url_2' left='200' top='200' height='200' width='200' level='2'/>
        这是图片内的文本
        <image mode='closing' track_id='2'/>
    </image>
</speak> <!--混合使用-->

视频(video)

支持自闭合:
插入的视频播放完成后自动结束
说明:同一时刻一个level最多支持出现一个视频,相邻视频的level不能相同

<speak>文本一<video url="http://localhost:8000/test_xiaozhao.mp4" left="10" top="20" width="40" height="80" level="0"/>文本二</speak>。

2.1.4 词条精修

当前支持在传入文本时通过标签进行词条精修,具体支持的标签为

标签说明示例
py指定读音的意思是,在田里除草
break插入停顿以色列国的官方语言是什么?乌尔都语希伯来语
speed语速调节单词 rabbitrabbit
volume音量调节单词 rabbitrabbit
pitch音调调节单词 rabbitrabbit

2.1.5 切换镜头 (仅3D支持)

支持3种镜头切换:3dCameraFrontAll、3dCameraFrontHalf、3dCameraFrontFace
例:那就让我们赶快看看今天有哪些<camera mode='Camera3D' scene='3dCameraFrontFace' sensor_height='36.0'/>好物,首先给大家介绍的这款手机。<camera mode='Camera3D' scene='3dCameraFrontHalf' sensor_height='36.0'/>哈喽,直播间的宝宝们,小琦刚跑完5公里,元气满满的跟大家见面啦,我可是一个很烫很烫的科技发烧友,对智能产品<camera mode='Camera3D' scene='3dCameraFrontAll' sensor_height='36.0'/>非常懂行的呦。

2.1.6 切换背景 (仅3D支持)

支持在ssml文本中控制背景图切换
例:<background type='image' url='https://lf3-speech.bytetos.com/obj/speech-tts-external/ec-live/xiaomi_whole_body.jpeg' transition_effect='shutters' scene_levelmap='0'/>那就让我们赶快看看今天有哪些好物。


2.2 Server-Side

格式类型描述备注
|DAT|00|数据帧传递audio binary数据pcm格式音频
|DAT|01|数据帧传递video binary数据h264格式视频
|DAT|02|事件帧传递json格式字符串用于回调事件通知,例如开始TTS、停止TTS等
|DAT|03|数据帧传递自定义binary数据离线生产的例如mp4格式数据
|DAT|04|数据帧传递自定义binary数据离线生产的最后一包数据
|MSG|00|消息帧传递json格式字符串用于错误信息返回等

2.2.1 消息帧字段描述

字段类型描述
codeint错误码
messagestring错误描述
typeint消息类型

2.2.1.1 错误码

错误码描述
1000处理正确
1001参数无效
1002服务器忙
1003内部错误
1004编码错误
1010其它错误

2.2.1.2 消息类型

消息类型描述
0开启session时, 返回加入房间的状态消息
1关闭session时,返回关闭房间的状态信息
2调用chat接口的回调信息
3调用interrupt接口时的回调信息
4调用视频生产接口时的回调信息

2.2.2 支持I帧调整

调整I帧间隔通过在初始化参数中通过I_frame_interval指定。

字段名层级类型默认值是否必填合法范围

I_frame_interval

2

int


不设置该字段时默认I帧间隔为250帧

[25,250]
含义:25代表每25帧视频有一帧I帧,当前I帧出现后过25帧是下一个I帧

示例

{
    "video":{
        "video_width":1080,
        "video_height":1920,
        "I_frame_interval":25
    },
    "role":"XiaoYu",
    "role_conf":{
        "voice_type":"BV009_DPE_ParaTaco"
    },
    "input_mode":"text"
}

2.2.3 支持码率调整

在交互过程中需要调整bitrate时通过chat接口指定。
原chat接口格式形如

|CTL|02|"今天天气真不错"

通过扩展chat接口支持bitrate调整。扩展后chat接口为|CTL|02|{json_string},json格式为

{
  "bitrate": 400, //int类型,单位为kbps,为空时不设置,合法范围是([400,5000])
}

即交互时使用原接口格式,调整bitrate时使用json格式。

2.2.4 支持视频创作场景添加字幕

2.2.4.1 使用方法

  • 当前仅支持在视频创作场景下添加字幕,实时流场景暂不支持

  • 添加字幕时需要在初始化参数指定video["subtitle_control"]=true

  • 文本驱动模式下(input_mode=text),字幕信息均从传入文本中获得

  • 音频驱动模式下(input_mode=audio),字幕信息需要在传入音频通过subtitle标签传入,示例如|CTL|02|<speak><audio url="http://xxxx/test.mp3" format="mp3"/><subtitle text="今天天气真不错"/></speak>

  • 当前仅在文本驱动模式下支持设置多种字幕效果,通过扩展chat接口传入。支持的效果设置及其字段说明如下:

字段名类型是否必传级别说明
fontnamestring非必需3字体名,当前支持的字体见“字体类型”列表
fontsizeint非必需3字号

bold

bool

非必需

3

是否加粗字体
fasle不加粗,默认值

italic

bool

非必需

3

是否控制斜体
fasle不控制斜体,默认值

underline

bool

非必需

3

是否添加下划线
fasle不添加,默认值

primary_colour

string

非必需

3

字幕颜色透明度,共8位
1-2位:透明度,00全透明,ff不透明
3-8位:为蓝-绿-红三色的十六进制代码相排列,颜色空间依次为BBGGRR

outline_colour

string

非必需

3

字幕描边颜色透明度,共8位
1-2位:透明度,00全透明,ff不透明
3-8位:为蓝-绿-红三色的十六进制代码相排列,颜色空间依次为BBGGRR

back_colour

string

非必需

3

字幕背景颜色透明度,共8位
1-2位:透明度,00全透明,ff不透明
3-8位:为蓝-绿-红三色的十六进制代码相排列,颜色空间依次为BBGGRR

margin_lint非必需3幕边框距左侧像素数
margin_rint非必需3字幕边框距右侧像素数
margin_vint非必需3字幕边框距底部像素数

json示例如

{
    "text":"<speak>今天天气真不错</speak>",
    "subtitle": {
        "global_style": {
            "fontname": "Source Han Serif CN",
            "fontsize": 18,
            "bold": true,
            "italic": true,
            "underline": true,
            "primary_colour": "0000ff00",
            "outline_colour": "0000ff00",
            "back_colour": "0000ff00",
            "margin_l": 100,
            "margin_r": 100,
            "margin_v": 140
        }
    }
}

传入的字幕效果是全局生效的,不针对单句字幕生效


2.2.4.2 支持的字幕字体

  • 文本驱动场景下,可以通过传递fontname设置不同的字幕字体,当前支持的所有字幕字体包括:
字体类别字体名称fontname
简体中文思源宋体 CNSource Han Serif CN
思源宋体 CN SemiBoldSource Han Serif CN SemiBold
思源宋体 CN BoldSource Han Serif CN Bold
思源黑体 CN NormalSource Han Sans CN Normal
思源黑体 CN HeavySource Han Sans CN Heavy
Roboto RegularRoboto
Roboto MediumRoboto Medium
庞门正道标题体PangMenZhengDao
卓健橄榄简体ZhuoJianGanLanJianTi Regular
智勇手书体ShouShuti
站酷小薇LOGO体xiaowei
站酷文艺体zcoolwenyiti
站酷庆科黄油体zcoolqingkehuangyouti-Regular
站酷高端黑zcool-gdh
站酷快乐体HappyZcool-2016
站酷酷黑ZCOOL_KuHei
优设标题黑YouSheBiaoTiHei
新叶念体新叶念体 Regular
素材集市康康体sucaijishi
庞门正道轻松体Pangmenzhengdaoqingsongti
沐瑶随心手写体MuyaoPleased
庞门正道粗书体PangMenZhengDao-Cu
联盟起艺卢帅正锐黑体lianmengqiyilushuaizhengruiheiti Regular
江西拙楷jiangxizhuokai Regular
汉仪贤二体XianErTi
寒蝉手拙体HCSZT Regular
繁体中文黄令东齐伋复刻体QIJIC
清松手写体1清松手寫體1
思源黑体-繁体中文版Source Han Sans TW
思源宋体-繁体中文版Source Han Serif TW
源云明体GenWanMin JP Regular
英文字幕站酷意大利体ZCOOL Addict Italic 01
PublicSans-RegularPublic Sans Regular
Raleway-RegularRaleway
Montserrat-RegularMontserrat Regular
SourceSansPro-RegularSource Sans Pro
SinkinSans-400RegularSinkin Sans 400 Regular
Quicksand-RegularQuicksand-Regular
KaushanScript-RegularKaushanScript-Regular
Cantarell-RegularCantarell Regular
ChunkFive-RegularChunkFive Regular

2.2.4.3 支持输出字幕及其时间信息

  • 视频创作的字幕场景下,可以在输出视频获得所有字幕事件回调信息,包括:voice_start、subtitle_on、subtitle_off、voice_end、all_subtitles 五种

  • 事件通过|DAT|02|传递,可通过type字段区分是哪种类型事件,消息格式为:

|DAT|02|数据帧传递json格式字符串用于回调事件通知,例如字幕开始、结束等

示例:

  • 传入文本为<speak>今天天气真不错,好想出去玩。玩什么呐?钓钓鱼,看看花享受大自然。</speak>

  • 对应的字幕事件:

{
    "callback_info": {
        "data": {
            "subtitles": [
                {
                    "end_time_ms": 2880,
                    "start_time_ms": 0,
                    "text": "今天天气真不错,好想出去玩。"
                },
                {
                    "end_time_ms": 4000,
                    "start_time_ms": 2880,
                    "text": "玩什么呐?"
                },
                {
                    "end_time_ms": 6760,
                    "start_time_ms": 4000,
                    "text": "钓钓鱼,看看花享受大自然。"
                }
            ]
        },
        "type": "all_subtitles" 
    }
}
  • 字段信息说明:
字段备注
start_time_ms对应字幕开始时间,单位为ms
end_time_ms对应字幕结束时间,单位为ms
text对应字幕文本
  • 文本驱动模式下(input_mode=text)时句维度的字幕时间信息均从文本中获得

  • 音频驱动模式下字幕信息需要在传入音频通过subtitle标签传入,且音频驱动模式暂不支持获得每句播报音频的准确时间信息,只能输出单句传入字幕的开始、结束时间信息,且字幕结束时间为实际获得的音频时长。

三、接口地址

2D

协议:WebSocket
接口地址:wss://openspeech.bytedance.com/api/v1/volc_virtual_human/tta/2d?appid={appid}&access_token={token}
使用接口前需要申请appid和具体使用的形象

3D

协议:WebSocket
接口地址:wss://openspeech.bytedance.com/api/v1/volc_virtual_human/tta/3d?appid={appid}&access_token={token}
使用接口前需要申请appid和具体使用的形象

四、场景介绍

视频生产

alt
适合仅同步生产数字人视频使用,支持mp4/mov/webm等格式,生产耗时约为视频时长*0.7左右。

实时交互

alt

  • 适合实时交互场景,数字人服务直接将数字人实时音视频流推送至ByteRTC房间

  • 使用RTC作为链路传输协议,链路延迟较低,在数字人接收到驱动命令至端上音视频展示延迟<1s

  • 客户端RTC SDK自带播放功能,客户侧需要根据场景,集成不同的ByteRTC客户端(web/windows/android/iOS),可以将数字人的音视频流进行渲染和播放。火山引擎侧RTC介绍

  • 请求中不能配置codec字段

  • 请求中必须携带rtc的相关配置,示例如下:

|CTL|00|{"role":"xx","rtc":{"app_id":"xxx","room":"xxx","uid":"xx","token":"xxx"}}
  • 由于RTC同一个房间内不能使用相同的uid,因此客户在拉流时,使用的uid不能与数字人请求中rtc参数中的uid一样

实时直播

alt

  • 适合直播场景,数字人服务直接将数字人实时音视频流推送至RTMP地址

  • 使用RTMP作为传输链路协议,链路延迟相对较大,在数字人接收到驱动命令至拉流地址展示延迟在5s左右

  • 客户端通过RTMP拉流地址获取数字人音视频流,进行展示和播放。VePlay具备拉取RTMP地址&播放功能

  • 推拉流地址可以从火山视频云产品上申请

  • 请求中不能配置codec字段

  • 请求中必须携带rtmp的相关配置,示例如下:

|CTL|00|{"role":"xx","rtmp":{"addr":"rtmp://xxxxx","live_id":"xxx"}}
五、Demo

5.1 视频生产

5.1.1 Python

# coding=utf-8

import websockets
import asyncio
import json

SUCC_CODE = 1000
ILLEGAL_PARAM_CODE = 1001
SRV_BUSY_CODE = 1002
INNER_ERR_CODE = 1003
OTHER_ERR_CODE = 1004

AUDIO_DATA_HEADER = "|DAT|00|"
VIDEO_DATA_HEADER = "|DAT|01|"
JSON_DATA_HEADER = "|DAT|02|"
SELF_DATA_HEADER = "|DAT|03|"
SELF_DATA_END_HEADER = "|DAT|04|"

MSG_HEADER = "|MSG|00|"

OPEN_SESSION_HEADER = "|CTL|00|"
CLOSE_SESSION_HEADER = "|CTL|01|"
CHAT_HEADER = "|CTL|02|"

VOICE_START = "voice_start"
VOICE_END = "voice_end"
VIDEO_URL = "video_url"

conn_header = {"Resource-Id": "volc.avatar.2d"}

# 这部分需要授权下发,根据实际值进行替换
appid = "xxxx"
token = "xxxx"

uri = f"wss://openspeech.bytedance.com/api/v1/volc_virtual_human/tta/2d?appid={appid}&access_token={token}"
uid = "avatar_py_demo"
codec = "mp4"

# 使用说明:测试前替换为具体使用的形象
role = "xxx"
pose = ""
clothes = ""

param = json.dumps({
    "uid": uid,
    "role": role,
    "codec": codec,  # 视频生产需要传codec,实时场景不需要传codec
    "role_conf": {
        "pose_type": pose,
        "clothes_type": clothes
    },
    "output_url": True
})


def parse_event(data):
    obj = json.loads(data)
    info = obj["callback_info"]
    return info["type"], info["data"]


async def generate_video(text):
    try:
        # 建立连接
        print("start to connect {}".format(uri))
        async with websockets.connect(uri, extra_headers=conn_header) as ws:
            # 开启session
            data = OPEN_SESSION_HEADER + param
            print(f"<- {data}")
            await ws.send(data)
            data = await ws.recv()
            print(f"-> {data}")
            # 发送需要播报的文本
            data = CHAT_HEADER + text
            print(f"<- {data}")
            await ws.send(data)
            while True:
                data = await ws.recv()
                header = data[0:8]
                if type(data) is str:
                    print(f"-> {data}")
                # 事件相关回调
                if header == JSON_DATA_HEADER:
                    event, event_data = parse_event(data[8:])
                    if event == VOICE_END:
                        # 关闭session,等待视频合成
                        print(f"<- {CLOSE_SESSION_HEADER}")
                        await ws.send(CLOSE_SESSION_HEADER)
                    elif event == VIDEO_URL:
                        url = event_data["video_url"]
                        print(f"\n Video produce success, url: {url}")
                        break
                # 控制指令相关回调
                elif header == MSG_HEADER:
                    msg = json.loads(data[8:])
                    if msg["code"] != 1000:
                        break
    except websockets.exceptions.ConnectionClosed as e:
        print(f"Connection closed, code: {e.code}, reason: {e.reason}")


async def generate_stream(text):
    audio_file = open("test.pcm", "wb")
    video_file = open("test.h264", "wb")
    try:
        # 建立连接
        async with websockets.connect(uri, extra_headers=conn_header) as ws:
            # 开启session
            data = OPEN_SESSION_HEADER + param
            print(f"<- {data}")
            await ws.send(data)
            data = await ws.recv()
            print(f"-> {data}")
            # 发送需要播报的文本
            data = CHAT_HEADER + text
            print(f"<- {data}")
            await ws.send(data)
            while True:
                data = await ws.recv()
                header = data[0:8]
                if type(data) is str:
                    print(f"-> {data}")
                # 事件相关回调
                if header == JSON_DATA_HEADER:
                    event, _ = parse_event(data[8:])
                    # 开始播报的事件
                    if event == VOICE_START:
                        pass
                    # 结束播报的事件
                    elif event == VOICE_END:
                        # 关闭session
                        print(f"<- {CLOSE_SESSION_HEADER}")
                        await ws.send(CLOSE_SESSION_HEADER)
                        break
                # 控制指令相关回调
                elif header == MSG_HEADER:
                    msg = json.loads(data[8:])
                    if msg["code"] != 1000:
                        break
                # 二进制相关数据回调
                else:
                    # 获取pcm格式音频数据
                    if bytes.decode(header) == AUDIO_DATA_HEADER:
                        audio_file.write(data[8:])
                    # 获取h264格式视频数据
                    elif bytes.decode(header) == VIDEO_DATA_HEADER:
                        video_file.write(data[8:])
    except websockets.exceptions.ConnectionClosed as e:
        print(f"Connection closed, code: {e.code}, reason: {e.reason}")
    finally:
        audio_file.close()
        video_file.close()


if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(generate_video("今天天气真不错。"))

5.1.2 Java