文本转动画服务,支持输入文本,实时返回音视频&视频生产的功能,TTA服务与2D&3D服务间以websocket协议进行交互。
新增语音转动画功能,支持音频URL或音频流式输入,驱动数字人进行播报
新增推流至ByteRTC房间功能,实现1v1实时交互 ByteRTC介绍
新增推流至RTMP地址功能,实现数字人实时直播 视频云直播服务介绍
针对在控制台下单的数字人资产,在调用TTA接口时,
格式 | 类型 | 描述 | 备注 |
---|---|---|---|
|CTL|00| | 控制帧 | 开启session | 控制帧后面追加json格式信息,例如uid、role等,开始session时支持对背景、logo、视频分辨率、横竖屏、主播相关配置(音色、姿态、服装、位置)设置 |
|CTL|01| | 控制帧 | 关闭session | |
|CTL|02| | 控制帧 | 发送chat命令
| 1.控制帧后面追加信息,支持文本驱动、音频驱动两种格式 |
|CTL|03| | 控制帧 | 打断数字人播报 | 当前只有文本驱动下生效 |
|CTL|08| | 控制帧 | 流式音频驱动 | |CTL|08|xxxx |
|CTL|09| | 控制帧 | 流式音频驱动尾包 | |CTL|09|xxxx |
字段 | 含义 | 层级 | 类型 | 是否必需 | 备注 |
---|---|---|---|---|---|
background | 背景图片/视频url | 1 | string | 非必需 | 可支持图片和视频作为背景,不设置或者为空时使用默认背景 |
logo | logo配置相关 | 1 | 无 | 非必需 | 如果logo字段存在,其他logo配置字段必须存在 |
logo_url | logo图url | 2 | string | 非必需 | 为空时忽略其他logo配置 |
logo_top_offset | logo上边距 | 2 | unsigned int | 非必需 | 可以为0 |
logo_left_offset | logo左边距 | 2 | unsigned int | 非必需 | 可以为0 |
logo_height | logo高度 | 2 | unsigned int | 非必需 | logo字段不空时不可为0 |
logo_width | logo宽度 | 2 | unsigned int | 非必需 | logo字段不空时不可为0 |
video | 视频配置相关 | 1 | 无 | 非必需 | 1.支持视频分辨率为1080p/720p/480p |
video_width | 生成视频流宽 | 2 | unsigned int | 非必需 | 1.宽高都不设定时默认宽1080,高1920 |
video_height | 生成视频流高 | 2 | unsigned int | 非必需 | |
role | 主播name | 1 | string | 必需 | 目前支持多个主播形象,各个形象支持的姿态、服装、动作各不相同,具体见“动作库说明”。
GuoXiaoyuan(小源)
COCO |
role_conf | 主播配置相关 | 1 | 无 | 非必需 | |
voice_type | 主播声音 | 2 | string | 非必需 |
BV405 (甜美小源)
BV008_DPE_ParaTaco (知性男声) 如需试听音色,请前往语音合成产品能力体验 |
pose_type | 主播姿态 | 2 | string | 非必需 | 合法值和主播形象相对应,详见“动作库说明” |
clothes_type | 主播服装 | 2 | string | 非必需 | |
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 | 主播上边距 | 2 | unsigned int | 非必需 | 0 <= role_top_offset < video_height |
speed | 调节数字人播报语速 | 2 | float | 非必需 | [0.25,3],默认值1.0 |
pitch | 调节数字人播报语调 | 2 | float | 非必需 | [0,10],默认值1.0 |
volume | 调节数字人播报音量 | 2 | float | 非必需 | [0,3],默认值1.0 |
input_mode | 设置引擎驱动模式 | 1 | string | 非必需 | text:文本驱动模式,默认值 |
codec | 离线视频生产的格式 | 1 | string | 非必需 | 合法值为mp4/webm/mov |
appid | 账号ID | 1 | string | 必需 | 授权下发,请联系对接人获取 |
rtc | RTC相关配置 | 1 | 非必需 | ||
app_id | RTC的app id | 2 | string | RTC场景下必需 | |
room | RTC的房间号 | 2 | string | RTC场景下必需 | |
uid | RTC的uid | 2 | string | RTC场景下必需 | |
token | 根据RTC房间号和uid生成的token | 2 | string | RTC场景下必需 | 生成token时可以指定有效期,需要确保在有效期内完成RTC交互 |
rtmp | RTMP相关配置 | 1 | 非必需 | ||
addr | RTMP推流地址 | 2 | string | RTMP场景下必需 | |
live_id | RTMP的live id | 2 | string | RTMP场景下必需 |
支持静默作为单个动作(例如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暂不支持)
形象 | 已支持姿态/服装组合 | 动作库 |
---|---|---|
GuoXiaoyuan | pose2_clothes1 | 0 opening_wave_hand |
XiaoHuan | pose1_clothes1 | OPENING_BOWING opening_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 激动 |
标签类型 | 标签说明 | 示例 |
---|---|---|
图片(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暂不支持) | <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"/>这是图片显示范围中的第二句话。显示结束了! 支持多轨道示例如:
ps:非自闭合image(mode=default)中不可嵌套image标签,下述为错误示例
| |
视频(video) | 支持自闭合: | <speak>文本一<video url="http://localhost:8000/test_xiaozhao.mp4" left="10" top="20" width="40" height="80" level="0"/>文本二</speak>。 |
当前支持在传入文本时通过标签进行词条精修,具体支持的标签为
标签 | 说明 | 示例 |
---|---|---|
py | 指定读音 | |
break | 插入停顿 | |
speed | 语速调节 | |
volume | 音量调节 | |
pitch | 音调调节 |
支持3种镜头切换:3dCameraFrontAll、3dCameraFrontHalf、3dCameraFrontFace
例:
支持在ssml文本中控制背景图切换
例:
格式 | 类型 | 描述 | 备注 |
---|---|---|---|
|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格式字符串 | 用于错误信息返回等 |
字段 | 类型 | 描述 |
---|---|---|
code | int | 错误码 |
message | string | 错误描述 |
type | int | 消息类型 |
错误码 | 描述 |
---|---|
1000 | 处理正确 |
1001 | 参数无效 |
1002 | 服务器忙 |
1003 | 内部错误 |
1004 | 编码错误 |
1010 | 其它错误 |
消息类型 | 描述 |
---|---|
0 | 开启session时, 返回加入房间的状态消息 |
1 | 关闭session时,返回关闭房间的状态信息 |
2 | 调用chat接口的回调信息 |
3 | 调用interrupt接口时的回调信息 |
4 | 调用视频生产接口时的回调信息 |
调整I帧间隔通过在初始化参数中通过I_frame_interval指定。
字段名 | 层级 | 类型 | 默认值 | 是否必填 | 合法范围 |
---|---|---|---|---|---|
I_frame_interval | 2 | int | 无 | 否 | [25,250] |
示例
{ "video":{ "video_width":1080, "video_height":1920, "I_frame_interval":25 }, "role":"XiaoYu", "role_conf":{ "voice_type":"BV009_DPE_ParaTaco" }, "input_mode":"text" }
在交互过程中需要调整bitrate时通过chat接口指定。
原chat接口格式形如
|CTL|02|"今天天气真不错"
通过扩展chat接口支持bitrate调整。扩展后chat接口为|CTL|02|{json_string},json格式为
{ "bitrate": 400, //int类型,单位为kbps,为空时不设置,合法范围是([400,5000]) }
即交互时使用原接口格式,调整bitrate时使用json格式。
当前仅支持在视频创作场景下添加字幕,实时流场景暂不支持
添加字幕时需要在初始化参数指定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接口传入。支持的效果设置及其字段说明如下:
字段名 | 类型 | 是否必传 | 级别 | 说明 |
---|---|---|---|---|
fontname | string | 非必需 | 3 | 字体名,当前支持的字体见“字体类型”列表 |
fontsize | int | 非必需 | 3 | 字号 |
bold | bool | 非必需 | 3 | 是否加粗字体 |
italic | bool | 非必需 | 3 | 是否控制斜体 |
underline | bool | 非必需 | 3 | 是否添加下划线 |
primary_colour | string | 非必需 | 3 | 字幕颜色透明度,共8位 |
outline_colour | string | 非必需 | 3 | 字幕描边颜色透明度,共8位 |
back_colour | string | 非必需 | 3 | 字幕背景颜色透明度,共8位 |
margin_l | int | 非必需 | 3 | 幕边框距左侧像素数 |
margin_r | int | 非必需 | 3 | 字幕边框距右侧像素数 |
margin_v | int | 非必需 | 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 } } }
传入的字幕效果是全局生效的,不针对单句字幕生效
字体类别 | 字体名称 | fontname |
---|---|---|
简体中文 | 思源宋体 CN | Source Han Serif CN |
思源宋体 CN SemiBold | Source Han Serif CN SemiBold | |
思源宋体 CN Bold | Source Han Serif CN Bold | |
思源黑体 CN Normal | Source Han Sans CN Normal | |
思源黑体 CN Heavy | Source Han Sans CN Heavy | |
Roboto Regular | Roboto | |
Roboto Medium | Roboto 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-Regular | Public Sans Regular | |
Raleway-Regular | Raleway | |
Montserrat-Regular | Montserrat Regular | |
SourceSansPro-Regular | Source Sans Pro | |
SinkinSans-400Regular | Sinkin Sans 400 Regular | |
Quicksand-Regular | Quicksand-Regular | |
KaushanScript-Regular | KaushanScript-Regular | |
Cantarell-Regular | Cantarell Regular | |
ChunkFive-Regular | ChunkFive Regular |
视频创作的字幕场景下,可以在输出视频获得所有字幕事件回调信息,包括: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
标签传入,且音频驱动模式暂不支持获得每句播报音频的准确时间信息,只能输出单句传入字幕的开始、结束时间信息,且字幕结束时间为实际获得的音频时长。
协议:WebSocket
接口地址:wss://openspeech.bytedance.com/api/v1/volc_virtual_human/tta/2d?appid={appid}&access_token={token}
使用接口前需要申请appid和具体使用的形象
协议:WebSocket
接口地址:wss://openspeech.bytedance.com/api/v1/volc_virtual_human/tta/3d?appid={appid}&access_token={token}
使用接口前需要申请appid和具体使用的形象
适合仅同步生产数字人视频使用,支持mp4/mov/webm等格式,生产耗时约为视频时长*0.7左右。
适合实时交互场景,数字人服务直接将数字人实时音视频流推送至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"}}
适合直播场景,数字人服务直接将数字人实时音视频流推送至RTMP地址
使用RTMP作为传输链路协议,链路延迟相对较大,在数字人接收到驱动命令至拉流地址展示延迟在5s左右
客户端通过RTMP拉流地址获取数字人音视频流,进行展示和播放。VePlay具备拉取RTMP地址&播放功能
推拉流地址可以从火山视频云产品上申请
请求中不能配置codec字段
请求中必须携带rtmp的相关配置,示例如下:
|CTL|00|{"role":"xx","rtmp":{"addr":"rtmp://xxxxx","live_id":"xxx"}}
# 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("今天天气真不错。"))