极客时间-从零打造音视频直播系统学习笔记 WebRTC 1对1通话 WebRTC处理过程
音视频采集 我们使用 getUserMedia
方法进行音视频流对象的采集
1 2 var promise = navigator.mediaDevices .getUserMedia (constraints);
其中constraints参数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 const mediaStreamContrains = { video : { frameRate : {min : 20 }, width : {min : 640 , ideal : 1280 }, height : {min : 360 , ideal : 720 }, aspectRatio : 16 /9 }, audio : { echoCancellation : true , noiseSuppression : true , autoGainControl : true } };
![image-20220327134534844](/Users/xaviershi/Library/Application Support/typora-user-images/image-20220327134534844.png)
Api和设备检测 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 if (!navigator.mediaDevices || !navigator.mediaDevices .enumerateDevices ) { console .log ("enumerateDevices() not supported." ); return ; } navigator.mediaDevices .enumerateDevices () .then (function (deviceInfos ) { deviceInfos.forEach (function (deviceInfo ) { console .log (deviceInfo.kind + ": " + deviceInfo.label + " id = " + deviceInfo.deviceId ); }); }) .catch (function (err ) { console .log (err.name + ": " + err.message ); });
用摄像头给自己拍照并保存 首先获取视频流到video标签里面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 'use strict' var videoplay = document .querySelector ('video#player' );function gotMediaStream (stream ){ videoplay.srcObject = stream; } function handleError (err ){ console .log ('getUserMedia error:' , err); } var constraints = { video : { width : 1280 , height : 720 , frameRate :15 , }, audio : false } navigator.mediaDevices .getUserMedia (constraints) .then (gotMediaStream) .catch (handleError);
然后将video标签给canvas做参数用于截图
1 2 3 4 5 6 7 8 9 10 11 12 ... var picture = document .querySelector ('canvas#picture' );picture.width = 640 ; picture.height = 480 ; ... picture.getContext ('2d' ).drawImage (videoplay, 0 , 0 , picture.width , picture.height ); ...
最后创建a标签用于下载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ... function downLoad (url ){ var oA = document .createElement ("a" ); oA.download = 'photo' ; oA.href = url; document .body .appendChild (oA); oA.click (); oA.remove (); } ... document .querySelector ("button#save" ).onclick = function ( ){ downLoad (canvas.toDataURL ("image/jpeg" )); } ....
如何录制本地音视频 1 2 var mediaRecorder = new MediaRecorder (stream[, options]);
stream,通过 getUserMedia 获取的本地视频流或通过RTCPeerConnection获取的远程视频流
options,可选项,指定视频格式、编解码器、码率等相关信息
1 2 3 4 5 6 7 8 9 10 11 <html> ... <body> ... <button id="record" >Start Record </button> <button id ="recplay" disabled > Play</button > <button id ="download" disabled > Download</button > ... </body> </html>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 ... var buffer;... function handleDataAvailable (e ){ if (e && e.data && e.data .size > 0 ){ buffer.push (e.data ); } } function startRecord ( ){ buffer = []; var options = { mimeType : 'video/webm;codecs=vp8' } if (!MediaRecorder .isTypeSupported (options.mimeType )){ console .error (`${options.mimeType} is not supported!` ); return ; } try { mediaRecorder = new MediaRecorder (window .stream , options); }catch (e){ console .error ('Failed to create MediaRecorder:' , e); return ; } mediaRecorder.ondataavailable = handleDataAvailable; mediaRecorder.start (10 ); } ...
回放录制的内容
1 2 3 4 5 6 var blob = new Blob (buffer, {type : 'video/webm' });recvideo.src = window .URL .createObjectURL (blob); recvideo.srcObject = null ; recvideo.controls = true ; recvideo.play ();
下载录制好的文件
1 2 3 4 5 6 7 8 9 10 11 btnDownload.onclick = ()=> { var blob = new Blob (buffer, {type : 'video/webm' }); var url = window .URL .createObjectURL (blob); var a = document .createElement ('a' ); a.href = url; a.style .display = 'none' ; a.download = 'aaa.webm' ; a.click (); }
共享桌面 WebRTC与传统RDP/VNC共享桌面协议不太一样,因为webrtc不需要远程控制,所以它采用的是视频采集传输编码解码那一套,而RDP/VNC则是采用的图片那一套+指令控制鼠标
数据采集,WebRTC采用的DirectX方式进行采集
编码,采用的H264/Vp8等视频编码方式
传输,流媒体传输协议,数据可丢
解码,视频解码技术解码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 var promise = navigator.mediaDevices .getDisplayMedia (constraints);... function getDeskStream (stream ){ localStream = stream; } function shareDesktop ( ){ if (IsPC ()){ navigator.mediaDevices .getDisplayMedia ({video : true }) .then (getDeskStream) .catch (handleError); return true ; } return false ; } ... ... <video autoplay playsinline id="deskVideo" ></video> ... ... var deskVideo = document .querySelect ("video/deskVideo" ); ... function getDeskStream (stream ){ localStream = stream; deskVideo.srcObject = stream; } ...
不能再采集桌面的同时采集音频。
录制本地桌面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 ... var buffer;... function handleDataAvailable (e ){ if (e && e.data && e.data .size > 0 ){ buffer.push (e.data ); } } function startRecord ( ){ buffer = []; var options = { mimeType : 'video/webm;codecs=vp8' } if (!MediaRecorder .isTypeSupported (options.mimeType )){ console .error (`${options.mimeType} is not supported!` ); return ; } try { mediaRecorder = new MediaRecorder (localStream, options); }catch (e){ console .error ('Failed to create MediaRecorder:' , e); return ; } mediaRecorder.ondataavailable = handleDataAvailable; mediaRecorder.start (10 ); } ...