惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

美团技术团队
博客园_首页
量子位
F
Fortinet All Blogs
L
LangChain Blog
The Cloudflare Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
大猫的无限游戏
大猫的无限游戏
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Visual Studio Blog
Blog — PlanetScale
Blog — PlanetScale
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - Franky
G
Google Developers Blog
阮一峰的网络日志
阮一峰的网络日志
T
Tailwind CSS Blog
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
有赞技术团队
有赞技术团队
U
Unit 42
IT之家
IT之家

张鑫旭-鑫空间-鑫生活

1分钟速度了解text-align match-parent声明 « 张鑫旭-鑫空间-鑫生活 光标的形状也能设置了,就是CSS caret-shape属性 « 张鑫旭-鑫空间-鑫生活 pretext与文字四面环绕效果的实现 « 张鑫旭-鑫空间-鑫生活 JSON.rawJSON方法的作用是什么? « 张鑫旭-鑫空间-鑫生活 如何使用CSS判断鼠标从哪个方向进入元素? « 张鑫旭-鑫空间-鑫生活 借助mediabunny纯JS实现视频水印、剪裁、合成等功能 « 张鑫旭-鑫空间-鑫生活 务必谨慎使用JS WeakRef弱引用 « 张鑫旭-鑫空间-鑫生活 CSS六边形头像的实现与蜂巢布局 « 张鑫旭-鑫空间-鑫生活 CSS corner-shape与背景底纹技术 « 张鑫旭-鑫空间-鑫生活 浅学WebTransport API:下一代Web双向通信技术 « 张鑫旭-鑫空间-鑫生活 HTML dialog元素新支持了closedBy属性 « 张鑫旭-鑫空间-鑫生活 HTML interestfor属性与悬停popover交互效果 « 张鑫旭-鑫空间-鑫生活 CSS3模拟window7炫酷界面效果展示 « 张鑫旭-鑫空间-鑫生活 图片旋转+剪裁js插件(兼容各浏览器) « 张鑫旭-鑫空间-鑫生活 纯js无图片无外链CSS图片幻灯片播放插件 « 张鑫旭-鑫空间-鑫生活 CSS border三角、圆角图形生成技术简介 « 张鑫旭-鑫空间-鑫生活 CSS “渐进增强”在web制作中常见应用举例 « 张鑫旭-鑫空间-鑫生活 让IE6/IE7/IE8浏览器支持CSS3属性 « 张鑫旭-鑫空间-鑫生活 jQuery – 高亮动态显示页面HTML代码插件 « 张鑫旭-鑫空间-鑫生活 翻译 – 逐渐消失的Flash网站 « 张鑫旭-鑫空间-鑫生活 CSS reset的重新审视 – 避免样式重置 « 张鑫旭-鑫空间-鑫生活 新浪微博插入话题后部分文字选中的js实现 « 张鑫旭-鑫空间-鑫生活 JavaScript实现http地址自动检测并添加URL链接 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变背景(gradient)效果 « 张鑫旭-鑫空间-鑫生活 CSS content内容生成技术以及应用 « 张鑫旭-鑫空间-鑫生活 CSS gradient渐变之webkit核心浏览器下的使用 « 张鑫旭-鑫空间-鑫生活 CSS渐变之CSS3 gradient在Firefox3.6下的使用 « 张鑫旭-鑫空间-鑫生活 区分IE8/IE7/IE6及其他浏览器-CSS “\9″hack « 张鑫旭-鑫空间-鑫生活 CSS实现跨浏览器兼容性的盒阴影效果 « 张鑫旭-鑫空间-鑫生活 CSS3&HTML5各浏览器支持情况一览表 « 张鑫旭-鑫空间-鑫生活
JS改变AudioBuffer音量并下载为新audio音频 « 张鑫旭-鑫空间...
张鑫旭,zhangxinxu · 2023-10-09 · via 张鑫旭-鑫空间-鑫生活

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11026 鑫空间-鑫生活
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

音频波形图

如今的Web越来越强,几乎常见的音视频开发需求都能使用纯JS搞定了。

一、这里需要个标题

这里介绍一个不太常见的使用场景的技术实现。

啥呢,就是音频的音量调整,并转换成新文件。

如果仅仅是调整播放的音量,那很简单。

如果你使用的是 <audio> 元素,直接改变volume属性就好了。

audio.volume = 0.5;

over~

如果没有audio元素,而是使用的Web Audio API,希望在 AudioBuffer 层面设置播放的音量,则可以使用GainNodes实现。

假设我们有个在线的MP3音频叫做“bgmusic.mp3”,则可以这么处理。

// 定义一个AudioContext对象
// 因为 Web Audio API都是源自此对象
const audioContext = new AudioContext();
// 创建一个gainNode对象
// gainNode可以对音频输出进行一些控制
const gainNode = audioContext.createGain();
// 音量设置为20%
gainNode.gain.value = 0.2;
// 这个很有必要,建立联系
gainNode.connect(audioContext.destination);

// 创建AudioBufferSourceNode
let source = audioContext.createBufferSource();
// 获取音频资源
fetch('./bgmusic.mp3')
  .then(res => res.arrayBuffer())
  .then(buffer => audioContext.decodeAudioData(buffer))
  .then(audioBuffer => {
    source.buffer = audioBuffer;
    source.connect(gainNode);
  });

// 当需要播放的时候,执行
source.start(0);

您可以狠狠地点击这里体验效果:使用gainNode改变音频播放音量demo

上面的是原音频,音量还是很猛的。

点击下面的按钮,则会听到轻很多的声音,这个音量的降低就是GainNodes实现的。

demo页面的点击播放按钮

然而,GainNodes降低音量仅仅是在播放层面的控制,并不是改变原始的音频音量大小。

所以,如果现在有个需求,希望可以下载这个音量减小后的音频,那使用gainNode API 实现的方法就无效,此时,需要借助其他的方法。

二、采样与音频数据的重置

音频的本质是波,现实世界的波是连续的,但是音频却不是,本质上是一个一个的点采样来的。

如下图所示:

采样就是打点

例如在1s内打48000个点,那么采样率就是48000。

采样率越高,音频质量越好,音频文件的体积也就越大。

所以,想要改变音频原始的音量,可以获取到音频每个点的采样数据,然后和音量对应的比例相乘就好了。

OK,原理清楚了,那该怎么实现呢?

嗯……想了下,还是直接放代码吧,没多少人对ArrayBuffer,AudioBuffer,AudioData等概念有兴趣的。

就是这个,拿去复制粘贴吧。

// 音量
const volume = 0.2;
// 定义一个AudioContext对象
// 因为 Web Audio API都是源自此对象
const audioContext = new AudioContext();
// 降低音量后的audioBuffer数据
let newAudioBuffer = null;
// 获取音频资源
fetch('./bgmusic.mp3')
  .then(res => res.arrayBuffer())
  .then(buffer => audioContext.decodeAudioData(buffer))
  .then(audioBuffer => {
    newAudioBuffer = new AudioBuffer({
        length: audioBuffer.length,
        numberOfChannels: audioBuffer.numberOfChannels,
        sampleRate: audioBuffer.sampleRate
    });
    
    for (let channel = 0; channel < audioBuffer.numberOfChannels; channel += 1) {
        const channelData = audioBuffer.getChannelData(channel);
        const copiedChannelData = newAudioBuffer.getChannelData(channel);
    
        for (let sample = 0; sample < channelData.length; sample += 1) {
            copiedChannelData[sample] = channelData[sample] * volume;
        }
    }
});

此时,newAudioBuffer就是音量降低到20%时候的audioBuffer数据。

我们可以使用此数据进行音频的播放,或者编码,或者下载,都可以。

三、如何作为文件下载

这个以前其实分享过,纯JS合成音频,或者说AudioBuffer数据转音频,目前只支持wav格式(哪怕后缀是mp3,其实也是wav格式)。

// 转换 AudioBuffer 为 Wave 格式的 Blob 地址
function bufferToWave(abuffer, len) {
    // 略,详见下面的演示页面
}

您可以狠狠地点击这里:MP3音频在线音量降低并下载demo

点击按钮后,执行类似下面的JS代码:

const blob = bufferToWave(newAudioBuffer, newAudioBuffer.length);

就可以get到音量降低后的音频了,你也可以选择下载此音频。

点击按钮后的效果预览

四、本文只是开胃菜

本文只是开胃菜,下一篇文章,我们会更进一步,看看如何借助 Web Audio API 实现音频的拼接与合并。

噢啦,将捏。

“将捏”是再见的意思。

表示本文正文内容到此为止了。

要是本文的内容对你的工作或学习帮了大忙,想要聊表谢意,可以等什么时候京东搞活动的时候,入手我的《CSS世界》三部曲……之一就可以了。

当然,也欢迎点赞或。

? ? ? ? ?

本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11026

(本篇完)