
人工智能AI Agent多模态语音AI 应用【免费下载链接】ten-frameworkOpen-source framework for conversational voice AI agents项目地址https://gitcode.com/TEN-framework/ten-framework点击查看免费下载导读本文以 TEN Framework 仓库中的示例扩展web_audio_control_go为主线讲解如何用 Go 编写一个浏览器 ↔ 扩展 ↔ TEN 图三层联动的 Web 音频控制扩展它内置 HTTP 服务器与 WebSocket 通道让用户直接在浏览器里输入音频文件路径、点击按钮触发播放并把 ASR 转写结果实时推回页面展示。读完本文你将掌握该扩展的配置属性、Graph 接线方式、HTTP/WebSocket API 协议、Go 源码级实现原理以及如何在 transcriber_demo 示例应用中把它与音频播放、ASR、VAD 等扩展串成一条完整链路。扩展定位Web 端与 TEN 运行时之间的桥web_audio_control_go是一个用 Go 编写的 TEN Framework 扩展extension其核心作用是为 TEN 应用提供一个基于浏览器的控制界面。它的双向职责非常清晰控制方向浏览器通过 HTTP 请求POST /api/start_play把用户的播放意图交给扩展扩展将其封装为 TEN 命令start_play通过SendCmd发给图内的音频播放扩展回传方向图内 ASR 扩展产出的转写结果asr_result数据到达扩展后由BroadcastAsrResult通过 WebSocket 推送给所有连接的浏览器页面实时展示。扩展的官方描述manifest.json将其定位为 Web-based audio control extension with real-time transcription display标签为go、web、audio、websocket并声明依赖系统包ten_runtime_go版本0.11。它属于 transcriber_demo 示例应用的ten_packages/extension目录可作为示例直接参考或复制到自己的 TEN 项目中。架构链路原文档给出的整体数据流如下User Browser --HTTP/WebSocket-- Web Server (Go Extension) --TEN Protocol-- TEN Framework | v Audio Player Extension | v ASR Extension (Transcription)结合仓库源码可以进一步细化这条链路server/server.go 中的路由注册浏览器加载扩展内嵌的静态页面index.html用户提交音频文件路径与循环播放选项页面以表单方式POST /api/start_play扩展解析表单构造start_play命令并tenEnv.SendCmd发送给图内的音频播放扩展音频播放扩展输出pcm_frame音频帧送往 ASR 扩展ASR 扩展输出asr_result数据扩展在OnData中解析出text与final字段并通过 WebSocket 广播浏览器onmessage收到消息后把文本渲染为卡片并自动滚动到最新内容。从源码结构看该扩展还通过audio_frame_inpcm_frame接收 VAD 输出的音频帧并在OnAudioFrame中检测is_speech属性调用BroadcastVadStatus将说话状态推送到前端实现当前是否有人在说话的实时可视化详见后文实际源码中的扩展能力。配置属性http_port与http_host扩展在 property.json 中声明了两个属性{ http_host: 0.0.0.0, http_port: 8001 }属性类型默认值说明http_portint648001HTTP/WebSocket 服务器监听端口http_hoststring0.0.0.0监听地址默认绑定所有网卡原文档仅介绍了http_port实际源码main.go在OnStart中同时读取这两个属性host, err : tenEnv.GetPropertyString(http_host) if err ! nil { host 0.0.0.0 // 获取失败时回退默认值 } port, err : tenEnv.GetPropertyInt64(http_port) if err ! nil { port 8001 // 获取失败时回退默认值 }也就是说即便属性缺失或类型不匹配扩展也会静默回退到默认值不会导致启动失败。需要注意的是http_port被声明为int64在 JSON 配置中应写成数字而非字符串。若需监听指定网卡可在 Graph 节点属性中覆盖http_host在 transcriber_demo 的 property.json 中该节点未显式配置属性因此实际运行时使用默认的0.0.0.0:8001。扩展 API 契约命令与数据manifest.json 的api字段声明了完整的对外契约cmd_outstart_play对外发送的播放命令audio_frame_in / audio_frame_outpcm_frame接收/转发音频帧data_inasr_result接收转写数据。发送的命令start_play由 HTTP 请求触发扩展构造 TEN 命令并发送。命令属性file_pathstring要播放的音频文件路径必填loop_playbackbool是否循环播放可选。对应的构造逻辑见 server/server.go 的handleStartPlay先校验file_path非空再依次cmd.SetPropertyString(file_path, ...)、cmd.SetProperty(loop_playback, ...)最后tenEnv.SendCmd(cmd, nil)fire-and-forget不等待响应。接收的数据asr_result扩展通过OnData接收图内 ASR 扩展发送的转写数据main.go。原文档称接收的数据名为display_text但实际源码按asr_result匹配if dataName asr_result { text, _ : data.GetPropertyString(text) final, _ : data.GetPropertyBool(final) e.server.BroadcastAsrResult(text, final) }数据属性textstring转写的文本内容finalbool是否为最终结果false表示中间结果/interim。这一点以源码为准在 transcriber_demo 的 property.json 中azure_asr_python的data_out名称就是asr_result与OnData的匹配逻辑一致。文档编写时若仍沿用display_text命名需注意与源码保持一致否则数据无法被接收。实战接线把扩展串进 TEN Graph通用 Graph 配置原文档示例原文档给出了在predefined_graphs中组合 web_control、audio_player、asr 三个扩展的最小配置要点如下web_control节点addon 为web_audio_control_go通过property设置http_port命令流web_control的cmd_out名start_play指向audio_player音频流audio_player的audio_frame_out名pcm_frame指向asr数据流asr的data_out名display_text指向web_control。{ nodes: [ { type: extension, name: web_control, addon: web_audio_control_go, property: { http_port: 8001 } }, { type: extension, name: audio_player, addon: audio_file_player_python }, { type: extension, name: asr, addon: your_asr_extension } ], connections: [ { extension: web_control, cmd_out: [ { name: start_play, dest: [{ extension: audio_player }] } ] }, { extension: audio_player, audio_frame_out: [ { name: pcm_frame, dest: [{ extension: asr }] } ] }, { extension: asr, data_out: [ { name: display_text, dest: [{ extension: web_control }] } ] } ] }仓库中的真实接线transcriber_demo仓库中 transcriber_demo 的 property.json 给出了该扩展的真实落地方案比原文档示例更完整包含四个节点与多条数据流节点azure_asr_pythonASR属性用${env:AZURE_STT_KEY|}、${env:AZURE_STT_REGION|}、${env:AZURE_STT_LANGUAGE|en-US}做环境变量注入、web_audio_control_go、audio_file_player_python音频播放、vtt_nodejs录音/VTT 会话命令流web_audio_control_go的start_play→audio_file_player_pythonstart_recording/stop_recording→vtt_nodejs音频帧流web_audio_control_go与audio_file_player_python的pcm_frame同时分发到azure_asr_python和vtt_nodejs数据流azure_asr_python的asr_result分发到web_audio_control_go与vtt_nodejs。这也解释了扩展为何同时具备audio_frame_in接收来自播放器的pcm_frame与audio_frame_out把音频帧转发给 ASR。此外start_recording/stop_recording命令虽然未在扩展文档的 API 章节列出但已由 server/server.go 的/api/start_recording、/api/stop_recording路由实现属于文档之外的真实能力。访问与操作 Web 界面应用启动后浏览器访问http://localhost:8001根路径/会在 server/server.go 中被重定向到/static/index.html。界面操作流程在 Audio File Path 输入框中填写音频文件路径也可通过文件选择器上传见下可选勾选 Loop Playback 启用循环播放点击 ▶️ Start Transcription 按钮开始播放与转写转写文本实时显示在下方 Transcription Results 区域每条文本以卡片形式呈现并自动滚动到最新内容。前端页面还提供了两个附加能力index.html 中的元素可印证fileSelector文件选择器与selectFileBtn按钮对应/api/upload上传接口页面底部还提供跳转到/static/recordings.html录音回放页与/static/microphone.html麦克风采集页的入口。连接状态与自动重连页面顶部有连接状态指示器connectionStatus/statusTextConnected与服务器连接正常Disconnected与服务器断开连接。前端通过connectWebSocket()建立ws://连接断线后在onclose回调中以 3 秒间隔自动重连setInterval(connectWebSocket, 3000)无需刷新页面即可恢复实时转写推送。错误提示文件不存在等播放失败场景HTTP 接口返回错误 JSON前端statusMessage区域给出明确提示网络错误ws.onerror/onclose被触发页面进入断开状态并提示。WebSocket 消息协议服务器 → 客户端原文档给出的简化格式{ type: text, data: Transcribed text content }实际源码server/server.go中WebSocketMessage结构体定义的字段更丰富type取值包括asr_result、audio_data、vad_status、error{ type: asr_result, text: 转写文本, final: true, is_speech: false, sample_rate: 16000, channels: 1, samples_per_channel: 320 }转写推送走asr_result类型含text与final前端据此区分中间结果与最终结果VAD 状态走vad_status类型含is_speech用于实时显示说话状态浏览器向服务器上传麦克风音频时先发送一个audio_data类型的 JSON 元数据声明sample_rate、channels、samples_per_channel随后紧跟二进制音频帧服务器收到后调用audioDataHandler封装为pcm_frame音频帧发回 TEN 图。客户端 → 服务器文本消息JSON用于上传音频元数据type: audio_data及采样参数二进制消息PCM 音频数据服务器解析元数据后以16-bit PCM、interleave 格式、mono封装成 TEN 音频帧。HTTP APIPOST /api/start_play启动音频播放。请求参数Form Datafile_path音频文件路径必填loop_playback是否循环播放true/false可选。该接口同时支持multipart/form-data与application/x-www-form-urlencoded源码先尝试ParseMultipartForm失败则回退ParseForm。成功响应{ status: ok, message: Playback started }错误响应{ status: error, message: file_path is required }注意file_path为空时返回 HTTP 400命令构造或发送失败时返回 HTTP 500。由于是 fire-and-forget 发送接口并不等待播放器确认立即返回成功。POST /api/upload源码补充上传音频文件multipart/form-data字段名file上限 100MB。文件以时间戳_原文件名命名保存到系统临时目录audio_uploads成功返回{ status: ok, message: File uploaded successfully, file_path: /tmp/audio_uploads/... }前端可将返回的file_path回填到输入框再调用start_play。POST /api/start_recording 与 /api/stop_recording源码补充分别构造start_recording/stop_recording命令发送给录音扩展如vtt_nodejs用于控制会话录制。GET /api/list_sessions源码补充读取./recordings目录下各会话的metadata.json返回会话列表供录音回放页使用。技术栈与依赖后端GoWeb 框架net/http标准库WebSocketgithub.com/gorilla/websocket前端HTML5 CSS3 原生 JavaScript无框架TEN 运行时Go bindingten_framework/ten_runtime。依赖声明见 go.modmodule ten_packages/extension/web_audio_control_go go 1.20 replace ten_framework ../../../ten_packages/system/ten_runtime_go/interface require ( github.com/gorilla/websocket v1.5.1 ten_framework v0.0.0-00010101000000-000000000000 )其中replace指令把ten_framework指向仓库内ten_packages/system/ten_runtime_go/interface这是 TEN 项目内扩展的标准做法无需联网拉取运行时源码。项目结构packages/example_apps/transcriber_demo/ten_packages/extension/web_audio_control_go/ ├── main.go # 扩展入口属性读取、OnStart/OnStop、OnData、OnAudioFrame、handleAudioData ├── server/ │ ├── server.go # Web 服务器实现HTTP 路由、WebSocket、上传、命令转发、广播 │ └── static/ │ ├── index.html # 主控制页面含文件选择、录音回放入口 │ ├── microphone.html # 麦克风音频采集页面 │ └── recordings.html # 录音会话回放页面 ├── manifest.json # 扩展清单API 契约、依赖、显示名与描述 ├── property.json # 默认配置http_host / http_port ├── go.mod / go.sum # Go 模块定义与校验和 ├── LICENSE # Apache License 2.0 └── docs/ # README.en-US.md / README.zh-CN.md前端静态文件通过//go:embed static/*直接编译进二进制运行期无需额外部署静态资源目录见 server/server.go。实际源码中的扩展能力文档之外的实现细节生命周期管理OnStart读取属性 →server.NewWebServer(host, port, tenEnv)→ 设置音频数据处理回调 →go e.server.Start()异步启动 HTTP 服务 →OnStartDone()OnStop调用server.Stop()关闭所有 WebSocket 连接并关闭 HTTP 服务器再OnStopDone()。浏览器音频上传 → TEN 音频帧handleAudioData是浏览器麦克风/上传音频进入 TEN 图的入口用ten.NewAudioFrame(pcm_frame)创建音频帧设置采样率、channel layout 0mono、每样本 2 字节16-bit PCM、AudioFrameDataFmtInterleave交织格式与每通道采样数AllocBufLockBufcopyUnlockBuf填充数据后tenEnv.SendAudioFrame发送。该路径与 Graph 中audio_frame_out: pcm_frame的声明一一对应。VAD 状态回传OnAudioFrame检查帧上的is_speech属性VAD 扩展加注有该属性则BroadcastVadStatus把布尔状态推给所有前端无该属性未经 VAD则直接返回。这使得浏览器页面可以在人开始/停止说话时实时切换状态显示。广播与并发安全clients表以sync.RWMutex保护BroadcastAsrResult/BroadcastVadStatus遍历所有客户端WriteJSON写失败即关闭并移除该连接避免向失效连接反复写入。常见问题排查浏览器打不开http://localhost:8001确认扩展所在应用已启动且http_port未被占用若在远端部署需改用主机 IP 或配置端口转发。点击 Start 后提示file_path is requiredfile_path为空需填写音频文件在运行环境的绝对路径或先用/api/upload上传后回填返回路径。ASR 结果不显示核对 Graph 中 ASR 的data_out名称是否为asr_result与OnData匹配并确认data流已指向web_audio_control_go。日志查看扩展使用key_point日志类别输出关键事件如服务启动、WebSocket 连接、最终 ASR 结果可在 transcriber_demo 的 property.json 的log配置基础上将key_point级别的日志输出到控制台或logs/debug.log文件便于定位问题。许可证Apache License 2.0LICENSE。该扩展由 TEN Framework Team 维护随仓库以 Apache 2.0 协议开源。赞分享人工智能AI Agent多模态语音AI 应用【免费下载链接】ten-frameworkOpen-source framework for conversational voice AI agents项目地址https://gitcode.com/TEN-framework/ten-framework点击查看免费下载相关推荐TEN Framework 实战用 Go 编写 Web 音频控制扩展web_audio_control_go实现浏览器驱动的实时转写TEN Framework 实战用 Go 编写 Web 音频控制扩展web_audio_control_go实现浏览器驱动的实时转写 导读 本文以 TEN人工智能AI Agent多模态语音AI 应用TEN Framework 音频文件播放器扩展audio_file_player_python实战指南多格式音频转 16kHz PCM 与 10ms 帧级播放TEN Framework 音频文件播放器扩展audio_file_player_python实战指南多格式音频转 16kHz PCM 与 10ms 帧级人工智能AI Agent多模态语音AI 应用TEN Framework 讯飞实时转写扩展 iflytek_asr_python 集成指南TEN Framework 讯飞实时转写扩展 iflytek_asr_python 集成指南 本指南以 iflytek_asr_python 扩展为主线介绍如人工智能AI Agent多模态语音AI 应用上一篇HamsterBase完全指南如何用这款本地优先的知识收集工具构建你的私人网页档案馆下一篇PowerJob Zookeeper注册中心终极指南替代默认数据库方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考