网页中的音视频裁剪&拼接&合并

一、需求描述

项目中有一个配音需求:

1)首先,前台会拿到一个英语视频,视频的内容是A和B用英语交流;

2)然后,用户可以选择为某一个角色配音,假如选择为A配音,那么视频在播放到A的位置时会静音,并录制用户的声音。以此类推,直到视频播放结束;

3)最后,将用户的录音替换到视频中,并生成新的视频文件,后续上传服务器。

另外,已知每个角色说话的起始时间和结束时间(这个由后台管理来配置)。

二、需求分析

2.1 实现方式

实现该功能的方式大体有两个:

1)使用ffmpeg.wasm

2)使用Web Audio API等原生JS

第二种方式我没实践,但理论上应该可以实现,只是估计会较复杂,代码较多;此处,我选择方式一。

2.2 功能拆分

根据该功能的操作流程,可将其拆分为:

1)音视频分离,获得纯音频文件和纯视频文件

2)音频剪切,从上一步得到的音频文件中裁剪到除配音角色外的其它音频片段

3)录音,获取到配音音频片段

4)音频拼接,将上面两步得到的音频片段按顺序拼接成一个

5)音视频合并,将纯视频文件和上一步得到的音频文件合并为一个文件

三、代码实现

3.1 引入依赖库

html 复制代码
<!-- 注:文末附件会提供,或自行从网上获取 -->
<script src="/js/ffmpeg/umd/ffmpeg.js"></script>
<script src="/js/util/umd/index.js"></script>

3.2 初始化ffmpeg

javascript 复制代码
const { fetchFile } = FFmpegUtil;
const { FFmpeg } = FFmpegWASM;
let ffmpeg = new FFmpeg();
await ffmpeg.load({coreURL: "/js/core/umd/ffmpeg-core.js",});

3.3 音视频分离

javascript 复制代码
// 在Demo中,视频文件通过input[type=file]标签获得
const { name, size } = files[0];
await ffmpeg.writeFile(name, await fetchFile(files[0]));
// 音视频分离
await ffmpeg.exec(['-i', name, '-c:v', 'copy', '-an', 'output.mp4'])
await ffmpeg.exec(['-i', name, '-vn', '-acodec', 'libmp3lame', 'output.mp3'])

在上面代码中-acodec标识了使用mp3音频编码器,如果使用copy原音频的编码方式,在网页中可能会报错"Invalid audio stream. Exactly one MP3 audio stream is required"

javascript 复制代码
await ffmpeg.exec(['-i', name, '-vn', '-acodec', 'copy', 'output.mp3']); // 会报错

3.4 音频剪切

javascript 复制代码
// -ss 起始时间,-t 持续时间
await ffmpeg.exec(['-i', 'output.mp3', '-ss', '00:00:00.000', '-t', '00:00:10.000', 'split_0.mp3'])
await ffmpeg.exec(['-i', 'output.mp3', '-ss', '00:00:20.000', '-t', '00:00:10.000', 'split_2.mp3'])

3.5 配音录制

javascript 复制代码
const record = (duration, callback) => {
  if (!duration) return;
  // 变量及函数声明
  recorder = [];
  recordTimer = null;
  let _isStop = false;
  async function startRecording () {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' });
    mediaRecorder.ondataavailable = handleDataAvailable;
    mediaRecorder.start();
  }
  function handleDataAvailable(event) {
    if (recorder) { recorder.push(event.data); }
    if (_isStop) {callback && callback();}
  }
  function stopRecording() {
    mediaRecorder.stop();
    _isStop = true;
  }
  // 调用
  startRecording();
  recordTimer = setTimeout(() => {
    stopRecording();
  }, duration);
}

在上面这段代码中,需要注意的是:录音结束后的回调函数是放在handleDataAvailable中的,这是因为当mediaRecorder.stop()停止录制后,会再出发一次dataavailable事件,然后才把最后的数据分片存储到recorder中。所以代码中定义了一个_isStop变量来辅助完成这个过程。

javascript 复制代码
// 将配音数据保存到文件
let split_1 = await audioChunks2Unit8Array(recorder);
await ffmpeg.writeFile('split_1.mp3', split_1);

在上面这段代码中,之前获得的录音数据是个Blob数组,ffmpeg不支持直接对其进行操作,所以要将它转换为Unit8Array才能写到文件。

3.6 音频拼接

javascript 复制代码
await ffmpeg.exec(['-i', 'split_0.mp3', '-i', 'split_1.mp3', '-i', 'split_2.mp3', '-filter_complex', '[0:a][1:a][2:a]concat=n=3:v=0:a=1', '-ac', '2', '-c:a', 'libmp3lame', '-q:a', '4', 'merge.mp3'])

参数解释:

0:a\]\[1:a\]\[2:a\]concat=n=3: 将第一段素材的音频、a1和a2合并,n=3表示三段。 v=0:a=1: 不要声音,只要音频。 -ac:设定声音的channel数 -c:a:指定音频编码器 libmp3lame:mp3音频编码器 -q:a:表示输出的音频质量,一般是1到5之间(1为质量最高)

3.7 音视频合并

javascript 复制代码
await ffmpeg.exec(['-i', 'output.mp4', '-i', 'merge.mp3', '-c:v', 'copy', '-c:a', 'copy', 'result.mp4'])

参数解释:

-c:v copy:视频编码不变。

-c:a copy :音频编码不变。

最后得到合并后的视频数据(Unit8Array)。

四、附件

之前在网上查找ffmpeg.wasm资源时,很多都残缺不全,所以把相关的依赖库放在网盘了(文件来自官方github仓库,其中的示例页面我稍微美化了一下样式)。

https://download.csdn.net/download/xueshen1106/88772981

相关推荐
VOOHU_20189 小时前
VOOHU沃虎:音频变压器的主要作用是什么?什么情况下必须使用?
网络·物联网·音视频·电子元器件
APIshop10 小时前
小红书笔记视频详情接口深度解析:smallredbook.item_get_video_pro
数据库·笔记·音视频
AI服务老曹13 小时前
【架构深评】深度解析异构计算下的 AI 视频管理平台:从 GB28181 接入到 X86/ARM 容器化部署的全链路实战
人工智能·架构·音视频
YWamy13 小时前
视频会议如何重构智能硬件生态?适配难点与场景落地全解析
音视频
ai产品老杨14 小时前
【架构深析】打破硬件壁垒:支持 X86/ARM 异构计算与源码交付的 GB28181 视频 AI 平台设计实践
arm开发·架构·音视频
美狐美颜SDK开放平台15 小时前
直播App画面发灰、卡顿严重?美颜SDK接入与优化全解析
人工智能·音视频·美颜sdk·短视频美颜sdk
开开心心就好15 小时前
解决打印机共享难题的实用工具
人工智能·vscode·游戏·macos·音视频·语音识别·媒体
ai产品老杨16 小时前
深度解析:基于异构计算架构的 AI 视频中台(支持 GB28181、RTSP、Docker 部署与源码交付)
人工智能·架构·音视频
做萤石二次开发的哈哈17 小时前
萤石音视频 SDK 对比维度有哪些?
音视频
Cho1yon17 小时前
【第14期:多屏播放dvr视频和其他三方视频黑屏分析思路闪屏
车载系统·音视频