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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM