核心组件
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 防卡顿