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[]);
Media.SelectAudioPlayoutDevice(apd[]);
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
WebRTC for UWP的更多相关文章
- UWP 律师查询 MVVM
APP简介 律师查询是基于聚合数据的律师查询接口做的,这个接口目前处于停用状态,但是,由于我是之前申请的,所以,还可以用,应该是无法再申请了. 效果图 开发 一.HttpHelper 既然是请求接口的 ...
- 领域驱动和MVVM应用于UWP开发的一些思考
领域驱动和MVVM应用于UWP开发的一些思考 0x00 起因 有段时间没写博客了,其实最近本来是根据梳理的MSDN上的资料(UWP开发目录整理)有条不紊的进行UWP学习的.学习中有了心得体会或遇到了问 ...
- UWP中实现自定义标题栏
UWP中实现自定义标题栏 0x00 起因 在UWP开发中,有时候我们希望实现自定义标题栏,例如在标题栏中加入搜索框.按钮之类的控件.搜了下资料居然在一个日文网站找到了一篇介绍这个主题的文章: http ...
- UWP中新加的数据绑定方式x:Bind分析总结
UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...
- MVVM框架从WPF移植到UWP遇到的问题和解决方法
MVVM框架从WPF移植到UWP遇到的问题和解决方法 0x00 起因 这几天开始学习UWP了,之前有WPF经验,所以总体感觉还可以,看了一些基础概念和主题,写了几个测试程序,突然想起来了前一段时间在W ...
- UWP学习目录整理
UWP学习目录整理 0x00 可以忽略的废话 10月6号靠着半听半猜和文字直播的补充看完了微软的秋季新品发布会,信仰充值成功,对UWP的开发十分感兴趣,打算后面找时间学习一下.谁想到学习的欲望越来越强 ...
- UWP开发必备:常用数据列表控件汇总比较
今天是想通过实例将UWP开发常用的数据列表做汇总比较,作为以后项目开发参考.UWP开发必备知识点总结请参照[UWP开发必备以及常用知识点总结]. 本次主要讨论以下控件: GridView:用于显示数据 ...
- UWP开发必备以及常用知识点总结
一直在学UWP,一直在写Code,自己到达了什么水平?还有多少东西需要学习才能独挡一面?我想对刚接触UWP的开发者都有这种困惑,偶尔停下来总结分析一下还是很有收获的! 以下内容是自己开发中经常遇到的一 ...
- UWP开发之Mvvmlight实践九:基于MVVM的项目架构分享
在前几章介绍了不少MVVM以及Mvvmlight实例,那实际企业开发中将以那种架构开发比较好?怎样分层开发才能节省成本? 本文特别分享实际企业项目开发中使用过的项目架构,欢迎参照使用!有不好的地方欢迎 ...
随机推荐
- 转:探秘腾讯Android手机游戏平台之不安装游戏APK直接启动法
前言 相信这样一个问题,大家都不会陌生, “有什么的方法可以使Android的程序APK不用安装,而能够直接启动”. 发现最后的结局都是不能实现这个美好的愿望,而腾讯Android手机游戏平台却又能实 ...
- (转)linux文件读写的流程
转自http://hi.baidu.com/_kouu/item/4e9db87580328244ef1e53d0 在<linux内核虚拟文件系统浅析>这篇文章中,我们看到文件是如何被打开 ...
- PE渲染引擎 一
PE是我业余时间做的一个纯dx11的渲染框架.主要就是练手.如果有时间,会把它“扩展”成真正的引擎(标配至少要有个对应的编辑器吧 -_!!). 目前实现的有: obj文件加载,binormal计算. ...
- Mybatis对MySQL中BLOB字段的读取
1.在sqlMapConfig中,定义一个typeHandlers <typeHandlers> <typeHandler jdbcType="BLOB" jav ...
- C#连接Oracle简单教程
要点:本文主要介绍如何使用最简单的方法让C#操作Oracle数据库,不需要安装Oracle客户端之类的东西. 最近由于工作需要,要使用C#从SQLServer向Oracle导入数据.之前没有怎么接触过 ...
- rsync同步Nginx日志遇到问题总结
一.目的 将nginx 日志通过普通用户利用rsync公钥认证的方式实时同步到本地服务器上,之后使用elk程序进行处理. 二.遇到问题及解决方法思路 问题1.文件权限:nginx 的日志默认权限如下: ...
- C#使用 UdpClient 类进行简单通信的例子
UdpClient 类提供了一些简单的方法,用于在阻止同步模式下发送和接收无连接 UDP 数据报. 因为 UDP 是无连接传输协议,所以不需要在发送和接收数据前建立远程主机连接.但您可以选择使用下面两 ...
- [新手学Java]使用内省(Introspector)操作JavaBean属性
获取类bean中的所有属性: @Test //获取类bean中的所有属性 public void test1() throws Exception{ BeanInfo info = Introspec ...
- 重新想象 Windows 8.1 Store Apps (79) - 控件增强: MediaElement, Frame
[源码下载] 重新想象 Windows 8.1 Store Apps (79) - 控件增强: MediaElement, Frame 作者:webabcd 介绍重新想象 Windows 8.1 St ...
- elasticsearch 之IK分词器安装
IK分词器地址:https://github.com/medcl/elasticsearch-analysis-ik 安装好ES之后就可以安装分词器插件了 记住选择ES对应的版本 对应的有版本选择下载 ...