首页 » 前端 » Vue.js » 正文

让 vue2 的 video.js 支持 avi

发布者:站点默认
2018/12/21 浏览数(997) 分类:Vue.js 让 vue2 的 video.js 支持 avi已关闭评论

nginx

location /videos/player {
  add_header Cross-Origin-Opener-Policy "same-origin";
  add_header Cross-Origin-Embedder-Policy "require-corp";
}

vue.config.js

devServer: {
  proxy: {},
  // 可能会影响图片的加载
  headers: {
    "Cross-Origin-Opener-Policy": "same-origin",
    "Cross-Origin-Embedder-Policy": "require-corp",
  },
}

package.json

"dependencies": {
  "@ffmpeg/core": "~0.10.0",
  "@ffmpeg/ffmpeg": "~0.10.1",
}

从 node_modules/@ffmpeg 的 dist 目录中找到以下文件放入 public/js/

ffmpeg-core.js
ffmpeg-core.wasm
ffmpeg-core.worker.js

AviPlayer.vue (节选)

import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg";
export default {
  data() {
    return {
      src: null,
      loading: false, // false 或 xx%
    };
  },
  computed: {
    ext() {
      let self = this;
      let ext = null;
      if (self.src) {
        ext = self.src
          .replace(/.*(?=\.w+)/, "") // http://a/b/c/d.e?f=g -> .e?f=g
          .replace(/\?.*/, ""); // .e?f=g -> .e
        ext = ext && ext.toLowerCase();
      }
      return ext;
    },
  },
  methods: {
    async convertAvi2mp4(aviSrc) {
      let self = this;
      let src = aviSrc;
      try {
        const ffmpeg = createFFmpeg({
          log: true,
          corePath: "/js/ffmpeg-core.js", // 不写这行时会从 CDN 中加载
        });
        ffmpeg.setProgress(({ ratio }) => {
          let progress = Math.floor(ratio * 100);
          progress = progress < 100 ? `${progress}%` : "准备中";
          self.loading = progress;
        });
        await ffmpeg.load();
        // ffmpeg.FS("writeFile", `videoFile${self.ext}`, await fetchFile(src)); // 无 fetch 进度
        ffmpeg.FS("writeFile", `videoFile${self.ext}`, await self.getFile(src)); // 有 fetch 进度
        await ffmpeg.run("-i", `videoFile${self.ext}`, "videoFile.mp4");
        const data = ffmpeg.FS("readFile", "videoFile.mp4");
        src = URL.createObjectURL(new Blob([data.buffer], { type: "video/mp4" }));
      } catch (e) {
        console.log("avi2mp4.fail", e);
      }
    },
    // 带进度版的 fetchFile
    async getFile(src) {
      let data = src;
      if (src instanceof File || src instanceof Blob) {
        data = await readFromBlobOrFile(src);
      } else {
        const res = await fetch(src)
          .then((response) => {
            const contentLength = response.headers.get('Content-Length');
            const contentType = response.headers.get('Content-Type');
            const total = contentLength ? parseInt(contentLength, 10) : NaN;
            const reader = response.body.getReader();
            let received = 0; let blobParts = [];
            return new Promise((resolve, reject) => {
              const process = () => {
                reader.read()
                  .then(({ value, done }) => {
                    if (done) {
                      const blob = new Blob(blobParts, { type: contentType }); resolve(blob);
                    } else {
                      blobParts.push(value);
                      received += value.length;
                      let progress = Math.floor((received / total) * 100); 
                      progress = progress < 100 ? `已下载${progress}%` : '准备读取';
                      console.log('下载进度', `${progress}, ${received}/${total}`);
                      process();
                    }
                  }, reject);
              };
              process();
            });
          })
          .catch((e) => new Promise((resolve, reject) => reject(e)));
        data = await res.arrayBuffer();
      }
      const blob = new Uint8Array(data);
      return blob;
    },
  },
};
点击返回顶部
  1. 留言
  2. 联系方式