代码之家  ›  专栏  ›  技术社区  ›  maracuja-juice

创建音频-网络的无缝循环

  •  7
  • maracuja-juice  · 技术社区  · 7 年前


    这是我迄今为止尝试的:

    第一种方法是在HTML中使用音频,它会循环,但从曲目的末尾到开头仍然有明显的延迟。

    <audio loop autoplay>
        <source src="audio.mp3" type="audio/mpeg">
    <audio>
    

    let myAudio = new Audio(file);
    myAudio.loop = true; 
    myAudio.play();
    

    之后,我尝试了这个(根据 this answer )

    myAudio.addEventListener(
        'timeupdate',
        function() {
            var buffer = .44;
            if (this.currentTime > this.duration - buffer) {
                this.currentTime = 0;
                this.play();
            }
         },
         false
    );
    

    我转向图书馆 SeamlessLoop ( GitHub )并在Chromium浏览器中实现了无缝循环(但在最新的Safari中没有。没有在其他浏览器中测试)。我使用的代码:

    let loop = new SeamlessLoop();
    // My File is 58 Seconds long. Btw there aren't any gaps in the file.
    loop.addUri(file, 58000, 'sound1');
    loop.callback(soundsLoaded);
    function soundsLoaded() {
        let n = 1;
        loop.start('sound' + n);
    }
    

    编辑: 我尝试了另一种方法:通过两种不同的音频元素循环播放:

    var current_player = "a";
    var player_a = document.createElement("audio");
    var player_b = document.createElement("audio");
    
    player_a.src = "sounds/back_music.ogg";
    player_b.src = player_a.src;
    
    function loopIt(){
        var player = null;
    
        if(current_player == "a"){
            player = player_b;
            current_player = "b";
        }
        else{
            player = player_a;
            current_player = "a";
        }
    
        player.play();
    
        /*
            3104.897 is the length of the audio clip in milliseconds.
            Received from player.duration. 
            This is a different file than the first one
        */
        setTimeout(loopIt, 3104.897); 
    }
    
    loopIt();
    


    谁能引导我进入正确的方向,无缝地循环音频?

    2 回复  |  直到 7 年前
        1
  •  10
  •   Community CDub    4 年前

    Web Audio API 相反这有几个警告,但它将允许您精确地循环到单个样本级别。

    需要注意的是,您必须将整个文件加载到内存中。这可能不适用于大文件。如果文件只有几秒钟,那么应该没有任何问题。

    第二个问题是,您必须手动编写控制按钮(如果需要),因为API具有低级方法。这意味着播放、暂停/停止、静音、音量等。扫描和可能的暂停可能是他们自己的挑战。

    support Web Audio API -在这种情况下,你将不得不回退到常规的音频API,甚至Flash,但如果你的目标是现代浏览器,这应该不是当今的一个大问题。

    实例

    这将加载一个4巴的鼓环,并在循环时没有任何间隙。主要步骤包括:

    • 它从启用CORS的源加载音频(这很重要,要么使用与页面相同的域,要么设置外部服务器以允许跨源使用,就像Dropbox在本例中为我们所做的那样)。
    • AudioContext然后解码加载的文件
    • 解码后的文件用于源节点
    • 源节点连接到输出
    • 启用循环,并从内存中播放缓冲区。

    var actx = new (AudioContext || webkitAudioContext)(),
        src = "https://dl.dropboxusercontent.com/s/fdcf2lwsa748qav/drum44.wav",
        audioData, srcNode;  // global so we can access them from handlers
    
    // Load some audio (CORS need to be allowed or we won't be able to decode the data)
    fetch(src, {mode: "cors"}).then(function(resp) {return resp.arrayBuffer()}).then(decode);
    
    // Decode the audio file, then start the show
    function decode(buffer) {
      actx.decodeAudioData(buffer, playLoop);
    }
    
    // Sets up a new source node as needed as stopping will render current invalid
    function playLoop(abuffer) {
      if (!audioData) audioData = abuffer;  // create a reference for control buttons
      srcNode = actx.createBufferSource();  // create audio source
      srcNode.buffer = abuffer;             // use decoded buffer
      srcNode.connect(actx.destination);    // create output
      srcNode.loop = true;                  // takes care of perfect looping
      srcNode.start();                      // play...
    }
    
    // Simple example control
    document.querySelector("button").onclick = function() {
      if (srcNode) {
        srcNode.stop();
        srcNode = null;   
        this.innerText = "Play";
      } else {
        playLoop(audioData);
        this.innerText = "Stop";
      }
    };
    <button>Stop</button>
        2
  •  2
  •   TERRESK    7 年前

    有一个非常简单的解决方案,只需使用 loopify 它利用了html5网络音频api,并且可以很好地与多种格式兼容,而不仅仅是开发人员所说的wav。

    <script src="loopify.js" type="text/javascript"></script>
    <script>
        loopify("yourfile.mp3|ogg|webm|flac",ready);
    
        function ready(err,loop){
          if (err) {
            console.warn(err);
          }
    
            loop.play();
        }
    </script>
    

    这将自动播放文件,如果你想有开始和停止按钮,例如看看他的 demo