我收到了一封来自 Notary Sojac 的电子邮件,他看到了我在 鼠标悬停时播放声音 上的教程。在那个教程中,我们不得不采用一些相当笨拙的行为才能使声音很好地响应我们的事件。Notary Sojac 对现有代码进行了更新,使其工作得更好,但更重要的是,他正在研究 Web Audio API 来完成此类操作。我甚至都不知道有这个东西。事实证明,它不是控制 HTML5 音频元素,而是比那更底层的访问。
以下是 Notary Sojac 的一篇客座文章,解释了所有这些内容。
我们都对 HTML5 canvas 的功能印象深刻。创建一种标准化和逻辑化的 2d 绘图操作方法的想法为一个令人惊叹的新世界打开了大门,在这个世界里,一个程序员可以学习一门语言并开发出可以部署到所有相关平台的惊人产品!想想这对我们来说有多重要。现在想想谁会想要一个拥有错误、故障的音频系统、只在你点击后几秒钟发出声音并且有时完全忘记发出声音的惊人的图形应用程序?如果你走 HTML5 <audio>
元素路线,你就会得到这种产品(*尤其是在移动平台上*)。在桌面浏览器中它更好,但不幸的是,由于本文范围之外的原因,它永远不会完美。但截至目前,对于桌面来说,仍然存在希望。未来移动应用程序也存在希望。这个希望的名字是……
Web Audio API
Web Audio API 旨在实现高精度和低级访问。你实际上可以将数据位写入样本。我不确定样本是什么,但我认为它与麦克风在特定时间点对空气的压力有关(也就是麦克风的驱动器位置)。如果你问我,这相当底层。在 Google Chrome 中,所有音频功能都由一个单独的线程处理,以确保不会出现故障。
8 月 21 日,Mozilla 开始公开宣布他们正在放弃其 最初的、开创性的“音频数据 API”,并开始在其浏览器中实现 Google 的“Web Audio API”。但这意味着,在撰写本文时,你需要为 Firefox 使用一个后备方案。
你可以从 Chris Wilson 的这个 Google I/O 演讲中听到很多有用的信息
如何使用它
不幸的是,与普通的 HTML5 音频元素相比,你需要使用更多 JavaScript 才能使用 Web Audio API,但通常情况下,Web Audio API 的精度是必不可少的。
首先我们需要加载声音,这可以通过这样的函数来完成
// you'll put the PCM audio in here
var audioBuffer = null;
var context = new webkitAudioContext();
function loadDogSound(url, variableToBufferSound) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
variableToBufferSoundIn = buffer;
}, onError);
}
request.send();
}
然后我们播放缓冲区,使用这样的函数
function playSound(buffer) {
// creates a sound source
var source = context.createBufferSource();
// tell the source which sound to play
source.buffer = buffer;
// connect the source to the context's destination (the speakers)
source.connect(context.destination);
// play the source now
source.noteOn(0);
}
对于我们这些只是想播放简单的鼠标悬停音效的设计师来说,这实在太多了。幸运的是,我为使用 Web Audio API 搭建了一个 小型 JavaScript 框架。
使用这个新的 API,只需要做以下几件事:
- 创建一个 AudioContext
- 将声音加载到该 AudioContext 中
- 播放声音
所有这些步骤都是单行代码!包含了对旧 HTML5 的后备支持!
<script src="javascripts/webAudioApiForDesigners.js"></script>
<script>
// 1
var context = initializeNewWebAudioContext();
// 2
context.loadSound('audio/beep.ogg', 'beep');
$("#nav-one a")
.mouseenter(function() {
// 3
context.playSound('beep');
});
</script>
HTML5 音频元素可能是不好的选择的原因列表
- 声音在错误的时间听到的延迟问题
- 同时播放多个声音文件时出现无法解释的爆裂声
- 可以同时播放的 HTML5 音频元素数量有限
HTML5 可能更适合你的项目的原因
- 使用简单直接
- 可以很好地播放背景音乐
- 最终(大胆猜测:不早于未来 3 年内)这些 html DOM 元素的错误将被修复
更多信息
HTML5 Rocks 提供了一个 可靠的入门介绍。
很棒的东西!不错的框架,正是需要的。如果幸运的话,jQuery 开发人员可能会开始将其中一些内容集成到未来的版本中!
我想看到一个通过将特定声音分配给特定键盘键来工作的版本,这样我就可以制作一个简单的鼓机/键盘/合成器。
非常感谢您的帮助。
我的天啊,你是对的!我们将能够播放任何合成的音效,比如风琴、贝斯吉他等等,直接从键盘上播放。MIDI 的可能性是无限的。键盘有这么多键,这将非常酷。有人会利用这个并为自己赢得名声。
@Louis
http://stuartmemo.com/qwerty-hancock/
@Norman
恐怕事实并非如此。在没有明显延迟的情况下,实时控制音频是不可能的。Flash 音频 API 已经存在几年了,并且具有完整的 MIDI 支持,但存在同样的问题。这就是为什么我们仍然需要低延迟 (ASIO) 声卡。
@28inch 了解了,感谢您提供的信息,我不知道这一点。
@louis
http://www.schillmania.com/projects/soundmanager2/demo/mpc/
碰巧是用 Safari 浏览器浏览,点击了演示按钮,并收到后备消息(“此浏览器不支持 Web Audio API。将改用 HTML 5 音频元素。”),但没有音频。不知道为什么。在 Firefox 中,它也使用 HTML 5 后备,音频在那里。
我使用 Firefox,我也收到了这条消息,也听到了声音,并想知道这是怎么回事,尤其是在查看源代码后发现没有 HTML 5 音频标签。有人知道这是怎么发生的么?
只有最新的 Safari 浏览器支持 Web Audio API。苹果似乎没有向那些没有购买最新版苹果软件的用户提供该软件。这使得 Linux 和 Windows 开发人员更难为该平台开发解决方案,并且对于那些没有时间跟踪在哪里可以购买最新更新以及他们的系统是否有资格的用户来说也更困难。好消息是 Web Audio API 将在最近的移动平台上可用,因此苹果在这方面值得称赞。
苹果只在其网络浏览器中支持 .mp3 格式,这似乎很神秘(但却是事实)。只有当他们从 mp3 专利持有者那里获得付款而不是向他们支付费用时,这个决定才有意义。FF 在准备就绪时不会以这种方式运行(它仍在采用该技术的过程中)。显然,Chrome 的浏览器旨在与 .ogg 和 webm 等开放标准一起使用。
我设法去了苹果商店查看了一下(我的图书馆只有PC),正如我所怀疑的那样,将代码修改为加载mp3而不是ogg后,成功了。苹果让我做这样的事情似乎有点小题大做,我会和他们抱怨一段时间,然后以一种巧妙和合乎逻辑的方式更新框架以支持备用格式。现在我正在将操作系统切换到Linux Mint,所以我有很多开发环境的东西需要设置,而且工作需要我进行Bacula维护。
这将解决...
“发生了某些次优情况”
错误,如果您执行以下操作...
context.loadSound([‘audio/beep.mp3’], [‘audio/beep.ogg’], ‘beep’);
或者可能类似于以下内容...
context[‘beep’].loadFallbackSound(‘audio/beep.mp3’)
但请给我一两天时间来编写代码。
而*我*得到了
“在尝试解码某些音频数据时发生了某些次优情况。”
(在Safari 6.0中)
网站上根本不应该使用任何音频元素的普遍原因:它们仅仅是令人讨厌的!智能手机在触摸时发出声音或相机预设发出声音也是如此。好的,这只是个人意见,但如果您使用公共交通工具,您就会知道我这句话背后的含义……
同意。
当我听到大多数网站播放声音时,我会本能地使用⌘W离开那里。
当然,声音仍然适用于游戏或视频/动画。
“XMLHttpRequest 无法加载。- 跨源请求仅支持 HTTP。”
有没有办法使其在本地环境中工作?
您是否使用带有 WAMP 服务器的本地服务器,因此它看起来像
http://localhost/etc/
因为从技术上讲,那是 http
好吧,我刚刚尝试在 MAMP 中运行它,但我收到此错误
“在尝试解码某些音频数据时发生了某些次优情况。”
sdfsdfsdfsdfsdfsdf s sa sf à á f sà sa ssf
sdfdfdfsdf
sf
sdf
sdf
sf
sdf
在 Safari 中浏览演示时,我也收到了一些奇怪的消息。不过,它在 Chrome 中运行完美。
看起来 Safari 对 Web Audio API 的支持不稳定,因为它只是在最近的 6.0 版本中引入的。也许过一段时间后,支持会更可靠。http://www.html5audio.org/2012/07/safari-6-arrives-bringing-web-audio-api-to-apples-browser.html
如果您真的需要在各种平台上都能正常工作的悬停声音“某些内容”,您可能需要设置一些浏览器检测并为旧版本提供 Flash 版本。哎呀。
因此比旧版本更流畅。干得好 :)
听起来在让声音按需播放方面存在很多技术问题。考虑到这一点,我的建议可能在技术上不可行,但为什么 CSS 不涵盖应该在悬停时播放的声音?CSS 处理标记的呈现,但几乎只处理视觉效果。为什么 CSS 不处理这种音频呈现?如果您希望按钮在悬停时更改颜色,则使用 CSS。为什么当您希望按钮在悬停时发出哔哔声时,这不是 CSS?就此而言,为什么 CSS 不处理您想要在 :target 上播放的声音?CSS 动画(如 z-index 动画)结束时会发生什么情况?
太好了。我得试试这个。
多年来,我见过网站上播放声音(例如,当悬停在元素上时)。我惊讶于很少有网站所有者实际这样做,因为它很酷且独特。(超越了网站的“外观”,而且易于操作)。
我应该停止说话,开始自己动手了!
有趣的想法;正如您指出的那样,HTML5/Canvas 中出现的创新数量令人惊叹——但我真的希望这不会导致网站噪音泛滥,因为我在浏览网站时最讨厌的事情之一就是“未经请求的噪音”。
关于如何在鼠标停止悬停在元素上时停止播放声音有什么建议吗?我使用的音频片段长 5 秒,当用户意外地将鼠标悬停在多个元素上时,情况会变得非常糟糕,哈哈。
我尝试使用此代码,但没有成功
`webkitAudioContext.prototype.stopSound = function() {
if (source) {
source.noteOff(0);
}
}`
`$(“#button1”).mouseleave(function() {
context.stopSound(‘voice1’);
});`
`$(“#button2”).mouseleave(function() {
context.stopSound(‘voice2’);
});`
有什么想法吗?
嘿,Mel,很高兴看到你在思考这项新技术的可能性。当我最初设计框架时,我只有一个目标,一次播放许多声音,并根据需要让它们重叠(在最终到达/dev/null,它们的来源之前,在背景中平静地回响)。这需要快速启动新的声音,而无需在数组或任何其他地方保存对它们的引用,因此在主分支的当前形式中,编写 stop() 方法并不容易。
幸运的是,代码还很新鲜,所以我开始在 github 上创建一个新分支,在那里我正在测试允许逐个文件播放声音、一次播放一个声音且没有任何相同声音重叠的代码。
现在已经很晚了,但是查看“stop-sound-effects”分支。那里的代码和演示应该允许您很好地执行 .stopSound(),并且由于使用了新的底层语法,它被设置为完全不允许声音重叠。
initializeNewWebAudioContext({ “enableIE”:false, “oneSoundAtATime”:true})
请告诉我它是否满足您的需求。它可能仍然存在错误,现在对我来说有点过了睡觉的时间。
谢谢各位,我会看看这些链接。
非常有用!谢谢。