Js使用ffmpeg在视频中合成音频背景音乐
ffmpeg
使用场景是需要在web端对视频的背景音乐进行混音合成。
注意:
以下所有的使用案例均基于vue3 setup。
同时由于@ffmpeg版本不同会导致使用的api不同,使用案例前需要注意@ffmpeg版本问题
。
如果使用的是0.12+需要使用新的api,详情请看 文档
npm
npm install @ffmpeg/ffmpeg@^0.11.0npm install @ffmpeg/core@^0.11.0
视频中合成背景音乐
<template></template><script setup>
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 URLconst 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>