Js使用ffmpeg在视频中合成音频背景音乐

news/2024/7/10 21:57:49 标签: javascript, ffmpeg, 音视频

ffmpeg_0">Js使用ffmpeg在视频中合成音频背景音乐

ffmpeg_2">ffmpeg

使用场景是需要在web端对视频的背景音乐进行混音合成。


注意:

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

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

如果使用的是0.12+需要使用新的api,详情请看 文档


npm

npm install @ffmpeg/ffmpeg@^0.11.0

npm install @ffmpeg/core@^0.11.0

视频中合成背景音乐

<template></template>

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

const ffmpeg = createFFmpeg({ log: true });

/**
 * 根据在线的音频地址将音频合成到视频背景音乐中
 * @param {string} url 在线视频链接
 * @param {string} type 视频类型
 * @param {object} voiceItem 音频素材对象
 * @param {string} voiceItem.startT 音频素材出现的开始时间
 * @param {number} voiceItem.url 音频素材的地址url
 */
const videoVoiceCompose = async (url, type, voiceItem) => {
    if (!ffmpeg.isLoaded()) {
        await ffmpeg.load();
    }
    if (!url) return;

    const {url: voiceUrl, startT: startTime} = voiceItem;

    const inputName = `input.${type}`;
    const outputName = `output.${type}`;
    const voiceType = voiceUrl.split(".").pop();
    const voiceFileName = `image.${voiceType}`;

    // 将输入文件保存到虚拟文件系统
    if (url.startsWith('blob:')) {
        // 处理 Blob URL
        const arrayBuffer = await fetchBlobAsArrayBuffer(url);
        ffmpeg.FS('writeFile', inputName, new Uint8Array(arrayBuffer));
    } else if (url.startsWith('http://') || url.startsWith('https://')) {
        // 处理网络地址
        await ffmpeg.FS('writeFile', inputName, await fetchFile(url));
    }
    await ffmpeg.FS('writeFile', voiceFileName, await fetchFile(voiceUrl));

    // 运行 FFmpeg 命令
    try {
        await ffmpeg.run(
            '-i', inputName,
            '-i', voiceFileName,
            '-filter_complex', `[1:a]adelay=${startTime * 1000}|${startTime * 1000}[a1];[0:a][a1]amix=inputs=2:duration=first[aout]`,
            '-map', `0:v`,
            '-map', `[aout]`,
            '-c:v', 'copy',
            '-c:a', 'aac',
            "-strict", "experimental",
            outputName,
            "-hide_banner"
        )

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

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

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

        return {
            fileUrl,
            outputName
        };
    } catch (e) {
        console.log(e);
    }
}

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

onMounted(async () => {
	const url = "http://xxx.mp4"
	const type = /\.([a-zA-Z0-9]+)$/.exec(url)?.[1];
	// 从2s开始将 http://xxx.mp3 中的背景音乐合成到url的视频背景音乐中
    const {fileUrl} = await videoVoiceCompose (url, type, {url: "http://xxx.mp3", startT: 2})
    downloadFile(fileUrl)
})

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

http://www.niftyadmin.cn/n/5311911.html

相关文章

ES6---Set和Map详解

ES6里面的Set和Map用法&#xff1a; 1.Set是一种新的数据结构&#xff0c;类似于数组&#xff0c;里面的成员是唯一的&#xff0c;没有重复的值。 Set实例的方法分为两大类&#xff1a; let set new Set()(1)操作方法: 1>set.add() — 添加某个值&#xff0c;返回set结构…

redis原子命令和 lua 脚本解决并发问题

目录 使用单命令原子操作incr、decrsetex 使用 lua 脚本封装复杂命令微原子操作 我们在使用 Redis 时&#xff0c;不可避免地会遇到并发访问的问题&#xff0c;比如说如果多个用户同时下单就会对缓存在 Redis 中的商品库存并发更新。一旦有了并发写操作&#xff0c;数据就会被…

【IOS】惯性导航详解(包含角度、加速度、修正方式的api分析)

参考文献 iPhone的惯性导航&#xff0c;基于步态。https://www.docin.com/p-811792664.html Inertial Odometry on Handheld Smartphones: https://arxiv.org/pdf/1703.00154.pdf 惯性导航项目相关代码&#xff1a;https://github.com/topics/inertial-navigation-systems use…

利用自编码器(AutoEncoder, AE),对图像或信号进行降维和聚类,并将隐空间在2D空间中可视化,通过Matlab编程实现

自编码器(AutoEncoder)是一种无监督学习方法,用于对数据进行降维和聚类。它通过学习输入数据的低维表示来重构输入数据,同时保持数据的分布不变。在图像或信号处理中,自编码器可以用于提取特征、压缩数据以及可视化隐藏空间。 首先,我们需要构建一个自编码器模型。自编码…

Qt 多进程编程-将子程序嵌入到主窗口

关键字&#xff1a;GPT4、QProcess、FindWindowEx、Qt 、嵌入 文章目录 前言调用外部程序关于 QProcess 嵌入到主程序显示FindWindowEx & FindWindowFindWindowFindWindowEx使用场景 结束 前言 今天计划是稍微研究一下Qt的多进程编程&#xff0c;因为最近的程序感觉有点慢…

Golang : Bson\Json互转

代码 package bson_jsonimport ("encoding/json""errors""fmt""gopkg.in/mgo.v2/bson""os""testing" )type User struct {Name string json:"name,omitempty" bson:"name,omitempty"CSD…

java导出word套打

这篇文档手把手教你完成导出word套打&#xff0c;有这个demo&#xff0c;其他word套打导出都通用。 1、主要依赖 <!--hutool--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.3.0</ve…

环信IM Demo登录方式如何修改为自己项目的?

在环信即时通讯云IM 官网下载Demo&#xff0c;本地运行只有手机验证码的方式登录&#xff1f;怎么更改为自己项目的Appkey和用户去进行登录呢&#xff1f; &#x1f447;&#x1f447;&#x1f447;本文以Web端为例&#xff0c;教大家如何更改代码来实现 1、 VUE2 Demo vue2…