FFmpeg——在Vue项目中使用FFmpeg(安装、配置、使用、SharedArrayBuffer、跨域隔离、避坑...)

个人简介

👀个人主页: 前端杂货铺
🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒Three.js🍖数据结构与算法体系教程

🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

内容参考链接
Canvas 录制视频Canvas 录制视频
录制视频的解决方案使用 Canvas 录制视频尚存问题的解决方案
在 Vue 项目中使用 FFmpeg

文章目录

    • 前言
    • 在 Vue 项目中使用 FFmpeg
      • FFmpeg.wasm 简介
      • 在 Vue 项目中安装并配置 FFmpeg
      • 在 Vue 项目中使用 FFmpeg
        • SharedArrayBuffer 的前世今生
        • 解决 SharedArrayBuffer 报错问题
        • FFmpeg 的一些坑
    • 总结

前言

大家好,这里是前端杂货铺

在 Canvas 录制视频 一文中,我们使用了 MediaRecorder API 在 Canvas 画布中进行了页面的视频录制,并成功输出了 WebM 格式 的视频。

在 使用 Canvas 录制视频尚存问题的解决方案 一文中,我们通过下载 FFmpeg,进行了视频格式的转换及视频帧率的设置。

但在 Vue 项目中怎么使用 FFmpeg 呢?接下来,我们一起进行详细探索!


在 Vue 项目中使用 FFmpeg

在浏览器中我们是无法直接使用 FFmpeg 软件的,但好在有个东西叫 FFmpeg.wasm,它可以让 FFmpeg 的功能在浏览器中使用!当然,我们可以在 Vue 项目中使用 FFmpeg.wasm 来代替手动输入命令行操作的 FFmpeg 软件!!

FFmpeg.wasm 简介

什么是 FFmpeg.wasm?

FFmpeg.wasm 是 FFmpeg 的纯 WebAssembly 接口,可以在浏览器内录制音频和视频,并进行转换和流式传输。

什么是 WebAssembly?

WebAssembly(简称wasm)是一个虚拟指令集体系架构(virtual ISA),整体架构包括核心的ISA定义、二进制编码、程序语义的定义与执行,以及面向不同的嵌入环境(如Web)的应用编程接口(WebAssembly API)。其目标是为 C/C++等语言编写的程序经过编译,在确保安全和接近原生应用的运行速度更好地在 Web 平台上运行。

所以,FFmpeg.wasm 就是 C语言 编写的程序,通过编译后,它可以在 Web 平台(比如浏览器)上运行。

FFmpeg.wasm(Github源码)

在这里插入图片描述


在 Vue 项目中安装并配置 FFmpeg

第一步:想要在 Vue 项目中使用 FFmpeg 第一步当然是要有个 Vue 项目,Vue 项目的搭建就不做介绍了,不清楚的同学可以自行百度查询(资料很多)。在此,博主使用的是 Vue2 的项目(具体版本为 ^2.6.11)【说明:大家并不需要刻意与我的项目版本保持一致】。

第二步:找到 package.json 文件,在指定区域输入下图中蓝框的内容【说明:@ffmpeg/ffmpeg 和 @ffmpeg/ffmpeg 并非最新版本,请按照自己需要安装所需版本】

在这里插入图片描述

第三步:终端键入 npm icnpm i, 回车

在这里插入图片描述

我们可以在 node_modules 文件夹中查看是否真正安装完成

在这里插入图片描述

第四步:复制 ffmpeg-core.jsffmpeg-core.wasmffmpeg-core.worker.js 文件,放入静态资源文件夹中【说明:Vue项目创建完之后默认生成 public 文件夹(用来存放静态资源的),所以我们需要把它们三个复制一份放入 public 文件夹中(若静态资源文件夹名称改了,就放入改到的地方即可)】

在这里插入图片描述

第五步:在需要使用 ffmpeg 的 vue 组件中引入 ffmpeg

import FFmpeg from "@ffmpeg/ffmpeg";
const { createFFmpeg, fetchFile } = FFmpeg;
const ffmpeg = createFFmpeg({
  corePath: "./ffmpeg-core.js", // 核心文件的路径
  log: true, // 是否在控制台打印日志,true => 打印
});

至此,安装和配置 FFmpeg 就告一段落…


在 Vue 项目中使用 FFmpeg

在 Canvas 录制视频 一文中,我们编写了通过 MediaRecorder API 在 Canvas 画布中进行了页面的视频录制的代码,把它稍作改变放入 vue 组件中就得到了下面的代码

简单讲解一下:

  1. draw() 方法用于绘制画布上显示的内容
  2. startRecording() 方法用于开始对画布进行视频录制
  3. stopAndblobDownload() 方法用于结束对画布进行的视频录制,并使用 FFmpeg 对视频流进行处理(转换格式、设置帧率等)
<template>
  <div>
    <canvas id="webm-canvas" height="500" width="500" style="margin: auto"></canvas>
    <button @click="startRecording">开始录制</button>
    <button @click="stopAndblobDownload">停止录制</button>
  </div>
</template>

<script>
import FFmpeg from "@ffmpeg/ffmpeg";
const { createFFmpeg, fetchFile } = FFmpeg;
const ffmpeg = createFFmpeg({
  corePath: "./ffmpeg-core.js", // 核心文件的路径
  log: true, // 是否在控制台打印日志,true => 打印
});

export default {
  name: "HelloWorld",
  data() {
    return {
      recorder: null,
      allChunks: []
    };
  },
  mounted() {
    this.draw();
  },
  methods: {
    draw() {
      let canvas = document.getElementById("webm-canvas");
      let context = canvas.getContext("2d");
      // window.requestAnimationFrame(draw);
      var x = 0;
      var speed = 1;
      var text = "前端杂货铺";
      var fontSize = 20;
      setInterval(() => {
        // 清空画布(否则字体移动后颜色会遗留在画布上)
        context.clearRect(0, 0, canvas.width, canvas.height);
        // 设置字体
        context.font = fontSize + "px Arial"; //设置字体大小和类型
        context.fillStyle = "orange"; //设置文本颜色
        context.fillText(text, x, canvas.height / 2); //绘制文本
        // x要移动
        x += speed;
        // 如果文本达到画布边缘,改变方向
        if (x > canvas.width - 100 || x < 0) {
          speed = -speed;
        }
      }, 10);
    },
    startRecording() {
      let canvas = document.getElementById("webm-canvas");
      // 实时视频捕获画布,参数为帧率
      const stream = canvas.captureStream(60); // 60 FPS
      // 创建一个对指定的 stream 进行录制的 MediaRecorder 对象
      this.recorder = new MediaRecorder(stream, {
        mimeType: "video/webm;codecs=vp9", // 设置媒体类型
      });
      // 当数据有效时触发的事件,数据有效时可以把数据存储到缓存区里
      this.recorder.ondataavailable = (e) => {
        console.log("TCL: e", e);
        this.allChunks.push(e.data);
      };
      this.recorder.start(10);
    },
    async stopAndblobDownload() {
      // 异步加载 ffmpeg
      await ffmpeg.load();
      // 结束录像
      this.recorder.stop();
      // createElement() 方法通过指定名称创建一个元素
      const link = document.createElement("a");
      link.style.display = "none";
      // 创建一个 Blob 对象,用于存储二进制数据
      const fullBlob = new Blob(this.allChunks);
      let name = "demo";
      // 写文件,fullBlob 存放录制视频流的 blob 数据
      ffmpeg.FS("writeFile", name, await fetchFile(fullBlob));
      // 执行 ffmpeg ('-r', '10' 表示设置视频帧率为 10fps)('output.avi' 表示生成视频的格式为 .avi)
      await ffmpeg.run('-i', name, '-r', '10', 'output.avi');
      // 读取刚刚执行的文件,存放到 data 中
      const data = ffmpeg.FS('readFile', 'output.avi');
      // 把 data 的 buffer 数据传入 blob 实例中,创建一个包含所需数据的 URL
      const downloadUrl = window.URL.createObjectURL(new Blob([data.buffer], {type:'video/avi'}));
      // 获取或设置链接的 URL 属性
      link.href = downloadUrl;
      // 点击链接时,浏览器下载文件
      link.download = `前端杂货铺${Math.random().toFixed(4)}.avi`;
      // 向节点的子节点列表的末尾添加新的子节点
      document.body.appendChild(link);
      // 模拟用户点击链接的操作
      link.click();
      // 删除 HTML 文档中的链接元素
      link.remove();
    },
  },
};
</script>
<style>
canvas {
  box-shadow: 0 0 10px gray;
  display: block;
}

body {
  text-align: center;
}

button {
  margin-top: 20px;
}
</style>

此时,运行我们的项目,点击开始录制后,再点击结束录制

在这里插入图片描述

SharedArrayBuffer 的前世今生

此时,控制台就会暴露出一个问题:SharedArrayBuffer is not defined

在这里插入图片描述

不要慌,我们先来了解一下 SharedArrayBuffer 是什么?

MDN 上是这样解释的:SharedArrayBuffer 对象用来表示一个通用的原始二进制数据缓冲区,类似于 ArrayBuffer 对象,但它可以用来在共享内存上创建视图。与可转移的 ArrayBuffer 不同,SharedArrayBuffer 不是可转移对象。

官方的说明有点抽象。其实 SharedArrayBuffer 就是一种 JavaScript 对象,它允许多个 Web Worker 线程共享相同的内存空间。这就意味着不同的线程可以同时访问和修改相同的数据,而无需复制数据或担心数据同步的问题。它允许以更有效的方式进行多线程编程,从而提高性能。

那么此时为什么会报 SharedArrayBuffer is not defined 的错误呢?

这就要溯源到 2018 年了,其实在 2018 之前,在支持 SharedArrayBuffer 的各大主流浏览器中都是可以正常使用它的。直到 2018 年暴露出了 幽灵漏洞(Spectre漏洞)*,它导致了浏览器性能的严重倒退,各大主流浏览器厂商便都禁用了 SharedArrayBuffer!!

直到 2021 年才正式放开了对 SharedArrayBuffer 的使用。

SharedArrayBuffer 在各大主流浏览器中的支持情况:

在这里插入图片描述

既然都放开了对 SharedArrayBuffer 的使用,那么为什么还会报错呢?

虽然各大主流浏览器都已经陆续开始支持 SharedArrayBuffer ,但它也不是那么随便就能使用的,而是需要我们进行一些配置,开启了跨域隔离 才能正常使用。

在控制台中输入 crossOriginIsolated 回车,为 false,则说明并没有开启跨域隔离

在这里插入图片描述

解决 SharedArrayBuffer 报错问题

在我们的项目中创建并打开 vue.config.js 文件,如果你的项目使用了 webpack 打包工具,那么就打开你的 webpack.config.js 文件,进行如下配置,配置完成之后记得重启一下项目,让我们刚刚的配置生效

在这里插入图片描述

module.exports = {
    devServer: {
        headers: {
            "Cross-Origin-Opener-Policy": "same-origin", // 保护你的源站点免受攻击
            "Cross-Origin-Embedder-Policy": "require-corp", // 保护受害者免受你的源站点的影响
        },
    },
}

我们看一下是否开启了跨域隔离,为 true,确实已开启

在这里插入图片描述

此时,再点击开始录制后点击结束录制,控制台便不会报错了,并且还会生成我们所需要的视频文件,很完美

在这里插入图片描述


FFmpeg 的一些坑

我们解决了 SharedArrayBuffer 问题后,在 ffmpeg 执行的时候也可能遇到执行失败的问题。

比如说,在 webm 转 mp4 格式时当你的分辨率设置成奇数(比如:499x499)时,就可能导致 ffmpeg 转码失败(错误:width not divisible by 2 (499x499)),所以我们尽量控制把分辨率为偶数。

建议大家在开发过程中把 log: true 打开,方便调试开发!!


总结

本文,我们首先讲解了 FFmpeg 在 Vue 项目中的安装与配置,之后在 Vue 项目中编码简单使用了一下 FFmpeg,然后在运行项目时报了错让我们认识到了 SharedArrayBuffer 并成功找到了解决方案,最后我们了解到了 FFmpeg 在使用时的一些坑,明确了要注意查看 log 日志内容…

FFmpeg 无疑是一款非常强大的多媒体处理工具,在 Vue 项目中利用 “纯前端” 就能实现视频的录制和视频编码转码后的输出,这看起来确实是一件非常 cool 的事!

其实坚持学习,热爱生活得你更 cool

好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!


参考资料:

  1. 百度百科 · FFmpeg、幽灵漏洞
  2. MDN官方文档 · SharedArrayBuffer
  3. 由一个报错引发的浏览器跨域隔离探索【作者:网络安全小肖_知乎】
  4. Canvas录制视频【作者:前端杂货铺_CSDN】
  5. FFmpeg——使用Canvas录制视频尚存问题的解决方案 【作者:前端杂货铺_CSDN】

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/252575.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kali Linux安装Xrdp远程桌面工具结合内网穿透实现远程访问Kali桌面

文章目录 前言1. Kali 安装Xrdp2. 本地远程Kali桌面3. Kali 安装Cpolar 内网穿透4. 配置公网远程地址5. 公网远程Kali桌面连接6. 固定连接公网地址7. 固定地址连接测试 前言 Kali远程桌面的好处在于&#xff0c;它允许用户从远程位置访问Kali系统&#xff0c;而无需直接物理访…

韩顺平学java第二阶段之BS框架002

这边讲了php都可以&#xff0c;反正就是打通双方的间隔就行了∑(っД;)っ卧槽&#xff0c;不见了

sap table 获取 valuation class MBEW 查表获取

参考 https://www.tcodesearch.com/sap-tables/search?qvaluationclass

尚硅谷Docker笔记-基础篇

B站视频&#xff1a;https://www.bilibili.com/video/BV1gr4y1U7CY 1.Docker简介 解决了运行环境和配置问题的软件容器 方便做持续集成并有助于整体发布的容器虚拟化技术 容器与虚拟机比较 Docker 容器是在操作系统层面上实现虚拟化&#xff0c;直接复用本地主机的操作系统…

12、ble_mesh_vendor_model 服务端,自定义模型

1、初始化流程&#xff0c;存储初始化&#xff0c;nvs擦除&#xff0c; board_init();初始化LED。 2、bluetooth_init();ble协议栈初始化 3、ble_mesh_get_dev_uuid(dev_uuid);//获取设备uuid加载到mac&#xff0c;后两位dev uuid 4、ble_mesh_init();//ble mesh协议栈初始化。…

使用Jemeter对HTTP接口压测

我们不应该仅仅局限于某一种工具&#xff0c;性能测试能使用的工具非常多&#xff0c;选择适合的就是最好的。笔者已经使用Loadrunner进行多年的项目性能测试实战经验&#xff0c;也算略有小成&#xff0c;任何性能测试&#xff08;如压力测试、负载测试、疲劳强度测试等&#…

关键点检测之修改labelme标注的json中类别名

import json import os import shutil#source_dir表示数据扩增之后的文件夹路径&#xff0c;此时标注的是多分类的标签 #new_dir表示转化之后得到的二分类文件夹def to2class():#json存放路径source_dir r1#json保存路径new_dir r1for i in os.listdir(source_dir):if i.ends…

十七、如何将MapReduce程序提交到YARN运行

1、启动某个节点的某一个用户 hadoopnode1:~$ jps 13025 Jps hadoopnode1:~$ yarn --daemon start resourcemanager hadoopnode1:~$ jps 13170 ResourceManager 13253 Jps hadoopnode1:~$ yarn --daemon start nodemanager hadoopnode1:~$ jps 13170 ResourceManager 15062 Jp…

D3D12可编程渲染流水线

一、初始化D3D库 启用 DirectX数学库 x86需要启用SSE2指令集&#xff0c;所有平台均需将浮点模型设置为fast。默认为&#xff1a; 精度 (/fp:precise)。 #include <DirectXMath.h> #include <DirectXPackedVector.h> 启用调试模式下的内存泄漏检测 // Enabl…

vue实现公式编辑器组件

实现方式一 1、效果图 2、实现代码 组件弹框实现 样式自己调整 公式的数字与汉字元素、符号 建立元素表 动态获取 完整代码&#xff08;calculate.vue&#xff09; <template><div id"formulaPage"><divref"formulaView"class"f…

pyqt5实现振动波形数据标注工具

pyqt5实现振动波形数据标注工具 1、效果图 2、实现功能 1、数据库连接 2、数据筛选 3、波形图展示、频谱图展示 4、特征展示&#xff1a;时域、频域 5、数据标注与添加 6、模型训练与分类识别3、部分核心代码 3.1、连接数据库 # -*- coding: utf-8 -*-""" c…

技术探秘:在RISC Zero中验证FHE——由隐藏到证明:FHE验证的ZK路径(1)

1. 引言 开源代码实现见&#xff1a; https://github.com/hashcloak/fhe_risc0_zkvm&#xff08;Rust&#xff09;https://github.com/weikengchen/vfhe-profiled&#xff08;Rust&#xff09;https://github.com/l2iterative/vfhe0&#xff08;Rust&#xff09; L2IV Resea…

后端开发——统一处理异常Spring MVC机制

一、Spring MVC的统一处理异常机制 在Spring MVC中&#xff0c;存在统一处理异常的机制&#xff0c; 具体表现为&#xff1a;无论是哪个处理请求的过程中出现异常&#xff0c;每种类型的异常只需要编写一段处理异常的代码即可&#xff01; 统一处理异常的核心是定义处理异常的…

【INTEL(ALTERA)】Agilex7 FPGA Development Kit DK-DEV-AGI027R1BES编程/烧录/烧写/下载步骤

DK-DEV-AGI027R1BES 的编程步骤&#xff1a; 将外部 USB Blaster II 连接到 J10- 外部 JTAG 接头。将交换机 SW5.3 设置为 ON&#xff08;首次&#xff09;。打开 英特尔 Quartus Prime Pro Edition 软件编程工具。单击 硬件设置 &#xff0c;然后选择 USB Blaster II。将硬件…

LeetCode - 460 LFU缓存(Java JS Python)

题目来源 460. LFU 缓存 - 力扣&#xff08;LeetCode&#xff09; 题目描述 请你为 最不经常使用&#xff08;LFU&#xff09;缓存算法设计并实现数据结构。 实现 LFUCache 类&#xff1a; LFUCache(int capacity) - 用数据结构的容量 capacity 初始化对象int get(int key)…

RocketMQ系统性学习-SpringCloud Alibaba集成RocketMQ以及消息追踪、延时消息实战

文章目录 消息追踪延时消息实战 消息追踪 设置消息追踪需要修改 broker 启动的配置文件&#xff0c;添加一行配置&#xff1a;traceTopicEnabletrue 即可&#xff0c;操作如下&#xff1a; # 进入到 rocketmq 的安装目录中 # 先复制一份配置文件 cp broker.conf custom.conf …

高并发音频转口型服务器开发

课程名称&#xff1a;高并发口型服务器开发 高并发口型服务器 哈喽&#xff0c;大家好&#xff0c;我叫人宅&#xff0c;很高兴和大家一起分享本套课程&#xff0c;高并发口型服务器开发。 虚拟人的口型一直是我们避免不了问题&#xff0c;即使我们不做虚拟人实时口型&#x…

WorkPlus搭建高效即时通讯,打造高效协作新标杆

在现代企业中&#xff0c;即时通讯已成为团队沟通和协作的重要组成部分。作为一款创新的即时通讯工具&#xff0c;WorkPlus致力于提供高效、便捷的沟通和协作体验&#xff0c;打造全新的企业沟通标杆。 WorkPlus的出色之处在于其高效的即时通讯能力。无论是团队内部交流还是跨团…

H266/VVC标准的编码结构介绍

概述 CVS&#xff1a; H266的编码码流包含一个或多个编码视频序列&#xff08;Coded Video Swquence&#xff0c;CVS&#xff09;&#xff0c;每个CVS以帧内随机接入点&#xff08;Intra Random Access Point&#xff0c; IRAP&#xff09;或逐渐解码刷新&#xff08;Gradual …

MySQL 教程 2.2

MySQL WHERE 子句 我们知道从 MySQL 表中使用 SELECT 语句来读取数据。 如需有条件地从表中选取数据&#xff0c;可将 WHERE 子句添加到 SELECT 语句中。 WHERE 子句用于在 MySQL 中过滤查询结果&#xff0c;只返回满足特定条件的行。 语法 以下是 SQL SELECT 语句使用 WH…