如今的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实现的。
然而,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世界》三部曲......之一就可以了。
当然,也欢迎点赞或分享。
? ? ? ? ?
(本篇完)