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音频
代码结构
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文件,播放服务端音频