简体   繁体   English

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

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

I'm experimenting with porting a simple audio utility called VoiceWalker to Javascript. 我正在尝试将名为VoiceWalker的简单音频实用程序移植到Javascript。 VoiceWalker is a tool to help people transcribe audio, and it works like this: VoiceWalker是一个帮助人们录制音频的工具,它的工作原理如下:

VoiceWalker播放模式 http://i.imgur.com/rafgl.png http://i.imgur.com/rafgl.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 come 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? 提出一个与上述模式匹配的开始/停止时间列表是一个简单的命题,但是有一个问题:如何排队我的clip()调用,以便只有在另一个停止后才能运行?

Make clip call itself: 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);
}

Follow the structure of other API's in JavaScript: have your clip function also take in a "what to do next" function. 遵循JavaScript中其他API的结构:让剪辑功能也采用“下一步做什么”功能。 (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. 当这个计算完成拼写单词时,它将调用onSuccess ,这将是我们的回调。 Once we have spell() , we can try to use it: 一旦我们有了spell() ,我们就可以尝试使用它:

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. 尝试调用startIt ,你会发现它做了它的事情。

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. 每个好的JavaScript异步API都允许您在计算成功后定义“下一步做什么”。 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. 这段代码期望有一个id为“debug”的html元素 - 我为此使用了一个段落。 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 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.

相关问题 我可以使用 HTML5 音频元素在使用 React Hooks 的功能组件中播放声音文件吗? - Can I use an HTML5 audio element to play a sound file in a functional component using React Hooks? Javascript HTML5音频-如果已经播放,则不播放声音吗? - Javascript HTML5 audio - Dont play sound if already playing? HTML5音频-当其他声音开始时停止当前播放 - HTML5 Audio - stop current play when another sound is started 如何在不使用的情况下在JavaScript中播放声音 <audio> 标签? - How can I play sound in JavaScript, without using the <audio> tag? 您可以使用JavaScript或html5编辑音频以通过耳机的2个扬声器播放不同数量的声音吗? - can you edit audio to play different amounts of sound through the 2 speakers of headphones using JavaScript or html5 如何确定播放HTML5音频是否确实在发出声音? - How to determine if playing HTML5 audio is actually making sound? 在HTML5中,我可以同时多次播放同一个声音吗? - In HTML5, can I play the same sound more than once at the same time? 如何通过Web声音API播放声音样本? - how can i play piece of sound sample by web sound API? 如何使用angularjs播放多个音频剪辑? 我可以从HTML中选择文件吗? - How can I play multiple audio clips with angularjs? Can I pick the file from my html? 使用HTML5和Javascript播放声音的最佳方式 - Best way to play sound with HTML5 and Javascript
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM