Js使用ffmpeg进行视频剪辑和画面截取

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

ffmpeg

使用场景是需要在web端进行视频的裁剪,包括使用 在线视频url本地视频文件 的裁剪,以及对视频内容的截取等功能。

前端进行视频操作可能会导致性能下降,最好通过后端使用java,c++进行处理,本文的案例是备选方案。


注意:

以下所有的使用案例均基于vue3 setup。

同时由于@ffmpeg版本不同会导致使用的api不同,使用案例前需要注意@ffmpeg版本问题

如果使用的是0.12+需要使用新的api,详情请看 文档文章来源地址https://www.toymoban.com/news/detail-731080.html


npm

npm install @ffmpeg/ffmpeg@^0.10.0

npm install @ffmpeg/core@^0.10.0

在线视频url剪辑

<script setup>
// "@ffmpeg/core": "^0.10.0",
// "@ffmpeg/ffmpeg": "^0.10.0",

import { ref, onMounted, onUnmounted } from 'vue'
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';

const ffmpeg = createFFmpeg({ log: true });
const fileType = ref("") // 视频文件类型

/**
 * 根据在线的视频地址截取片段
 * @param {string} url 在线视频链接
 * @param {number|string} startTime 截取开始时间
 * @param {number|string} endTime 截取结束时间
 * @param {Function} callBack 回调函数
 */
const videoCut = async (url, startTime, endTime, callBack) => {
    if (!ffmpeg.isLoaded()) {
        await ffmpeg.load();
    }
    if(!url) return;

    fileType.value = url.split(".").pop()

    const inputName = `input.${fileType.value}`;
    const outputName = `output.${fileType.value}`;

    // 将输入文件保存到虚拟文件系统
    await ffmpeg.FS('writeFile', inputName, await fetchFile(url));

    // 运行 FFmpeg 命令
    try {
        await ffmpeg.run(
            '-ss', `${startTime}`,
            '-t', `${endTime - startTime}`,
            '-i', inputName,
            '-vcodec', 'copy',
            '-acodec', 'copy',
            outputName
        );

        // 读取输出文件
        let arrayBuffer = ffmpeg.FS('readFile', outputName).buffer; // 读取缓存

        // 创建下载链接并通过回调下载保存到本地
        const fileUrl = URL.createObjectURL(new Blob([arrayBuffer])); // 转为Blob URL
        callBack && callBack(fileUrl)

        // 释放内存
        ffmpeg.FS('unlink', inputName);
        ffmpeg.FS('unlink', outputName);
    } catch (e) { }
}

const downloadFile = (url, fileName = `clip.${fileType.value}`) => {
    const link = document.createElement('a');
    link.href = url;
    link.download = fileName;
    link.click();
}

onMounted(() => {
    videoCut("https://视频.mp4", 0, 3, downloadFile)
})

onUnmounted(() => {
    ffmpeg.exit();
})
</script>

本地视频文件剪辑

<template>
    <input type="file" @change="fileChange">
</template>

<script setup>
import { ref, onUnmounted } from 'vue'
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';

const ffmpeg = createFFmpeg({ log: true });
const fileType = ref("") // 视频文件类型

const fileChange = (e) => {
    if (!e.target.files[0]) return;
    const file = e.target.files[0];
    fileType.value = file.name.split(".").pop()

    videoCut(file, 0, 3, downloadFile)
}

/**
 * 根据选择的视频文件截取片段
 * @param {file} file 选择的视频文件
 * @param {number|string} startTime 截取开始时间
 * @param {number|string} endTime 截取结束时间
 * @param {Function} callBack 回调函数
 */
const videoCut = async (file, startTime, endTime, callBack) => {
    if (!ffmpeg.isLoaded()) {
        await ffmpeg.load();
    }
    if(!file) return;

    const inputName = `input.${fileType.value}`;
    const outputName = `output.${fileType.value}`;

    const orgFileBuffer = await file.arrayBuffer()

    // 将输入文件保存到虚拟文件系统
    await ffmpeg.FS('writeFile', inputName, await fetchFile(new Blob([orgFileBuffer])));

    try {
        await ffmpeg.run(
            '-ss', `${startTime}`,
            '-t', `${endTime - startTime}`,
            '-i', inputName,
            '-vcodec', 'copy',
            '-acodec', 'copy',
            outputName
        );

        // 读取输出文件
        let arrayBuffer = ffmpeg.FS('readFile', outputName).buffer; // 读取缓存

        // 创建下载链接并通过回调下载保存到本地
        const fileUrl = URL.createObjectURL(new Blob([arrayBuffer])); // 转为Blob URL
        callBack && callBack(fileUrl)

        // 释放内存
        ffmpeg.FS('unlink', inputName);
        ffmpeg.FS('unlink', outputName);
    } catch (e) {}
}

const downloadFile = (url, fileName = `clip.${fileType.value}`) => {
    const link = document.createElement('a');
    link.href = url;
    link.download = fileName;
    link.click();
}

onUnmounted(() => {
    ffmpeg.exit();
})
</script>

获取视频画面截图

<template>
    <input type="file" @change="fileChange">
</template>

<script setup>
import { ref, onUnmounted } from 'vue'
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';

const ffmpeg = createFFmpeg({ log: true });
const fileType = ref("") // 视频文件类型

const fileChange = (e) => {
    if (!e.target.files[0]) return;
    const file = e.target.files[0];
    fileType.value = file.name.split(".").pop()

    // 由于这里一秒截取一帧 ,截取5次, 所以如果视频不足5秒会导致截取和读取失败
    // 回调中是base64图片组成的数组,需要在前面拼接 "data:image/png;base64," ,然后在img的src中赋值即可
    videoFrame(file, 5, 1, (data) => console.log(data))
}

/**
 * 根据选择的视频文件获取视频截图
 * @param {file} file 选择的视频文件
 * @param {number|string} count 截取图片的次数
 * @param {number|string} interval 截取图片的间隔
 * @param {Function} callBack 回调
 */
const videoFrame = async (file, count, interval, callBack) => {
    if (!ffmpeg.isLoaded()) {
        await ffmpeg.load();
    }
    if(!file) return;

    const inputName = `input.${fileType.value}`;

    const orgFileBuffer = await file.arrayBuffer()

    // 将输入文件保存到虚拟文件系统
    await ffmpeg.FS('writeFile', inputName, await fetchFile(new Blob([orgFileBuffer])));

    try {
        await ffmpeg.run(
            "-i",
            inputName,
            "-r",
            `${interval}`,
            "-ss",
            "0",
            "-vframes",
            `${count}`,
            "-f",
            "image2",
            "-s",
            "88*50",
            "image-%02d.png"
        );
        const baseArr = []

        for (let i = 0; i < count; i++) {
            let temp = i + 1;
            if (temp < 10) {
                temp = "0" + temp;
            }
            baseArr.push(
                arrayBufferToBase64(ffmpeg.FS("readFile", "image-" + temp + ".png"))
            );
        }

        callBack && callBack(baseArr)

        // 释放内存
        ffmpeg.FS('unlink', inputName);
    } catch (e) {}
}

const arrayBufferToBase64 = (array) => {
    array = new Uint8Array(array);
    var length = array.byteLength;
    var table = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'];
    var base64Str = "";
    for (var i = 0; length - i >= 3; i += 3) {
        var num1 = array[i];
        var num2 = array[i + 1];
        var num3 = array[i + 2];
        base64Str +=
            table[num1 >>> 2] +
            table[((num1 & 0b11) << 4) | (num2 >>> 4)] +
            table[((num2 & 0b1111) << 2) | (num3 >>> 6)] +
            table[num3 & 0b111111];
    }
    var lastByte = length - i;
    if (lastByte === 1) {
        var lastNum1 = array[i];
        base64Str +=
            table[lastNum1 >>> 2] + table[(lastNum1 & 0b11) << 4] + "==";
    } else if (lastByte === 2) {
        // eslint-disable-next-line no-redeclare
        var lastNum1 = array[i];
        var lastNum2 = array[i + 1];
        base64Str +=
            table[lastNum1 >>> 2] +
            table[((lastNum1 & 0b11) << 4) | (lastNum2 >>> 4)] +
            table[(lastNum2 & 0b1111) << 2] +
            "=";
    }
    return base64Str
}

onUnmounted(() => {
    ffmpeg.exit();
})
</script>

到了这里,关于Js使用ffmpeg进行视频剪辑和画面截取的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Vue 3 + ffmpeg + wasm 实现前端视频剪辑、音频剪辑、音波展示、视频抽帧、gif抽帧、帧播放器、字幕、贴图、时间轴、素材轨道

    预览 www.bilibili.com/video/BV1YT411Y7YJ 技术栈: 💪 Vue 3、Vue-Router 4、Vite、pnpm、esbuild、TypeScript ☀️ Pinia 状态管理 🌪 Tailwind 原子css集成 💥 ffmpeg、wasm 底层音视频处理集成 功能 多轨道时间轴,支持帧缩放,时间缩放 支持多种类型轨道的添加删除 多功能轨道调节,支持音视频轨

    2024年02月11日
    浏览(35)
  • 用python进行视频剪辑源码

    利用moviepy和pydub将一段视频进行区间切割 三、遇到的问题 moviepy切割后的视频没有声音 解决方案:通过pydub切割后再合并 合并时,不支持mp3、 wav等格式 解决方案:统一保存为mp4

    2024年01月17日
    浏览(22)
  • Windows 下融合使用开源组件进行视频内容分析,shotcut ,autocut 剪辑 whisper智能化编辑双语字幕等

    下面以这个黄仁勋访谈视频为例简要介绍分析的步骤 https://youtu.be/lXLBTBBil2U https://github.com/openai/whisper 提升: 安装如果需要在conda 中使用 ffmpeg 的话,也是可以直接用 conda install ffmpeg https://github.com/openai/whisper/discussions/1172 We are thrilled to introduce Subper (https://subtitlewhisper.com), a f

    2024年04月09日
    浏览(33)
  • 音视频剪辑|FFMPEG|windows10下的音视频格式转换,遮挡填充,GIF动图制作,背景音频抽取,替换

    最近对于音视频和图像的处理问题比较感兴趣,但发现很多目前需要的功能要么需要付费但不会过于麻烦,要么比较麻烦,很可能某个功能实现需要安装很多软件 例如,视频转GIF动图,该功能的实现要么使用Photoshop全家桶,要么找在线网站,或者是wps充会员,或者找其它方法

    2024年02月20日
    浏览(44)
  • windows10|音视频剪辑|FFMPEG录屏和网络推流源初步的生成

    FFMPEG的功能强大是毋庸置疑的,那么录屏的需求大家在某些时候大家可能是非常需要的,例如,现有的项目需要演示,因此录制一段演示视频;亦或者做内容分发直播的,比如游戏主播,需要录制在玩某个游戏的精彩片段,以创建一个后期的视频素材库; 亦或者通过FFMPEG抓取

    2024年02月20日
    浏览(55)
  • 使用ffmpeg进行视频截取

    通过ffmpeg -i命令查看视频基本信息 指定截取视频的 开始时间 和 结束时间 ,进行视频截取 或者: 指定截取视频的 开始时间 和 截取的秒数 ,进行视频截取 -i ./input.mp4  指定输入视频路径 -ss 00:00:10  指定截取视频的开始时间点 -to 00:00:15  指定截取视频的结束时间点 -t 5 指定

    2024年01月18日
    浏览(28)
  • 使用ffmpeg对视频进行画面裁剪

    现在需要对一个视频进行裁剪,保留左半的视频,不想用Python去写脚本,太麻烦,因此需要ffmpeg的command直接做切割 crop的参数,分表代表,宽,高,起始x,起始y. 起点是视频的左上角

    2024年02月16日
    浏览(33)
  • 视频剪辑音效处理软件有哪些?视频剪辑软件那个好用

    音效是视频剪辑的重要部分,能起到画龙点睛的作用。在短视频平台中,一段出彩的音效能将原本平平无奇的视频变得生动有趣。那么,视频剪辑音效处理软件有哪些?本文会给大家介绍好用的音效处理软件,同时也会介绍视频剪辑音效处理技巧。感兴趣的小伙伴不容错过。

    2024年02月10日
    浏览(32)
  • 2023年新手如何学剪辑视频 想学视频剪辑如何入门

    随着短视频、vlog等媒体形式的兴起,视频剪辑已经成为了热门技能。甚至有人说,不会修图可以,但不能不会剪视频。实际上,随着各种智能软件的发展,视频剪辑已经变得越来越简单。接下来,一起来看看新手如何学剪辑视频,想学视频剪辑如何入门。 新手如何学剪辑视

    2024年02月13日
    浏览(32)
  • 剪辑视频的方法和步骤 剪辑视频基本技巧有哪些

    经常有人问,剪辑视频的方法和步骤是怎样的?现在学剪辑还来得及吗?其实只要有心学,什么时候都不晚!今天我们就来讲讲剪辑视频的步骤以及剪辑视频基本技巧有哪些? 一、剪辑视频的方法和步骤 1、剪辑视频方法 剪辑视频的方法有很多,可以通过手机相册自带的剪辑

    2024年02月12日
    浏览(27)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包