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

posted @ 2021-12-23 15:09  CHHC  阅读(2537)  评论(1编辑  收藏  举报