?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開發平臺入口頁面(提交技術工單)