“Offer comes, ask friends to take it! I am participating in the 2022 Spring Recruit Punch card campaign. Click here for more details.”
Premise: The video uploaded in the project of the company has different encoding formats, but when playing in the browser, there is a black screen (with sound). Even the video in MP4 format cannot be played. After checking, it is found that the Video TAB of Chrome browser only supports partial video formats
Usually we use MP4 format, but MP4 is divided into three types: 1.MPEG4(DivX), 2.MPEG4(Xvid), and 3.AVC(H264). Only H264 videos can be played in HTML
Video formats and encodings supported by the tag:
MP4 = MPEG 4 files use H264 video codec and AAC audio codec
WebM = WebM files use VP8 video codecs and Vorbis audio codecs
Ogg = Ogg files use 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: Internet Explorer 8 and earlier versions do not support the video TAB.
Use FFMPEG transcoding
Preview address: 642134542.github. IO /vue-ffmpeg/
1. Principle:
Ffmpeg. wasm is a pure WebAssembly/JavaScript port for FFMPEG. It supports recording, converting, and streaming video and audio within the browser.
The advent of Webassembly makes front-end transcoding possible
2, according to the official website configuration
2.1 NPM install
npm install @ffmpeg/ffmpeg @ffmpeg/core
Copy the code
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>Copy the code
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);
Copy the code
3, the results
The page loads and uploads normally, but an error occurs during transcoding
ReferenceError: SharedArrayBuffer is not defined,
Therefore, the SharedArrayBuffer error needs to be resolved
Compatibility check caniuse.com/?search=Sha…
You can see that SharedArrayBuffer is supported in Google Browser version 79 and above
Why is SharedArrayBuffer not defined
After a hundred degrees and view the issue, because the Security policy mechanism of Google Browser has changed
July 2017 (Chrome 60) SharedArrayBuffer introduced.
Chrome 92 limits SharedArrayBuffer to be used only in Cross-Origin Isolated pages.
Android Chrome 88 has the same restriction.
From the conclusion above, it can be seen that browsers in version 60-91 can be opened normally
What about the 92 version
In vue-CLI development environment we can configure in vue.config.js
devServer: {
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
},
}
Copy the code
4, effects,
You can see the file reading and transcoding process in the console,
And the page can display the video and play normally
5. Optimization:
5.1, corePath
The corePath address in createFFmpeg is CDN online, so we need to replace it with our own local resource.
But using import keeps returning errors
NPM install is still not working
We have to put ffmPEg-core. js, ffmPEg-core. wasm, and ffmPEg-core.worker.js in public
5.2, load,
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.
*/
});
Copy the code
6. Deployment:
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;
Copy the code
But there are still error messages
Solutions:
1. Use HTTPS instead of HTTP
2. Use Chrome 60-91
7. Error messages may exist
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. Github Page cannot set the request header. How to solve the SharedArrayBuffer error
One answer to the Stack Overflow question offers a solution github.com/gzuidhof/co… The developer simply needs to introduce coi-serviceworker.js in index.html
<script src="coi-serviceworker.js"></script>
Copy the code
Reference links:
1, juejin. Cn/post / 701696…