注意:说明:
一、核心概念
在正式接入 AI 字幕前,建议先了解以下核心概念:
| 概念 | 说明 |
| SourceLanguage | 设置需要进行语音识别的语言,用于语音识别。支持 20 种语言,包括中英混合识别。详细可参见:源语言列表。 |
| TranslationLanguage | 开启翻译后,生成的翻译字幕的语言类型,用于开启翻译功能后区分语言类型。详细可参见:翻译语言列表。 |
| TranscriberMessage | 单条字幕消息,对应说话人的一段连续语音,包含原文、译文、说话人信息与完成状态。 |
| TranscriberState | 字幕模块的实时状态数据,通过订阅该状态可在 UI 上展示字幕列表与运行状态。 |
二、环境配置
AI 字幕功能基于 AtomicXCore SDK 提供的 AITranscriberStore 接口实现。在正式调用接口前,请确保已完成对应平台的 AtomicXCore SDK 集成,并成功进房。
AndroidiOSFlutterWeb
·已集成 atomicxcore 依赖,并在工程中引入 io.trtc.tuikit.atomicxcore.api.ai.AITranscriberStore。
·确保已在房间内(完成 startLive 或 joinLive)再调用字幕相关接口。
·已通过 CocoaPods 集成 AtomicXCore,并在源码中 import AtomicXCore。
·确保已在房间内(完成 startLive 或 joinLive)再调用字幕相关接口。
·已在 pubspec.yaml 中引入 atomic_x_core 依赖。
·确保已在房间内(完成 startLive 或 joinLive)再调用字幕相关接口。
·已集成 tuikit-atomicx-vue3 依赖,并从中引入 useAITranscriberStateLive。
·确保已在房间内(完成 startLive 或 joinLive)再调用字幕相关接口。
三、创建 AITranscriberStore 实例
AI 字幕相关接口通过 AITranscriberStore 管理,需使用工厂方法按房间 ID 创建实例。同一房间 ID 多次创建会返回同一实例。
AndroidiOSFlutterWebimport io.trtc.tuikit.atomicxcore.api.ai.AITranscriberStore// 按房间 ID 创建实例(同一房间多次调用返回同一实例)val transcriberStore = AITranscriberStore.create("your_room_id")import AtomicXCore// 按房间 ID 创建实例(同一房间多次调用返回同一实例)let transcriberStore = AITranscriberStore.create(roomID: "your_room_id")import 'package:atomic_x_core/api/ai/ai_transcriber_store.dart';// 按房间 ID 创建实例(同一房间多次调用返回同一实例)final transcriberStore = AITranscriberStore.create("your_room_id");Web 端通过 tuikit-atomicx-vue3 提供的 useAITranscriberStateLive Composable 使用 AI 字幕能力,无需手动按房间 ID 创建实例。在组件中调用该 Hook 即可获取字幕状态与操作方法,内部会自动关联当前所在房间。import { useAITranscriberStateLive } from 'tuikit-atomicx-vue3';// 在组件 setup 中调用,获取状态与操作方法(同一房间共享同一份状态)const { myLanguage, realtimeMessageList, isTranscriptionRunning, transcriptionConfig, startTranscription, updateTranscription, stopTranscription,} = useAITranscriberStateLive();
四、订阅字幕状态
字幕的实时数据(消息列表、运行状态、配置等)通过状态发布器(State / StateFlow / ValueListenable)对外提供。建议在开启字幕前先完成订阅,以便及时刷新 UI。
五、状态字段说明
| 字段 | 类型 | 说明 |
| selfLanguage | SourceLanguage | 当前用户设置的源语言 |
| realtimeMessageList | List<TranscriberMessage> | 实时字幕消息列表,随转写进度自动更新 |
| isTranscriptionRunning | Bool | 转写服务是否正在运行 |
| transcriptionConfig | TranscriptionConfig | 当前转写配置 |
六、订阅示例
AndroidiOSFlutterWebimport kotlinx.coroutines.launchimport androidx.lifecycle.lifecycleScopeimport io.trtc.tuikit.atomicxcore.api.ai.AITranscriberStore// 订阅实时字幕消息列表lifecycleScope.launch { transcriberStore.transcriberState.realtimeMessageList.collect { messages -> messages.forEach { message -> println("Speaker: ${message.speakerUserName}") println("Source text: ${message.sourceText}") message.translationTexts.forEach { (lang, text) -> println("Translation[$lang]: $text") } } }}// 订阅转写运行状态lifecycleScope.launch { transcriberStore.transcriberState.isTranscriptionRunning.collect { running -> println("Transcription running: $running") }}// 订阅字幕整体状态transcriberStore.state.subscribe { state in for message in state.realtimeMessageList { print("Speaker: \\(message.speakerUserName)") print("Source text: \\(message.sourceText)") for (lang, text) in message.translationTexts { print("Translation[\\(lang)]: \\(text)") } } print("Transcription running: \\(state.isTranscriptionRunning)")}import 'package:atomic_x_core/api/ai/ai_transcriber_store.dart';// 订阅实时字幕消息列表transcriberStore.transcriberState.realtimeMessageList.addListener(() { final messages = transcriberStore.transcriberState.realtimeMessageList.value; for (final message in messages) { print("Speaker: ${message.speakerUserName}"); print("Source text: ${message.sourceText}"); message.translationTexts.forEach((lang, text) { print("Translation[$lang]: $text"); }); }});// 订阅转写运行状态transcriberStore.transcriberState.isTranscriptionRunning.addListener(() { final running = transcriberStore.transcriberState.isTranscriptionRunning.value; print("Transcription running: $running");});Web 端字幕状态以 Vue 响应式数据(ref)形式对外提供,可直接在模板中渲染,或使用 watch 监听变化。import { watch } from 'vue';import { useAITranscriberStateLive } from 'tuikit-atomicx-vue3';const { realtimeMessageList, isTranscriptionRunning,} = useAITranscriberStateLive();// 订阅实时字幕消息列表watch(realtimeMessageList, (messages) => { messages.forEach((message) => { console.log(`Speaker: ${message.speakerUserName}`); console.log(`Source text: ${message.sourceText}`); Object.entries(message.translationTexts).forEach(([lang, text]) => { console.log(`Translation[${lang}]: ${text}`); }); });});// 订阅转写运行状态watch(isTranscriptionRunning, (running) => { console.log(`Transcription running: ${running}`);});
七、开启 AI 字幕
完成实例创建与状态订阅后,调用 startTranscription 开启实时转写。如需同时开启翻译,请在 TranscriptionConfig 中将 enableTranslation 设置为 true。
开启 AI 字幕后,系统会根据麦上成员的语音流生成转写内容;若同时开启翻译,系统会根据说话人的源语言与当前配置的目标语言生成译文。使用时请注意以下规则:
·只有当麦上其他成员设置的源语言和自己的源语言不同时,才会显示翻译语言。
myLanguage 表示当前用户希望看到的字幕语言,也会作为当前用户本人说话语言的默认判断依据。
例如,房主开启了字幕和翻译,并将自己的 myLanguage 设置为英语。如果当前麦上只有房主一人,且房主本人说话,系统会认为该语音的源语言就是英语,因此只会看到原文,不会额外生成“翻译后的英语内容”。
如需验证翻译效果,可以让另一位说不同语言的麦上成员参与发言。例如麦上观众使用中文发言,房主侧即可看到该成员的原文及对应译文。
·建议麦上成员主动传入自己的说话语言。
myLanguage 用于声明当前用户的说话语言,传入与实际语言匹配的值可以提升识别准确率。
如果麦上成员未调用相关接口传入 myLanguage,系统会默认读取该用户的手机系统语言作为兜底语言。因此,即使未显式设置语言,用户开启 AI 字幕后仍可能看到字幕内容,但为了获得更准确的识别效果,建议引导用户主动选择或传入自己的常用说话语言。
·麦下观众开启字幕不会主动触发转写任务,但可以追加翻译任务。
麦下观众开启字幕时,只会订阅房间内已有的转写结果,不会单独触发转写机器人进房拉取麦上成员的音频流进行识别。
如果房间内已有麦上成员开启字幕,并且转写任务正在运行,麦下观众开启字幕后即可看到转写内容;此时麦下观众也可以开启翻译,系统会基于已有转写结果为该观众追加对应的翻译任务。
注意:说明:
注意:源语言 myLanguage 表示当前用户希望看到的字幕语言,同时也会作为当前用户本人发言时的识别语言。建议传入与当前用户使用语言一致的值。开启翻译后,系统会将其他语言的麦上成员发言翻译为 myLanguage 对应的语言。
AndroidiOSFlutterWebimport io.trtc.tuikit.atomicxcore.api.ai.SourceLanguageimport io.trtc.tuikit.atomicxcore.api.ai.TranscriptionConfigimport io.trtc.tuikit.atomicxcore.api.ai.AITranscriberStore// 1. 配置转写参数:开启翻译val config = TranscriptionConfig(enableTranslation = true)// 2. 开启转写,指定源语言为中英混合transcriberStore.startTranscription( myLanguage = SourceLanguage.CHINESE_ENGLISH, config = config) { code, message -> if (code != 0) { println("Start transcription failed: $message") } else { println("Start transcription success") }}import AtomicXCore// 1. 配置转写参数:开启翻译let config = TranscriptionConfig(enableTranslation: true)// 2. 开启转写,指定源语言为中英混合transcriberStore.startTranscription(myLanguage: .chineseEnglish, config: config) { error in if let error = error { print("Start transcription failed: \\(error)") } else { print("Start transcription success") }}import 'package:atomic_x_core/api/ai/ai_transcriber_store.dart';// 1. 配置转写参数:开启翻译final config = TranscriptionConfig(enableTranslation: true);// 2. 开启转写,指定源语言为中英混合final result = await transcriberStore.startTranscription( SourceLanguage.chineseEnglish, config: config,);if (!result.isSuccess) { print("Start transcription failed: ${result.errorMessage}");} else { print("Start transcription success");}Web 端通过 startTranscription 传入 myLanguage 与 config 开启转写。接口返回 Promise,可用 try/catch 处理结果。import { useAITranscriberStateLive } from 'tuikit-atomicx-vue3';const { startTranscription } = useAITranscriberStateLive();// 开启转写,指定源语言为中英混合,并开启翻译try { await startTranscription({ myLanguage: 'zh_en', config: { enableTranslation: true }, }); console.log('Start transcription success');} catch (error) { console.error('Start transcription failed:', error);}
八、更新字幕配置
转写服务运行期间,可调用 updateTranscription 动态修改源语言或翻译开关,无需停止后重启。
AndroidiOSFlutterWebimport io.trtc.tuikit.atomicxcore.api.ai.SourceLanguageimport io.trtc.tuikit.atomicxcore.api.ai.TranscriptionConfigimport io.trtc.tuikit.atomicxcore.api.ai.AITranscriberStore// 运行中切换源语言为英语,并关闭翻译val newConfig = TranscriptionConfig(enableTranslation = false)transcriberStore.updateTranscription( myLanguage = SourceLanguage.ENGLISH, config = newConfig) { code, message -> if (code != 0) { println("Update transcription failed: $message") }}import AtomicXCore// 运行中切换源语言为英语,并关闭翻译var newConfig = TranscriptionConfig(enableTranslation: false)transcriberStore.updateTranscription(myLanguage: .english, config: newConfig) { error in if let error = error { print("Update transcription failed: \\(error)") }}import 'package:atomic_x_core/api/ai/ai_transcriber_store.dart';// 运行中切换源语言为英语,并关闭翻译final newConfig = TranscriptionConfig(enableTranslation: false);final result = await transcriberStore.updateTranscription( SourceLanguage.english, config: newConfig,);if (!result.isSuccess) { print("Update transcription failed: ${result.errorMessage}");}import { useAITranscriberStateLive } from 'tuikit-atomicx-vue3';const { updateTranscription } = useAITranscriberStateLive();// 运行中切换源语言为英语,并关闭翻译try { await updateTranscription({ myLanguage: 'en', config: { enableTranslation: false }, });} catch (error) { console.error('Update transcription failed:', error);}
九、停止 AI 字幕
当需要停止转写时,调用 stopTranscription。停止后转写机器人将不再识别语音,字幕消息列表也不再更新。
AndroidiOSFlutterWebimport io.trtc.tuikit.atomicxcore.api.ai.AITranscriberStoretranscriberStore.stopTranscription { code, message -> if (code != 0) { println("Stop transcription failed: $message") } else { println("Stop transcription success") }}import AtomicXCoretranscriberStore.stopTranscription { error in if let error = error { print("Stop transcription failed: \\(error)") } else { print("Stop transcription success") }}import 'package:atomic_x_core/api/ai/ai_transcriber_store.dart';final result = await transcriberStore.stopTranscription();if (!result.isSuccess) { print("Stop transcription failed: ${result.errorMessage}");} else { print("Stop transcription success");}import { useAITranscriberStateLive } from 'tuikit-atomicx-vue3';const { stopTranscription } = useAITranscriberStateLive();try { await stopTranscription(); console.log('Stop transcription success');} catch (error) { console.error('Stop transcription failed:', error);}
十、字幕消息结构
每条字幕消息对应说话人的一段连续语音,结构如下:
| 属性 | 类型 | 说明 |
| segmentId | String | 字幕段唯一标识 |
| speakerUserId | String | 说话人用户 ID |
| speakerUserName | String | 说话人昵称 |
| sourceText | String | 识别出的原文 |
| translationTexts | Map<TranslationLanguage, String> | 目标语言的译文 |
| timestamp | Int / Long | 消息时间戳 |
| isCompleted | Bool | 该段语音是否已结束。为 true 后原文与译文不再更新 |
注意:说明:
十一、完整使用示例
以下示例展示从创建实例、订阅状态到开启字幕的完整流程。
AndroidiOSFlutterWebimport io.trtc.tuikit.atomicxcore.api.ai.AITranscriberStoreimport io.trtc.tuikit.atomicxcore.api.ai.SourceLanguageimport io.trtc.tuikit.atomicxcore.api.ai.TranscriptionConfigimport androidx.lifecycle.lifecycleScopeimport kotlinx.coroutines.launchfun setupAITranscriber(roomID: String) { // 1. 创建实例 val store = AITranscriberStore.create(roomID) // 2. 订阅字幕消息 lifecycleScope.launch { store.transcriberState.realtimeMessageList.collect { messages -> messages.forEach { msg -> Log.d("AITranscriber", "[${msg.speakerUserName}] ${msg.sourceText}") } } } // 3. 开启字幕(含翻译) val transConfig = TranscriptionConfig(enableTranslation = true) store.startTranscription( myLanguage = SourceLanguage.CHINESE_ENGLISH, config = transConfig ) { code, message -> if (code != 0) Log.e("AITranscriber", "start failed: $message") }}import AtomicXCorefunc setupAITranscriber(roomID: String) { // 1. 创建实例 let store = AITranscriberStore.create(roomID: roomID) // 2. 订阅字幕状态 store.state.subscribe { state in for msg in state.realtimeMessageList { print("[\\(msg.speakerUserName)] \\(msg.sourceText)") } } // 3. 开启字幕(含翻译) let transConfig = TranscriptionConfig(enableTranslation: true) store.startTranscription(myLanguage: .chineseEnglish, config: transConfig) { error in if let error = error { print("start failed: \\(error)") } }}import 'package:atomic_x_core/api/ai/ai_transcriber_store.dart';Future<void> setupAITranscriber(String roomID) async { // 1. 创建实例 final store = AITranscriberStore.create(roomID); // 2. 订阅字幕消息 store.transcriberState.realtimeMessageList.addListener(() { final messages = store.transcriberState.realtimeMessageList.value; for (final msg in messages) { print("[${msg.speakerUserName}] ${msg.sourceText}"); } }); // 3. 开启字幕(含翻译) final transConfig = TranscriptionConfig(enableTranslation: true); final transResult = await store.startTranscription( SourceLanguage.chineseEnglish, config: transConfig, ); if (!transResult.isSuccess) { print("start failed: ${transResult.errorMessage}"); }}<script setup lang="ts">import { ref } from 'vue';import { useAITranscriberStateLive } from 'tuikit-atomicx-vue3';const { realtimeMessageList, isTranscriptionRunning, startTranscription, updateTranscription, stopTranscription,} = useAITranscriberStateLive();const myLanguage = ref<'zh' | 'en' | 'ja' | 'ko'>('zh');const enableTranslation = ref(true);const loading = ref(false);// 开启 / 停止字幕async function handleClick() { if (loading.value) { return; } loading.value = true; try { if (isTranscriptionRunning.value) { await stopTranscription(); } else { await startTranscription({ myLanguage: myLanguage.value, config: { enableTranslation: enableTranslation.value }, }); } } catch (error: any) { console.error('[AITranscriber] failed:', error); } finally { loading.value = false; }}// 运行中动态切换源语言async function handleLanguageChange(next: typeof myLanguage.value) { myLanguage.value = next; if (isTranscriptionRunning.value) { await updateTranscription({ myLanguage: next, config: { enableTranslation: enableTranslation.value }, }); }}</script><template> <div> <select :value="myLanguage" @change="handleLanguageChange(($event.target as HTMLSelectElement).value as any)" > <option value="zh">中文</option> <option value="en">English</option> <option value="ja">日本語</option> <option value="ko">한국어</option> </select> <label> <input v-model="enableTranslation" type="checkbox" :disabled="isTranscriptionRunning" /> Enable translation </label> <button :disabled="loading" @click="handleClick"> {{ isTranscriptionRunning ? 'Stop subtitle' : 'Start subtitle' }} </button> <ul> <li v-for="msg in realtimeMessageList" :key="msg.segmentID" > <strong>{{ msg.speakerUserName || msg.speakerUserID }}:</strong> <span>{{ msg.sourceText }}</span> <em v-if="msg.translationTexts?.[myLanguage]"> ({{ msg.translationTexts[myLanguage] }}) </em> </li> </ul> </div></template>
十三、源语言列表
转写服务支持以下 20 种源语言,请选择与说话人语言匹配的项以获得最佳识别准确率。中英混合场景建议使用 chineseEnglish。
注意:说明:
注意:AI 字幕默认支持识别中文、英文、日文、韩文,如需支持其他语言,请 联系我们 进行配置。
| 语言 | 取值 | 说明 |
| chineseEnglish | zh_en | 中英文混合 |
| chinese | zh | 中文 |
| english | en | 英语 |
| cantonese | zh-yue | 粤语 |
| vietnamese | vi | 越南语 |
| japanese | ja | 日语 |
| korean | ko | 韩语 |
| indonesian | id | 印尼语 |
| thai | th | 泰语 |
| portuguese | pt | 葡萄牙语 |
| turkish | tr | 土耳其语 |
| arabic | ar | 阿拉伯语 |
| spanish | es | 西班牙语 |
| hindi | hi | 印地语 |
| french | fr | 法语 |
| malay | ms | 马来语 |
| filipino | fil | 菲律宾语 |
| german | de | 德语 |
| italian | it | 意大利语 |
| russian | ru | 俄语 |
十四、翻译语言列表
转写文字支持实时翻译为以下 15 种目标语言。
| 语言 | 取值 | 说明 |
| chinese | zh | 中文 |
| english | en | 英语 |
| vietnamese | vi | 越南语 |
| japanese | ja | 日语 |
| korean | ko | 韩语 |
| indonesian | id | 印尼语 |
| thai | th | 泰语 |
| portuguese | pt | 葡萄牙语 |
| arabic | ar | 阿拉伯语 |
| spanish | es | 西班牙语 |
| french | fr | 法语 |
| malay | ms | 马来语 |
| german | de | 德语 |
| italian | it | 意大利语 |
| russian | ru | 俄语 |
十六、开启字幕失败,调用 startTranscription 接口报错。
请确认以下前置条件是否满足:
1. 当前 SDKAppID 可能未开通直播 AI 实时转写服务,请先在控制台开通对应能力。
2. 已成功进房(房间状态为已连接),AI 字幕仅在房内可用。
3. 源语言 myLanguage 已正确传入,且取值在支持的语言列表内。
4. 房间内至少存在一路有效的音频流,否则转写机器人无语音可识别。
十七、开启翻译后,为什么只看到原文,没有看到译文。
请确认当前麦上是否存在使用其他语言发言的成员。
myLanguage 表示当前用户希望看到的字幕语言,也会作为当前用户本人说话语言的默认判断依据。
例如,房主开启字幕和翻译时传入 myLanguage 为英语,如果当前麦上只有房主一人或者其他麦上成员的 myLanguage 也为英语,系统会默认认为两位麦上成员说的都是英语,因此只会返回原文,不会再生成一份英语译文。
如需验证翻译效果,可以让另一位说不同语言的麦上成员发言。例如中文观众上麦发言,房主侧即可看到该成员的原文和翻译结果。
十八、麦上成员没有传入 myLanguage,是否还能使用 AI 字幕?
可以,如果麦上成员未显式传入 myLanguage,系统会读取该成员的手机系统语言作为兜底语言。用户开启 AI 字幕后仍可以看到字幕内容。
但手机系统语言不一定等同于用户实际说话语言,因此建议在业务侧引导用户选择或传入自己的实际说话语言,以提升语音识别准确率。
十九、麦下观众开启字幕或翻译后,为什么没有内容?
1. 麦下观众开启字幕不会主动触发转写任务。只有麦上成员开启了 AI 字幕,房间内已有转写任务正在运行时,麦下观众开启字幕后才能接收到字幕内容。
2. 如果麦上主播没有开启字幕,麦下观众单独开启字幕不会产生内容,因为此时房间内没有可订阅的转写结果。
3. 当已有转写任务运行时,麦下观众可以在接收原文字幕的基础上开启翻译,系统会基于已有转写结果追加对应的翻译任务。
20、字幕消息一直不更新,realtimeMessageList 为空。
请检查:
1. 房间内是否有成员正在说话(有音频上行)。
2. 是否已正确订阅 realtimeMessageList 状态,且订阅时机早于或等于开启转写的时机。
3. 转写服务是否处于运行中(isTranscriptionRunning 为 true)。
21、转写过程中切换源语言后,历史字幕是否会保留?
切换源语言不会清空历史字幕消息列表。历史消息保持不变,新的语音段将以新的源语言进行识别。如需清空展示,可在 UI 层自行处理列表数据。