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开发平台入口页面(提交技术工单)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/90481.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/90481.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kafka4.0集群部署

kafka4.0是最新版kafka&#xff0c;可在kafka官网下载&#xff0c;依赖的jdk版本要求在jdk17及jdk17以上tar -xzf kafka_2.13-4.0.0.tgzmv kafka_2.13-4.0.0 kafkacd kafka# 随便一台节点运行生成随机uuid&#xff0c;后面每台节点都要使用此uuidbin/kafka-storage.sh random-u…

【News】同为科技亮相首届气象经济博览会

7月18日&#xff0c;由中国气象服务协会主办的国内首个以“气象经济”为核心的国家级博览会——首届气象经济博览会&#xff08;以下简称“博览会”&#xff09;在合肥滨湖国际会展中心开幕。北京同为科技有限公司&#xff08;TOWE&#xff09;作为雷电防护领域的技术领导企业&…

数据结构 堆(2)---堆的实现

上篇文章我们详细介绍了堆和树的基本概念以及它们之间的关系&#xff0c;还要知道一般实现堆的方式是使用顺序结构的数组进行存储数据及实现。下来我们看看利用顺序结构的数组如何实现对的内容:1.堆的实现关于堆的实现&#xff0c;也是三个文件&#xff0c;头文件&#xff0c;实…

Arraylist与LinkedList区别

&#x1f4da; 欢迎来到我的Java八股文专栏&#xff01; &#x1f389;各位程序员小伙伴们好呀~ &#x1f44b; 我是雪碧聊技术&#xff0c;很高兴能在CSDN与大家相遇&#xff01;✨&#x1f680; 专栏介绍这个专栏将专注于分享Java面试中的经典"八股文"知识点 &…

Java实战:基于Spring Cloud的电商微服务架构设计——从拆分到高可用的全流程解析

引言 2023年双十一大促期间,某传统电商平台的单体应用再次“爆雷”:凌晨1点订单量突破50万单/分钟时,用户服务因数据库连接池被订单模块占满,导致登录接口响应时间从200ms飙升至5秒,大量用户流失。技术团队紧急回滚后发现:这个运行了7年的单体应用,早已变成“代码泥潭”…

STL学习(二、vector容器)

1.vector构造函数函数原型vector<int> v // 默认构造&#xff0c;size为0vector(const_iterator beg, const_iterator end) // 将v的[begin, end) 元素拷贝过来vector(n, elem) // 构造函数将n个elem拷贝到本身vector(const vector & v) // 拷贝构造2.vect…

深度学习-算子

概念&#xff1a;标识数字图像中亮度变化明显的点处理步骤1.滤波处理算子通常被称为滤波器。2.增强确定各点sobel算子概念&#xff1a;主要用于获得数字图像的一阶梯度&#xff0c;本质是梯度运算。Scharr算子Scharr算子 是一种用于边缘检测的梯度算子&#xff0c;它是Sobel算子…

全国产8通道250M AD FMC子卡

4片8路ADS42LB69标准FMC采集子卡自研成品ADC采集子卡和定制化设计ADC采集子卡&#xff0c;实测采集指标均与手册标称值一致。该板卡有全国产化和进口两个版本&#xff0c;基于FMC标准设计&#xff0c;实现8路16bit/250MSPS ADC采集功能&#xff0c;遵循 VITA 57 标准&#xff0…

【牛客网C语言刷题合集】(三)

&#x1f31f;菜鸟主页&#xff1a;晨非辰的主页 &#x1f440;学习专栏&#xff1a;《C语言刷题集》 &#x1f4aa;学习阶段&#xff1a;C语言方向初学者 ⏳名言欣赏&#xff1a;"任何足够先进的bug都与魔法无异。" 前言&#xff1a;刷题博客主要记录在学习编程语言…

Python之--字典

定义字典&#xff08;dict&#xff09;是一种无序、可变且可哈希的数据结构&#xff0c;字典是根据一个信息来查找另一个信息&#xff0c;它表示索引用的键和对应的值构成的成对关系。特点&#xff08;1&#xff09;字典与列表一样&#xff0c;是Python里面的可变数据类型。&am…

【ARM】ARM微架构

1、 文档目标对 ARM 微架构的概念有初步的了解。2、 问题场景在和客户沟通和新同事交流时对于 ARM 架构和微架构二者有什么区别和联系&#xff0c;做一个简单的介绍。3、软硬件环境1、软件版本&#xff1a;不涉及2 、电脑环境&#xff1a;不涉及4、关于 ARM 架构和微架构架构不…

c++注意点(11)----设计模式(工厂方法)

创建型模式工厂方法模式是一种创建型设计模式&#xff0c; 其在父类中提供一个创建对象的方法&#xff0c; 允许子类决定实例化对象的类型。为什么需要工厂方法模式&#xff1f;看一个 “没有工厂模式” 的痛点场景&#xff1a;假设你在开发一个游戏&#xff0c;最初只有 “战士…

基于Kubernetes的微服务CI/CD:Jenkins Pipeline全流程实践

一、部署gitlab GitLab 是一个集代码托管、CI/CD、项目管理、安全扫描于一体的 DevOps 平台&#xff0c;提供从代码编写到部署的全生命周期管理。它支持 Git 版本控制&#xff0c;内置自动化流水线&#xff0c;可与 Kubernetes 集成&#xff0c;实现云原生应用的持续交付。同时…

Spring Bean初始化及@PostConstruc执行顺序

目录 1. Bean初始化执行顺序 2. 成员变量初始化顺序 2.1 普通Java类&#xff08;非Spring环境&#xff09; (1) 默认初始化(即初始分配内存) (2) 显式初始化 (3) 构造器初始化 (4)完整顺序 2.2 Spring管理的Bean&#xff08;依赖注入场景&#xff09; (1) 普通成员变量…

webRTC合并本地源码修改和官方更新

一、总体思路&#xff1a;基于 Git 分支管理改动origin/main 是官方 WebRTC 主干&#xff08;来自 webrtc.googlesource.com&#xff09;。my/webrtc 是你自己开发和修改的分支。每次 Google 更新 WebRTC&#xff0c;你从 origin/main 拉新代码&#xff0c;再把 my/webrtc 分支…

c++注意点(12)----设计模式(生成器)

创建型模式生成器模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它专注于将复杂对象的构建过程与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。就像是做饭&#xff0c;你可以自己慢慢做&#xff0c;各个步骤自己选择。而使用生成…

[特殊字符] VLA 如何“绕过”手眼标定?—— 当机器人学会了“看一眼就动手”

&#x1f52e; VLA 如何“绕过”手眼标定&#xff1f;—— 当机器人学会了“看一眼就动手” 作者&#xff1a;石去皿 发布时间&#xff1a;2025年7月 在传统机器人系统中&#xff0c;“手眼标定”是每一个工程师都绕不开的课题。 你必须精确测量相机和机械臂之间的空间变换关系…

《Maven 核心基础笔记(第一天)》

1.说明maven软件依赖管理和项目构建功能maven是为Java项目工作的 功能体现&#xff1a;依赖管理&#xff0c;项目构建 依赖管理&#xff1a;我们只需要写配置文件(pom.xml)&#xff0c;maven就会帮我们下载依赖&#xff0c;并且也会下载依赖的依赖。 项目构建&#xff1a;项目源…

Yolo底层原理学习(V1~V3)(第一篇)

一&#xff0c;卷积后的特征图大小计算众所周知&#xff0c;提到深度学习&#xff0c;必不可少的会提及卷积&#xff0c;那么如何计算卷积之后的图片大小呢&#xff1f;下图呈现&#xff1a;如图&#xff0c; 我们令FH&#xff0c;FW为原图像的长度FH*FW。P为padding的长度&…

前端开发项目性能瓶颈分析

1. 使用 rollup-plugin-visualizer 分析构建 借助 rollup-plugin-visualizer 插件&#xff0c;可以分析通过 rollup 构建出的产物内容&#xff0c;并生成可视化图表&#xff0c;帮助你分析打包后的文件大小以及各个模块的占用情况。 1.1. 安装插件 你需要在你的项目中安装 r…