无延迟播放音频Base64

时间:2020-05-11 18:14:59

标签: javascript audio electron

我有一个Object,里面有几个base64(音频)。 base64将开始播放keydown事件。在某些情况下(Base64大小有点高),播放之前会发生延迟。有什么方法可以消除这种延迟,或者至少可以减少延迟?

在JavaScript中运行并在Electron上运行的应用

//audio base64s object
var audio = {A: new Audio('base64[1]'), B: new Audio('base64[2]'), C: new Audio('base64[3]')};

//audio will start plying with key down
function keydown(ev) {
    if (audio[String.fromCharCode(ev.keyCode)].classList.contains('holding') == false) {
        audio[String.fromCharCode(ev.keyCode)].classList.add('holding');
        if (audio[String.fromCharCode(ev.keyCode)].paused) {
            playPromise = audio[String.fromCharCode(ev.keyCode)].play();
                if (playPromise) {
                playPromise.then(function() {
                    setTimeout(function() {
                            // Follow up operation
                        }, audio.duration * 1000); 
                    }).catch(function() {
                        // Audio loading failure
                });        
        } else {
            audio[String.fromCharCode(ev.keyCode)].currentTime = 0;
        } 
    }
}

1 个答案:

答案 0 :(得分:1)

我为您写了一个完整的示例,并在下面加上注释。

一些关键要点:

  • 如果您需要任何便利或对时间的控制,则需要使用Web Audio API。没有它,您将无法控制音频播放的缓冲或其他行为。

  • 请勿为此使用base64。不用了Base64编码是一种将二进制数据编码为文本格式的方法。这里没有文本格式,因此没有必要。使用base64编码时,会增加33%的存储开销,使用CPU,内存等。这里没有理由。

  • 请使用适当的文件API来获取所需的内容。要解码音频样本,我们需要一个数组缓冲区。因此,我们可以在文件本身上使用.arrayBuffer()方法来获取该信息。这样会始终将内容保留为二进制格式,并允许浏览器在需要时进行内存映射。

代码:

const audioContext = new AudioContext();
let buffer;

document.addEventListener('DOMContentLoaded', (e) => {
    document.querySelector('input[type="file"]').addEventListener('change', async (e) => {
    // Start the AudioContext, now that we have user ineraction
    audioContext.resume();

    // Ensure we actually have at least one file before continuing
    if ( !(e.currentTarget.files && e.currentTarget.files[0]) ) {
        return;
    }

    // Read the file and decode the audio
    buffer = await audioContext.decodeAudioData(
        await e.currentTarget.files[0].arrayBuffer()
    );
  });
});

document.addEventListener('keydown', (e) => {
    // Ensure we've loaded audio
    if (!buffer) {
    return;
  }

  // Create the node that will play our previously decoded buffer
  bufferSourceNode = audioContext.createBufferSource();
  bufferSourceNode.buffer = buffer;

  // Hook up the buffer source to our output node (speakers, headphones, etc.)
  bufferSourceNode.connect(audioContext.destination);

  // Adjust pitch based on the key we pressed, just for fun
  bufferSourceNode.detune.value = (e.keyCode - 65) * 100;

  // Start playing... right now
  bufferSourceNode.start();
});

JSFiddle:https://jsfiddle.net/bradisbell/sc9jpxvn/1/