Web语音对讲示例

PCM文件生成
1. 在线语音合成 https://ttsmaker.cn/
2. 音频转码 ffmpeg.exe -i test.mp3 -f s16le -ar 8000 -ac 1 -vn output.pcm

RTP播放测试
新建stream.sdp文件,使用vlc打开该文件,如8kHz 单声道 16-bit:

v=0
o=- 0 0 IN IP4 127.0.0.1
s=PCM Audio Stream
c=IN IP4 127.0.0.1
t=0 0
m=audio 5004 RTP/AVP 96
a=rtpmap:96 L16/8000/1

技术实现

流媒体:SDP流媒体信息、RTP打包、RTP解包

通信层:websocket

界面层:Html获取麦克风音频数据,播放PCM音频

代码结构

image

image

media.sdp

复制代码

v=0
o=- 0 0 IN IP4 127.0.0.1
s=RTP PCM Audio Stream
c=IN IP4 127.0.0.1
t=0 0
m=audio 5504 RTP/AVP 96
a=rtpmap:96 L16/8000/1

复制代码

talk_G711Alaw.sdp

复制代码

v=0
o=- 0 0 IN IP4 127.0.0.1
s=s=RTP G711 Audio Stream
c=IN IP4 127.0.0.1
t=0 0
m=audio 5004 RTP/AVP 8
a=rtpmap:8 PCMA/8000

复制代码

talk_PCM.sdp

复制代码

v=0
o=- 0 0 IN IP4 127.0.0.1
s=s=RTP G711 Audio Stream
c=IN IP4 127.0.0.1
t=0 0
m=audio 5004 RTP/AVP 96
a=rtpmap:96 L16/8000/1

复制代码

复制代码

using System.Net;
using System.Net.Sockets;

namespace RTPService.rtp
{
    public class RtpStreamer
    {
        private UdpClient udpClient;
        private IPEndPoint remoteEndPoint;
        private RtpPacketizer packetizer;
        private int frameSize;
        private int sampleRate;
        private int channel;
        private int bytesPerSample;

        public RtpStreamer(string remoteAddress, int remotePort, uint ssrc, int sampleRate = 8000, int bitDepth = 16, int channel = 1, byte payloadType = 96, bool isBigEndian = false)
        {
            udpClient = new UdpClient();
            remoteEndPoint = new IPEndPoint(IPAddress.Parse(remoteAddress), remotePort);

            this.sampleRate = sampleRate;
            this.channel = channel;
            this.bytesPerSample = bitDepth / 8;

            packetizer = new RtpPacketizer(ssrc, sampleRate, channel, bytesPerSample, payloadType, isBigEndian);

            // 计算适当的帧大小 (20ms 的数据)
            frameSize = (sampleRate * channel * bytesPerSample * 20) / 1000;
            // 确保帧大小是样本大小的倍数
            int sampleSize = channel * bytesPerSample;
            frameSize = (frameSize / sampleSize) * sampleSize;

            Console.WriteLine($"Streaming parameters: SSRC={ssrc},SampleRate={sampleRate}, bitDepth={bitDepth}, Channels={channel}, PayloadType={payloadType}, isBigEndian={isBigEndian}, FrameSize={frameSize}");
        }

        public void StreamPcmFile(string filePath)
        {
            using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                byte[] buffer = new byte[frameSize];
                int bytesRead;

                while ((bytesRead = fileStream.Read(buffer, 0, frameSize)) > 0)
                {
                    SendRtp(buffer, bytesRead);

                    // 等待适当的时间以保持正确的速率
                    int samples = bytesRead / (channel * bytesPerSample);
                    int delayMs = (samples * 1000) / sampleRate;
                    Thread.Sleep(delayMs);
                }
            }
        }

        public byte[] CreateRtpPacket(byte[] buffer, int bytesRead)
        {
            return packetizer.CreateRtpPacket(buffer, 0, bytesRead);
        }

        public byte[] DepacketizeRtpPacket(byte[] rtp)
        {
            return packetizer.DepacketizeRtpPacket(rtp);
        }

        public void SendRtp(byte[] buffer, int bytesRead)
        {
            // 创建RTP包
            byte[] rtpPacket = CreateRtpPacket(buffer, bytesRead);

            // 发送RTP包
            udpClient.Send(rtpPacket, rtpPacket.Length, remoteEndPoint);

            // 发送RTSP over UDP
            //byte[] rtspPacket = packetizer.CreateRtspPacket(rtpPacket);
            //udpClient.Send(rtspPacket, rtspPacket.Length, remoteEndPoint);
        }

        public void Close()
        {
            //udpClient?.Close();
        }
    }
}

复制代码

功能

1. 播放本地音频文件

2. 音频播放:服务端推送音频文件并播放

3. 音频回调:RTP解包并进行音频播放

4. 开始对讲:测试流程:html将麦克风数据转base64,websocket发送中间件,转成音频编码:G.711alaw,进行rtp打包,udp发送到5004,vlc播放sdp文件测试

5. 结束对讲

6. 摄像头播放:测试流程:读取pcm文件,进行rtp打包,udp发送到5504,vlc播放sdp文件,播放服务端音频

image

image

### Vue 前端通过 WebSocket 实现天翼视联语音对讲功能的方案 #### 1. 技术背景 在现代 Web 应用中,WebSocket 提供了一种高效的双向通信机制,特别适用于实时数据传输场景,例如语音对讲。Vue.js 作为前端框架,能够很好地与 WebSocket 集成,实现复杂的交互逻辑[^1]。 #### 2. 实现步骤 ##### 2.1 WebSocket 连接初始化 在 Vue 组件中初始化 WebSocket 连接,并传递必要的身份验证信息(如 token)。以下是一个示例代码片段: ```javascript export default { data() { return { websock: null, websocketPath: 'ws://your-server-address/apiSocket', }; }, methods: { initWebSocket() { this.websock = new WebSocket(this.websocketPath + '?token=' + Vue.cookie.get('token')); this.websock.onopen = this.websocketOnopen; this.websock.onerror = this.websocketOnerror; this.websock.onmessage = this.websocketOnmessage; this.websock.onclose = this.websocketOnclose; }, websocketOnopen() { console.log('WebSocket connection established.'); }, websocketOnerror(e) { console.error('WebSocket error:', e); }, websocketOnmessage(e) { this.receiveMessage(e.data); }, websocketOnclose(e) { console.log('WebSocket connection closed:', e); }, receiveMessage(data) { // 处理接收到的数据,可能需要解析二进制流并转换为音频格式 this.playAudio(data); }, playAudio(audioData) { const audioContext = new (window.AudioContext || window.webkitAudioContext)(); const uint8Array = new Uint8Array(audioData); audioContext.decodeAudioData(uint8Array.buffer, (buffer) => { const source = audioContext.createBufferSource(); source.buffer = buffer; source.connect(audioContext.destination); source.start(); }); }, }, mounted() { this.initWebSocket(); }, beforeDestroy() { this.websock.close(); }, }; ``` 上述代码展示了如何在 Vue 组件中初始化 WebSocket 连接,并处理接收到的语音数据[^1]。 ##### 2.2 数据处理与播放 当服务器通过 WebSocket 返回二进制数据时,前端需要将其解析为可播放的音频格式。通常情况下,这些数据会被转换为 WAV 或其他常见音频格式后进行播放[^4]。 ##### 2.3 错误处理与重连机制 为了确保连接的稳定性,建议在 WebSocket 断开时自动尝试重新连接。以下是一个简单的重连逻辑: ```javascript methods: { reconnectWebSocket() { setTimeout(() => { this.initWebSocket(); }, 5000); // 每隔5秒尝试重连 }, websocketOnclose(e) { console.log('WebSocket connection closed:', e); this.reconnectWebSocket(); }, }, ``` #### 3. 注意事项 - **网络条件**:确保网络环境稳定,避免因高延迟或丢包导致的语音质量下降。 - **音频编解码**:根据实际需求选择合适的音频编解码器,例如 Opus 或 PCM[^4]。 - **安全性**:通过 HTTPS 和 WSS 协议保障数据传输的安全性,同时使用有效的身份验证机制防止未授权访问。 #### 4. 扩展功能 - **多设备支持**:允许多个设备同时参与语音对讲,提升应用场景的灵活性。 - **音量调节**:提供用户界面选项以调整播放音量。 - **日志记录**:记录通信过程中的关键事件,便于调试和问题排查。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值