繁体   English   中英

如何排队一系列声音HTML5 <audio> 声音片段按顺序播放?

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

我正在尝试将名为VoiceWalker的简单音频实用程序移植到Javascript。 VoiceWalker是一个帮助人们录制音频的工具,它的工作原理如下:

VoiceWalker播放模式 http://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()调用,以便只有在另一个停止后才能运行?

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

遵循JavaScript中其他API的结构:让剪辑功能也采用“下一步做什么”功能。 (更多技术术语:“回调”)。 我们的想法是你的剪辑功能知道它的工作何时完成,然后可以在合适的时间调用回调。

举个例子,假设我们有一个函数可以慢慢拼出一个单词给文档的正文:

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都允许您在计算成功后定义“下一步做什么”。 您可以编写自己的函数来执行相同的操作。

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.

这里看一下,它可以应用于音频或视频元素。

这是一个可以做你想要的模块。

它设置为播放两次剪辑两次 ,中间间隔短暂停顿 ,然后提前半秒 ,再次暂停,然后从新起点开始播放接下来的两秒,依此类推。 (您可以在顶部的属性中轻松更改这些设置)。

这段代码期望有一个id为“debug”的html元素 - 我为此使用了一个段落。 如果您愿意,可以删除对该元素的所有引用。 (其中有四个,开始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();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM