zoukankan      html  css  js  c++  java
  • WebRTC for UWP

    首先还是简单的介绍下webRTC吧:

      WebRTC,名称源自网页实时通信(Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的技术,是谷歌2010年以6820万美元收购Global IP Solutions公司而获得的一项技术。2011年5月开放了工程的源代码,在行业内得到了广泛的支持和应用,成为下一代视频通话的标准。(摘自百度百科)

      简而言之,webrtc就是一种让浏览器获得更好的音视频实时通话的技术,现在各大浏览器都已经支持。由于是开源的,所以不仅仅局限于浏览器,各大平都有相应编译的版本,包括uwp。

      介绍完了(虽然你肯定还不明白),那就来谈谈uwp的实现吧。

      首先要使用webrtc需要在nuget包管理中搜索并安装”webrtc“,或者在nuget控制台输入Install-Package WebRTC。安装完成后using webrtc_winrt_api;这个命名空间,接下来就可以直接用了。

      先来说下使用webrtc需要具备的条件:

        1.发送连接信息和打洞信息的服务器,也就是信令服务器。不过这个没有什么要求,只要可以把信息送到对方就可以了。你可以使用任何协议来完成信令传输,比如socket,websocket,http等等。

        2.打洞服务器IceServer。这个服务器需要有两个功能:

          1. NAT/防火墙穿越
          2. 如果点对点通信建立失败,可以作为中转服务器

      如果网络条件具备了,那么请接着往下看:

      WebRTC这里提供了三个接口:

         MediaStream:通过MediaStream的API能够通过设备的摄像头及麦克风获得视频、音频的同步流
         RTCPeerConnection:RTCPeerConnection是WebRTC用于构建点对点之间稳定、高效的流传输的组件
         RTCDataChannel:RTCDataChannel建立一个高吞吐量、低延时的信道,用于传输任意数据 

    这和web端以及其他平台是一致的,只不过实现的方法略微不同。

      下面来看看如何获取视频流以及音频流:

    首先最重要的是初始化 

     WebRTC.Initialize(this.Dispatcher);

    接下来

                Media = Media.CreateMedia();//创建一个Media对象
    
                RTCMediaStreamConstraints mediaStreamConstraints = new RTCMediaStreamConstraints() //设置要获取的流 
                {
                    audioEnabled = true,
                    videoEnabled = true
                }; 
    
                var apd = Media.GetAudioPlayoutDevices(); 
                var acd = Media.GetAudioCaptureDevices(); 
                var vcd = Media.GetVideoCaptureDevices(); 
                Media.SelectAudioCaptureDevice(acd[0]);
                Media.SelectAudioPlayoutDevice(apd[0]); 
                Media.SelectVideoDevice(vcd.First(p => p.Location.Panel == Windows.Devices.Enumeration.Panel.Front));//设置视频捕获设备
                var mediaStream = await Media.GetUserMedia(mediaStreamConstraints);//获取视频流 这里视频和音频是一起传输的
                var videotracs = mediaStream.GetVideoTracks();
                var audiotracs = mediaStream.GetAudioTracks();
                var source = Media.CreateMediaSource(videotracs.FirstOrDefault(), mediaStream.Id);//创建播放源
                LocalMediaPlayer.SetMediaStreamSource(source); //设置MediaElement的播放源

    现在就已经获取到了本地视频了,如果媒体播放控件的autoplay为true的话,那么视频已经开始播放,你将看到自己帅气的脸庞。

    下面就要开始连接了,首先创建一个RTCPeerconnection并包含你的打洞服务器IceServer:

            List<RTCIceServer> iceservers = new List<RTCIceServer>()
                  {
                        new RTCIceServer {Url="<your server>",Username="<your name>" },
                        new RTCIceServer {Url="<your server>",Username="<your name>" },
                        new RTCIceServer {Url="<your server>",Username="<your name>" },
                        new RTCIceServer {Url="<your server>",Username="<your name>" }
                   }; //不一定是这么多个
    
                RTCConfiguration configuration = new RTCConfiguration() { BundlePolicy = RTCBundlePolicy.Balanced, IceServers = servers, IceTransportPolicy = RTCIceTransportPolicy.All };
                conn = new RTCPeerConnection(configuration);
                conn.AddStream(mediaStream);
                conn.OnIceCandidate += Conn_OnIceCandidate;
                conn.OnAddStream += Conn_OnAddStream;

    接下来开始连接:

      Step1:视频通话发起方Creeat一个Offer,设置Peerconnection的LocalDescription,把offer的Sdp发送到视频通话接收方:

     public async Task CreatOffer() //此时是发起方的操作
            {
                var offer = await conn.CreateOffer();
                await conn.SetLocalDescription(offer);
                await Send_Message(offer.Sdp);
            }

      Step2:接收方收到Offer消息,此时同发起方一样,初始化并创建mediaStream,创建peerconnection。设置peerconnection的RemoteDescription,创建一个Answer,设置LocalDescription,发送Answer的Sdp给发起方:

     async public Task CreatAnswer(string offersdp) //此时是接受方的操作
            { 
                var offer = new RTCSessionDescription(RTCSdpType.Offer, offersdp);
                await conn.SetRemoteDescription(offer);
                var answer = await conn.CreateAnswer();
                await conn.SetLocalDescription(answer); 
                await Send_Message(answer.Sdp);    
            }

    于此同时,RTCPeerconnection的OnIceCandidate事件会被触发,发送Candidate的数据到另一端

      private async void Conn_OnIceCandidate(RTCPeerConnectionIceEvent __param0) //此事件接收方和发起方都需要
            {
                var Candidate = __param0.Candidate;
                var candidate = JsonConvert.SerializeObject(Candidate);
                await Send_Message(candidate);
            }

    接收到Candidate后将Candidate添加到Peerconnection

      await conn.AddIceCandidate(JsonConvert.DeserializeObject<RTCIceCandidate>(CandidateMsg));//两边都与要添加,candidatemsg为收到的信息,而非自己的

    当上述过程完成后,Peerconnection的OnAddStream事件会被触发,这也代表通信建立完成,通话开始。将接收到的stream添加到MEdiaElement:

                var stream = __param0.Stream;
                var videotracks = stream.GetVideoTracks();
                var source = Media.CreateMediaSource(videotracks.FirstOrDefault(), stream.Id); 
                RemoteMediaPlayer.SetMediaStreamSource(source);
                RemoteMediaPlayer.Play(); 

    好了一个完整的WebRTC通话过程就完成了!

    让我们再来回顾一下整个过程:Server代表发起方,Client代表接收方(很显然这样称呼是不正确的)

      Step1.  WebRTC.Initialize                Server & Client

      Step2.  Media.CreatMedia                Server & Client

      Step3.  Media.GetUserMedia              Server & Client

      Step4.  new RTCPeerconnection             Server & Client

      Step5.  Conn.AddStream                 Server & Client

      Step6.  CreatOffer                     Server

      Step7.  SetLocalDescription               Server

      Step8.  Send Offer.Sdp                  Server

      Step9.  SetRemoteDescription               Client

      Step10.  CreatAnswer                    Client

      Step11.  SerLocalDescription                Client

      Step12.  Send Answer.Sdp                 Client

      Step13.  Send Candidate                 Server & Client

      Step14.  AddCandidate                  Server & Client

      

  • 相关阅读:
    js中const,var,let区别与用法
    poi excel 导出
    spring 实体类 date类型字段处理
    mysql 1449 : The user specified as a definer ('root'@'%') does not exist
    pjax学习
    上传文件 connection reset
    mysql连接问题
    Scala Actor Model
    Scala 隐式转换
    Scala Trait+Match+Case class+偏函数
  • 原文地址:https://www.cnblogs.com/Yixin-ran/p/webrtc.html
Copyright © 2011-2022 走看看