WebRTC(三)用屏幕分享录制一段视频

前一章节了解了屏幕分享的API,感觉跟我们常用的“屏幕共享”好像。

那么可不可以用此进行一个屏幕录制呢?

“纸上得来终觉浅,觉知此事要躬行。”看着挺简单的一个东西,没有落实都算说大话。

首先画上三个按钮:

<button @click="start" :disabled="disabled.start">开始录制button>
<button @click="stop" :disabled="disabled.stop">结束录制button>
<button @click="download" :disabled="disabled.download">下载文件button>

添加上简单的样式:

button {
     
	margin: 0 1em 1em 0;
  	padding: 0.5em 1.2em 0.6em 1.2em;
  	border: none;
  	border-radius: 4px;
  	background-color: #d84a38;
  	font-family: 'Roboto', sans-serif;
  	font-size: 0.8em;
  	color: white;
  	cursor: pointer;
}
button:hover {
     
  	background-color: #c03434;
}
button[disabled] {
     
  	background-color: #c03434;
  	pointer-events: none;
}

初始化数据:

data() {
     
	return {
     
		// 本地流
      	stream: null,
      	// 媒体录制
      	mediaRecorder: null,
      	// 数据块
      	chunks: [],
      	// 录制结果
      	recording: null,
      	// 按钮禁用
      	disabled: {
     
        	start: false,
        	stop: true,
        	download: true
      	}
  	}
},

需要的方法:

methods: {
     
	// 获取屏幕分享的权限
    openScreenCapture() {
     
		...
	},
	 // 开始屏幕分享录制
    async start() {
     
		....
	},
	// 停止屏幕分享录制
    stop() {
     
		...
	},
	// 下载录制的视频内容
    download() {
     
		...
	}
}

ok~ 下面进入每个方法内部看看都需要些什么操作。

首先我们要获取屏幕分享的权限,

由于每个浏览器的实现不同,所以这里需要做个兼容处理。

// 获取屏幕分享的权限
openScreenCapture() {
     
	if (navigator.getDisplayMedia) {
     
      	return navigator.getDisplayMedia({
      video: true });
  	} else if (navigator.mediaDevices.getDisplayMedia) {
     
        return navigator.mediaDevices.getDisplayMedia({
      video: true });
  	} else {
     
        return navigator.mediaDevices.getUserMedia({
     
          	video: {
      mediaSource: 'screen' },
        });
  	}
},

当点击“开始录制”按钮后,依次设置三个按钮的禁用状态,

如果之前录制的内容没有清空,那么就用revokeObjectURL方法移除。

获取屏幕分享权限后,实例化一个MediaRecorder对象进行录制存储。

监听dataavailable,当有可用数据时,将其push进数据块中进行存储。

// 开始屏幕分享录制
async start() {
     
  	this.disabled.start = true;
  	this.disabled.stop = false;
   	this.disabled.download = true;

   	if (this.recording) {
     
      	window.URL.revokeObjectURL(this.recording);
  	}

	// 获取屏幕分享权限
  	this.stream = await this.$options.methods.openScreenCapture();
	// 实例化一个MediaRecorder对象
   	this.mediaRecorder = new MediaRecorder(this.stream, {
     mimeType: 'video/webm'});
   	// 监听可用数据
   	this.mediaRecorder.addEventListener('dataavailable', event => {
     
      	if (event.data && event.data.size > 0) {
     
          	this.chunks.push(event.data);
        }
  	});
  	// 开始录制
   	this.mediaRecorder.start(10);
},

当点击“停止录制”按钮后,需要将数据块保存到一个内存URL中方便后续下载使用。

// 停止屏幕分享录制
stop() {
     
  	this.disabled.start = true;
   	this.disabled.stop = true;
   	this.disabled.download = false;

	// 停止录制
  	this.mediaRecorder.stop();
  	// 释放MediaRecorder
  	this.mediaRecorder = null;
  	// 停止所有流式视频轨道
  	this.stream.getTracks().forEach(track => track.stop());
  	// 释放getDisplayMedia或getUserMedia
  	this.stream = null;

	// 获取当前文件的一个内存URL
  	this.recording = window.URL.createObjectURL(new Blob(this.chunks, {
     type: 'video/webm'}));
},

当点击“下载文件”按钮时,更新下载元素的链接href,并自动触发点击事件进行弹窗提示下载。

// 下载录制的视频内容
download() {
     
  	this.disabled.start = false;
   	this.disabled.stop = true;
   	this.disabled.download = true;
      
  	const downloadLink = document.querySelector('a#download');
  	downloadLink.href = this.recording;
  	// download 规定作为文件名来使用的文本
   	downloadLink.download = 'screen-recording.webm';
   	downloadLink.click();
}

当进行完以上操作后,发现确实将屏幕分享的导出一段视频了。

但是…

这个视频是没有声音的,音量按钮处为一个“静音”标识,且不能调节音量大小。
WebRTC(三)用屏幕分享录制一段视频_第1张图片
getDisplayMedia 默认只支持视频轨道,不支持音频轨道,

反正我试了几个浏览器均不支持音频轨道,没能验证有的博客写的如下开启音频轨道:

navigator.mediaDevices.getDisplayMedia({
     
	video: true,
	audio: true
})

不过,在经过上一章节的学习,我们知道MediaStream是由多个MediaStreamTrack组成的,

那么应该就可以给当前getDisplayMedia获取的视频轨道,再加上一个音频轨道,组成一个MediaStream。

其他部分不用更改,只用在MediaRecorder录制这个MediaStream之前,将其进行改造即可。

...
// 获取麦克风权限
const audioTrack = await navigator.mediaDevices.getUserMedia({
      audio: true });
// 获取屏幕分享权限
this.stream = await this.$options.methods.openScreenCapture();
// 给MediaStream添加音频轨道
this.stream.addTrack(audioTrack.getAudioTracks()[0]);

// 实例化一个MediaRecorder对象
this.mediaRecorder = new MediaRecorder(this.stream, {
     mimeType: 'video/webm'});
...

此刻,就变成一个有声音的真正的屏幕分享了 ~
WebRTC(三)用屏幕分享录制一段视频_第2张图片

你可能感兴趣的:(前端音视频)