AI 音频产品开发模板及流程(二)
AI 音频产品开发模板及流程(一)
6. 同声传译
- 实时翻译,发言与翻译几乎同步,极大提升沟通效率。
- 支持多语言互译,适用于国际会议、商务洽谈等多场景。
- 自动断句、转写和翻译,减少人工干预,提升准确性。
- 翻译结果可由设备自动播放,交流体验自然流畅。
功能展示
代码片段
// 录音相关配置,并开始录音const startRcordFn = async () => {// 设备需要在线if (!isOnline) return;// 开启了翻译,但没有选择翻译语言时,给出提示if (needTranslate && !translationLanguage) {showToast({icon: 'none',title: Strings.getLang('realtime_recording_translation_no_select_tip'),});return;}try {setControlBtnLoading(true);const config: any = {// 录音类型,0:呼叫、1:会议recordType: currRecordType,// DP 控制超时时间,单位秒controlTimeout: 5,// 灌流超时时间,单位秒dataTimeout: 10,// 0:文件转写、1:实时转写transferType: 1,// 是否需要翻译needTranslate,// 输入语言originalLanguage: originLanguage,// 智能体 ID,后面具体根据提供的 SDK 获取 agentIdagentId: '',// 录音通道,0:BLE、1:Bt、2:microrecordChannel,// TTS 流编码方式,通过编码后将流写入到耳机设备,0:opus_silk、1:opus_celtttsEncode: isOpusCelt ? 1 : 0,};if (needTranslate) {// 目标语言config.targetLanguage = translationLanguage;}await tttStartRecord({deviceId,config,});setInterval(1000);lastTimeRef.current = Date.now();setControlBtnLoading(false);} catch (error) {setControlBtnLoading(false);}};// 点击开始录音对应的回调const handleStartRecord = useCallback(async () => {// 申请录音权限if (isBtEntryVersion) {ty.authorize({scope: 'scope.record',success: () => {startRcordFn();},fail: e => {ty.showToast({ title: Strings.getLang('no_record_permisson'), icon: 'error' });console.log('cope.record: ', e);},});return;}startRcordFn();}, [deviceId,isOnline,controlBtnLoading,currRecordType,needTranslate,originLanguage,translationLanguage,recordChannel,isBtEntryVersion,offlineUsage,]);
// 暂停const handlePauseRecord = async () => {if (controlBtnLoading) return;try {setControlBtnLoading(true);const d = await tttPauseRecord(deviceId);setInterval(undefined);setControlBtnLoading(false);} catch (error) {console.log('fail', error);setControlBtnLoading(false);}};
// 继续录音const handleResumeRecord = async () => {if (controlBtnLoading) return;try {setControlBtnLoading(true);await tttResumeRecord(deviceId);setInterval(1000);lastTimeRef.current = Date.now();setControlBtnLoading(false);} catch (error) {setControlBtnLoading(false);}};
// 停止const handleStopRecord = async () => {if (controlBtnLoading) return;try {ty.showLoading({ title: '' });await tttStopRecord(deviceId);setDuration(0);setInterval(undefined);ty.hideLoading({complete: () => {backToHome(fromType);},});} catch (error) {ty.hideLoading();}};
// 监听 ASR 和翻译返回onRecordTransferRealTimeRecognizeStatusUpdateEvent(handleRecrodChange);// 处理 ASR 和翻译const handleRecrodChange = d => {try {const {// 阶段,0:任务、4:ASR、5:翻译、6:skill、7:TTSphase,// 阶段状态,0:未开启、1:进行中、2:结束、3:取消status,requestId,// 转写的文本text,// 错误码errorCode,} = d;// ASR 阶段,接收并实时更新对应 requestId 文本if (phase === 4) {const currTextItemIdx = currTextListRef.current.findIndex(item => item.id === requestId);if (currTextItemIdx > -1) {const newList = currTextListRef.current.map(item =>item.id === requestId ? { ...item, text } : item);currTextListRef.current = newList;setTextList(newList);} else {if (!text) return;const newList = [...currTextListRef.current,{id: requestId,text,},];currTextListRef.current = newList;setTextList(newList);}// 翻译返回阶段,接收并展示 status=2 即已完成翻译的} else if (phase === 5 && status === 2) {let resText = '';if (text && text !== 'null') {if (isJsonString(text)) {const textArr = JSON.parse(text);const isArr = Array.isArray(textArr);// 数字的 string 类型如 111,isJsonString 判断为 json 字符串,会导致 .join 失败resText = isArr ? textArr?.join('\n') : textArr;} else {resText = text;}}if (!resText) {return;}const newList = currTextListRef.current.map(item => {return item.id === requestId ? { ...item, text: `${item.text}\n${resText}` } : item;});currTextListRef.current = newList;setTextList(newList);}} catch (error) {console.warn(error);}};
7. 现场录音
- 可自动录制现场环境中的所有声音,完整还原现场交流内容,便于后续查证和回顾。
- 支持录音内容的转写和 AI 总结,快速提炼关键信息,提高信息处理效率。
- 降低人工记录成本,避免遗漏重要细节,提升工作和沟通的准确性。
- 适用于会议记录、课堂笔记、采访等多种场景,增强产品的实用性和智能化水平。
功能展示
代码片段
// 录音相关配置,并调用 App 能力开始录音const startRecordFn = async () => {try {setControlBtnLoading(true);await tttStartRecord({deviceId,config: {// 出错时是否要保留音频文件saveDataWhenError: true,// 录音类型,0:呼叫、1:会议recordType: currRecordType,// DP 控制超时时间,单位秒controlTimeout: 5,// 灌流超时时间 单位秒dataTimeout: 10,// 0:文件转写、1:实时转写transferType: 0,// 录音通道,0:BLE、1:Bt、2:microrecordChannel,// TTS 流编码方式,通过编码后将流写入到耳机设备,0:opus_silk、1:opus_celtttsEncode: isOpusCelt ? 1 : 0,},},);setInterval(1000);lastTimeRef.current = Date.now();setControlBtnLoading(false);} catch (error) {setControlBtnLoading(false);}}; // 点击开始录音的回调const handleStartRecord = useCallback(async () => {// 申请权限if (isBtEntryVersion) {ty.authorize({scope: 'scope.record',success: () => {startRecordFn();},fail: e => {ty.showToast({ title: Strings.getLang('no_record_permisson'), icon: 'error' });},});return;}startRecordFn();}, [currRecordType, recordChannel, isBtEntryVersion]);
// 暂停const handlePauseRecord = async () => {try {setControlBtnLoading(true);await tttPauseRecord(deviceId);setInterval(undefined);setControlBtnLoading(false);} catch (error) {console.log('fail', error);setControlBtnLoading(false);}};
// 继续录音const handleResumeRecord = async () => {try {setControlBtnLoading(true);await tttResumeRecord(deviceId);setInterval(1000);lastTimeRef.current = Date.now();setControlBtnLoading(false);} catch (error) {setControlBtnLoading(false);}};
// 停止const handleStopRecord = async () => {try {ty.showLoading({ title: '' });await tttStopRecord(deviceId);setDuration(0);setInterval(undefined);ty.hideLoading();backToHome();} catch (error) {ty.hideLoading();}};
8. 转录和 AI 总结
- 将音频内容转写为可编辑的文字,便于保存和后续处理。
- 利用 AI 技术根据选择的模板对转写内容进行智能总结,快速提炼关键信息,提升信息获取效率。
- 降低人工整理和阅读成本,避免遗漏重要内容。
- 支持生成结构化的 Markdown 格式文本,方便文档归档和分享。
- 适用于会议纪要、通话记录、面对面交流、课堂笔记等多种场景,增强产品的实用性和智能化水平。
功能展示
代码片段
{/* 转录结果 */}
<View className={styles.content}><Tabs.SegmentedPickeractiveKey={currTab}tabActiveTextStyle={{color: 'rgba(54, 120, 227, 1)',fontWeight: '600',}}style={{ backgroundColor: 'rgba(241, 241, 241, 1)' }}onChange={activeKey => {setCurrTab(activeKey);}}><Tabs.TabPanel tab={Strings.getLang('recording_detail_tab_stt')} tabKey="stt" /><Tabs.TabPanel tab={Strings.getLang('recording_detail_tab_summary')} tabKey="summary" /><Tabs.TabPaneltab={Strings.getLang('recording_detail_tab_mind_map')}tabKey="mindMap"/></Tabs.SegmentedPicker>{currTab === 'stt' && (<SttContentplayerStatus={playerStatus}wavFilePath={recordFile?.wavFilePath}transferStatus={transferStatus}sttData={sttData}recordType={recordFile?.recordType}currPlayTime={currPlayTime}onChangePlayerStatus={status => {setPlayerStatus(status);}}innerAudioContextRef={innerAudioContextRef}isEditMode={isEditMode}onUpdateSttData={handleUpdateSttData}/>)}{currTab === 'summary' && (<SummaryContent summary={summary} transferStatus={transferStatus} />)}{currTab === 'mindMap' && (<MindMapContent summary={summary} transferStatus={transferStatus} />)}{(transferStatus === TRANSFER_STATUS.Initial ||transferStatus === TRANSFER_STATUS.Failed) &&!(currTab === 'stt' && recordFile?.transferType === TransferType.REALTIME) && (<><EmptyContent type={EMPTY_TYPE.NO_TRANSCRIPTION} /><ButtonclassName={styles.generateButton}onClick={() => {// 先选择模版setShowTemplatePopup(true);}}><Text className={styles.generateText}>{Strings.getLang('generate')}</Text></Button></>)}
</View>
// 开始转录总结const handleStartTransfer = async (selectTemplate: TRANSFER_TEMPLATE) => {if (isLoading.current) return;try {isLoading.current = true;ty.showLoading({ title: '' });await tttTransfer({recordTransferId: currRecordTransferId.current,template: selectTemplate,language: recordFile?.originalLanguage || language,});setTransferStatus(TRANSFER_STATUS.Processing);const fileDetail: any = await tttGetFilesDetail({recordTransferId: currRecordTransferId.current,amplitudeMaxCount: 100,});setRecordFile(fileDetail);dispatch(updateRecordTransferResultList());ty.hideLoading();isLoading.current = false;} catch (error) {console.log(error);dispatch(updateRecordTransferResultList());ty.hideLoading();isLoading.current = false;}};
// 获取转录和转写详情
const getFileDetail = async () => {// loadingconst finishLoading = () => {ty.hideLoading();isLoading.current = false;};try {isLoading.current = true;ty.showLoading({ title: '' });const recordTransferId = currRecordTransferId.current;// 获取录音详情const fileDetail = await tttGetFilesDetail({recordTransferId,amplitudeMaxCount: 100,});if (fileDetail) {setRecordFile(fileDetail);const { storageKey, transfer, visit, status, recordId, transferType } = fileDetail;if (!visit) {updateFileVisitStatus();}setTransferStatus(transfer);// 实时转写直接取用 App 接口的转写数据if (transferType === TransferType.REALTIME) {// 获取转写数据const realTimeResult: any = await tttGetRecordTransferRealTimeResult({recordId,});const { list } = realTimeResult;const newData = list.filter(item => !!item?.asr && item?.asr !== 'null').map(item => ({asrId: item.asrId,startSecond: Math.floor(item.beginOffset / 1000),endSecond: Math.floor(item.endOffset / 1000),text: item.asr,transText: item.translate,channel: item.channel,}));setSttData(newData);originSttData.current = newData;// 获取客户端本地总结数据tttGetRecordTransferSummaryResult({recordTransferId,from: 0,}).then((d: any) => {if (d?.text) {resolveSummaryText(d?.text);}});// 获取云端总结数据tttGetRecordTransferSummaryResult({recordTransferId,from: 1, // 云端}).then((d: any) => {if (d?.text) {tttSaveRecordTransferSummaryResult({ recordTransferId, text: d?.text });resolveSummaryText(d?.text);}});} else {// status 文件同步状态,0:未上传、1:上传中、2:已上传、3:上传失败// transfer 转录状态,0:未转录、1:转录中、2:已转录、3:转录失败if (status === 2 && transfer === 2) {// 获取客户端本地转写数据tttGetRecordTransferRecognizeResult({recordTransferId,from: 0, // 本地}).then((d: any) => {if (d?.text) {resolveSttText(d?.text);}});// 获取云端转写数据tttGetRecordTransferRecognizeResult({recordTransferId,from: 1, // 云端}).then((d: any) => {if (d?.text) {// 缓存到客户端本地tttSaveRecordTransferRecognizeResult({ recordTransferId, text: d?.text });resolveSttText(d?.text);}});// 获取客户端本地总结数据tttGetRecordTransferSummaryResult({recordTransferId,from: 0,}).then((d: any) => {if (d?.text) {resolveSummaryText(d?.text);}});// 获取云端总结数据tttGetRecordTransferSummaryResult({recordTransferId,from: 1, // 云端}).then((d: any) => {if (d?.text) {tttSaveRecordTransferSummaryResult({ recordTransferId, text: d?.text });resolveSummaryText(d?.text);}});}}finishLoading();}} catch (error) {console.log('error', error);finishLoading();}
};
9. 结束
- 恭喜你 🎉 完成了本教程的学习!
- 有任何问题可以提交工单👉涂鸦IoT开发平台入口页面(提交技术工单)