ffmpeg realizes web online transcoding and playback

"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 MP4format, but it is divided into three types MP4: "1. MPEG4(DivX)", "2. MPEG4(Xvid)", "3. ". AVC(H264)Only H264videos of the type can be htmlplayed

Video formats and encodings supported by the tag:

MP4= MPEG 4file uses H264video codec and AACaudio codec

WebM= WebMfile uses VP8video codec and Vorbisaudio codec

Ogg= Oggfile uses Theoravideo codec and Vorbisaudio 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.wasmFFmpeg 的纯 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报错

兼容性查看caniuse.com/?search=Sha…

image.png

可以看到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.jsand ffmpeg-core.wasmffmpeg-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>
复制代码

Reference link:

1、juejin.cn/post/701696…

Guess you like

Origin juejin.im/post/7078898276203757581