簡體   English   中英

無需再次下載即可克隆音頻源

[英]Cloning audio source without having to download it again

我正在使用 javascript 在瀏覽器中創建鋼琴。 為了讓我同時多次播放相同的鍵,而不是僅僅播放音頻對象,我克隆它並播放克隆,否則我必須等待音頻完成或重新啟動它,我不這樣做'不想。

我做過這樣的事情:

var audioSrc = new Audio('path/');
window.onkeypress = function(event) {
    var currentAudioSrc = audioSrc.cloneNode();
    currentAudioSrc.play();
}

問題是,我正在檢查 chrome 的檢查器,我注意到每次克隆對象時,瀏覽器都會再次下載它

在此處輸入圖片說明

我查了一些想實現類似事情的人,發現他們中的大多數人都有和我一樣的問題,他們重新下載了文件。 我發現可以同時多次播放相同音頻源的唯一示例是 SoundJs http://www.createjs.com/SoundJS

我嘗試檢查源可以但無法弄清楚它是如何完成的。 任何的想法?


使用 webAudioAPI 你可以做這樣的事情:

  • 通過 XMLHttpRequest 下載一次文件。
  • 將響應附加到緩沖區
  • 創建一個新的 bufferSource 並在每次調用時播放
  • 如果不支持 webAudioAPI (IE),則回退到您的第一個實現

 window.AudioContext = window.AudioContext||window.webkitAudioContext; if(!window.AudioContext) yourFirstImplementation(); else{ var buffer, ctx = new AudioContext(), gainNode = ctx.createGain(); gainNode.connect(ctx.destination); var vol = document.querySelector('input'); vol.value = gainNode.gain.value; vol.addEventListener('change', function(){ gainNode.gain.value = this.value; }, false); function createBuffer(){ ctx.decodeAudioData(this.response, function(b) { buffer = b; }, function(e){console.warn(e)}); var button = document.querySelector('button'); button.addEventListener('click', function(){playSound(buffer)}); button.className = 'ready'; } var file = 'https://dl.dropboxusercontent.com/s/agepbh2agnduknz/camera.mp3', xhr = new XMLHttpRequest(); xhr.onload = createBuffer; xhr.open('GET', file, true); xhr.responseType = 'arraybuffer'; xhr.send(); function playSound(buf){ var source = ctx.createBufferSource(); source.buffer = buf; source.connect(gainNode); source.onended = function(){if(this.stop)this.stop(); if(this.disconnect)this.disconnect();} source.start(0); } } function yourFirstImplementation(){ alert('webAudioAPI is not supported by your browser'); }
 button{opacity: .2;} button.ready{opacity: 1};
 <button>play</button> <input type="range" max="5" step=".01" title="volume"/>

cloneNode有一個布爾參數:

var dupNode = node.cloneNode(deep);
/*
  node
    The node to be cloned.
  dupNode
    The new node that will be a clone of node
  deep(Optional)
     true if the children of the node should also be cloned, or false to clone only the specified node.
*/

另請注意MDN

Deep 是一個可選參數。 如果省略,該方法就好像 deep 的值為 true,默認使用深度克隆作為默認行為。 要創建淺克隆,必須將 deep 設置為 false。

此行為已在最新規范中更改,如果省略,該方法將表現為 deep 的值為 false。 盡管它仍然是可選的,但您應該始終為向后和向前兼容性提供深層參數

所以,嘗試使用deep = false來防止下載資源:

var audioSrc = new Audio('path/');
window.onkeypress = function(event) {
    var currentAudioSrc = audioSrc.cloneNode(false);
    currentAudioSrc.play();
}

手動加載它並將二進制數據的Blob URL分配給src

<audio id="audioEl" data-src="audio.mp3"></audio>
var xhr = new XMLHttpRequest();
xhr.open('GET', audioEl.dataset.src);
xhr.responseType = 'blob';
xhr.onload = () => {
    audioEl.src = URL.createObjectURL(xhr.response);
};
xhr.send();

這樣,當您克隆它時,只會克隆對內存中二進制數據的引用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM