How can I queue a series of sound HTML5 <audio> sound clips to play in sequence?

后端 未结 4 2039
长情又很酷
长情又很酷 2020-12-18 04:19

I\'m experimenting with porting a simple audio utility called VoiceWalker to Javascript. VoiceWalker is a tool to help people transcribe audio, and it works like this:

相关标签:
4条回答
  • 2020-12-18 04:31

    Here is a module which will do what you want.

    It is set up to play two seconds of the clip twice, with a short pause in between, then advance the starting point half a second, pause briefly again, and then play the next two seconds from the new starting point, and so on. (You can change these settings very easily in the properties at the top).

    This code expects there to be an html element with id "debug" - I used a paragraph for this. You can delete all reference to this element if you wish. (There are four of these, the line which begins var d..., and the three lines which begin 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();
    
    0 讨论(0)
  • 2020-12-18 04:33

    Make clip call itself:

    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);
    }
    
    0 讨论(0)
  • 2020-12-18 04:36

    Follow the structure of other API's in JavaScript: have your clip function also take in a "what to do next" function. (More technical term: "callback"). The idea is that your clip function knows when it's done with its work, and can then call the callback at the right time.

    As an example, let's say that we have a function that will slowly spell out a word to the document's body:

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

    When this computation finishes spelling out the word, it will call onSuccess, which is going to be our callback. Once we have spell(), we can try to use it:

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

    Try calling startIt and you'll see it do its thing.

    This approach allows us to chain together these asynchronous computations. Every good JavaScript asynchronous API allows you to define "what to do next" after the computation succeeds. You can write your own functions to do the same.

    0 讨论(0)
  • 2020-12-18 04:50
    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.
    

    take a look at it here, it can be applied to an audio or video element.

    0 讨论(0)
提交回复
热议问题