个人简介
👀个人主页: 前端杂货铺
🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒Three.js🍖数据结构与算法体系教程🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧
文章目录
- 前言
- MediaRecorder
- Canvas
- 录制视频
- 尚存问题
前言
大家好,这里是前端杂货铺。
今天我们要探讨一个新问题,如何在 Canvas 画布上录制视频并输出?
Canvas录屏
直入主题,基本技术路线:MediaRecorder录制媒体流 - Canvas绘制动画 - 导出录像视频
以上方式录制的视频还存在一些问题,我们在下文将逐步分析和解决…
MediaRecorder
MediaRecorder 是 MediaStream Recording API 提供的用来进行 媒体轻松录制的接口,他需要通过调用 MediaRecorder() 构造方法进行实例化
MediaStream 接口是一个 媒体内容的流。一个流包含几个轨道,比如视频和音频轨道
简单地说,MediaStream 是一个用于表示音频或视频流的接口,而 MediaRecorder 则是对指定的 MediaStream 进行录制的类。它们都是WebRTC(Web实时通信)的一部分,通常一起使用来实现音视频通话或录制功能
MediaRecorder() 构造函数会创建一对指定的 MediaStream 进行录制的 MediaRecorder 对象
var mediaRecorder = new MediaRecorder(stream[, options]);
参数说明:
stream: MediaStream 将要录制的流。它可以是来自于使用 navigator.mediaDevices.getUserMedia() 创建的流或者来自于 <audio>
, <video>
以及 <canvas>
DOM 元素
备注:navigator.mediaDevices.getUserMedia() 用于获取用户的媒体设备,如音频和视频的输入设备
options:一个字典对象,它可以包含下列属性:
- mimeType: 为新构建的 MediaRecorder 指定录制容器的 MIME 类型。在应用中通过调用
MediaRecorder.isTypeSupported()
来检查浏览器是否支持此种 mimeType - audioBitsPerSecond: 指定音频的比特率
- videoBitsPerSecond: 指定视频的比特率
- bitsPerSecond: 指定音频和视频的比特率。此属性可以用来指定上面两个属性。如果上面两个属性只有其中之一和此属性被指定,则此属性可以用于设定另外一个属性。
备注: 如果视频/音频的比特率没有指定,视频默认采用的比特率是 2.5Mbps,但音频的默认比特率并不固定,音频的默认比特率根据采样率和轨道数自适应。
相关知识:
- mimeType:控制文件类型,可以使用
MediaRecorder.isTypeSupported('video/webm')
和MediaRecorder.isTypeSupported('video/mp4')
查看浏览器支持的视频格式(目前谷歌支持 webm 而不支持 mp4) - 比特率:单位时间内传输或处理的比特数量(bit),它反映了数据传输的速度,比特率越高,传输速度越快
更多详细内容请参照官方文档:MediaRecorder官方文档 | MediaStream官方文档
Canvas
Canvas 是 HTML5 的新元素,它用于 图形的绘制,绘制图形需要通过脚本(通常是JavaScript)来完成。
下面我们来创建一个画布,并在画布上绘制文字:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#webm-canvas {
width: 200px;
height: 100px;
border: 1px solid #d3d3d3;
}
</style>
</head>
<body>
<canvas id="webm-canvas"></canvas>
</body>
<script>
let canvas = document.getElementById("webm-canvas");
// 创建context对象,该对象是内建的HTML5对象,拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法
let context = canvas.getContext("2d");
// 定义字体
context.font="30px Arial";
// 设置颜色
context.fillStyle = "orange";
// 在 canvas 上绘制实心的文本
context.fillText("前端杂货铺", 10, 50);
</script>
</html>
更多详细内容请参照其他文档:HTML5-Canvas
录制视频
下面我们就使用 MediaRecorder 和 Canvas 及 DOM 操作,实现基本的 Canvas 视频录制
- 运行代码后先点击开始录制,数秒过后点击下载录像,即可在浏览器下载录像
- 在浏览器中打开录像,即可观看(可拖动进度条,可播放可暂停)
Canvas录制视频
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
canvas {
box-shadow: 0 0 10px gray;
display: block;
}
body {
text-align: center;
}
button {
margin-top: 20px;
}
</style>
</head>
<body>
<canvas id="webm-canvas" height=500 width=500 style="margin:auto;"></canvas>
<button onclick="startRecording()">开始录制</button>
<button onclick="stopAndblobDownload()">下载录像</button>
<script>
let canvas = document.getElementById("webm-canvas");
let context = canvas.getContext('2d');
window.requestAnimationFrame(draw);
var x = 0;
var speed = 1;
var text = "前端杂货铺";
var fontSize = 20;
function draw() {
// 清空画布(否则字体移动后颜色会遗留在画布上)
context.clearRect(0, 0, canvas.width, canvas.height);
// 设置字体
context.font = fontSize + "px Arial"; //设置字体大小和类型
context.fillStyle = "orange"; //设置文本颜色
context.fillText(text, x, canvas.height / 2); //绘制文本
// x要移动
x += speed;
// 如果文本达到画布边缘,改变方向
if (x > canvas.width - 100 || x < 0) {
speed = -speed;
}
window.requestAnimationFrame(draw);
}
let allChunks = [];
// 实时视频捕获画布,参数为帧率
const stream = canvas.captureStream(60); // 60 FPS
// 创建一个对指定的 stream 进行录制的 MediaRecorder 对象
const recorder = new MediaRecorder(stream, {
mimeType: 'video/webm;codecs=vp9' // 设置媒体类型
});
// 当数据有效时触发的事件,数据有效时可以把数据存储到缓存区里
recorder.ondataavailable = e => {
console.log("TCL: e", e)
allChunks.push(
e.data
);
}
// 结束并下载到浏览器默认位置
function stopAndblobDownload() {
// 结束录像
recorder.stop();
// createElement() 方法通过指定名称创建一个元素
const link = document.createElement('a');
link.style.display = 'none';
// 创建一个 Blob 对象,用于存储二进制数据
const fullBlob = new Blob(allChunks);
// 创建一个包含 Blob 数据的 URL
const downloadUrl = window.URL.createObjectURL(fullBlob);
// 获取或设置链接的 URL 属性
link.href = downloadUrl;
// 点击链接时,浏览器下载文件
link.download = `前端杂货铺${Math.random().toFixed(4)}.webm`;
// 向节点的子节点列表的末尾添加新的子节点
document.body.appendChild(link);
// 模拟用户点击链接的操作
link.click();
// 删除 HTML 文档中的链接元素
link.remove();
}
// 开始录像
function startRecording() {
recorder.start(10);
}
</script>
</body>
</html>
尚存问题
使用上面的方式对 Canvas录制视频 还存在一定的问题
1、录制的视频背景图片为黑色,没有保持画布本身的颜色
2、通过非浏览器打开视频,无法拖动进度条
3、MediaRecorder 原生支持 webm,不支持 avi、mp4、flv等格式
可以通过 link.download = "xxx.mp4"
, 但视频属性信息会丢失,也可能出现视频无法打开的问题
4、视频属性信息有丢失,无时长、数据速率和总比特率均为 0kbps,无帧速率
如果强行修改文件扩展名为 .mp4
,则属性信息均无
以上问题还需进一步调研,请期待接下来解决方案的文章,如果屏幕前的小伙伴知道解决方案还请不吝赐教
好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!
参考资料:
- 百度 · 文心一言
- HTML5-Canvas
- MediaRecorder官方文档
- MediaStream官方文档
- 分享一个canvas录屏的方案【作者:KaiKai】