Как поставить в очередь серию звуковых клипов HTML5 <audio>для последовательного воспроизведения? - PullRequest
5 голосов
/ 09 октября 2011

Я экспериментирую с переносом простой звуковой утилиты под названием VoiceWalker на Javascript.VoiceWalker - это инструмент, помогающий людям транскрибировать звук, и он работает следующим образом:

VoiceWalker playing patternhttp://i.imgur.com/rafgl.png

Таким образом, идея заключается в том, что он играет немного, повторяет его, перемещается вперед, воспроизводит другой бит, повторяет его, перемещается вперед и т. д.

Я собрал функцию для воспроизведения аудиоклипа, она выглядит так:

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

Это простое предложениесоставить список времени запуска / остановки, соответствующего указанному выше шаблону, но есть одна проблема: как мне поставить в очередь мои вызовы clip(), чтобы один из них выполнялся только после остановки другого?

Ответы [ 4 ]

6 голосов
/ 09 октября 2011

Сделай clip сам звони:

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);
}
5 голосов
/ 02 декабря 2011

Следуйте структуре других API в JavaScript: пусть ваша функция clip также принимает функцию «что делать дальше». (Более технический термин: «обратный вызов»). Идея состоит в том, что ваша функция клипа знает, когда она закончит свою работу, и затем может вызвать обратный вызов в нужное время.

В качестве примера, скажем, у нас есть функция, которая будет медленно произносить слово в теле документа:

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)
};

Когда это вычисление завершит написание слова, оно вызовет onSuccess , который будет нашим обратным вызовом. Когда у нас есть spell () , мы можем попытаться использовать его:

var startIt = function() {
    spell("hello", afterHello);
};

var afterHello = function() {
    spell("world", afterHelloWorld);
};

var afterHelloWorld = function() {
    alert("all done!"); 
};

Попробуйте позвонить startIt , и вы увидите, что он делает свое дело.

Этот подход позволяет нам связать воедино эти асинхронные вычисления. Каждый хороший JavaScript-асинхронный API позволяет вам определять, «что делать дальше» после успешного вычисления. Вы можете написать свои собственные функции, чтобы сделать то же самое.

1 голос
/ 26 ноября 2011
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.

посмотрите на это здесь , его можно применить к аудио или видео элементу.

0 голосов
/ 02 декабря 2011

Вот модуль, который будет делать то, что вы хотите.

Он настроен на воспроизведение двух секунд клипа дважды , с короткой паузой между ними, затем с продвижением начальной точки полсекунды , снова сделайте короткую паузу, а затем нажмите next через две секунды от новой начальной точки и т. д. (Вы можете очень легко изменить эти настройки в свойствах вверху).

В этом коде ожидается наличие элемента html с идентификатором "debug" - для этого я использовал параграф. Вы можете удалить все ссылки на этот элемент, если хотите. (Их четыре: строка, начинающаяся с var d ..., и три строки, начинающиеся с 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();
...