随着短视频的越来越流行,有时候需要把动态的 canvas 转换为视频然后发布到对应的平台上。当然最简单的办法就是利用录屏软件(如:QuickTime)直接将屏幕录制下来,然后通过一些视频编辑软件(如:imovie)加工处理下。
作为一名很懒的程序员,当然是希望能够自动转换为视频,一气呵成,不需要手工来处理。你还别说,现在的浏览器还真提供了对应的 API 来处理这个事情,本文就来简单介绍下。
通过 canvas 的 captureStream API,就可以把 canvas 变成一个 stream,然后结合 MediaRecorder API 就可以转换为 video。
const stream = canvas.captureStream();
const recorder = new MediaRecorder(stream, { mimeType: 'video/webm' });
const data = [];
recorder.ondataavailable = function (event) {
if (event.data && event.data.size) {
data.push(event.data);
}
};
recorder.onstop = () => {
const url = URL.createObjectURL(new Blob(data, { type: 'video/webm' }));
console.log('video url', url)
};
通过开始的时候调用 recorder.start() 和结束的时候调用 recorder.stop() 即可完成视频的录制工作。
注意:如果一个 canvas 操作完成后面不在变动的话,录制的时候会发现最终的视频并没有想要的长度。这是因为如果 canvas 不动的话后续就不再录制了。
解决办法也很简单,找到 canvas 中的一个元素,然后循环改变这个元素的透明度就可以(为了减少对视觉的影响,可以让透明度在 0.99 和 1 之间变化,这个目的就是让 canvas 一直在操作。当然用其他的方案也是可以)
通过 MediaRecorder 来录制视频时,需要指定录制视频的编码格式,如:video/webm,vide/mp4。 如果当前浏览器不支持的话则会报错。
可以先通过 MediaRecorder.isTypeSupported 方法检测浏览器是否支持,如:
MediaRecorder.isTypeSupported('video/webm');
MediaRecorder.isTypeSupported('video/mp4');
从目前的测试来看,video/webm 格式 chrome v81/firefox v76 都支持。但 video/mp4 目前都还不支持。
由于 webm 格式现在还没有那么流行,有些网站还不支持直接支持上传这个格式的视频,那么就需要把 webm 转换为 mp4 格式的视频。
通过测试发现,虽然 chrome v81 还不能直接支持 video/mp4 的格式,但已经支持了 video/webm;codecs=h264,也就是录制的视频是用 h264 格式来编码的。这样后续转码的时候视频部分可以直接拷贝,大大提升转码的速度。
通过这个方式录制的视频没有音频部分,而一般发布的视频都希望有音频作为 BGM。此时就可以通过 WebAssembly 版本的 ffmpeg 来完成了。
转换命令如下:
ffmpeg -i video.webm output.mp4; //转换格式
ffmpeg -i video.webm -i audio.mp3 -c:v copy -af apad -map 0:v -map 1:a -shortest out.mp4; // 添加音频
具体的可以通过 ffmpeg.wasm 库来完成,大致代码如下:
private async convertVideoUrl(url: string): Promise<string> {
const { audio, outVideoType, mimeType, workerOptions, transcodeOptions, concatDemuxerOptions } = this.config;
const { createFFmpeg } = window.FFmpeg;
const ffmpeg = createFFmpeg(workerOptions || {});
await ffmpeg.load();
const type = mimeType.split(';')[0].split('/')[1];
await ffmpeg.write(`video.${type}`, url);
if (audio) {
const audioType = audio.split('.').pop();
await ffmpeg.write(`1.${audioType}`, audio);
await ffmpeg.run(`-i video.${type} -i 1.${audioType} ${concatDemuxerOptions} out.${outVideoType}`);
} else {
if (type !== outVideoType) {
await ffmpeg.transcode(`video.${type} `, `out.${outVideoType}`, transcodeOptions);
}
}
const data = await ffmpeg.read(`out.${outVideoType}`);
const blob = new Blob([data.buffer], { type: `video/${outVideoType}` })
const mp4Url = URL.createObjectURL(blob);
return mp4Url;
}
为了方面使用,已经将录制视频和转换视频等操作封装成了一个库 canvas2video 。代码不多,功能也比较聚焦,可以直接使用。
]]>2019年完成跑步300KM,2020年定的目标是365KM。因为疫情耽误了几个月,不过还是要尽力完成。
12.17 - 10公里 - 家12.15 - 5公里 - 家12.12 - 5公里 - 家11.25 - 5公里 - 家11.21 - 5公里 - 家11.15 - 5公里 - 家10.30 - 5公里 - 家10.25 - 5公里 - 朝阳公园10.24 - 5公里 - 家10.19 - 7公里 - 家10.17 - 3公里 - 朝阳公园9.26 - 10公里 - 朝阳公园9.19 - 10公里 - 朝阳公园9.17 - 5公里 - 7989.15 - 10公里 - 7989.12 - 10公里 - 朝阳公园9.5 - 10公里 - 朝阳公园8.30 - 10公里 - 朝阳公园7.19 - 10公里 - 朝阳公园7.12 - 10公里 - 朝阳公园7.5 - 10公里 - 朝阳公园6.26 - 10公里 - 朝阳公园6.21 - 5公里 - 朝阳公园6.20 - 5公里 - 朝阳公园6.14 - 5公里 - 朝阳公园6.10 - 5公里 - 360健身房6.5 - 5公里 - 360健身房6.3 - 5公里 - 360健身房5.26 - 5公里 - 360健身房5.23 - 10公里 - 朝阳公园5.21 - 5公里 - 360健身房5.19 - 7公里 - 360健身房5.15 - 5公里 - 360健身房5.13 - 5公里 - 360健身房5.10 - 5公里 - 朝阳公园5.3 - 3公里 - 朱屋4.25 - 5公里 - 朝阳公园1.21 - 5公里 - 360健身房1.16 - 5公里 - 360健身房1.12 - 5公里 - 360健身房1.1 - 5公里 - 360健身房这是程序自动发布的文章。如果您看到这篇文章,表示您的 Blog 已经安装成功!
如果您对 Firekylin 不是很熟悉,可以先阅读以下常用操作了解一下。
Firekylin 的后台登录入口在 ~/admin
后台的 系统设置 提供了与网站相关的选项,例如可在其中的 基本设置 中设置网站名称、Logo地址等。
更多的设置,请参考 官方 WIKI 的 系统设置
Firekylin 没有内置评论模块。但是,Firekylin 可方便地使用第三方评论系统。在后台的 系统设置 的 评论设置 的 自定义 模式下粘贴第三方评论系统的代码即可。
Firekylin 还对 Disqus 、畅言 、网易云跟帖 提供了特别的支持,只需要填写对应的网站id即可,不需要粘贴具体的代码。
后台的 外观设置 可进行 菜单管理,包括新增菜单、删除菜单、菜单排序等。
新增菜单时,如填写了菜单属性(例如属性为 home),Firekylin 自带的主题会从图标库尝试寻找 icon-home 作为该菜单的图标,如未查到匹配的则不会显示图标。
Firekylin 目前只带了一套主题,所以基于 Firekylin 架构的网站长得都差不多^_^
主题外观的使用、修改、创建可参考官网 WIKI 的 主题外观。
欢迎越来越多的热心用户为 Firekylin 开发主题外观,开发手册详见 主题开发。
Firekylin 的编辑器为支持 Markdown 语法的编辑器。Markdown 是一种简化的标记语言,普通的纯文本内容(例如 Windows 的记事本撰写的内容)经过 Markdown 标记之后,可被渲染成赏心悦目的富格式文本。
好了,介绍就这么多,快开始你的 Blog 之旅吧!
]]>