打造流畅的音视频录制功能 (包含视频旋转支持) - 前端开发实践
最编程
2024-02-05 21:55:55
...
前言
需求要求对通话视频进行录制,调研了一下,发现了一个简单好用的Web API
,它可以在浏览器中捕获媒体流的数据,比如音频和视频,并将其保存为文件,下面用个例子简单介绍一下用法。
举例
首先创建一个 <video>
元素以及开始录制与结束录制按钮
<video id="videoElement" width="640" height="480"></video>
<button id="startRecording">开始录制</button>
<button id="stopRecording" disabled>停止录制</button>
将视频流绑定到<video>
元素上面:
// 获取video、button元素
const videoElement = document.getElementById('videoElement');
const startRecordingButton = document.getElementById('startRecording');
const stopRecordingButton = document.getElementById('stopRecording');
// 获取用户媒体流
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {
videoElement.srcObject = stream;
videoElement.play();
})
.catch(error => {
console.error('Error accessing the camera:', error);
});
当视频开始播放时为开始录制按钮和停止录制按钮分别添加了点击事件处理程序 startRecording
和 stopRecording
:
videoElement.onplaying = () => {
startRecordingButton.addEventListener('click', startRecording);
stopRecordingButton.addEventListener('click', stopRecording);
};
定义开始录制与结束录制事件,录制视频并下载到本地:
let mediaRecorder;
const recordedChunks = [];
function startRecording() {
mediaRecorder = new MediaRecorder(videoElement.captureStream());
mediaRecorder.ondataavailable = event => {
if (event.data.size > 0) {
recordedChunks.push(event.data);
}
};
mediaRecorder.onstop = () => {
const recordedBlob = new Blob(recordedChunks, { type: 'video/webm' });
const videoUrl = URL.createObjectURL(recordedBlob);
const a = document.createElement('a');
document.body.appendChild(a);
a.style = 'display: none';
a.href = videoUrl;
a.download = 'test.webm';
a.click();
window.URL.revokeObjectURL(videoUrl);
};
// 开始录制
mediaRecorder.start();
startRecordingButton.disabled = true;
stopRecordingButton.disabled = false;
}
function stopRecording() {
mediaRecorder.stop();
startRecordingButton.disabled = false;
stopRecordingButton.disabled = true;
}
彩蛋
如果后端返回的视频流为横向,录制下载的时候想要旋转方向可以使用canvas
实现,如果只是本地播放的话可以使用css transform
动画实现,下面介绍一下录制旋转视频的实现,对上面的代码做一下小的修改:
首先添加canvas
元素:
<canvas id="canvas" width="640" height="480"></canvas>
// 将原来的video元素设置为不可见,不然会有两个视频
<video id="videoElement" width="640" height="480" style='display: "none"'></video>
// 获取canvas元素
const canvas = document.getElementById('canvas');
点击开始录制的时候,在startRecording
方法中每隔一段时间就将视频流捕获到 Canvas
上并应用变换:
// 顺时针旋转 90 度
const ctx = canvas.getContext('2d');
setInterval(() => {
ctx.setTransform(1, 0, 0, 1, 0, 0); // 重置变换矩阵
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(canvas.width, 0);
ctx.rotate(90 * Math.PI / 180);
ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
}, 100);
// 逆时针旋转 90 度
const ctx = canvas.getContext('2d');
setInterval(() => {
ctx.setTransform(1, 0, 0, 1, 0, 0); // 重置变换矩阵
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(0, canvas.height); // 修改平移方向
ctx.rotate(-90 * Math.PI / 180);
ctx.drawImage(videoElement, 0, 0, canvas.height, canvas.width);
}, 100);
最后不要忘记录制的视频捕获的应该是canvas
上的视频流:
mediaRecorder = new MediaRecorder(canvas.captureStream());
完结,撒花。