"Offer is coming, dig friends to pick up! I am participating in the 2022 Spring Recruitment Check-in Event, click to view the details of the event ."
Premise: The video encoding format uploaded in the company's project is different, but in the browser playback, there is a black screen (with sound), even the video in MP4 format cannot be played, check and find out that chrome The browser's video tag only supports playback of some formats of video
Usually we use the MP4
format, but it is divided into three types MP4
: "1. MPEG4(DivX)
", "2. MPEG4(Xvid)
", "3. ". AVC(H264)
Only H264
videos of the type can be html
played
Video formats and encodings supported by the tag:
MP4
= MPEG 4
file uses H264
video codec and AAC
audio codec
WebM
= WebM
file uses VP8
video codec and Vorbis
audio codec
Ogg
= Ogg
file uses Theora
video codec and Vorbis
audio codec
Format | IE | Firefox | Opera | Chrome | Safari |
---|---|---|---|---|---|
Ogg | No | 3.5+ | 10.5+ | 5.0+ | No |
MPEG4 | 9.0+ | No | No | 5.0+ | 3.0+ |
WebM | No | 4.0+ | 10.6+ | 6.0+ | No |
Note: The video tag is not supported in Internet Explorer 8 and earlier.
Transcoding with FFMPEG
Preview address: 642134542.github.io/vue-ffmpeg/
1. Principle:
ffmpeg.wasm 是 FFmpeg 的纯 WebAssembly
/ JavaScript
端口。它支持在浏览器内录制、转换和流式传输视频和音频。
Webassembly
的出现为前端转码提供可能
2、按照官网配置
2.1 npm安装
npm install @ffmpeg/ffmpeg @ffmpeg/core
复制代码
2.2 html
<div>
<h3>Upload a video to transcode to mp4 (x264) and play!</h3>
<video id="output-video" controls ></video><br/>
<input type="file" id="uploader">
<p id="message"></p>
</div>
复制代码
2.3 js
const { createFFmpeg, fetchFile } = FFmpeg;
const ffmpeg = createFFmpeg({
corePath: 'https://unpkg.com/@ffmpeg/[email protected]/dist/ffmpeg-core.js',
log: true,
});
const transcode = async ({ target: { files } }) => {
const message = document.getElementById('message');
const { name } = files[0];
message.innerHTML = 'Loading ffmpeg-core.js';
await ffmpeg.load();
ffmpeg.FS('writeFile', 'name', await fetchFile(files[0]));
message.innerHTML = 'Start transcoding';
await ffmpeg.run('-i', 'name', 'output.mp4');
message.innerHTML = 'Complete transcoding';
const data = ffmpeg.FS('readFile', 'output.mp4');
const video = document.getElementById('output-video');
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
}
const elm = document.getElementById('uploader');
elm.addEventListener('change', transcode);
复制代码
3、结果
页面可以正常加载和上传,但是在转码过程中报错了
ReferenceError: SharedArrayBuffer is not defined,
所以需要解决SharedArrayBuffer
报错
可以看到SharedArrayBuffer是支持谷歌浏览器79版本以上
那么,为什么这里会出现SharedArrayBuffer is not defined的报错信息呢
经过一番百度和查看issue, 是因为谷歌浏览器的安全策略机制改变了
2017.7月(Chrome 60)引入 SharedArrayBuffer。
2021.7月(Chrome 92)限制 SharedArrayBuffer只能在 cross-origin isolated 页面使用。
Android Chrome 88 也进行了同样的限制。
从上述结论中,可以知道在60-91的版本的浏览器是可以正常打开的
那么92版本的呢
在vue-cli开发环境中我们可以再vue.config.js中配置
devServer: {
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
},
}
复制代码
4、效果
在控制台中可以看到读取文件和转码进程,
而且页面可以正常的显示视频并播放
5、优化:
5.1、corePath
createFFmpeg
中的corePath
的地址是cdn在线的,这里我们需要换成自己的本地资源,
但是使用import一直报错
估计是相关依赖并没有找到,npm install
还是不行
I had to put the package ffmpeg-core.js
and ffmpeg-core.wasm
ffmpeg-core.worker.js in public
5.2, loading
It takes a long time to read the file and transcode, so we need to add a loading layer and a progress bar
ffmpeg.setProgress(({ ratio }) => {
console.log(ratio);
this.percentage = Math.floor(ratio * 100)
/*
* ratio is a float number between 0 to 1.
*/
});
复制代码
6. Deployment:
Using ip or domain name access will still report an error SharedArrayBuffer is not defined
, so we need to configure the request header in the proxy
add_header Cross-Origin-Opener-Policy same-origin;
add_header Cross-Origin-Embedder-Policy require-corp;
复制代码
But still there is an error message
Solution :
1. Use https instead of http
2. Use chrome version 60-91 to access
7. There may be error messages
7.1、caught (in promise) Error: Oops, something went wrong in FS operation
Solution: Do not use Chinese names, the name can be escaped
7.2、Error: ffmpeg.FS('readFile', 'output.mp4') error. Check if the path exists
Solution: same as problem 1
7.3. The github page cannot set the header request header, how does the preview address resolve the SharedArrayBuffer error
In this question on Stack Overflow , there is an answer that provides a solution github.com/gzuidhof/co… Developers only need to import coi-serviceworker.js in index.html
<script src="coi-serviceworker.js"></script>
复制代码