![](/img/trans.png)
[英]Why is there an HTMLAudioElement and a seperate Audio class?
[英]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.