简体   繁体   English

无需再次下载即可克隆音频源

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

I'm creating a piano in the browser using javascript.我正在使用 javascript 在浏览器中创建钢琴。 In order for me to play the same key multiple times simultaneously, instead of just playing the Audio object, I clone it and play the clone, otherwise I'd have to wait for the audio to finish or to restart it, which I don't want.为了让我同时多次播放相同的键,而不是仅仅播放音频对象,我克隆它并播放克隆,否则我必须等待音频完成或重新启动它,我不这样做'不想。

I've done something like this:我做过这样的事情:

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

The problem is, I was checking chrome's inspector, and I noticed that every time I clone the object, the browser download it again问题是,我正在检查 chrome 的检查器,我注意到每次克隆对象时,浏览器都会再次下载它

在此处输入图片说明

I checked some people who wanted to achieve similar things, and noticed that most of them have the same problem that I do, they redownload the file.我查了一些想实现类似事情的人,发现他们中的大多数人都有和我一样的问题,他们重新下载了文件。 The only example I found that can play the same audio source multiple times simultaneously is SoundJs http://www.createjs.com/SoundJS我发现可以同时多次播放相同音频源的唯一示例是 SoundJs http://www.createjs.com/SoundJS

I tried checking the source could but couldn't figure out how it was done.我尝试检查源可以但无法弄清楚它是如何完成的。 Any idea?任何的想法?


With the webAudioAPI you could do something like that :使用 webAudioAPI 你可以做这样的事情:

  • Download once the file via XMLHttpRequest.通过 XMLHttpRequest 下载一次文件。
  • Append the response to a buffer将响应附加到缓冲区
  • Create a new bufferSource and play it on each call创建一个新的 bufferSource 并在每次调用时播放
  • Fallback to your first implementation if webAudioAPI is not supported (IE)如果不支持 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 have one boolean argument: 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.
*/

Also note fromMDN :另请注意MDN

Deep is an optional argument. Deep 是一个可选参数。 If omitted, the method acts as if the value of deep was true, defaulting to using deep cloning as the default behavior.如果省略,该方法就好像 deep 的值为 true,默认使用深度克隆作为默认行为。 To create a shallow clone, deep must be set to false.要创建浅克隆,必须将 deep 设置为 false。

This behavior has been changed in the latest spec, and if omitted, the method will act as if the value of deep was false.此行为已在最新规范中更改,如果省略,该方法将表现为 deep 的值为 false。 Though It's still optional, you should always provide the deep argument both for backward and forward compatibility尽管它仍然是可选的,但您应该始终为向后和向前兼容性提供深层参数

So, try to use deep = false to prevent download resource:所以,尝试使用deep = false来防止下载资源:

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

Load it manually and assign a Blob URL of the binary data to src :手动加载它并将二进制数据的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();

This way when you clone it, only the reference to the in-memory binary data is cloned.这样,当您克隆它时,只会克隆对内存中二进制数据的引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 AngularJS + Web API - 如何安全地下载excel文件而无需再次登录 - AngularJS + Web API - How to securely download an excel file without having to log in again 如何克隆div并使用regEx而不再次克隆? - How can I clone a div and use an regEx without cloning again? 如何使用 JS 触发下载音频链接,而无需浏览器导航到新页面? - How to trigger a download of an audio link using JS, without having the browser navigate to a new page? 克隆JavaScript对象。 再次:( - Cloning JavaScript Objects. Again :( WebAudio:克隆源AudioNode - WebAudio: cloning a source AudioNode Web Audio API - 克隆一个 audioBuffer - Web Audio API - Cloning an audioBuffer 如何重用已经下载的浏览器的音频,这样它就不会在使用相同音频文件的其他页面中再次下载它? - How can I reuse the audio a browser already downloaded so it doesn't download it again in other pages that use the same audio file? 创建写入流以在没有 Node.js 的情况下下载音频流 - Creating a write stream to download an audio stream without Node.js Google Drive Audio Streaming 不影响下载次数? - Google Drive Audio Streaming without affecting download count? 如何在没有用户交互的情况下下载和播放音频剪辑? - How can I download and play audio clips without user interaction?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM