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

推荐订阅源

博客园_首页
量子位
D
DataBreaches.Net
博客园 - 司徒正美
J
Java Code Geeks
博客园 - 【当耐特】
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
aimingoo的专栏
aimingoo的专栏
B
Blog
The Cloudflare Blog
D
Docker
I
InfoQ
爱范儿
爱范儿
MongoDB | Blog
MongoDB | Blog
腾讯CDC
月光博客
月光博客
Hugging Face - Blog
Hugging Face - Blog
Microsoft Azure Blog
Microsoft Azure Blog
Vercel News
Vercel News
阮一峰的网络日志
阮一峰的网络日志
小众软件
小众软件
S
SegmentFault 最新的问题
GbyAI
GbyAI
有赞技术团队
有赞技术团队

博客园 - 前端路引

高精度计算插件 decimal.js 处理 JS 浮点数精度问题(0.1 + 0.2 !== 0.3) 还在痛苦前端的拖拽排序吗?SortableJS 轻松搞定 浏览器 15 个常见指纹特征,使用插件 FingerprintJS 生成浏览器指纹 Web前端入门第 89 问:总结 8 种跨域通信处理方案 Web前端入门第 88 问:引入 JavaScript 的 script 标签究竟有多少用法? Web前端入门第 87 问:JavaScript 中 setInterval 和 setTimeout 细节 Web前端入门第 86 问:JavaScript 中的 Web Worker 为什么能提升代码性能? Web前端入门第 85 问:JavaScript 一个简单的 IndexedDB 数据库入门示例 Web前端入门第 84 问:JavaScript sessionStorage 那些容易踩坑的地方 Web前端入门第 83 问:JavaScript localStorage 有大小限制吗?溢出会怎样? Web前端入门第 82 问:JavaScript cookie 有大小限制吗?溢出会怎样? Web前端入门第 81 问:JavaScript cookie 的读写操作 Web前端入门第 80 问:JavaScript 哪些地方需要 try...catch 异常捕获 Web前端入门第 79 问:JavaScript async & await 的异步任务进化之路 Web前端入门第 78 问:JavaScript 比较少见的模版字符串用法 Web前端入门第 77 问:JavaScript 由程序触发绑定事件的几种方式 Web前端入门第 76 问:JavaScript 鼠标事件(mouse) enter/leave 和 over/out 区别 Web前端入门第 75 问:JavaScript 性能优化之事件委托(事件代理)原理 Web前端入门第 74 问:JavaScript 事件冒泡与事件捕获
Web前端入门第 90 问:JavaScript 也能无中生有的创建音频
前端路引 · 2025-11-13 · via 博客园 - 前端路引

网页播放音乐这个常识应该都知道,毕竟百度 MP3 搜索可是风靡一时!

但使用浏览器无中生有的创建音频,在 HTML5 规范落地之前可是一片空白。

AudioContext 的体量与 Canvas 差不了多少,一个针对图形图像,一个用于音频,两者结合起来就把 flash 给拉下了神坛~~


本文源之于一次技术研究,曾经有一个需求要用 H5 搞一个网页 K 歌,技术难点在于要将原唱、伴唱、录音的音频数据进行合并,后来寻寻觅觅的找到了 AudioContext 这个 API,虽然最终没用 H5 去实现,不过还是涨了见识!!

不废话,直接看代码:

<button id="button">经过我</button>

<script>
  window.AudioContext = window.AudioContext || window.webkitAudioContext;
  (function () {
    if (!window.AudioContext) {
      alert('当前浏览器不支持Web Audio API');
      return;
    }

    // 按钮元素
    var eleButton = document.getElementById('button');

    // 创建新的音频上下文接口
    var audioCtx = new AudioContext();

    // 发出的声音频率数据,表现为音调的高低
    var arrFrequency = [196.00, 220.00, 246.94, 261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25, 587.33, 659.25, 698.46, 783.99, 880.00, 987.77, 1046.50];

    // 音调依次递增或者递减处理需要的参数
    var start = 0, direction = 1;

    // 鼠标hover我们的按钮的时候
    eleButton.addEventListener('mouseenter', function () {
      // 当前频率
      var frequency = arrFrequency[start];
      // 如果到头,改变音调的变化规则(增减切换)
      if (!frequency) {
        direction = -1 * direction;
        start = start + 2 * direction;
        frequency = arrFrequency[start];
      }
      // 改变索引,下一次hover时候使用
      start = start + direction;

      // 创建一个OscillatorNode, 它表示一个周期性波形(振荡),基本上来说创造了一个音调
      var oscillator = audioCtx.createOscillator();
      // 创建一个GainNode,它可以控制音频的总音量
      var gainNode = audioCtx.createGain();
      // 把音量,音调和终节点进行关联
      oscillator.connect(gainNode);
      // audioCtx.destination返回AudioDestinationNode对象,表示当前audio context中所有节点的最终节点,一般表示音频渲染设备
      gainNode.connect(audioCtx.destination);
      // 指定音调的类型,其他还有square|triangle|sawtooth
      oscillator.type = 'sine';
      // 设置当前播放声音的频率,也就是最终播放声音的调调
      oscillator.frequency.value = frequency;
      // 当前时间设置音量为0
      gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
      // 0.01秒后音量为1
      gainNode.gain.linearRampToValueAtTime(1, audioCtx.currentTime + 0.01);
      // 音调从当前时间开始播放
      oscillator.start(audioCtx.currentTime);
      // 1秒内声音慢慢降低,是个不错的停止声音的方法
      gainNode.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 1);
      // 1秒后完全停止声音
      oscillator.stop(audioCtx.currentTime + 1);
    });
  })();
</script>

以上代码内容来源于大佬张鑫旭的博客:https://www.zhangxinxu.com/wordpress/2017/06/html5-web-audio-api-js-ux-voice/

注意:AudioContext 必须要在在用户有交互之后才能创建!!意思就是用户在网页上有点击操作之后才能开始播放音频。

否则报错警告:

The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page.

效果预览

可长按以下二维码跳转到大佬的体验地址:

{% asset_img qrcode.jpg %}

二维码链接:https://www.zhangxinxu.com/study/201706/button-hover-web-audio.html

其他示例

1、 oscillator.type 不同波形带来的声音效果:

https://codepen.io/gregh/pen/LxJEaj

2、又有大佬使用 AudioContext 搞出了小时候玩的游戏音乐:

https://codepen.io/gregh/pen/xqWwqz

写在最后

AudioContext 的 API 绝不止用来创建音频这么简单,往大了想一下,Canvas 可以把 PS 搬到浏览器,那些专业的音频处理软件是不是也可以搬到线上?

看看大佬对 AudioContext 的看法:

1

参考资料
https://www.zhangxinxu.com/wordpress/2017/06/html5-web-audio-api-js-ux-voice/
https://developer.mozilla.org/zh-CN/docs/Web/API/AudioContext