C#RTSP通信2:RTSP语音广播+语音对讲(WinForm版本)
C#RTSP通信1:C#高性能RTSP播放器(使用FFmepg封装自定义控件,使用简单)
C#RTSP通信2:RTSP语音广播+语音对讲(WinForm版本)
参考文章:
https://blog.csdn.net/u010293286/article/details/106070959
https://blog.csdn.net/buyicn/article/details/94590419
使用前提:摄像头支持 onvif backchannel
语音广播
语音对讲
发布文件
代码调用
using NAudio.Codecs; using NAudio.Wave; using RTSPClient; using System; using System.IO; using System.Threading; using System.Windows.Forms; namespace RtspAudio { public partial class MainForm : Form { RTSPSession session = new RTSPSession(); IWaveIn sourceStream; public MainForm() { InitializeComponent(); } private void MainForm_Load(object sender, EventArgs e) { // 录音初始化 sourceStream = new WaveInEvent(); sourceStream.WaveFormat = new WaveFormat(8000, 16, 1); sourceStream.DataAvailable += new EventHandler<WaveInEventArgs>(SourceStream_DataAvailable); sourceStream.StartRecording(); } private async void btnInit_Click(object sender, EventArgs e) { // rtsp 语音初始化 await session.InitVoice(txtRtspUrl.Text.Trim(), txtUserName.Text.Trim(), txtPassword.Text.Trim()); lblMsg.Text = session.Status ? "初始化成功" : "初始化失败:" + session.Errmsg; } private void btnCheckFile_Click(object sender, EventArgs e) { // 选择G711文件 openFileDialog1.Title = "请选择文件夹"; openFileDialog1.Filter = "(*.g711a)|*.g711a"; if (openFileDialog1.ShowDialog() == DialogResult.OK) { txtFile.Text = openFileDialog1.FileName; } } private void btnStartAudio_Click(object sender, EventArgs e) { if (!session.Status) return; session.VoiceStatus = 1; byte[] audio = File.ReadAllBytes(txtFile.Text.Trim());// out1_8k.g711a css.pcm left.g711a ThreadPool.QueueUserWorkItem(async p => { string note = ""; try { await session.PlayAudio_G711A(audio, 25, 8000, session.Ssrc2, session.Channel); note = "播放结束"; } catch (Exception ex) { note = "播放失败,errmsg:" + ex.Message; } this.BeginInvoke((EventHandler)(delegate { lblMsg.Text = note; })); }); lblMsg.Text = "开始播报"; } private void btnStopAudio_Click(object sender, EventArgs e) { if (!session.Status) return; session.VoiceStatus = 0; lblMsg.Text = "停止播报"; } private void btnStartTalk_Click(object sender, EventArgs e) { // 开始对讲 if (!session.Status) return; session.VoiceStatus = 2; lblMsg.Text = "开始对讲"; } private void btnStopTalk_Click(object sender, EventArgs e) { // 停止对讲 if (!session.Status) return; session.VoiceStatus = 0; lblMsg.Text = "停止对讲"; } private async void SourceStream_DataAvailable(object sender, WaveInEventArgs e) { if (!session.Status || (2 != session.VoiceStatus)) return; byte[] encoded = TwoWayAudio_Encode_MuLaw(e.Buffer, 0, e.BytesRecorded); try { await session.SendData(encoded, session.Channel); } catch (Exception ex) { this.BeginInvoke((EventHandler)(delegate { lblMsg.Text = "对讲失败,errmsg:" + ex.Message; })); } } private byte[] TwoWayAudio_Encode_MuLaw(byte[] data, int offset, int length) { byte[] encoded = new byte[length / 2]; int outIndex = 0; for (int n = 0; n < length; n += 2) { encoded[outIndex++] = MuLawEncoder.LinearToMuLawSample(BitConverter.ToInt16(data, offset + n)); } return encoded; } } }
C -> S
OPTIONS rtsp://192.168.3.2:554 RTSP/1.0\r\n
CSeq: 1\r\n
User-Agent: Cyaim RTSP Client 1.0\r\n
\r\n
S -> C
RTSP/1.0 200 OK\r\n
CSeq: 1\r\n
Public: OPTIONS, DESCRIBE, PLAY, PAUSE, SETUP, TEARDOWN, SET_PARAMETER, GET_PARAMETER\r\n
Date: Wed, Dec 22 2021 15:40:37 GMT\r\n
\r\n
C -> S
DESCRIBE rtsp://192.168.3.2:554 RTSP/1.0\r\n
CSeq: 2\r\n
User-Agent: Cyaim RTSP Client 1.0\r\n
Accept: application/sdp\r\n
Require: www.onvif.org/ver20/backchannel\r\n
\r\n
S -> C
RTSP/1.0 401 Unauthorized\r\n
CSeq: 2\r\n
WWW-Authenticate: Digest realm="IP Camera(C9596)", nonce="15a1f6c0ea78e483dd709e49bd3f1afe", stale="FALSE"\r\n
Date: Wed, Dec 22 2021 15:40:38 GMT\r\n
\r\n
C -> S
DESCRIBE rtsp://192.168.3.2:554 RTSP/1.0\r\n
CSeq: 3\r\n
User-Agent: Cyaim RTSP Client 1.0\r\n
Authorization: Digest username="admin", realm="IP Camera(C9596)", nonce="15a1f6c0ea78e483dd709e49bd3f1afe", uri="rtsp://192.168.3.2:554", response="0e8d143688babc1aedeb45a40ae0140a"\r\n
Accept: application/sdp\r\n
Require: www.onvif.org/ver20/backchannel\r\n
\r\n
S -> C
RTSP/1.0 200 OK\r\n
CSeq: 3\r\n
Content-type: application/sdp
Content-Base: rtsp://192.168.3.2:554/\r\n
Content-length: 801
\r\n
C -> S
SETUP rtsp://192.168.3.2:554/trackID=4 RTSP/1.0\r\n
CSeq: 4\r\n
User-Agent: Cyaim RTSP Client 1.0\r\n
Authorization: Digest username="admin", realm="IP Camera(C9596)", nonce="15a1f6c0ea78e483dd709e49bd3f1afe", uri="rtsp://192.168.3.2:554/", response="4514614688d6726387a09730c6c0ae2d"\r\n
Require: www.onvif.org/ver20/backchannel\r\n
Transport: RTP/AVP/TCP;unicast
\r\n
S -> C
RTSP/1.0 200 OK\r\n
CSeq: 4\r\n
Session: 396637933;timeout=60
Transport: RTP/AVP/TCP;unicast;interleaved=8-9;ssrc=7fc806fe;mode="play"
Date: Wed, Dec 22 2021 15:40:38 GMT\r\n
\r\n
C -> S
PLAY rtsp://192.168.3.2:554/ RTSP/1.0\r\n
CSeq: 5\r\n
User-Agent: Cyaim RTSP Client 1.0\r\n
Authorization: Digest username="admin", realm="IP Camera(C9596)", nonce="15a1f6c0ea78e483dd709e49bd3f1afe", uri="rtsp://192.168.3.2:554/", response="8fe7a6c6efe20d4eb95fee513f4879cf"\r\n
Require: www.onvif.org/ver20/backchannel\r\n
Session: 396637933
Range: npt=0.000-\r\n
\r\n
S -> C
RTSP/1.0 200 OK\r\n
CSeq: 5\r\n
Session: 396637933
RTP-Info: \r\n
Date: Wed, Dec 22 2021 15:40:38 GMT\r\n
\r\n