Comment puis-je mettre en file d'attente une série de sons HTML5 <audio> pour jouer en séquence?

Je expérimente avec un utilitaire audio simple appelé VoiceWalker à Javascript. VoiceWalker est un outil pour aider les personnes à transcrire de l'audio, et cela fonctionne comme ceci:

Modèle de lecture VoiceWalker Http://i.imgur.com/rafgl.png

Donc, l'idée est qu'il joue un peu, le répète, se déambule vers l'avant, joue un autre morceau, répète, dépêche, etc.

J'ai regroupé une fonction pour jouer un clip son, il ressemble à ceci:

function clip(audio, start, stop){ audio.currentTime = start; audio.play(); int = setInterval(function() { if (audio.currentTime > stop) { audio.pause(); clearInterval(int); } }, 10); } 

C'est une proposition simple de proposer une liste des temps de début / arrêt qui correspondent au schéma ci-dessus, mais il y a un problème: comment puis-je faire la queue de mes appels clip() afin que l'un ne fonctionnera que lorsque l'autre est arrêté?

Suivez la structure d'autres API en JavaScript: assurez-vous que votre fonction de clip prend également une fonction "à faire ensuite". (Terme plus technique: "rappel"). L'idée est que votre fonction de clip sait quand il est fait avec son travail, et peut alors appeler le rappel au bon moment.

Par exemple, disons que nous avons une fonction qui émettra peu à peu un mot au corps du document:

 var spell = function(word, onSuccess) { var i = 0; var intervalId = setInterval(function() { if (i >= word.length) { clearInterval(intervalId); onSuccess(); } else { document.body.appendChild( document.createTextNode(word.charAt(i))); i++; } }, 100) }; 

Lorsque ce calcul finit par préciser le mot, il appelleraSuccess, qui sera notre rappel. Une fois que nous avons épelé () , nous pouvons essayer de l'utiliser:

 var startIt = function() { spell("hello", afterHello); }; var afterHello = function() { spell("world", afterHelloWorld); }; var afterHelloWorld = function() { alert("all done!"); }; 

Essayez d'appeler startIt et vous le verrez faire son rôle .

Cette approche nous permet de chaîner ces calculs asynchrones. Chaque bonne API asynchrone JavaScript vous permet de définir "quoi faire après" après que le calcul réussit. Vous pouvez écrire vos propres fonctions pour faire de même.

Faire appel à un appel lui-même:

 function clip(audio, start, stop){ audio.currentTime = start; audio.play(); int = setInterval(function() { if (audio.currentTime > stop) { audio.pause(); clearInterval(int); // Play it again, 2 seconds further. clip(audio, start + 2, stop + 2); } }, 10); } 
 var count = 1; //initialize and set counter var clipstart = [0,10,20,30,40,50,60]; //initialize and set array of starting points var clipend = [5,15,25,35,45,55,65]; //initialize and set array of ending points var clip = document.getElementById('clip'); //the clip you want to work with var end; //initialize the current end point var start; //initialize the current start point function stop(){ //function to check if the clip needs to be stopped and asks for next track if(clip.currentTime >= end){ clip.pause(); //pause playback //if it's not on the 2 iteration, and the there are still cues left ask for next track. if(!(count == 1 && clipstart.length == 0)){ skip(); } } } function play(){ //skip to start and play clip.currentTime = start; clip.play(); } function skip(){ //sets the start and end points count++; if(count == 2){ count = 0; start = clipstart.shift(); end = clipend.shift(); } play(); } skip(); clip.addEventListener('timeupdate', stop); //listens for if the clip is playing, and if it is, every second run the stop function. 

Regardez-le ici , il peut être appliqué à un élément audio ou vidéo.

Voici un module qui fera ce que vous voulez.

Il est configuré pour jouer deux secondes du clip deux fois , avec une courte pause entre les deux, puis avance le point de départ une demi-seconde , pause brièvement à nouveau, puis jouez les deux secondes suivantes à partir du nouveau point de départ, et ainsi de suite. (Vous pouvez modifier ces paramètres très facilement dans les propriétés en haut).

Ce code s'attend à ce qu'il existe un élément html avec id "debug" – J'ai utilisé un paragraphe pour cela. Vous pouvez supprimer toute référence à cet élément si vous le souhaitez. (Il y en a quatre, la ligne qui commence var d …, et les trois lignes commençant d.innerHTML …).

 var VOICEWALKER = (function () { // properties var d = document.getElementById("debug"); var audio = document.getElementsByTagName('audio')[0]; var start = 0; var stop = 2; var advanceBy = 0.5; var pauseDuration = 500; // milliseconds between clips var intv; // reference to the setInterval timer var clipCount = 0; // how many times we have played this part of the clip var clipMax = 2; // how many times we shall play this part of the clip // methods var pauseFinished = function () { d.innerHTML = "Pause finished"; clip(); }; var pollClip = function () { d.innerHTML = String(audio.currentTime); if (audio.currentTime > stop) { audio.pause(); d.innerHTML = "Pause"; clearInterval(intv); clipCount += 1; if (clipCount === clipMax) { clipCount = 0; // advance clip start += advanceBy; stop += advanceBy; } // pause a little setTimeout(pauseFinished, pauseDuration); } }; var clip = function () { audio.currentTime = start; audio.play(); intv = setInterval(pollClip, 10); }; var init = function () { audio.addEventListener('canplaythrough', clip, false); }; return { init : init }; }()); VOICEWALKER.init();