亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Js如何使用ffmpeg進行視頻剪輯和畫面截取等功能

 更新時間:2024年04月11日 08:29:47   作者:Raccom  
在日常處理視頻文件時常常會用到視頻片段的截取功能,FFmpeg支持該功能,下面這篇文章主要給大家介紹了關于Js如何使用ffmpeg進行視頻剪輯和畫面截取等功能的相關資料,需要的朋友可以參考下

ffmpeg

使用場景是需要在web端進行視頻的裁剪,包括使用 在線視頻url 或 本地視頻文件 的裁剪,以及對視頻內容的截取等功能。

前端進行視頻操作可能會導致性能下降,最好通過后端使用java,c++進行處理,本文的案例是備選方案。

注意:

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

同時由于@ffmpeg版本不同會導致使用的api不同,使用案例前需要注意@ffmpeg版本問題。

如果使用的是0.12+需要使用新的api,詳情請看 文檔

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}`;

    // 將輸入文件保存到虛擬文件系統(tǒng)
    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; // 讀取緩存

        // 創(chuàng)建下載鏈接并通過回調下載保存到本地
        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()

    // 將輸入文件保存到虛擬文件系統(tǒng)
    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; // 讀取緩存

        // 創(chuàng)建下載鏈接并通過回調下載保存到本地
        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()

    // 將輸入文件保存到虛擬文件系統(tǒng)
    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進行視頻剪輯和畫面截取等功能的文章就介紹到這了,更多相關Js ffmpeg視頻剪輯和畫面截取內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • js實現簡單的隨機點名器

    js實現簡單的隨機點名器

    這篇文章主要為大家詳細介紹了js實現簡單的隨機點名器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • 前端實現跨頁面通信的最全實現方案指南

    前端實現跨頁面通信的最全實現方案指南

    這篇文章將從同源頁面,不同源頁面,父子框架三個維度,詳細為大家講解前端跨頁面通信的各種實現方案,并提供代碼示例和對比分析,需要的小伙伴可以參考下
    2025-04-04
  • 微信小程序收藏功能的實現代碼

    微信小程序收藏功能的實現代碼

    這篇文章主要介紹了微信小程序收藏功能的實現代碼,基本功能是點擊收藏后顯示已收藏,在另一個頁面出現目前點擊收藏的項目。需要的朋友可以參考下
    2018-06-06
  • JS原生數據雙向綁定實現代碼

    JS原生數據雙向綁定實現代碼

    本文通過實例代碼給大家介紹了JS原生數據雙向綁定問題,代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的的朋友參考下吧
    2017-08-08
  • js中document.referrer實現移動端返回上一頁

    js中document.referrer實現移動端返回上一頁

    本文主要介紹了document.referrer實現移動端返回上一頁的方法,具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • JS實現掃雷項目總結

    JS實現掃雷項目總結

    這篇文章主要為大家詳細介紹了JS實現掃雷項目總結,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • 基于代數方程庫Algebra.js解二元一次方程功能示例

    基于代數方程庫Algebra.js解二元一次方程功能示例

    這篇文章主要介紹了基于代數方程庫Algebra.js解二元一次方程功能,結合具體實例形式分析了方程庫Algebra.js計算方程的具體使用技巧,需要的朋友可以參考下
    2017-06-06
  • JavaScript中的style.display屬性操作

    JavaScript中的style.display屬性操作

    今天為大家介紹的是JavaScript中的style.display屬性操作實現代碼與參數介紹
    2013-03-03
  • Web程序員必備的7個JavaScript函數

    Web程序員必備的7個JavaScript函數

    這篇文章主要為大家詳細介紹了Web程序員必備的7個JavaScript函數,教會大家如何靈活運用JavaScript函數,感興趣的小伙伴們可以參考一下
    2016-06-06
  • 基于Bootstrap 3 JQuery及RegExp的表單驗證功能

    基于Bootstrap 3 JQuery及RegExp的表單驗證功能

    這篇文章主要介紹了基于Bootstrap 3 JQuery及RegExp的表單驗證功能,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-02-02

最新評論