• WebRTC媒体协商及实践


    WebRTC 处理流程图:

    在这里插入图片描述

    WebRTC 终端,负责音视频采集、编码、NAT穿越、音视频数据传输。

    Signal服务器,负责信令处理,如加入房间、离开房间、媒体协商消息的传递。

    STUN/TURN 服务器,负责获取WebRTC终端在公网的IP地址,以及NAT穿越失败后的数据中转。

    主要基础概念:

    帧率:摄像头一秒钟采集图像的次数;一般情况下,一秒可采集30张-100张图片。帧率越高,视频越平滑,占用带宽越大。

    编码帧:视频数据流通过编码器(H264/H265\VP8/VP9)压缩后的帧。

    ​ I 帧:关键帧。压缩率低,可以单独解码成一幅完整的图像。

    ​ P帧:参考帧。压缩率较高,解码时依赖于前面已解码的数据。

    ​ B帧:前后参考帧。压缩率最高,解码时依赖于前后已解码的帧,B帧后面的P帧要优先进行解码。

    非编码帧:音视频设备拍摄的未经过编码的原视频帧。编码格式一般为YUV、RBG格式。

    MediaTrack:媒体轨,可理解类似火车道的两条铁轨,每条轨数据是独立的,不会与其他轨相交;
    MediaStream:媒体流,音视频数据流,可存放0个或者多个音频轨或者视频轨。

    MediaDevices:该接口提供了访问(连接到计算机上)媒体设备(如摄像头、麦克风)以及截取屏幕的方法。MediaDeviceInfo: 表示每个输入/输出的设备信息:deviceId(设备唯一标识),label(设备名称),kind(设备种类,音频设备还是视频设备)。除非用户已授权访问媒体的权限(HTTPS请求),否则label字段始终为空。

    SDP: Session Description Protocal 会话描述协议,用文本描述各终端(PC\Android\IOS)所支持的音频编解码器、设定的参数、使用的传输协议及音视频媒体等。其包括会话描述、媒体描述。

    ​ 会话描述(v-m):SDP版本号、用户名(不关心可用 - 代替)、会话唯一标识(NTP时间戳)、版本号(每次会话数据修改,其值会递增),网络类型、IP类型、ip 地址 。

    ​ 媒体描述:媒体类型、媒体格式、传输协议、传输的IP和端口。

    ​ WebRTC 中的SDP:

    ​ Session Metadata 会话元数据

    ​ Network Description 网络描述

    ​ Stream Description 流描述

    ​ Security Description 安全描述

    ​ Qos Grouping Descriptions,服务质量描述

    //=============会话描述====================
    v=0 
    o=- 7017624586836067756 2 IN IP4 127.0.0.1
    s=-
    t=0 0
    ...
    
    //================媒体描述=================
    //================音频媒体=================
    /*
     * 音频使用端口1024收发数据
     * UDP/TLS/RTP/SAVPF 表示使用 dtls/srtp 协议对数据加密传输
     * 111、103 ... 表示本会话音频数据的 Payload Type
     */
     m=audio 1024 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 126 
    
    //==============网络描述==================
    //指明接收或者发送音频使用的IP地址,由于WebRTC使用ICE传输,这个被忽略。
    c=IN IP4 0.0.0.0
    //用来设置rtcp地址和端口,WebRTC不使用
    a=rtcp:9 IN IP4 0.0.0.0
    ...
    
    //==============音频安全描述================
    //ICE协商过程中的安全验证信息
    a=ice-ufrag:khLS
    a=ice-pwd:cxLzteJaJBou3DspNaPsJhlQ
    a=fingerprint:sha-256 FA:14:42:3B:C7:97:1B:E8:AE:0C2:71:03:05:05:16:8F:B9:C7:98:E9:60:43:4B:5B:2C:28:EE:5C:8F3:17
    ...
    
    //==============音频流媒体描述================
    a=rtpmap:111 opus/48000/2
    //minptime代表最小打包时长是10ms,useinbandfec=1代表使用opus编码内置fec特性
    a=fmtp:111 minptime=10;useinbandfec=1
    ...
    a=rtpmap:103 ISAC/16000
    a=rtpmap:104 ISAC/32000
    a=rtpmap:9 G722/8000
    ...
    
    //=================视频媒体=================
    m=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116 117 96 97 99 98
    ...
    //=================网络描述=================
    c=IN IP4 0.0.0.0
    a=rtcp:9 IN IP4 0.0.0.0
    ...
    //=================视频安全描述=================
    a=ice-ufrag:khLS
    a=ice-pwd:cxLzteJaJBou3DspNaPsJhlQ
    a=fingerprint:sha-256 FA:14:42:3B:C7:97:1B:E8:AE:0C2:71:03:05:05:16:8F:B9:C7:98:E9:60:43:4B:5B:2C:28:EE:5C:8F3:17
    ...
    
    //================视频流描述===============
    a=mid:video
    ...
    a=rtpmap:100 VP8/90000
    //================服务质量描述===============
    a=rtcp-fb:100 ccm fir
    a=rtcp-fb:100 nack //支持丢包重传,参考rfc4585
    a=rtcp-fb:100 nack pli
    a=rtcp-fb:100 goog-remb //支持使用rtcp包来控制发送方的码流
    a=rtcp-fb:100 transport-cc
    ...

    媒体协商:媒体协商的作用就是让双方找到共同支持的媒体能力,如双方都支持的编解码器,从而最终实现彼此之间的音视频通信。

    ​ 媒体协商流程如下(主要通过RTCPeerConnection对象进行呼叫方、被会叫方SDP交换、解析实现),
    在这里插入图片描述

    **NAT 穿越:**NAT穿越 使用UPD协议,NAT类型:

    ​ 1.完全锥型

    ​ 2.IP限制锥型

    ​ 3.端口限制锥型

    ​ 4.对称型

    ​ 对称型与对称型、对称型与端口限制型无法穿越。

    NAT探测逻辑图:

    在这里插入图片描述

    WebRTC 代码关键点实现:

    1:检测设备

    //可用来判断浏览器是否支持API 
    navigator.mediaDevices
    //enumerateDevices()方法:获取媒体输入输出设备列表
    navigator.mediaDevices.enumerateDevices

    在这里插入图片描述

    上面实例:kind 设备种类包含:audioinput、audiooutput、videoinput等;groupId标识为一个设备即包含输入设备也包含输出设备,例如带话筒的耳机。本机访问未通过https请求授权,故label字段为空。

    2:启动摄像头

    通过mediaDevices.getUserMedia方法打开摄像头(mediaStreamContrains里要配置video,否则不会启动摄像头)并获取视频流数据 给页面 video标签进行播放。

    <!--前端代码-->
    <div><video autoplay playsinline id="player"></video></div>
    ……
    //通过设置contranis 对音视频做详细的参数配置
    const  mediaStreamContranis={
        video : {//视频
    				width: 640,	//视频框宽
                    height: 480,//视频框高
                    frameRate:15,//帧率
                    facingMode: 'enviroment'//前/后置摄像头
    			},
    	audio:{//音频
    	    echoCancellation:true, //回音消除
        	noiseSuppression:true, //降噪
        	autoGainControl:true   //自动增益
        	}
       }
    function start(){
        ……
        //获取的音视频数据
    	navigator.mediaDevices.getUserMedia(constraints)
    		.then(gotMediaStream)
    		.catch(handleError);
    }
    ……
    function gotMediaStream(stream){
    	videoplay.srcObject = stream;
    }

    3:拍摄照片并开启滤镜效果

    界面canvas标签用来接收并展示抓拍到的照片。导入滤镜css样式为后续开启摄像头滤镜准备。

     <div><canvas id="picture"></canvas></div>
    
    <style>
                .none {
                    -webkit-filter: none;	
                }
    
                .blur {
                    -webkit-filter: blur(3px);	
                }
    
                .grayscale {
                    -webkit-filter: grayscale(1); 	
                }
    
                .invert {
                    -webkit-filter: invert(1);	
                }
    
                .sepia {
                    -webkit-filter: sepia(1);
                }
    
            </style>

    为画布canvas开启滤镜(此处是展示端显示滤镜效果)。

    picture.className = filtersSelect.value;

    调用canvas的drawImage方法进行视频抓拍(如果需要将抓拍照片保存为有展示的滤镜效果的图片,需要在调用drawImange方法时设置filter为滤镜样式。)

    var ctx  = picture.getContext('2d');
    ctx.drawImage(image,dx,dy,dWidth,dHeight);
    ctx.filter = '选择的滤镜样式';

    ​ 参数:

    ​ image:可以是一张图片,也可以是HTMLVideoElement(摄像头抓拍即此类型)。

    ​ dx,dy: 图片的起点坐标,x,y。

    ​ dWidth:图片的宽度。

    ​ dHeight:图片的高度。

    4:录制本地视频并播放

    ​ 创建录制对象new MediaRecorder(mediaStream,options)

    ​ 参数:

    ​ mediaStream :要录制的媒体流;

    ​ options:设置MIME类型(如:video/webm, video/mp4 )和音频及视频的码率

    //设置录制下来的多媒体格式
    var options = {
    		mimeTypes:'video/webm;codecs=vp8'
    	}
    mediaRecorder = new MediaRecorder(window.stream,options)
    //当有音视频数据来了之后出发该事件
    mediaRecorder.ondataavailable = handleDataAvailable;
    //开始录制
    mediaRecorder.start(10);//设置时间片段
    ……
    /**
    当该函数被触发后,将数据压入到blob中
    **/
    function handleDataAvailable(e){
    	if(e && e.data && e.data.size > 0){
    		buffer.push(e.data);
    	}
    }
    
    btnRecplay.onclick = function(){
    	var blob =  new Blob(buffer,{type:'video/webm'});
    	recplayer.src = window.URL.createObjectURL(blob);
    	recplayer.controls = true;
    	recplayer.srcObject = null;
    	recplayer.play();
    }

    mediaRecorder.ondataavailable 绑定ondataavailable 事件,接收到音视频数据时调用handleDataAvailable方法(自定义方法)将录制的视频数据放入buffer中,作为后续播放的Blob数据源。

    mediaRecorder.start(10) 设置时间片段,保证录制的视频分为多个一个固定长度(10ms)的片段存储,方便后续播放。

    5:共享桌面

    WebRTC共享桌面功能与共享音视频流类似,且WebRTC的远程桌面又不需要远程控制,其处理过程使用视频方式,而非传统意义上的RDP/VNC等远程桌面协议。

    其共享流程:PC桌面抓取 (DirectX)–> 录制桌面(编码) --> 共享远端(传输,WebRTC传输过程中数据可丢失) -->远短观看 (解码) -->远短渲染画面(GPU、OpenGL/D3D)

    抓取桌面Windows为例:

    mediaDevices.getDisplayMedia()方法跟打开摄像头mediaDevices.getUserMedia()方法调用方式类似,

    navigator.mediaDevices.getDisplayMedia(constraints)
    			.then(gotMediaStream)
    			.catch(handleError);

    远程桌面控制,需要借助信令服务器将远端的操作(鼠标位置和点击事件、键盘操作)转换成PC操作指令数据发回被操作端,被操作端解析并执行指令。

     
     转自:https://blog.csdn.net/fuxuan_7/article/details/109002699
  • 相关阅读:
    BestCoder Round #84
    codeforces#689BMike and Shortcuts
    POJ2985 并查集+线段树 求第k大的数
    Trie树模板 POJ1056
    新建zabbix数据库
    python输出菱形
    wmi获取计算机信息
    python测试IP地址是否ping通
    手机安装python环境
    Centos 8 安装zabbix 爬坑
  • 原文地址:https://www.cnblogs.com/javalinux/p/14446759.html
Copyright © 2020-2023  润新知