ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

语音对讲功能架构分析

语音对讲功能架构分析

核心组件

1. sidebar.vue - 主控制组件,负责语音采集、WebSocket通信、模式控制
2. voice.vue - 音频播放组件,使用 flv.js 播放实时音频流

数据流向

发送路径(麦克风 → 服务器)
麦克风设备
↓
getUserMedia() 采集 (单声道, 8kHz, 带回声消除/降噪)
↓
AudioContext 创建音频处理节点 (ScriptProcessor, 4096 buffer)
↓
onaudioprocess 回调触发
↓
compress() 压缩: 原始采样率 → 8kHz, Float32 → Int16
↓
Blob 封装
↓
WebSocket.send() 发送到服务器
接收路径(服务器 → 扬声器)
服务器推送音频流
↓
voice.vue 通过 flv.js 拉取 FLV 流
↓
URL格式: /realtime/{devNo}-{channelNum}-{dataType}-1.flv
↓
flv.js 解码播放


三种工作模式

1. 对讲模式 (voiceType = 1)
- 双向通信
- 发送: WebSocket 上传麦克风音频
- 接收: flv.js 播放 /realtime/{devNo}-{channel}-2-1.flv
- 调用 startRealTimeMedia API 开启, controlEnd 关闭
2. 监听模式 (voiceType = 2)
- 单向接收
- 只接收服务器音频流,不上传麦克风
- 播放 /realtime/{devNo}-{channel}-3-1.flv
- 不调用 connectToServer,不建立 WebSocket
3. 广播模式 (voiceType = 3)
- 单向广播
- 发送: WebSocket 上传麦克风音频
- 接收: flv.js 播放 /realtime/{devNo}-{channel}-4-1.flv
- 同时调用 controlEnd 关闭设备端音频输出


关键代码位置

- 麦克风采集: sidebar.vue:1540-1549 - record() 获取媒体流
- 音频处理: sidebar.vue:1517-1525 - onAudioProcess() 实时处理并发送
- 压缩算法: sidebar.vue:1550-1566 - compress() 降采样到 8kHz
- WebSocket连接: sidebar.vue:1567-1582 - connectToServer() 建立双向通道
- 播放控制: voice.vue:33-65 - controlStart() 启动播放


数据格式

- 采集: Float32Array, 原始采样率 (通常 44.1kHz/48kHz)
- 压缩后: Int16Array, 8kHz, 单声道
- 传输: Blob (WebSocket binary message)
- 播放: FLV 流 (HTTP-FLV)


控制流程

用户点击"开始"
↓
voiceControl() 检查麦克风权限
↓
显示 voice 组件
↓
根据 voiceType 调用不同逻辑:
- 类型1: controlStart() + connectToServer()
- 类型2: controlStart() (仅播放)
- 类型3: controlEnd() + connectToServer()
↓
voiceChange() 切换模式时:
- stopRecord() 停止采集
- ws.onclose() 关闭 WebSocket
- controlEnd() 关闭播放


技术要点

1. 回声消除: getUserMedia 启用 echoCancellation, noiseSuppression
2. 降采样: 通过 compress() 将高采样率音频压缩到 8kHz,减少带宽
3. 实时性: WebSocket 二进制传输,低延迟
4. 播放优化: flv.js 禁用 Worker,关闭缓冲,初始播放速率 0.9x 防卡顿

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进