簡體   English   中英

HTMLAudioElement音頻時間延遲

[英]HtmlAudioElement audio time delay

HTMLAudioElement接口提供對元素屬性的訪問。 每次請求都會延遲從服務器獲取聲音。

一個基本的例子:

  var flush = new Audio('hello.wav');
 $(document).on('click', function() {
  flush.play();  
 });

問題 :存在延遲(100ms +),因為即使聲音容量為30 KB,每個請求(想象10種以上不同的聲音)都需要從服務器下載聲音。

問題 :這個問題有解決方案嗎? 在DOM准備就緒時下載聲音,或為此使用其他方式。 這是主機/我的位置問題嗎? 主持人是Heroku。

您可以通過AJAX以Blob的形式預取所有文件,然后使用blobURI從內存中直接播放它們, 從而省去了獲取時間,但是您仍有解碼時間。

 const db_url = 'https://dl.dropboxusercontent.com/s/'; const urls = ['1cdwpm3gca9mlo0/kick.mp3', 'h2j6vm17r07jf03/snare.mp3', 'kbgd2jm7ezk3u3x/hihat.mp3', 'h8pvqqol3ovyle8/tom.mp3']; preload(urls) .then(blobURis => { blobURis.forEach((uri, i) => { const btn = document.createElement('button'); btn.onclick = e => new Audio(uri).play(); btn.textContent = urls[i].split('/')[1].split('.')[0]; document.body.appendChild(btn); }); }); function preload(urls) { const requests = urls.map(url => fetch(db_url + url) .then(r => r.blob()) // request as Blob .then(b => URL.createObjectURL(b)) // get a blobURI to access from memory ); return Promise.all(requests); } 

因此,您還可以預解碼文件,並始終對每個文件使用相同的<audio>

 const db_url = 'https://dl.dropboxusercontent.com/s/'; const urls = ['1cdwpm3gca9mlo0/kick.mp3', 'h2j6vm17r07jf03/snare.mp3', 'kbgd2jm7ezk3u3x/hihat.mp3', 'h8pvqqol3ovyle8/tom.mp3']; preload(urls) .then(blobURis => { blobURis.forEach((uri, i) => { const audio = new Audio(uri); audio.autoplay = false; const btn = document.createElement('button'); btn.onclick = e => { audio.currentTime = 0; audio.play(); } btn.textContent = urls[i].split('/')[1].split('.')[0]; document.body.appendChild(btn); }); }); function preload(urls) { const requests = urls.map(url => fetch(db_url + url) .then(r => r.blob()) .then(b => URL.createObjectURL(b)) ); return Promise.all(requests); } 

但是您仍然不能完全確定它是否會在您要求時啟動。

因此,絕對沒有延遲的最好方法是使用Web Audio API

 const db_url = 'https://dl.dropboxusercontent.com/s/'; const urls = ['1cdwpm3gca9mlo0/kick.mp3', 'h2j6vm17r07jf03/snare.mp3', 'kbgd2jm7ezk3u3x/hihat.mp3', 'h8pvqqol3ovyle8/tom.mp3']; const a_ctx = new (window.AudioContext || window.webkitAudioContext)(); preload(urls) .then(audioBuffers => { audioBuffers.forEach((buf, i) => { const btn = document.createElement('button'); btn.onclick = e => { const source = a_ctx.createBufferSource(); source.buffer = buf; source.connect(a_ctx.destination); source.start(0); }; btn.textContent = urls[i].split('/')[1].split('.')[0]; document.body.appendChild(btn); }); }); function preload(urls) { const requests = urls.map(url => fetch(db_url + url) .then(r => r.arrayBuffer()) // this time we request as ArrayBuffer .then(b => a_ctx.decodeAudioData(b)) ); return Promise.all(requests); } 
 <!-- Promising decodeAudioData for Safari https://github.com/mohayonao/promise-decode-audio-data/ [MIT] --> <script src="https://cdn.rawgit.com/mohayonao/promise-decode-audio-data/eb4b1322/build/promise-decode-audio-data.min.js"></script> 

Ps:所有示例都在ES6中,並且使用fetch API以便於閱讀,但是在ES5中和使用XMLHttpRequest可以完全相同。

暫無
暫無

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

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