Web前端JS如何获取 Video/Audio 视音频声道(左右声道|多声道)、视音频轨道、音频流数据

写在前面:

根据Web项目开发需求,需要在H5页面中,通过点击视频列表页中的任意视频进入视频详情页,然后根据视频的链接地址,主要是 .mp4 文件格式,在进行播放时实时的显示该视频的音频轨道情况,并实时的将各音频轨道数据以可视化(响度跳表)的形式展现出来。

实现效果

在这里插入图片描述

关键技术

在Web浏览器中,想要获取多媒体文件的相关数据信息,需要借助对应的API来完成,比如获取视音文件的音频信息,就需要用到Web Audio API,通过该API我们可以轻松做到播放声音、获取声音数据,修改声音数据、甚至还可以制造声音。

Web Audio API

Web Audio API 提供了在 Web 上控制音频的一个非常有效通用的系统,允许开发者来自选音频源,对音频添加特效,使音频可视化,添加空间效果(如平移),等等。
它可以设置不同的音频来源(包括节点、 ArrayBuffer 、用户设备等),对音频添加音效,生成可视化图形等。
Web Audio API 使用户可以在音频上下文(AudioContext)中进行音频操作,具有模块化路由的特点。在音频节点上操作进行基础的音频,它们连接在一起构成音频路由图。
即使在单个上下文中也支持多源,尽管这些音频源具有多种不同类型通道布局。这种模块化设计提供了灵活创建动态效果的复合音频的方法。

Web Audio API 是 JavaScript 中主要用于在网页应用中处理音频请求的一个高级应用接口,这个 API 目的是用于让最新技术与传统的游戏音频引擎的综合处理相兼容,也即尽力提供一些桌面音频处理程序的要求。

  • 查看音频播放期间调度事件发生的确切时间;
  • 支持各种类型的音频过滤波器以实现各种效果,包括回声、消除噪音等;
  • 支持利用合成声音(Sound synthesis)创建电子音乐;
  • 支持3D位置音频模拟效果,比如某种声音随着游戏场景而移动;
  • 支持外部输入的声音与 WebRTC 进行集成(调用 WebRTC ,在你的设备中增添吉他声),或者在 - WebRTC 中调用其他地方传输过来的声音;
  • 利用音频数据分析创造良好的可视化声音等。

了解更多API:
https://www.w3.org/TR/webaudio、https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Audio_API

实例代码

1. HTML标签

由于video和audio都有音频,所以我们可以video或者audio来获取输入源,除此以外,我们还可以通过 navigator.getUserMedia API 或 Ajax请求的方式来获取输入源。

<video loop controls><source src="./media/xxx.mp4" type="video/mp4" />
</video>
<audio loop controls><source src="./media/xxx.mp3" type="audio/mp3" />
</audio>
2.JavaScript代码

在创建AudioContext 上下文环境对象时, 由于浏览器安全策略要求音频上下文必须在用户事件(单击、键盘按键等)中启用。这意味着,如果您尝试在没有用户事件的情况下自动播放音乐,所以在loadedmetadata元数据已加载时再执行!!

// 创建一个 AudioContext 环境
const ac = new (window.AudioContext || window.webkitAudioContext)();// 从 video 或 audio 标签元素中拿到输入源
const audio = document.querySelector("video");
// const audio = document.querySelector("audio");// 创建并获取输入源
const audioSource = ac.createMediaElementSource(audio);
// 音频通道数 默认值是 2,最高能取 32
const channelCount = 2 || audioSource.channelCount;
// 创建音频处理器
const processor = ac.createScriptProcessor(2048, channelCount, channelCount);
// 链接音频处理器
audioSource.connect(processor).connect(ac.destination);
// connect到扬声器
audioSource.connect(ac.destination);// 监听音频处理器每次处理的样本帧
processor.onaudioprocess = (evt) => {//获取声轨1输入的缓冲区数据let input =evt.inputBuffer.getChannelData(0);//获取声轨1输出的缓冲区数据let output = evt.outputBuffer.getChannelData(0);
};
3. 完整实例代码

可以通过添加本地的视频 或 音频文件,来测试对应的声道,并实时的渲染到响度跳表中,需要注意的是,音频跳表从-60开始的原因主要是,当输出音量接近满载时,THD(总谐波失真)的表现会比较差,此时产生的谐波会盖掉原本存在的背景噪音,影响到测试成绩。因此,采用-60dB的测试信号。
音频跳表值通常在-60dB到+3dB之间。在音频设备测试中,跳表值反映了设备的频率响应和增益。不同的音频设备可能会有不同的跳表值范围,根据测试标准和设备要求而定。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><script async src="//hm.baidu.com/hm.js?f79493fc378b2235419a88daa91d5f6d"></script><title>Web前端JS如何获取 Video/Audio 视音频声道(左右声道|多声道)、视音频轨道、音频流数据</title><style>body {padding: 50px;}audio,input[type="file"] {width: 471px;}input[type="range"] {transform: rotate(-90deg);}button {font-size: 16px;}</style></head><body><h1>Web前端JS如何获取 Video/Audio 视音频声道(左右声道|多声道)、视音频轨道、音频流数据</h1><hr /><br /><br /><br /><button type="button" id="LBTN">左声道(L)</button><input type="range" id="L" min="-60" max="3" style="margin-left: 13px" />添加本地视音频:<input id="file" type="file" /><input type="range" id="R" min="-60" max="3" /><button type="button" id="RBTN">右声道(R)</button><br /><br /><div class="box"><button type="button" id="SLBTN">左环绕(SL)</button><input type="range" id="SL" min="-60" max="3" /><!--<audio  controls loop width="600"><source src="./media/xxx.mp3" type="audio/mp3" /></audio>--><video  controls loop width="600"><source src="./media/xxx.mp4" type="video/mp4" /></video><input type="range" id="SR" min="-60" max="3" /><button type="button" id="SRBTN">右环绕(SR)</button></div><script>// 获取本地视音频file.addEventListener("change", function () {const file = this.files[0];console.log(file);if ("video/mp4".startsWith("video")) {// video.src = window.URL.createObjectURL(file);audio.src = window.URL.createObjectURL(file);} else {audio.src = window.URL.createObjectURL(file);}});// 计算音频跳表数据const getDbFromFloat = (floatVal) => {return  (Math.log(10) / Math.log(floatVal)) * 20;};const audio = document.querySelector("video");let ac = null;// 音频元数据加载后执行audio.addEventListener("loadedmetadata", () => {// 上下文对象 由于浏览器安全策略要求音频上下文必须在用户事件(单击、键盘按键等)中启用。这意味着,如果您尝试在没有用户事件的情况下自动播放音乐,所以在loadedmetadata元数据已加载时再执行!!ac = new (window.AudioContext || window.webkitAudioContext)();// 创建并获取输入源const audioSource = ac.createMediaElementSource(audio);// 缓冲区大小 取值为 2 的幂次方的一个常数const bufferSize = 2048;// 音频通道数 默认值是 2,最高能取 32const channelCount = 4 || audioSource.channelCount;// 创建音频处理器const processor = ac.createScriptProcessor(bufferSize, channelCount, channelCount);// 链接音频处理器audioSource.connect(processor).connect(ac.destination);// 链接到扬声器audioSource.connect(ac.destination);audio.play();// 监听音频处理器每次处理的样本帧processor.onaudioprocess = (evt) => {// console.log("音频通道数:", evt.inputBuffer.numberOfChannels);//获取声轨1输入的缓冲区数据// evt.inputBuffer.getChannelData(0);//获取声轨1输出的缓冲区数据// evt.outputBuffer.getChannelData(0);{// 声轨1let input = evt.inputBuffer.getChannelData(0),len = input.length,i = 0;while (i < len) {L.value = getDbFromFloat(input[i++]);}};{// 声轨2let input = evt.inputBuffer.getChannelData(1),len = input.length,i = 0;while (i < len) {R.value = getDbFromFloat(input[i++]);}};{// 声轨3let input = evt.inputBuffer.getChannelData(2),len = input.length,i = 0;while (i < len) {SL.value = getDbFromFloat(input[i++]);}};{// 声轨4let input = evt.inputBuffer.getChannelData(3),len = input.length,i = 0;while (i < len) {SR.value = getDbFromFloat(input[i++]);}};};}, false );// 监听音频播放时,激活当前播放audio.addEventListener('play', () => {ac.resume();}, false );// 监听音频暂停时,挂起当前播放audio.addEventListener('pause', () => {ac.suspend();}, false );</script></body>
</html>
4. 完整实例效果

在这里插入图片描述

扩展封装

Npm:https://www.npmjs.com/package/mu-tooljs
GitHub:https://github.com/MuGuiLin/WebMediaAPI

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

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

相关文章

史上最全低代码平台盘点!三分钟盘点2023年顶尖二十个低代码平台!

史上最全低代码平台盘点&#xff01;三分钟盘点2023年顶尖二十个低代码平台&#xff01; 什么是低代码平台&#xff1f;2023年顶尖二十大低代码平台&#xff0c;哪个值得一试&#xff1f;低代码平台应该如何选择&#xff1f;本篇&#xff0c;我们将为大家盘点顶尖的十大低代码平…

分享一个简单的基于C语言嵌入式GUI界面切换代码

目录 前言 一、数据类型 二、页面调度 三、页面显示 四、视频展示 前言 最近在用LVGL写一个简单的UI界面&#xff0c;需要进行几个页面的切换&#xff0c;所以就自己写了一个简单页面切换代码&#xff0c;方便进行页面切换&#xff0c;同时使UI代码结构更加清晰。这个结构…

非常好的简历精选7篇

想要打造一份令人眼前一亮的简历&#xff0c;赢得招聘方的青睐&#xff1f;参考这7篇精选的“非常好的简历”案例&#xff01;无论是应届毕业生还是职场人士&#xff0c;都能从中借鉴灵感&#xff0c;提升简历质量。让求职之路更加顺畅&#xff0c;轻松斩获心仪职位&#xff01…

【java毕业设计源码】基于SSM框架的在线智能题库管理系统设计与实现

该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等学习内容。 目录 一、项目介绍&#xff1a; 二、文档学习资料&#xff1a; 三、模块截图&#xff1a; 四、开发技术与运行环境&#xff1a; 五、代码展示&#xff1a; 六、数据库表截图&#xff1a…

智能优化算法应用:基于入侵杂草算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于入侵杂草算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于入侵杂草算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.入侵杂草算法4.实验参数设定5.算法结果6.参考…

c# OpenCV安装(一)

一 通过NuGet 安装四个拓展包 OpenCvSharp4、OpenCvSharp4.Extensions、OpenCvSharp4.runtime.win、OpenCvSharp4.WpfExtensions C#使用OpenCV的一些代码 需要加头文件 using OpenCvSharp; //为了使用opencv using Point OpenCvSharp.Point; //为了确定我们使用的poin…

Android HCI日志分析案例1

案例1--蓝牙扫描设备过程分析 应用层发起搜索蓝牙设备&#xff0c;Android 官方提供的蓝牙扫描方式有三种&#xff0c;分别如下&#xff1a; BluetoothAdapter.startDiscovery(); //可以扫描经典蓝牙和BLE两种。BluetoothAdapter.startLeScan();//扫描低功耗蓝牙&#xff0c;…

数据领域建设的五大方向

1.数据技术的发力点 数据汇聚技术包括5G高速光纤ipv6下一代互联网、卫星互联网、叠加互联网、区块链、标识、编码和解析等&#xff1b;数据处理技术包括云计算、边缘计算、分布式计算、大数据处理、AI分析、绿色低碳、数据空间、隐私计算、区块链、数据脱敏、数据沙箱等&#…

stm32 can滤波器接收指定的ID

CAN 文章目录 CAN一、配置1、对扩展数据帧进行过滤:(只接收扩展数据帧)CAN_FilterIdHigh&#xff1a;CAN_FilterIdLow&#xff1a;2、对扩展远程帧过滤:(只接收扩展远程帧)3、对标准远程帧过滤:(只接收标准远程帧)4、对标准数据帧过滤:(只接收标准数据帧)5、对扩展帧进行过滤:(…

【Erlang进阶学习】2、匿名函数

受到其它一些函数式编程开发语言的影响&#xff0c;在Erlang语言中&#xff0c;将函数作为一个对象&#xff0c;赋予其“变量”的属性&#xff0c;即为我们的匿名函数 或 简称 fun&#xff0c;它具有以下特性&#xff1a; &#xff08;匿名函数&#xff1a;不是定义在Erlang模…

<DB2>《AIX服务器DB2数据库裸设备表空间扩容方案》

《AIX服务器DB2数据库裸设备表空间扩容方案》 1 表空间状态查看1.1 连接数据库&#xff08;实例用户操作&#xff09;1.2 查看表空间剩余&#xff08;实例用户操作&#xff09;1.3 查看所属表空间的容器属性&#xff08;实例用户操作&#xff09; 2 VG状态和LV状态查看2.1 查看…

leetCode 40.组合总和 II + 回溯算法 + 剪枝 + used数组 + 图解

给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的每个数字在每个组合中只能使用 一次 注意&#xff1a;解集不能包含重复的组合 示例 1: 输入: candidates [10,1,2,7,6,1,5], t…

基于51单片机的交通灯_可调时间_夜间+紧急模式

51单片机交通灯 1 讲解视频&#xff1a;2 功能要求3 仿真图&#xff1a;4 原理图PCB5 实物图6 程序设计&#xff1a;7 设计报告8 资料清单&#xff08;提供资料清单所有文件&#xff09;&#xff1a;设计资料下载链接&#xff1a; 51单片机简易交通灯_可调时间_夜间紧急 仿真代…

LeetCode | 101. 对称二叉树

LeetCode | 101. 对称二叉树 OJ链接 在本函数里不好进行判断&#xff0c;我们另外定义一个函数来如果两个都相等为空&#xff0c;就返回true一个为空&#xff0c;一个不为空都不为空,就比较值然后递归1的左&#xff0c;2的右&#xff0c;1的右&#xff0c;2的左 bool _isSymm…

Ubuntu安装过程记录

软件准备 硬件 Acer电脑&#xff0c;AMD a6-440m芯片 64g优盘一个&#xff0c;实际就用了不到5g。 Ubuntu &#xff1a;官网 下载Ubuntu桌面系统 | Ubuntu 下载桌面版Ubuntu 22.04.3 LTS LTS属于稳定版 u盘系统盘制作软件 Rufus &#xff1a;Rufus - 轻松创建 USB 启动…

linux常用命令-grep命令与ps命令详解(超详细)

文章目录 前言一、grep命令介绍1. grep命令简介2. grep命令的基本语法3. 常用的grep命令选项 二、grep命令示例用法1. 在文件中搜索匹配模式的行2. 忽略大小写地搜索匹配模式的行3. 反转匹配&#xff0c;只打印不匹配模式的行4. 显示匹配行的行号5. 统计匹配的行数6. 打印包含匹…

创投课程研报专题课 | 如何写出高质量研报

协会邀请了来自GPTDAO的分析师——Will作为VC创投课程研报专题课的嘉宾&#xff0c;将于北京时间12月2日(周六)晚上21:00 PM-22:00 PM&#xff0c;与所有对Web3投资、创业心怀热忱的朋友一同探讨《如何写出高质量的研报》这个激动人心的话题。 浙江大学学生区块链协会&#xff…

12.3_黑马MybatisPlus笔记(上)

目录 02 03 04 05 06 07 ​编辑 thinking:system.out::println?​编辑 thinking&#xff1a;list.of? 08 thinking&#xff1a;RequestParam和 ApiParam注解使用&#xff1f; thinking&#xff1a;RequestParam 和PathVariable的区别&#xff1f; ​编辑 ​编…

WPF Live Charts2 自学笔记

文章目录 前言实现效果微软平台的历史问题 WPF 项目搭建Nuget添加额外框架添加项目初始化livecharts配置其它LiveCharts2 案例简单案例Demo示例ViewViewModel GPU渲染 Github地址仓库 前言 LiveChart 是C# 上面很受欢迎的统计图 UI控件。最近在学WPFhalcon开发&#xff0c;想想…

《洛谷深入浅出进阶篇》模意义下的乘法逆元+洛谷P3811

什么是乘法逆元&#xff1f; 算数意义上的乘法逆元指的是倒数&#xff0c;即&#xff1a;a*&#xff08;1/a&#xff09;1 所以 1/a 是 a在算数意义下的乘法逆元&#xff0c;或者可以说二者互为逆元。 这有什么用呢&#xff1f; 除以a就等于乘上a的乘法逆元&#xff0c;乘以…