双向流式TTS语音对话 SDK 是基于豆包端到端实时语音大模型,提供低延迟、双向流式TTS音频生成能力,可用于构建文本到语音的工具。
Android: com.bytedance.speechengine:speechengine_tob:0.0.12
iOS: pod 'SpeechEngineToB', '0.0.12'
该版本需要自行添加TTNet 依赖,否则Android 会崩溃,iOS 会编译报错。示例如下:
Android:
implementation 'com.bytedance.boringssl.so:boringssl-so:1.3.6' implementation('org.chromium.net:cronet:4.2.210.3-tob') { exclude group: 'com.bytedance.common', module: 'wschannel' } implementation 'com.bytedance.frameworks.baselib:ttnet:4.2.210.3-tob'
iOS:
pod 'TTNetworkManager', '4.2.210.20'
maven { url "https://artifact.bytedance.com/repository/Volcengine/" }
// Network implementation 'com.bytedance.boringssl.so:boringssl-so:{LATEST_VERSION}' implementation('org.chromium.net:cronet:{LATEST_VERSION}') { exclude group: 'com.bytedance.common', module: 'wschannel' } implementation 'com.bytedance.frameworks.baselib:ttnet:{LATEST_VERSION}' // Speech Engine implementation 'com.bytedance.speechengine:speechengine_tob:{LATEST_VERSION}'
类别 | 兼容范围 |
|---|---|
系统 | 最低支持Android 4.4 以上版本,API LEVEL 19 |
架构 | armeabi-v7a,arm64-v8a |
网络 | 支持移动数据与 WiFi 两种网络环境 |
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-keep class com.bytedance.speech.speechengine.SpeechEngineImpl {*;}
创建语音对话 SDK 引擎实例前调用,完成网络环境等相关依赖配置。APP 生命周期内仅需执行一次。
SpeechEngineGenerator.PrepareEnvironment(getApplicationContext(), getApplication());
SpeechEngine engine = SpeechEngineGenerator.getInstance(); engine.createEngine();
其中 APPID 、TOKEN 获取方式参考 控制台使用FAQ-Q1 ,RESOURCE ID 设置为 volc.service_type.10029。
//【必需配置】Engine Name mSpeechEngine.setOptionString(SpeechEngineDefines.PARAMS_KEY_ENGINE_NAME_STRING,SpeechEngineDefines.BITTS_ENGINE); //【可选配置】本地日志文件路径,SDK会在该路径文件夹下生成名为 speech_sdk.log 的日志文件,开发时设置,线上关闭。 engine.setOptionString(SpeechEngineDefines.PARAMS_KEY_DEBUG_PATH_STRING, "已存在的文件夹路径,或者空字符串"); //【可选配置】日志级别,开发时设置为 TRACE(最低级别),线上设置 WARN; engine.setOptionString(SpeechEngineDefines.PARAMS_KEY_LOG_LEVEL_STRING, SpeechEngineDefines.LOG_LEVEL_TRACE); //【必需配置】鉴权相关:Appid engine.setOptionString(SpeechEngineDefines.PARAMS_KEY_APP_ID_STRING, "APPID"); //【必需配置】鉴权相关:Token engine.setOptionString(SpeechEngineDefines.PARAMS_KEY_APP_TOKEN_STRING, "ACCESS TOKEN"); //【必需配置】语音合成服务域名 mSpeechEngine.setOptionString(SpeechEngineDefines.PARAMS_KEY_TTS_ADDRESS_STRING, "wss://openspeech.bytedance.com"); //【必需配置】语音合成服务Uri mSpeechEngine.setOptionString(SpeechEngineDefines.PARAMS_KEY_TTS_URI_STRING, "/api/v3/tts/bidirection"); //【必需配置】语音合成服务Resource id mSpeechEngine.setOptionString(SpeechEngineDefines.PARAMS_KEY_RESOURCE_ID_STRING, "RESOURCE ID"); //【必需配置】语音合成服务StartSession时传入的音频相关参数,json字符串格式 mSpeechEngine.setOptionString(SpeechEngineDefines.PARAMS_KEY_START_ENGINE_PAYLOAD_STRING,startSessionPayload); //【可选配置】语音合成服务链接超时时间 mSpeechEngine.setOptionInt(SpeechEngineDefines.PARAMS_KEY_TTS_CONN_TIMEOUT_INT,100000); //【可选配置】是否将合成出的音频保存到设备上,为 true 时需要正确配置 PARAMS_KEY_TTS_AUDIO_PATH_STRING 才会生效 mSpeechEngine.setOptionBoolean(SpeechEngineDefines.PARAMS_KEY_TTS_ENABLE_DUMP_BOOL,true); //【可选配置】 TTS 播放音频文件保存目录,必须在合成之前创建好且 APP 具有访问权限,保存的音频文件名格式为 tts_{reqid}.wav, {reqid} 是本次合成的请求 id // PARAMS_KEY_TTS_ENABLE_DUMP_BOOL 配置为 true 的音频时为【必需配置】,否则为【可选配置】 mSpeechEngine.setOptionString(SpeechEngineDefines.PARAMS_KEY_TTS_AUDIO_PATH_STRING, mDebugPath); //【可选配置】语音合成服务请求的Header部分额外参数 mSpeechEngine.setOptionString(SpeechEngineDefines.PARAMS_KEY_REQUEST_HEADERS_STRING,"{}"); //【可选配置】是否使用内置播放器播放TTS音频 mSpeechEngine.setOptionBoolean(SpeechEngineDefines.PARAMS_KEY_TTS_ENABLE_PLAYER_BOOL,true); //【可选配置】是否打开播放器的数据回调 mSpeechEngine.setOptionBoolean(SpeechEngineDefines.PARAMS_KEY_ENABLE_PLAYER_AUDIO_CALLBACK_BOOL,true);
初始化引擎对象并设置回调监听。
// 初始化引擎实例 int ret = engine.initEngine(); if (ret != SpeechEngineDefines.ERR_NO_ERROR) { Log.e(SpeechDemoDefines.TAG, "初始化失败,返回值: " + ret); return; } engine.setContext(getApplicationContext()); engine.setListener(this);
语音对话 SDK 通过发送指令接口 sendDirective 触发各种操作,需要注意不建议在 SDK 的回调线程中调用该接口。
启动引擎的传参,请参考双向流式TTS的Event事件中 客户端事件 -> StartSession 的参数说明。
// 注意这里先调用同步停止,避免SDK内部异步线程带来的问题 engine.sendDirective(SpeechEngineDefines.DIRECTIVE_SYNC_STOP_ENGINE, ""); // 启动BiTTS引擎 int ret = engine.sendDirective(SpeechEngineDefines.DIRECTIVE_START_ENGINE, startSessionPayload); if (ret != SpeechEngineDefines.ERR_NO_ERROR) { Log.e(SpeechDemoDefines.TAG, "启动失败,返回值: " + ret); return; }
startSessionPayload参数示例如下,包含了音色、音频生成参数。
"{\"user\":{\"uid\":\"YOURUID\"},\"req_params\":{\"speaker\":\"zh_female_roumeinvyou_emo_v2_mars_bigtts\",\"audio_params\":{\"emotion\":\"excited\",\"loudness_rate\":50}}}"
【火山】双向流式TTS - iOS SDK 接口文档
*注:黄色为文档正式上线前待修改内容。
双向流式TTS语音对话 SDK 是基于豆包端到端实时语音大模型,提供低延迟、双向流式TTS音频生成能力,可用于构建文本到语音的工具。
source 'https://github.com/CocoaPods/Specs.git' source 'https://github.com/volcengine/volcengine-specs.git' # TTNet pod 'TTNetworkManager', '{LATEST_VERSION}' # Speech pod 'SpeechEngineToB', '{LATEST_VERSION}'
类别 | 兼容范围 |
|---|---|
系统 | 最低支持 iOS 12.0 |
架构 | armv7,arm64,x86_64 |
网络 | 支持移动数据与 WiFi 两种网络环境 |
创建语音对话 SDK 引擎实例前调用,完成网络环境等相关依赖配置。APP 生命周期内仅需执行一次。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { return [SpeechEngine prepareEnvironment]; }
语音对话 SDK 通过如下方式获取相关实例。
//创建实例 self.engine = [[SpeechEngine alloc] init]; //添加引擎代理,需要实现回调方法 [self.engine createEngineWithDelegate:self];
其中 APPID 、TOKEN 获取方式参考 控制台使用FAQ-Q1 ,RESOURCE ID 设置为 volc.service_type.10029,URI设置为/api/v3/tts/bidirection。
//【必需配置】Engine Name [self.curEngine setStringParam:SE_BITTS_ENGINE forKey:SE_PARAMS_KEY_ENGINE_NAME_STRING]; //【可选配置】本地日志文件路径,SDK会在该路径文件夹下生成名为 speech_sdk.log 的日志文件,开发时设置,线上关闭。 [self.engine setStringParam:@"已存在的文件夹路径,或者空字符串" forKey:SE_PARAMS_KEY_DEBUG_PATH_STRING]; //【可选配置】日志级别,开发时设置为 TRACE(最低级别),线上设置 WARN; [self.engine setStringParam:SE_LOG_LEVEL_TRACE forKey:SE_PARAMS_KEY_LOG_LEVEL_STRING]; //【可选配置】自定义请求Header [self.curEngine setStringParam:headerStr forKey:SE_PARAMS_KEY_REQUEST_HEADERS_STRING]; //【可选配置】是否使用 SDK 内置播放器播放合成出的音频,默认为 true [self.curEngine setBoolParam:[self.settings getBool:SETTING_TTS_ENABLE_PLAYER] forKey:SE_PARAMS_KEY_TTS_ENABLE_PLAYER_BOOL]; //【可选配置】是否令 SDK 通过回调返回播放器播放的pcm音频数据,默认不返回。 // 开启后,SDK 会流式返回音频,收到 SEPlayerStartPlayAudio SEPlayerFinishPlayAudio表示开始播放当前句对应音频 //收到SEPlayerAudioData表示流式的pcm音频数据 [self.curEngine setBoolParam:[self.settings getBool:SETTING_ENABLE_PLAYER_AUDIO_CALL_BACK] ? SETtsDataCallbackModeAll : SETtsDataCallbackModeNone forKey:SE_PARAMS_KEY_ENABLE_PLAYER_AUDIO_CALLBACK_BOOL]; //【可选配置】是否将合成出的音频保存到设备上,为 true 时需要正确配置 PARAMS_KEY_TTS_AUDIO_PATH_STRING 才会生效 [self.curEngine setBoolParam:[self.settings getBool:SETTING_TTS_ENABLE_DUMP] //【可选配置】TTS播放文件保存路径,如不为空字符串,则SDK会将播放器音频保存到该路径下,文件格式为 .wav [self.curEngine setStringParam:self.debugPath forKey:SE_PARAMS_KEY_TTS_AUDIO_PATH_STRING]; //【必需配置】在线合成鉴权相关:Appid [self.curEngine setStringParam:self.ttsAppId forKey:SE_PARAMS_KEY_APP_ID_STRING]; //【必需配置】语音合成服务域名 [self.curEngine setStringParam:ttsAddress forKey:SE_PARAMS_KEY_TTS_ADDRESS_STRING]; //【必需配置】语音合成服务Uri [self.curEngine setStringParam:ttsUri forKey:SE_PARAMS_KEY_TTS_URI_STRING]; //【必需配置】语音合成服务资源id [self.curEngine setStringParam:resourceId forKey: SE_PARAMS_KEY_RESOURCE_ID_STRING]; //【可选配置】TTS连接超时时间 [self.curEngine setIntParam:10000 forKey:SE_PARAMS_KEY_TTS_CONN_TIMEOUT_INT]; //【必需配置】StarSession时的payload,指定音频生成相关参数,不包含待合成的文本 [self.curEngine setStringParam:startPayload forKey:SE_PARAMS_KEY_START_ENGINE_PAYLOAD_STRING];
初始化引擎对象并设置回调监听。
// 初始化引擎实例 SEEngineErrorCode ret = [self.engine initEngine]; if (ret != SENoError) { NSLog(@"初始化失败,返回值: %d", ret); return; }
语音对话 SDK 通过发送指令接口 sendDirective 触发各种操作,需要注意不建议在 SDK 的回调线程中调用该接口。
启动引擎的传参为StartSession命令的参数,详细参数可以见双向流式TTS的Event事件。
// 注意这里先调用同步停止,避免SDK内部异步线程带来的问题 int ret = mSpeechEngine.sendDirective(SpeechEngineDefines.DIRECTIVE_SYNC_STOP_ENGINE, ""); if (ret != SpeechEngineDefines.ERR_NO_ERROR) { Log.e(SpeechDemoDefines.TAG, "send directive stop failed, " + ret); return; } // 启动BiTTS引擎 ret = mSpeechEngine.sendDirective(SpeechEngineDefines.DIRECTIVE_START_ENGINE, startSessionPayload); if (ret != SpeechEngineDefines.ERR_NO_ERROR) { Log.e(SpeechDemoDefines.TAG, "send directive start failed, " + ret); return; }
startSessionPayload参数示例如下,包含了音色、音频生成参数。
"{\"user\":{\"uid\":\"YOURUID\"},\"req_params\":{\"speaker\":\"zh_female_roumeinvyou_emo_v2_mars_bigtts\",\"audio_params\":{\"emotion\":\"excited\",\"loudness_rate\":50}}}"
说明
注意:启动BiTTS引擎只完成了建连操作,没有发起StartSession,在开始合成前需要先调用sendDirective(SpeechEngineDefines.DIRECTIVE_EVENT_START_SESSION,"")
双向流式TTS支持在一个链接中多次调用StartSession和FinishSession。每调用一次表示开始合成服务和结束合成服务。
调用StartSession时data字段有如下2种设置方式
int ret = 0; ret = mSpeechEngine.sendDirective(SpeechEngineDefines.DIRECTIVE_EVENT_START_SESSION,""); //或者传入更新后的新参数 //ret = mSpeechEngine.sendDirective(SpeechEngineDefines.DIRECTIVE_EVENT_START_SESSION,startSessionPayload); if(ret!=0){ Log.e(SpeechDemoDefines.TAG, "发送StartSession failed: " + ret); String message = "发送StartSession指令失败, " + ret; sendSynthesisDirectiveFailed(message); }
如果没有文本了,或者需要强制结束时可以调用FinishSession让服务端基于已收到的文本完成音频合成并返回。
说明
注意:如果传输文本最后不包含标点符号,那么服务端会等待后续文本到来才会触发合成。超时4秒没有收到后续文本也会触发合成。如果期望服务端立马开始合成则需要调用FinishSession。
int ret = 0; ret = mSpeechEngine.sendDirective(SpeechEngineDefines.DIRECTIVE_EVENT_FINISH_SESSION, ""); if(ret!=0){ Log.e(SpeechDemoDefines.TAG, "发送FinishSession failed: " + ret); String message = "发送FinishSession指令失败, " + ret; sendSynthesisDirectiveFailed(message); }
文本内容需要拼装车json格式的字符串传入。如果有其他参数可以透传给服务端。
String result = "{\"req_params\":{\"text\":\"" + text + "\"}}"; int ret = mSpeechEngine.sendDirective(SpeechEngineDefines.DIRECTIVE_EVENT_TASK_REQUEST, result); if (ret != 0) { Log.e(SpeechDemoDefines.TAG, "Synthesis faile: " + ret); String message = "发送合成指令失败, " + ret; sendSynthesisDirectiveFailed(message); }
说明
可以调用多次DIRECTIVE_EVENT_TASK_REQUEST向服务端发送待合成的文本内容。服务端会切句逐个返回。如果需要立即返回音频内容,可以在发送DIRECTIVE_EVENT_TASK_REQUEST前后调用StartSession和FinishSession确保音频马上返回。
如果要取消当前合成服务,期望服务端不再返回音频。则调用CancleSession
int ret = 0; ret = mSpeechEngine.sendDirective(SpeechEngineDefines.DIRECTIVE_EVENT_CANCLE_SESSION, ""); if(ret!=0){ Log.e(SpeechDemoDefines.TAG, "发送FinishSession failed: " + ret); String message = "发送FinishSession指令失败, " + ret; sendSynthesisDirectiveFailed(message); }
可以在播放音频时发送指令DIRECTIVE_PAUSE_PLAYER,暂停tts音频播放。
int ret = mSpeechEngine.sendDirective(SpeechEngineDefines.DIRECTIVE_PAUSE_PLAYER, ""); Log.d(SpeechDemoDefines.TAG, "Pause playback status:" + ret);
可以在播放音频时发送指令DIRECTIVE_RESUME_PLAYER,恢复tts音频播放
int ret = mSpeechEngine.sendDirective(SpeechEngineDefines.DIRECTIVE_RESUME_PLAYER, ""); Log.d(SpeechDemoDefines.TAG, "Resume playback status:" + ret);
// 会等待回调函数执行完成,不可在回调线程中执行。 mSpeechEngine.sendDirective(SpeechEngineDefines.DIRECTIVE_SYNC_STOP_ENGINE, "");
启动引擎后,SDK会不断回调消息。回调的消息内容,请参考双向流式TTS的Event服务事件说明。
@Override public void onSpeechMessage(int type, byte[] data, int len) { String stdData = ""; stdData = new String(data); switch (type) { case SpeechEngineDefines.MESSAGE_TYPE_ENGINE_START: // Callback: 引擎启动成功回调 Log.i(SpeechDemoDefines.TAG, "Callback: 引擎启动成功: data: " + stdData); break; case SpeechEngineDefines.MESSAGE_TYPE_ENGINE_STOP: // Callback: 引擎关闭回调 Log.i(SpeechDemoDefines.TAG, "Callback: 引擎关闭: data: " + stdData); break; case SpeechEngineDefines.MESSAGE_TYPE_ENGINE_ERROR: // Callback: 错误信息回调 Log.e(SpeechDemoDefines.TAG, "Callback: 错误信息: " + stdData); break; case SpeechEngineDefines.MESSAGE_TYPE_EVENT_TTS_SENTENCE_START: // Callback: 合成开始回调 Log.e(SpeechDemoDefines.TAG, "Callback: TTS_SENTENCE_START: " + stdData); break; case SpeechEngineDefines.MESSAGE_TYPE_EVENT_TTS_SENTENCE_END: // Callback: 合成结束回调 Log.e(SpeechDemoDefines.TAG, "Callback: TTS_SENTENCE_END: " + stdData); break; case SpeechEngineDefines.MESSAGE_TYPE_EVENT_TTS_RESPONSE: Log.e(SpeechDemoDefines.TAG, "Callback: TTS_RESPONSE: data len " + stdData.length()); break; case SpeechEngineDefines.MESSAGE_TYPE_EVENT_TTS_ENDED: Log.e(SpeechDemoDefines.TAG, "Callback: TTSEnded: " + stdData); break; case SpeechEngineDefines.MESSAGE_TYPE_PLAYER_AUDIO_DATA: break; case SpeechEngineDefines.MESSAGE_TYPE_PLAYER_START_PLAY_AUDIO: // Callback: 播放开始回调 Log.e(SpeechDemoDefines.TAG, "Callback: 播放开始: " + stdData); break; case SpeechEngineDefines.MESSAGE_TYPE_PLAYER_FINISH_PLAY_AUDIO: // Callback: 播放结束回调 Log.e(SpeechDemoDefines.TAG, "Callback: 播放结束: " + stdData); break; default: break; } }
当不再需要语音对话后,建议对引擎实例进行销毁,释放内存资源。
// 内部会执行SYNC_STOP,不可在回调线程中执行。 engine.destroyEngine(); engine = null;
其中 APPID 、TOKEN 获取方式参考 控制台使用FAQ-Q1
RESOURCE ID 设置为 volc.service_type.10029,BITTS_DEFAULT_START_PAYLOAD为使用合成服务时的音频相关参数。。