最近写项目的时候有一个关于视频录制需求,js视频录制通常使用MediaRecorder来实现,使用起来也非常的简单,MediaRecorder的MDN文档。
但是录制视频之后出现了一个问题是录制的视频是不能操作进度条的。去网上搜索发现是因为MediaRecorder录制的视频文件缺少视频总时长等信息导致的,有很多种解决方案,我试了其中的三种,效果最好的是ebmljs。
1,使用:fix-webm-duration;
地址:fix-webm-duration,README上有安装和使用的教程。
使用这个方法后录制的视频在浏览器或者其他播放器上打开是可以操作进度条的,但是在window系统自带的播放器上仍然不能操作进度条。
2,使用:ebmljs
关于ebmljs,我并没有找到他的github仓库是什么,网上有很多的js文件,但是很多是有问题的。我使用的是文章中的这个文件,目前使用下来没有遇到什么问题。
创建一个ebml.util.js文件,用来放置处理视频blob数据的工具函数getSeekableBlob:
// ebml.util.js
/**
* @param {Blob} file - File or Blob object.
* @param {function} callback - Callback function.
* @example
* getSeekableBlob(blob or file, callback);
* @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code}
*/
export function getSeekableBlob(inputBlob, callback) {
const reader = new window.EBML.Reader()
const decoder = new window.EBML.Decoder()
const tool = window.EBML.tools
const fileReader = new FileReader()
fileReader.onload = function (e) {
const ebmlElms = decoder.decode(this.result)
ebmlElms.forEach(function (element) {
reader.read(element)
})
reader.stop()
const refinedMetadataBuf = tool.makeMetadataSeekable(
reader.metadatas,
reader.duration,
reader.cues
)
const body = this.result.slice(reader.metadataSize)
const newBlob = new Blob([refinedMetadataBuf, body], {
type: 'video/webm'
})
callback(newBlob)
}
fileReader.readAsArrayBuffer(inputBlob)
}
关于EBML.js的引入方式:
将EBML.js文件放到项目的public目录的js目录下,并在项目的index.html中引入:

最开始我在vue项目中是在ebml.util.js文件中通过import的方式导入EBML.js中的方法的,但是出现了报错:
import导入:
// ebml.util.js
import {Reader,Decoder,tools} from './EBML'
报错:
Router error: SyntaxError: The requested module '/src/utils/video/EBML.js' does not provide an export named 'Decoder'
//请求的模块"/src/utils/video/EBML.js"没有提供名为"Decoder"的导出。
(at ebml.util.js:2:16)
原因是:在EBML.js中的开头有一段很长的判断,作用是通过检测不同的javaScript环境,然后将内部的方法使用不同的方式对外暴露,供外部使用。而在vue中是属于浏览器环境,于是EBML.js中的方法被挂载到了window对象上。下面一段是验证的方法(蓝色字体)。
引入方式:
// ebml.util.js
import './EBML';//在ebml.util.js直接导入EBML.js文件
在ebml.util.js中的getSeekableBlob函数中打印window,调用getSeekableBlob后,浏览器控制台显示:
可以看到EBML.js中的方法被挂载到了window对象的EBML属性上。
然后在需要使用的地方导入getSeekableBlob并使用:
// 引入ebml.util.js用来处理blob给webm视频添加进度条
import { getSeekableBlob } from "./video/ebml.util.js";
//参数blob是webm视频的blob数据
getSeekableBlob(blob, function(fixedBlob) {
//fixedBlob就是处理好之后的视频blob,你可以用它来做后续的操作
});
使用ebmljs处理好之后的webm视频就可以在window系统自带的播放器以及浏览器上操作进度条了。
3.转换视频格式为MP4
看网上还有使用 ffmpeg.wasm将webm转为MP4格式的方式来修复进度条,在一些在线转换视频格式的网站将webm视频转换成MP4后确实有进度条了,但是在项目中使用 ffmpeg.wasm将webm视频转为MP4后却没有什么作用,可能在线网站使用的是其他的方式转换视频格式的。(关于使用ffmpeg.wasm转换好像还有问题,记得使用 ffmpeg.wasm还要把MediaRecorder中的mimeType设置为mp4否则转换不了好像,写这一块过去挺久了,不确定是不是有这个问题,如果有使用 ffmpeg.wasm将MediaRecorder录制的视频转为mp4格式,遇到转换不了的情况可以试一下这个)
转换视频的在线网站:免费在线将 WEBM 转换为 MP4。
ffmpeg.wasm:ffmpeg.wasm
vue项目使用 ffmpeg.wasm的实例:ffmpeg.wasm/apps/vue-vite-app at main · ffmpegwasm/ffmpeg.wasm · GitHub