Files
story/device-simulator-windows

Windows 语音终端模拟器

该程序使用Electron和火山引擎Web RTC SDK模拟一台真实语音终端。它采集Windows麦克风、加入平台分配的RTC房间、发布本地音频、订阅并播放豆包智能体音频,并通过设备v2接口完成激活、状态等待、心跳、Token续签和结束通话。进房后还会启动RTC实时字幕,收集长者与智能体的最终话轮并通过现有turns:batch设备接口可靠上传;字幕未成功启动时拒绝继续激活通话,避免生成没有聊天记录的完成通话。

创建通话返回的隐私策略允许原录音时,模拟器同时通过RTC原始音频帧回调采集长者near和智能体far轨道。结束通话后自动封装为单声道WAV PCM16、按平台限制分片、申请短期对象地址直传,并等待后台完整性与容器校验完成。家庭工作台的通话记录会标记“可听聊天语音”,获得独立PLAY授权的账号可在详情中选择“听长者语音”或“听智能体语音”。

构建

Set-Location .\device-simulator-windows
npm install
npm run build

输出:release/voice-device-simulator-0.1.0-windows-x64.exe。

连接公网测试服务器时,可以直接双击EXE,也可以使用launch-cloud-device.ps1启动。Electron主进程优先读取启动脚本传入的临时环境变量,否则从当前Windows用户的%LOCALAPPDATA%\DataTerminalVoiceDevice\server-device-secret读取设备签名密钥。密钥不写入源码、安装包或浏览器存储,也不会回传到渲染进程;输入框留空并显示“已从Windows安全凭据文件加载”即表示可直接检测。

自动连续性验证

本地回归时可让模拟器自动启动通话、播放一段测试音频,并把双方最终字幕写入JSON结果文件。该入口只接受本机文件和回环地址,不影响正常交互使用:

$env:SIMULATOR_AUTO_TEST = '1'
$env:SIMULATOR_AUTOMATED_AUDIO_PATH = 'C:\path\to\question.wav'
$env:SIMULATOR_AUTO_RESULT_PATH = 'C:\path\to\result.json'
& .\release\voice-device-simulator-0.1.0-windows-x64.exe

测试会等待长者与智能体的最终字幕,结束通话后退出;结果文件包含通话ID、最终话轮和通过/失败状态。测试音频支持WAV、MP3和OGG,大小不得超过10 MB。

安全边界

  • RTC AppKey、火山AK/SK和豆包Access Token只存在本地后端的受保护文件中;
  • 模拟器安装包只接收平台签发的短期RTC Token;
  • 设备签名密钥只驻留Electron主进程内存,不写入浏览器存储;
  • 当前测试构建只允许设备API地址指向localhost、127.0.0.1或固定测试服务器https://121.41.46.238,避免误连其他环境;
  • 关闭软件或结束通话时停止音频采集并销毁RTC引擎。
  • 未取得record_near或record_far授权的轨道不会注册PCM回调;upload_allowed=false时不会采集或上传任何原录音。

实时字幕前提

测试所用RTC AppID必须在火山RTC控制台开启“实时字幕”和“流式语音识别”。流式语音识别凭据来自豆包语音控制台创建的“流式语音识别”应用,包括APP ID、Access Token和Cluster ID;“音视频字幕生成”类型不能替代该应用。未开通时程序会显示ServiceAccessDenied并清理本次未激活通话。

最终字幕会在程序的“实时字幕与上传”区域显示。每条最终字幕使用通话内稳定键和严格递增序号上传;网络失败时留在内存队列,并在心跳及结束通话前重试。存在未上传字幕时,程序不会结束并丢弃当前通话。

完整本地启动顺序见本地真实RTC联调说明。