ffmpeg.wasm处理视频

这篇具有很好参考价值的文章主要介绍了ffmpeg.wasm处理视频。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.ffmpeg.wasm

github.com/ffmpegwasm/…

ffmpeg & wasm 是什么

ffmpeg是功能非常强大的视频处理开源软件,很多视频播放器就是使用它来做为内核。

webassembly 是 Binary Code, 是编译目标。WebAssembly将很多编程语言带到了Web中。

wasm解决了性能问题,将各种耗性能的app从Desktop搬到Web上。

想用ffmpeg纯web端实现处理视频。就要用到wasm提高操作性能,就是ffmpeg.wasm做的事情。

2.前端实现

不使用node, 纯前端项目,实现在browser上处理视频。

ffmpeg.wasm,ffmpeg,wasm,音视频

上图是git的文档, 只需要在本地引入ffmpeg.min.js (文件很小22KB)就可以了。

2.1 获取ffmpeg.min.js文件。

install 后,会看到文件ffmpeg/dist/ffmpeg.min.js。

ffmpeg.wasm,ffmpeg,wasm,音视频

然后,直接将ffmpeg.min.js文件放到public下,打包后,直接在根目录。

ffmpeg.wasm,ffmpeg,wasm,音视频

ffmpeg.wasm,ffmpeg,wasm,音视频

2.2 index页面引入

这里引入后,使用时就很方便,直接获取 const { createFFmpeg, fetchFile } = FFmpeg;

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
    <script src="/ffmpeg.min.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.jsx"></script>
  </body>
</html>
复制代码

注意: 纯前端不需要install @ffmpeg/ffmpeg @ffmpeg/core。上面install,就为了方便拿ffmpeg.min.js

按照上面2步,到这里都比较简单,按理可以直接使用了。但是会遇到比较麻烦的跨域隔离问题。当给网站设置好跨域隔离后,又会发现网站上其他资源获取不了。哎,所以在使用前,要先处理一下跨域隔离。

先会发现报错信息,SharedArrayBuffer is not defined。因为shareArrayBuffer 要求跨域隔离same-origin。

3.跨域隔离(本地&部署)

git上有一句提醒:SharedArrayBuffer is only available to pages that are cross-origin isolated.So you need to host your own server with Cross-Origin-Embedder-Policy: require-corp and Cross-Origin-Opener-Policy: same-origin headers to use ffmpeg.wasm.

因为用了sharedArrayBuffer共享内存。然后shareArrayBuffer要求host设置跨域隔离same-origin。

3.1本地处理

这里demo用了vite+react,直接在vite.config.js中设置。其他框架类似设置就可以。

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
​
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  server: {
  headers: {
      "Cross-Origin-Opener-Policy": "same-origin",
      "Cross-Origin-Embedder-Policy": "require-corp",
    },
  },
})
复制代码

3.2部署处理

响应用户的HTTP请求时,增加HTTP header, coop + coep 这两个响应头。

Response Headers

cross-origin-embedder-policy: require-corp

cross-origin-opener-policy: same-origin

到这里,可以正常使用ffmpeg.wasm了。但是会发现网站上其他的图片视频等资源获取不到了。 会看到新的报错信息。接下来处理一下网站上的其他资源获取问题。

ffmpeg.wasm,ffmpeg,wasm,音视频

Because your site has the Cross-Origin Embedder Policy (COEP) enabled, each resource must specify a suitable Cross-Origin Resource Policy (CORP). This behavior prevents a document from loading cross-origin resources which don’t explicitly grant permission to be loaded.

3.3跨域隔离后,加载其他资源(图片视频等)

因为host加了两个响应头启用了跨域隔离。那这个host上的其他资源,所有跨域资源都需要明确被允许加载。比如图片和视频。

明确被允许加载,有两种实现方式,一种是CORP,另一种是 CORS。

CORS

<img crossOrigin="anonymous" alt="图片" src={value} /> 
<video crossOrigin="anonymous" controls width={200} src={URL.createObjectURL(video)} />
复制代码

CORP

对应的图片或者视频域名配置加header。Cross-Origin-Resource- Policy:cross-origin

4.各种视频操作

完成上面引入和跨域隔离两步,就可以愉快地各种操作使用ffmpeg了。

4.1视频剪切

ffmpeg.wasm,ffmpeg,wasm,音视频

如图可以看到 fetchFile 接受的入参格式,下面代码尝试了传file,和直接用图片地址都可以。

import { useState } from "react";
import { InputNumber, Button, Card } from "antd";
// import { createFFmpeg, fetchFile } from "@ffmpeg/ffmpeg";
// const ffmpeg = createFFmpeg({
//   corePath: CONFIG.IS_TEST
//     ? "http://localhost:3000/ffmpeg-core.js"
//     : "ffmpeg-core.js",
//   log: true,
// });
​
// eslint-disable-next-line no-undef
const { createFFmpeg, fetchFile } = FFmpeg;
const ffmpeg = createFFmpeg({
  log: true,
});
​
const fakeUrl =
  "https://*****.mp4";
​
function VideoSlice() {
  const [video, setVideo] = useState();
  const [start, setStart] = useState(0);
  const [length, setLength] = useState(0);
  const [partVideo, setPartVideo] = useState();
​
  const sliceVideo = async (source) => {
    if (!ffmpeg.isLoaded()) {
      await ffmpeg.load();
    }
​
    ffmpeg.FS("writeFile", "vid.mp4", await fetchFile(source));
    await ffmpeg.run(
      "-i",
      "vid.mp4",
      "-s",
      "480x320",
      "-r",
      "3",
      "-t",
      String(length),
      "-ss",
      String(start),
      "-f",
      "mp4",
      "out.mp4"
    );
​
    const data = ffmpeg.FS("readFile", "out.mp4");
    const url = URL.createObjectURL(
      new Blob([data.buffer], { type: "video/mp4" })
    );
    setPartVideo(url);
  };
​
  return (
    <Card title="视频切片">
      {video && <video controls width={250} src={URL.createObjectURL(video)} />}
      <input
        type="file"
        onChange={(e) => {
          setVideo(e.target.files?.item(0));
        }}
      />
      <div>Url: {fakeUrl}</div>
      <div>
        <span>开始时间: </span>
        <InputNumber
          onChange={(value) => {
            setStart(value);
          }}
        />
        <span>结束时间: </span>
        <InputNumber
          onChange={(value) => {
            setLength(value - start);
          }}
        />
        <Button
          type="primary"
          style={{ marginLeft: 30 }}
          onClick={() => {
            sliceVideo(video);
          }}
        >
          截取
        </Button>
        <Button
          type="primary"
          style={{ marginLeft: 30 }}
          onClick={() => {
            sliceVideo(fakeUrl);
          }}
        >
          Url截取
        </Button>
      </div>
      {partVideo && <video controls src={partVideo} width={250} />}
    </Card>
  );
}
​
export default VideoSlice;
​
复制代码

4.2视频合并

import { useState } from "react";
import { Button, Card } from "antd";
​
const { createFFmpeg, fetchFile } = FFmpeg;
const ffmpeg = createFFmpeg({
  log: true,
});
​
function VideoSlice() {
  const [videoList, setVideoList] = useState([]);
  const [mergerVideo, setMergerVideo] = useState();
​
  const handleMergerVideo = async (source) => {
    if (!ffmpeg.isLoaded()) {
      await ffmpeg.load();
    }
​
    ffmpeg.FS("writeFile", "vid1.mp4", await fetchFile(videoList[0]));
    ffmpeg.FS("writeFile", "vid2.mp4", await fetchFile(videoList[1]));
​
​
    // concat协议 适合视频MPEG格式,其他格式文件,先转码再合并
    await ffmpeg.run("-i", "vid1.mp4", "-c", "copy", "-bsf:v", "h264_mp4toannexb", "-f", "mpegts", "vid1.ts");
    await ffmpeg.run("-i", "vid2.mp4", "-c", "copy", "-bsf:v", "h264_mp4toannexb", "-f", "mpegts", "vid2.ts");
    await ffmpeg.run("-i", "concat:vid1.ts|vid2.ts", "-c", "copy", "-bsf:a", "aac_adtstoasc", "-movflags", "+faststart", "out.mp4" );
​
    const data = ffmpeg.FS("readFile", "out.mp4");
    const url = URL.createObjectURL(
      new Blob([data.buffer], { type: "video/mp4" })
    );
    setMergerVideo(url);
  };
​
  return (
    <Card title="视频合并">
      {videoList[0] && <video controls width={250} src={URL.createObjectURL(videoList[0])} />}
      {videoList[1] && <video controls width={250} src={URL.createObjectURL(videoList[1])} />}
      <input
        type="file"
        onChange={(e) => {
          const newList = [...videoList, e.target.files?.item(0)];
          setVideoList(newList);
        }}
      />
      <div>
        <Button
          type="primary"
          style={{ marginLeft: 30 }}
          onClick={() => {
            handleMergerVideo(videoList);
          }}
        >
          合并
        </Button>
      </div>
      {mergerVideo && <video controls src={mergerVideo} width={250} />}
    </Card>
  );
}
​
export default VideoSlice;
​
复制代码

4.3图片转视频

import { useState } from "react";
import { Card, Button } from "antd";
​
const { createFFmpeg, fetchFile } = FFmpeg;
const ffmpeg = createFFmpeg({
  log: true,
});
​
export default function ImgToVideo () {
    const [imgs, setImgs] = useState([]);
    const [videoUrl, setVideoUrl] = useState();
​
    const imgToVideo = async () => {
        if (!ffmpeg.isLoaded()) {
            await ffmpeg.load();
          }
          console.log(imgs[0]);
        for (let i in imgs) {
            ffmpeg.FS('writeFile', `${i}.png`, await fetchFile(imgs[i]))
        }
        await ffmpeg.run('-r', "1", '-f', 'image2', '-i', '%d.png', 'video.mp4')
        const data = ffmpeg.FS('readFile', 'video.mp4')
        const url = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }))
        setVideoUrl(url);
    }
​
    return (
        <Card title="图片转视频">
          {
            imgs.length > 0 && imgs.map((item, index) => <p key={index}>{item.name}</p>)
          }
          <input
            type="file"
            onChange={(e) => {
            const list = [...imgs, e.target.files?.item(0)];
            setImgs(list);
            }}
          />
          <Button onClick={imgToVideo}>转视频</Button>
          {videoUrl && <video controls src={videoUrl} width={250} />}
        </Card>
    )
};
复制代码

5.注意点

实际项目实现该功能,考虑到用户机器性能情况比较差,不采用这种纯web端的方式。

下载的话,ffmpeg-core.wasm 是8.5M,就还好。

ffmpeg.wasm,ffmpeg,wasm,音视频

但是运行时,用Core i7, 内存8G电脑测试剪切一个3秒的视频。浏览器的任务管理器可以看到cpu占比就挺高的。

原文链接:ffmpeg.wasm处理视频 - 掘金

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓文章来源地址https://www.toymoban.com/news/detail-649176.html

到了这里,关于ffmpeg.wasm处理视频的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 音视频处理 ffmpeg中级开发 H264编码

    libavcodec/avcodec.h 常用的数据结构 AVCodec 编码器结构体 AVCodecContext 编码器上下文 AVFrame 解码后的帧 结构体内存的分配和释放 av_frame_alloc 申请 av_frame_free() 释放 avcodec_alloc_context3() 创建编码器上下文 avcodec_free_context() 释放编码器上下文 解码步骤 avcodec_find_decoder 查找解码器 avcod

    2024年02月01日
    浏览(87)
  • 强大开源的音视频处理工具ffmpeg安装与使用

    FFmpeg 是一个开源的跨平台音视频处理工具,提供了丰富的命令行模式下音视频处理功能,包括格式转换、编解码、过滤器应用等。 由于 FFmpeg 支持的格式广泛,且可用于多个平台和操作系统(如 Windows、Linux、MacOS 等),因此它已成为许多多媒体应用程序和服务的核心组件。

    2024年02月05日
    浏览(74)
  • 开源的跨平台的音视频处理工具FFmpeg

    FFmpeg是一个开源的跨平台的音视频处理工具,可以对音频、视频进行转码、裁剪、调节音量、添加水印等操作。 广泛的格式支持。 FFmpeg能够解码、编码、转码、复用、分离、流式传输、过滤和播放几乎人类和机器所创造的任何内容。它支持最古老且晦涩难懂的格式,也支持

    2024年02月15日
    浏览(68)
  • 音视频处理工具FFmpeg与Java结合的简单使用

    一、什么是FFmpeg FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcod

    2024年02月11日
    浏览(66)
  • FFmpeg——开源的开源的跨平台音视频处理框架简介

    引言:         FFmpeg是一个开源的跨平台音视频处理框架,可以处理多种音视频格式。它由Fabrice Bellard于2000年创建,最初是一个只包括解码器的项目。后来,很多开发者参与其中,为FFmpeg增加了多种新的功能,例如编码器、过滤器、muxer、demuxer等等,使它成为了一个完整

    2024年03月23日
    浏览(71)
  • 【音视频处理】基础框架介绍,FFmpeg、GStreamer、OpenCV、OpenGL

    大家好,欢迎来到停止重构的频道。  本期我们介绍 音视频处理的基础框架 。 包括FFmpeg、GStreamer、OpenCV、OpenGL 。 我们按这样的分类介绍 : 1、编解码处理:FFmpeg、GStreamer 2、图像分析:OpenCV 3、复杂图像生成:OpenGL 首先是编解码处理的基础框架,这类基础框架的 应用场景

    2024年02月08日
    浏览(50)
  • 阿里云国际站代理商:FFmpeg 处理音视频文件的常用方法

    阿里云代理商( 聚搜云 )专业服务于阿里云ECS服务器采购、阿里云Ddos采购、阿里云waf采购、对象存储OSS、阿里云企业邮箱采购、阿里云国际站代理商、阿里云国际站充值、云安全中心(态势感知)、阿里云高可用云数据库RDS、web应用云waf防火墙、阿里云vpc企业网、阿里云

    2024年02月02日
    浏览(77)
  • Qt/C++音视频开发50-不同ffmpeg版本之间的差异处理

    ffmpeg的版本众多,从2010年开始计算的项目的话,基本上还在使用的有ffmpeg2/3/4/5/6,最近几年版本彪的比较厉害,直接4/5/6,大版本之间接口有一些变化,特别是一些废弃接口被彻底删除了,而网络上的各种文章几乎都是ffmpeg3左右为主的,所以本人在写这个全功能播放组件的时

    2024年02月14日
    浏览(56)
  • Java如何整合FFmpeg、FFprobe等音视频处理工具,零基础照样玩

    最后奉上工具的学习资料(感兴趣的可以看看),废话不多说!!!!! FFmpeg是啥 :​ ffmpeg(命令行工具) 是一个快速的音视频转换工具。 FFmpeg能干啥 :如果你用过爱剪辑的话或者其他一些音视频处理软件的话,你可以理解他们能做的你用玩意都能做。 为啥要用FFmpeg :开源

    2024年02月02日
    浏览(77)
  • 【音视频处理】转编码H264 to H265,FFmpeg,代码分享讲解

    大家好,欢迎来到停止重构的频道。 本期我们讨论音视频文件 转编码 ,如将视频H264转H265等。 内容中所提及的 代码都会放在GitHub ,感兴趣的小伙伴可以到GitHub下载。 我们按这样的顺序展开讨论:​ 1、  编码的作用  2、  转编码的工作原理 3、  编解码器安装  4、  示

    2024年02月11日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包