Javascript-在音轨中的确切位置时将音频搜索到特定位置 [英] Javascript - Seek audio to certain position when at exact position in audio track

查看:99
本文介绍了Javascript-在音轨中的确切位置时将音频搜索到特定位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

场景:

  1. 音频从 0:00 开始播放.恰好在 0:05 ,曲目向前跳转到 0:30 .
  2. 该曲目立即在 0:30 开始播放,并且恰好在 0:35 ,该曲目向后跳到 0:05 ,然后播放音频文件的其余部分
  1. Audio starts playing from 0:00. At exactly 0:05, the track skips forwards to 0:30.
  2. The track immediately starts playing at 0:30, and at exactly 0:35, the track skips backwards to 0:05 and plays the rest of the audio file

摘要:播放:0:00到0.05 跳过:0:05到0:30 播放:0:30到0:35 跳过:0:35至0:05 播放:0.05至END

真正的问题是需要立即无缝地跳过.例如,setTimeout非常不准确,漂移意味着在这种情况下无法使用.

The real problem comes when there is the need for a immediate and seamless skip. For example, setTimeout is very inaccurate and drifts meaning it cannot be used in this case.

我尝试使用Web Audio API来完成此操作,但是我仍然无法立即过渡.我目前正在使用AudioBufferSourceNode.start(when, offset, duration);计划加载歌曲的片段,对于上面的示例,最初传入(0 [when], 0 [offset], 0:05 [duration]).此后,我仍然使用setTimeout调用同一函数以仅在 0:30 之前运行,并安排类似(0 [when] + 0:05 [previous duration], 0:30 [offset], 0:05 [duration])的时间.

I have tried to use the Web Audio API to accomplish this, but I'm still unable to get an immediate transition. I'm currently scheduling segments of a loaded song using AudioBufferSourceNode.start(when, offset, duration);, initially passing in (0 [when], 0 [offset], 0:05 [duration]) for the example above. After this, I'm still using setTimeout to call the same function to run just short of 0:30 and scheduling something like (0 [when] + 0:05 [previous duration], 0:30 [offset], 0:05 [duration]).

此示例

var AudioContext = window.AudioContext || window.webkitAudioContext,
    audioCtx     = new AudioContext();
    
var skipQueue = [0, 5, 30, 35, 5];
    
// getSong(); // load in the preview song (https://audiojungle.net/item/inspiring/9325839?s_rank=1)

playSound(0, 0);

function getSong() {
    console.log("Loading song...");

    request = new XMLHttpRequest();
    // request.open('GET', "https://preview.s3.envato.com/files/230851789/preview.mp3?response-content-disposition=attachment%3Bfilename%3D20382637_uplifting-cinematic-epic_by_jwaldenmusic_preview.mp3&Expires=1501966849&Signature=HUMfPw3b4ap13cyrc0ZrNNumb0s4AXr7eKHezyIR-rU845u65oQpxjmZDl8AUZU7cR1KuQGV4TLkQ~egPt5hCiw7SUBRApXw3nnrRdtf~M6PXbNqVYhrhfNq4Y~MgvZdd1NEetv2rCjhirLw4OIhkiC2xH2jvbN6mggnhNnw8ZemBzDH3stCVDTEPGuRgUJrwLwsgBHmy5D2Ef0It~oN8LGG~O~LFB5MGHHmRSjejhjnrfSngWNF9SPI3qn7hOE6WDvcEbNe2vBm5TvEx2OTSlYQc1472rrkGDcxzOHGu9jLEizL-sSiV61uVAp5wqKxd2xNBcsUn3EXXnjMIAmUIQ__&Key-Pair-Id=APKAIEEC7ZU2JC6FKENA", true); // free preview from envato
    request.responseType = "arraybuffer";

    request.onload = function() {
        var audioData = request.response;

        audioCtx.decodeAudioData(audioData, function(buffer) {
            audioBuffer = buffer;

            console.log("Ready to play!");
            
            playSong()
        }, function(e) {
            "Error with decoding audio data" + e.err
        });
    }

    request.send();
}


function playSound(previousPlay, nextPlay) {
    // source        = audioCtx.createBufferSource();
    // source.buffer = audioBuffer;
    // source.connect(audioCtx.destination);
    
    skipQueue.shift();

    var duration = Math.abs(skipQueue[0] - previousPlay);

    // source.start(nextPlay, previousPlay, duration);
    
    console.log("Running: source.start(" + nextPlay + ", " + previousPlay + ", " + duration + ")");
    console.log("Current Time: " + previousPlay);
    console.log("Next Play in: " + duration + " (Skipping from " + skipQueue[0] + " to " + skipQueue[1] + ")");

    if (skipQueue.length > 1) {
      setTimeout(function() {
          playSound(skipQueue[0], nextPlay + duration);
      }, 1000 * duration - 50); // take 50ms off for drift that'll be corrected in scheduling
    }
}

<strong>Expected:</strong><br />
Play: 0:00 to 0.05, Skip: 0:05 to 0:30, Play: 0:30 to 0:35, Skip: 0:35 to 0:05, Play: 0.05 to END

我无法使这个简化的示例100%正常运行,但是您可以在控制台中看到我的尝试.由于StackOverflow不支持AJAX,因此我也注释掉了代码.

I can't get this simplified down example 100% working, but you can see what my attempt is in the console. I've also commented out code since StackOverflow doesn't support AJAX.

我愿意使用您想到的任何其他API或方法!

I'm open to using any other API or method that you have in mind!

推荐答案

在AudioBufferSourceNode上实际调用start()时,您从不会显示,因此我无法进行显式调试.但是,简而言之,您需要安排停止和在发生声音时提前开始,而不是尝试交换"在setTimeout回调中播放的活动声音(或尝试在声音停止播放后使其对齐).

You don't ever show when you actually call start() on an AudioBufferSourceNode, so I can't explicitly debug. But in short, you need to schedule the stops and starts AHEAD of when they need to happen, not try to "swap" the active sound playing in a setTimeout callback (or try to get them to align once the sound has stopped playing).

例如,您将执行以下操作:

For example, you'd do something like:

var bs1 = audioCtx.createBufferSourceNode();
var bs2 = audioCtx.createBufferSourceNode();
var bs3 = audioCtx.createBufferSourceNode();
var now = audioCtx.currentTime + 0.020; // add 20ms for scheduling slop

bs1.buffer = audioBuffer;
bs1.connect( audioCtx.destination );
bs2.buffer = audioBuffer;
bs2.connect( audioCtx.destination );
bs3.buffer = audioBuffer;
bs3.connect( audioCtx.destination );
bs1.start( now, 0, 5 );  // time, offset, duration
bs2.start( now+5, 30, 5 );
bs3.start( now+10, 5 );   // no duration; play to end

如果要取消此播放,则必须断开缓冲源节点的连接.

If you want to cancel this playing, you'll have to disconnect the buffersource nodes.

这篇关于Javascript-在音轨中的确切位置时将音频搜索到特定位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆