te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - How can I queue a series of sound HTML5 <audio> sound clips to play in sequence? - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin2浏览0评论

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:

.png

So the idea there is that it plays a bit, repeats it, scoots forward, plays another bit, repeats that, scoots forward, etc.

I've cobbled together a function to play a sound clip, it looks like this:

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

It's an easy proposition to e up with a list of start/stop times that match the pattern above, but there's one problem: how do I queue up my clip() calls so that one will only run after the other has stopped?

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:

https://i.sstatic/wyl1J.png

So the idea there is that it plays a bit, repeats it, scoots forward, plays another bit, repeats that, scoots forward, etc.

I've cobbled together a function to play a sound clip, it looks like this:

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

It's an easy proposition to e up with a list of start/stop times that match the pattern above, but there's one problem: how do I queue up my clip() calls so that one will only run after the other has stopped?

Share Improve this question edited Dec 1, 2011 at 21:51 Bo Persson 92.3k31 gold badges153 silver badges208 bronze badges asked Oct 9, 2011 at 3:51 user18015user18015
Add a ment  | 

4 Answers 4

Reset to default 6

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

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 putation 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 putations. Every good JavaScript asynchronous API allows you to define "what to do next" after the putation succeeds. You can write your own functions to do the same.

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.

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)

  1. 暂无评论