7-1 【基础铺垫,学前有概念】WebRTC录制基本知识
7-2 【来点实战】录制音视频实战
录制完后开始播放。
录制完后也可以单击下载。
<html>
<meta charset="utf-8">
<head>
<title>WebRTC 获取视频和音频</title>
<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>
</head>
<body>
<section>
<div>
<label>audio input device:</label>
<select id="audioSource"></select>
</div>
<div>
<label>audio output device:</label>
<select id="audioOutput"></select>
</div>
<div>
<label>video input device:</label>
<select id="videoSource"></select>
</div>
</section>
<section>
<div>
<label>Filter:</label>
<select id="filter">
<option value="none">None</option>
<option value="blur">blur</option>
<option value="grayscale">Grayscale</option>
<option value="invert">Invert</option>
<option value="sepia">sepia</option>
</select>
</div>
</section>
<section>
<table>
<!-- <audio autoplay controls id="audioplayer"></audio> -->
<tr>
<td><video autoplay playsinline id="player"></video> </td>
<td><video playsinline id="recplayer"></video></td>
<td><div id='constraints' class='output'></div></td>
</tr>
<tr>
<td><button id="record">Start Record</button></td>
<td><button id="recplay" disabled>Play</button></td>
<td><button id="download" disabled>Download</button></td>
</tr>
</table>
</section>
<section>
<div>
<button id="snapshot">Take snapshot</button>
</div>
<div>
<canvas id="picture"></canvas>
</div>
</section>
<script src="http://webrtc.github.io/adapter/adapter-latest.js"></script>
<script src="./js/client.js"></script>
</body>
</html>
'use strict'
//devices
var audioSource = document.querySelector('select#audioSource');
var audioOutput = document.querySelector('select#audioOutput');
var videoSource = document.querySelector('select#videoSource');
//filter
var filtersSelect = document.querySelector('select#filter');
//picture
var snapshot = document.querySelector('button#snapshot');
var picture = document.querySelector('canvas#picture');
picture.width = 640;
picture.height = 480;
//videoplay
var videoplay = document.querySelector('video#player');
//var audioplay = document.querySelector('audio#audioplayer');
//div
var divConstraints = document.querySelector('div#constraints');
//record
var recvideo = document.querySelector('video#recplayer');
var btnRecord = document.querySelector('button#record');
var btnPlay = document.querySelector('button#recplay');
var btnDownload = document.querySelector('button#download');
var buffer;
var mediaRecorder;
function gotDevices(deviceInfos){
deviceInfos.forEach(function(deviceinfo){
var option = document.createElement('option');
option.text = deviceinfo.label;
option.value = deviceinfo.deviceId;
if(deviceinfo.kind === 'audioinput'){
audioSource.appendChild(option);
}else if(deviceinfo.kind === 'audiooutput'){
audioOutput.appendChild(option);
}else if(deviceinfo.kind === 'videoinput'){
videoSource.appendChild(option);
}
})
}
function gotMediaStream(stream){
var videoTrack = stream.getVideoTracks()[0];
var videoConstraints = videoTrack.getSettings();
divConstraints.textContent = JSON.stringify(videoConstraints, null, 2);
window.stream = stream;
videoplay.srcObject = stream;
//audioplay.srcObject = stream;
return navigator.mediaDevices.enumerateDevices();
}
function handleError(err){
console.log('getUserMedia error:', err);
}
//匹配视频设备切换
function start() {
if(!navigator.mediaDevices ||
!navigator.mediaDevices.getUserMedia){
console.log('getUserMedia is not supported!');
}else{
var deviceId = videoSource.value;
var constraints = {
video : {
width: 640,
height: 480,
frameRate: 15,
facingMode: 'environment' ,
deviceId : deviceId ? {exact:deviceId} : undefined
},
audio : false
//{
//noiseSuppression: true,
//echoCancellation: true
//}
}
navigator.mediaDevices.getUserMedia(constraints)
.then(gotMediaStream)
.then(gotDevices)
.catch(handleError);
}
}
start();
videoSource.onchange = start;
filtersSelect.onchange = function(){
videoplay.className = filtersSelect.value;
}
snapshot.onclick = function() {
picture.className = filtersSelect.value; //如果先前使用了滤镜,则在截图后,也会使用滤镜
picture.getContext('2d').drawImage(videoplay, 0, 0, picture.width, picture.height);
}
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);
}
function stopRecord(){
mediaRecorder.stop();
}
btnRecord.onclick = ()=>{
if(btnRecord.textContent === 'Start Record'){
startRecord();
btnRecord.textContent = 'Stop Record';
btnPlay.disabled = true;
btnDownload.disabled = true;
}else{
stopRecord();
btnRecord.textContent = 'Start Record';
btnPlay.disabled = false;
btnDownload.disabled = false;
}
}
btnPlay.onclick = ()=> {
var blob = new Blob(buffer, {type: 'video/webm'});
recvideo.src = window.URL.createObjectURL(blob);
recvideo.srcObject = null;
recvideo.controls = true; //控制标签
recvideo.play();
}
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();
}
7-3 【来点实战】WebRTC采集屏幕数据
打开谷歌浏览器,输入 chrome://flags 查看支持的选项
打开下面链接,启动某个功能。
chrome://flags/#enable-experimental-web-platform-features
代码实现,主要将上一节的
getUserMedia修改为getDisplayMedia。代码实现
<html>
<meta charset="utf-8">
<head>
<title>WebRTC 获取视频和音频</title>
<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>
</head>
<body>
<section>
<div>
<label>audio input device:</label>
<select id="audioSource"></select>
</div>
<div>
<label>audio output device:</label>
<select id="audioOutput"></select>
</div>
<div>
<label>video input device:</label>
<select id="videoSource"></select>
</div>
</section>
<section>
<div>
<label>Filter:</label>
<select id="filter">
<option value="none">None</option>
<option value="blur">blur</option>
<option value="grayscale">Grayscale</option>
<option value="invert">Invert</option>
<option value="sepia">sepia</option>
</select>
</div>
</section>
<section>
<table>
<!-- <audio autoplay controls id="audioplayer"></audio> -->
<tr>
<td><video autoplay playsinline id="player"></video> </td>
<td><video playsinline id="recplayer"></video></td>
<td><div id='constraints' class='output'></div></td>
</tr>
<tr>
<td><button id="record">Start Record</button></td>
<td><button id="recplay" disabled>Play</button></td>
<td><button id="download" disabled>Download</button></td>
</tr>
</table>
</section>
<section>
<div>
<button id="snapshot">Take snapshot</button>
</div>
<div>
<canvas id="picture"></canvas>
</div>
</section>
<script src="http://webrtc.github.io/adapter/adapter-latest.js"></script>
<script src="./js/client.js"></script>
</body>
</html>
'use strict'
//devices
var audioSource = document.querySelector('select#audioSource');
var audioOutput = document.querySelector('select#audioOutput');
var videoSource = document.querySelector('select#videoSource');
//filter
var filtersSelect = document.querySelector('select#filter');
//picture
var snapshot = document.querySelector('button#snapshot');
var picture = document.querySelector('canvas#picture');
picture.width = 640;
picture.height = 480;
//videoplay
var videoplay = document.querySelector('video#player');
//var audioplay = document.querySelector('audio#audioplayer');
//div
var divConstraints = document.querySelector('div#constraints');
//record
var recvideo = document.querySelector('video#recplayer');
var btnRecord = document.querySelector('button#record');
var btnPlay = document.querySelector('button#recplay');
var btnDownload = document.querySelector('button#download');
var buffer;
var mediaRecorder;
function gotDevices(deviceInfos){
deviceInfos.forEach(function(deviceinfo){
var option = document.createElement('option');
option.text = deviceinfo.label;
option.value = deviceinfo.deviceId;
if(deviceinfo.kind === 'audioinput'){
audioSource.appendChild(option);
}else if(deviceinfo.kind === 'audiooutput'){
audioOutput.appendChild(option);
}else if(deviceinfo.kind === 'videoinput'){
videoSource.appendChild(option);
}
})
}
function gotMediaStream(stream){
var videoTrack = stream.getVideoTracks()[0];
var videoConstraints = videoTrack.getSettings();
divConstraints.textContent = JSON.stringify(videoConstraints, null, 2);
window.stream = stream;
videoplay.srcObject = stream;
//audioplay.srcObject = stream;
return navigator.mediaDevices.enumerateDevices();
}
function handleError(err){
console.log('getDisplayMedia error:', err);
}
//匹配视频设备切换
function start() {
if(!navigator.mediaDevices ||
!navigator.mediaDevices.getDisplayMedia){
console.log('getDisplayMedia is not supported!');
}else{
var deviceId = videoSource.value;
var constraints = {
// video : {
// width: 640,
// height: 480,
// frameRate: 15,
// facingMode: 'environment' ,
// deviceId : deviceId ? {exact:deviceId} : undefined
// },
video :true,
audio : false
//{
//noiseSuppression: true,
//echoCancellation: true
//}
}
navigator.mediaDevices.getDisplayMedia(constraints)
.then(gotMediaStream)
.then(gotDevices)
.catch(handleError);
}
}
start();
videoSource.onchange = start;
filtersSelect.onchange = function(){
videoplay.className = filtersSelect.value;
}
snapshot.onclick = function() {
picture.className = filtersSelect.value; //如果先前使用了滤镜,则在截图后,也会使用滤镜
picture.getContext('2d').drawImage(videoplay, 0, 0, picture.width, picture.height);
}
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);
}
function stopRecord(){
mediaRecorder.stop();
}
btnRecord.onclick = ()=>{
if(btnRecord.textContent === 'Start Record'){
startRecord();
btnRecord.textContent = 'Stop Record';
btnPlay.disabled = true;
btnDownload.disabled = true;
}else{
stopRecord();
btnRecord.textContent = 'Start Record';
btnPlay.disabled = false;
btnDownload.disabled = false;
}
}
btnPlay.onclick = ()=> {
var blob = new Blob(buffer, {type: 'video/webm'});
recvideo.src = window.URL.createObjectURL(blob);
recvideo.srcObject = null;
recvideo.controls = true; //控制标签
recvideo.play();
}
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();
}