如何在每次按键时播放(非常)短的.mp3音频文件?

时间:2017-10-04 16:35:08

标签: javascript html5 html5-audio

我正在构建一个包含表单和(作为渐进增强/ UX效果)的网络应用程序,我想要一个按键来触发按键音效。

我将.mp3声音效果剪得很短(0.18秒)。

然而,当我在笔记本电脑上测试我在Firefox上的设置时,似乎有一个可听到的延迟(而不是每个按键都会发出声音效果)。

在我的Android上的Firefox Mobile上,很少有按键发出声音效果 - 可能每8个按键一次。

我是否正在努力实现使用现有网络技术无法实现的目标,或者我只是以错误的方式接近这一点?

这是我的设置:

var myInput = document.getElementsByTagName('input')[0];
var keypress = document.getElementsByClassName('keypress')[0];

function playSoundEffect() {
    keypress.play();
}

myInput.addEventListener('keydown', playSoundEffect, false);

/* I've also tried...
myInput.addEventListener('keyup', playSoundEffect, false);
myInput.addEventListener('keypress', playSoundEffect, false);
*/
input {
width: 90vw;
}
<input type="text" placeholder="Type to hear the sound effect..." />

<audio class="keypress">
<source src="http://handsoffhri.org/.assets/theme/elements/mp3/keypress.mp3" type="audio/mpeg">
</audio>

第二次尝试:

感谢@StackingForHeap和@ zero298下面的有用评论,我已经重构了我的设置:

var myInput = document.getElementsByTagName('input')[0];

function playSoundEffect() {
    var jsKeypress = new Audio('http://handsoffhri.org/.assets/theme/elements/mp3/keypress.mp3');
    jsKeypress.play();
}

myInput.addEventListener('input', playSoundEffect, false);
input {
width: 90vw;
}
<input type="text" placeholder="Type to hear the sound effect..." />

这绝对是一项改进 - 每次创建一个新的Audio对象允许每个对象独立于任何先前创建的Audio对象开始播放。

2 个答案:

答案 0 :(得分:1)

我尝试使用howler.js库执行相同的过程,它看起来效果很好。 这是example

 var myInput = document.getElementsByTagName('input')[0];
  var sound = new Howl({
    src:['http://handsoffhri.org/.assets/theme/elements/mp3/keypress.mp3']
  });

  sound.play();


  function playSoundEffect() {
    sound.play();
   }

  myInput.addEventListener('keydown', playSoundEffect, false);

答案 1 :(得分:1)

我已经看了你的第二次尝试,看起来很合理(请原谅双关语)。但是,我只是对它进行了一次破解,我能够得到相当不错的结果:

这使用我在Freesound.org: UI Confirmation Alert, C4.wav上找到的音频文件。

这会创建一个AudioContext,而不仅仅是Audio,并反复使用相同的,已加载的缓冲区。我还在试着看看那里是否有性能提升。

看起来你必须一遍又一遍地制作源节点:

  

AudioBufferSourceNode只能播放一次;每次打电话后   start(),如果要播放相同的节点,则必须创建新节点   再次响起。幸运的是,这些节点创建起来非常便宜,   并且实际的AudioBuffers可以重复使用   声音。实际上,你可以在火灾中使用这些节点并忘记&#34;方式:   创建节点,调用start()开始播放声音,不要   甚至懒得去拿它。它将自动成为   在适当的时间收集垃圾,直到收到   声音播放完毕后的某个时间。

&#13;
&#13;
/*jslint browser:true, esversion:6, devel:true*/
/*global AudioContext*/

(function() {
  "use strict";

  function main() {
    let ctx = new AudioContext();

    fetch("/res/audio/twinkle.wav")
      .then(res => res.arrayBuffer())
      .then((buffer) => {
        return new Promise((resolve, reject) => {
          ctx.decodeAudioData(buffer, (audioBuffer) => {
            resolve(audioBuffer);
          });
        });
      })
      .then((audioBuffer) => {
        document.addEventListener("keydown", (e) => {
          console.log(e.keyCode);
          if (e.keyCode === 37) { // The "left arrow" key
            let source = ctx.createBufferSource();
            source.buffer = audioBuffer;
            source.connect(ctx.destination);
            source.start(0);
          }
        });
      });
  }
  document.addEventListener("DOMContentLoaded", main);
}());
&#13;
&#13;
&#13;