IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    JS改变AudioBuffer音量并下载为新audio音频

    张 鑫旭发表于 2023-10-09 14:50:57
    love 0

    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

    (本篇完)



沪ICP备19023445号-2号
友情链接