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

news2024/10/6 18:34:06

一、需求描述

        项目中有一个配音需求:

        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 引入依赖库

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

        3.2 初始化ffmpeg

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

        3.3 音视频分离

// 在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”

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

        3.4 音频剪切

// -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 配音录制

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变量来辅助完成这个过程。

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

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

        3.6 音频拼接

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 音视频合并

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1714058.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Centos7时区设置及手动修改时间

一、修改系统时区 1、查看时区命令 timedatectl 2、设置时区命令 #下面将时区设置为上海时区 timedatectl set-timezone Asia/Shanghai 3、查看时区看一下新时区有没有生效 timedatectl 二、手动修改系统时间 修改系统时间 date -s "2023-12-25 16:05:10" 查…

display: none 和 visibility: hidden 的共性与区别

display: none 和 visibility: hidden 的共性与区别 共性&#xff1a;display: none 和 visibility: hidden 都是用于设置元素可见性的样式 区别 display: none 使元素及其占位完全消失&#xff1a;元素及其所有子元素将从文档流和布局中完全消失&#xff0c;就像它们不存在一…

对于高速信号完整性,一块聊聊啊(17)

再来对前仿和后仿的仿真内容回顾一下&#xff1a; 从概念上有个根本的理解 前仿真又可以分为布局前仿真和布局后仿真。前者是在设计的最初阶段&#xff0c;建立和验证详细的电气拓扑结构并以此制定出详细的约束规则。后者是在布局完成的状态下&#xff0c;在布线过程中遇到的…

论文阅读:Correcting Motion Distortion for LIDAR HD-Map Localization

目录 概要 Motivation 整体架构流程 技术细节 小结 论文地址&#xff1a;http://arxiv.org/pdf/2308.13694.pdf 代码地址&#xff1a;https://github.com/mcdermatt/VICET 概要 激光雷达的畸变矫正是一个非常重要的工作。由于扫描式激光雷达传感器需要有限的时间来创建…

python如何安装tar.gz

首先我们到官网下载tar.gz。 然后解压我们下载的pip-9.0.1文件&#xff0c;我的解压后放在d&#xff1a;/p下 运行cmd&#xff0c;输入cd d:\p&#xff0c;按回车键&#xff0c;随后再次输入d: 在d:\p>的光标处输入pip-9.0.1\setup.py install&#xff0c;然后按回车键。 最…

图片转excel表格工具的工具,分享3个专业的识别软件!

在数字化时代&#xff0c;我们时常面临将图片中的表格数据转换为可编辑的Excel表格的需求。无论是工作中的数据整理&#xff0c;还是学习中的资料汇总&#xff0c;这一需求都显得尤为迫切。幸运的是&#xff0c;市面上已经涌现出众多优秀的图片转Excel表格工具&#xff0c;它们…

长方形边框 上方中间有缺口 css

<div class"text_6">大234234师掌4234柜</div><div class"text-wrapper_1"><span class"paragraph_1">四川慧创云戈科技有限公司推出的“大师掌柜”&#xff0c;是一个以餐饮外卖为切入口&#xff0c;专注实体小店新零售…

windows10远程桌面端口,修改Windows 10远程桌面端口的步骤

在Windows 10操作系统中&#xff0c;远程桌面功能为企业用户、技术支持人员以及个人用户提供了极大的便利&#xff0c;允许他们远程访问和管理另一台计算机的桌面环境。然而&#xff0c;默认的远程桌面端口&#xff08;通常为3389&#xff09;常常成为安全漏洞的潜在目标&#…

vscode中更改 git托管的项目里的文件 不显示在 修改项 changes里面

目录 一、问题 二、原因及解决方法 三、总结 tiips:如嫌繁琐&#xff0c;直接移步总结即可&#xff01; 一、问题 1.在vscode中修改 从 git拉取下来的代码&#xff0c;本地不显示被修改的文件&#xff1b;文件夹只有最外层显示红色修改图标;但是里面的被修改的文件也没有被…

Mysql中的慢查询

Mysql慢查询的一些sql命令 慢查询的默认事件为10秒 #注意&#xff1a;慢查询一般是在调试阶段开启的&#xff0c;在开发阶段中一般不会开启&#xff0c;会对效率产生延误 #查询慢查询是否开启 show variables like %general%; #慢查询时间设置 show variables like long_query…

数据库约束命令

mysql中&#xff1a; id中存在auto_increment CREATE TABLE u_user(id int PRIMARY KEY auto_increment,u_name VARCHAR(10) NOT NULL UNIQUE,age int CHECK(age>0 && age<120),u_status char(1) DEFAULT(1),gender char(1) ); INSERT into u_user(u_name,age,u…

智能监控技术助力山林生态养鸡:打造智慧安全的养殖新模式

随着现代科技的不断发展&#xff0c;智能化、自动化的养殖方式逐渐受到广大养殖户的青睐。特别是在山林生态养鸡领域&#xff0c;智能化监控方案的引入不仅提高了养殖效率&#xff0c;更有助于保障鸡只的健康与安全。视频监控系统EasyCVR视频汇聚/安防监控视频管理平台在山林生…

百亿数据存储-高并发搜索如何设计?

最近好多小伙伴都跑来问小北&#xff0c;百亿级别的数据存储要怎么设计架构啊&#xff1f; 听说面试里经常问到这个问题。 就像前几天&#xff0c;有位同学去字节面试&#xff0c;就碰到了这个问题&#xff1a; “百亿级数据存储&#xff0c;你怎么设计&#xff1f;” 他们回答…

NTP服务的DDoS攻击:原理和防御

NTP协议作为一种关键的互联网基础设施组件&#xff0c;旨在确保全球网络设备间的时钟同步&#xff0c;对于维护数据一致性和安全性至关重要。然而&#xff0c;其设计上的某些特性也为恶意行为者提供了发动大规模分布式拒绝服务(DDoS)攻击的机会。以下是NTP服务DDoS攻击及其防御…

7款令人惊艳的UI界面设计模板分享

UI界面设计始终围绕用户展开&#xff0c;终极产品界面设计中的用户体验功能必须细致。对于UI设计师来说&#xff0c;欣赏优秀的UI界面设计模板不仅能给我们带来源源不断的灵感&#xff0c;还能激发我们对谁的思考和感悟。为了激发设计师的设计思维和灵感&#xff0c;本文将介绍…

国内前十款专业外盘期货交易app软件排名盘点(综合版)

随着社会经济的不断发展&#xff0c;现在投资者倾向于投资各种项目以获取超额收益。在选择外盘期货交易app软件时&#xff0c;有几个关键的因素需要考虑。首先是软件的可靠度和安全度&#xff0c;因为交易涉及到实际资金。因此&#xff0c;需要选择具备专业资质、经验丰富、充分…

C语言序列化和反序列化--TPL(一)

TPL TPL说明网站 C语言中高效的序列化 您可以使用tpl快速轻松地存储和重新加载C数据。Tpl是一个用于序列化C数据的库。数据以自然二进制形式存储。该API很小&#xff0c;并试图保持“不碍事”。Tpl可以序列化许多C数据类型&#xff0c;包括结构。Tpl与文件、内存缓冲区和文件…

【Linux|数据恢复】extundelete和ext4magic数据恢复工具使用

环境&#xff1a;Centos7.6_x86 一、extundelete工具 1、extundelete介绍 Extundelete 是一个数据恢复工具&#xff0c;用于从 ext3 或 ext4 分区中恢复删除文件。根据官网0.2.4版本介绍是支持ext4&#xff0c;但实际上使用发现ext4格式不行&#xff0c;会报以下错误&#xf…

真实故障分享,H3C ER3208G3-X路由器-双绞线一闪一停

六类非屏蔽双绞线 网线钳 如上图所示&#xff0c;2号线接到h3c路由器出现网线一闪一停&#xff0c;用对线器测试一到8芯能一一对应&#xff0c;无法上网。2号线接到h3c交换机能正常上网&#xff0c;难道是网线对568A 568B有要求&#xff1f; 解决方式&#xff1a;通过两端568…

如何正确申请DigiCert OV通配符SSL证书以保护多个子域名?

在网络时代&#xff0c;网站安全性日益受到重视&#xff0c;而HTTPS协议作为保护网站和用户隐私的重要手段&#xff0c;其重要性不言而喻。HTTPS通过加密技术保护数据在传输过程中的安全性&#xff0c;确保网站的可靠性和安全性。然而&#xff0c;许多网站管理员对于如何申请一…