我正在为iOS上的safari播放音频做一些R& D。我知道在必须通过用户发起的事件完成时,以编程方式播放音频存在限制。我想知道的是,如果我们可以发起一个播放列表。我希望能够通过一个数组并在我从初始按钮开始后逐个播放声音。我的代码看起来像这样:
<button id="play-btn">Play sounds</button><br/>
<input class="text-input" type="text" placeholder="text for a sound here" value="hello world"><br/>
<input class="text-input" type="text" placeholder="text for a sound here" value="typing a sound"><br/>
<input class="text-input" type="text" placeholder="text for a sound here" value="my name is kobby"><br/>
<input class="text-input" type="text" placeholder="text for a sound here" value="whatup allisha"><br/>
我的js看起来像这样:
(函数(){
function createAudioFile(text){
console.log('audio file create', this);
var audioSrc = "http://vaas.acapela-group.com/Services/Streamer?req_voice=sharon22k&req_text="
+ text.split(' ').join('+') + "&cl_login=EVAL_VAAS&cl_app=EVAL_7285884&cl_pwd=h1j1endv";
var audioFile = new Audio();
audioFile.src = audioSrc;
if(audioFile.canPlayType('audio/mp3')) console.log('can play mp3');
if(audioFile.canPlayType('audio/ogg')) console.log('can play ogg');
console.log(audioFile);
return audioFile;
}
var btn = document.querySelector('#play-btn');
var inputs = Array.prototype.slice.call(document.querySelectorAll('.text-input'));
btn.addEventListener('click', function(){
//keep this context obj through all new callbacks or function calls
var ctx = this;
console.log('initial click', this);
var values = inputs.map(function(el, i){
return el.value;
});
console.log(values);
var currentAudioIndex = 0;
function playAudio(){
console.log('playing audio', this);
var audioFile = createAudioFile.call(ctx,values[currentAudioIndex]);
var events = ['loadstart', 'stalled', 'suspend', 'waiting', 'progress', 'error', 'abort'];
for( var i = 0, len = events.length; i<len; i++ ){
audioFile.addEventListener(events[i], function(evt){{
console.log(events[i] + ' just fired');
}}.bind(ctx));
}
audioFile.addEventListener('ended', function(){
console.log('audio end',this);
currentAudioIndex ++;
audioFile = null;//for ram purposes
if(currentAudioIndex < values.length) playAudio.call(ctx);
}.bind(ctx), false);
audioFile.load();
audioFile.play();
}
playAudio.call(ctx);
}, false);
})();
这适用于Chrome,它可以播放我正在使用的Vaas帐户中的所有4种声音。但它只能在iPad上播放第一个声音。
无论如何我可以做递归函数并仍然保持调用堆栈吗?我在开始时传递的是同一个环境,但这似乎还不够?任何有关这方面的帮助都会很棒!
由于 Kobby
答案 0 :(得分:0)
这里最好的解决方案是使用Web Audio API而不是Audio对象。 Web Audio API可以广泛使用,甚至可以在iOS 6中使用。这将允许您拥有一个可以将声音叠加在一起的常量AudioContext,如果您愿意,甚至可以同时播放多个。
一个&#34;陷阱&#34;是iOS Safari实现了较旧的Web Audio API,因此它使用AudioBufferSource.prototype.noteOn(ms)
和noteOff(ms)
而不是start()
和stop()
;它足够简单到polyfill。
如果您想继续使用Audio
方法,请注意中间会有一秒钟的沉默。另外,我建议在同一个对象上重新分配src
属性,而不是创建新的属性,以避免这样的问题。