Search code examples
javascripthtmlhtml5-videohtml5-audiopopcornjs

How can I sync an audio source with an external video and crossfade volume between the two?


I need a solution that works in Chrome and can accept any YouTube, Vimeo, SoundCloud, or custom URL.

I have a feeling Popcorn.js can help me out with this task.


Solution

  • Here's a solution using Popcorn.js and jQuery:

    index.html

    <div id="choose">
      <p>Audio URL:
        <input type="text" id="audio-url" />
        <br/>(Example: http://thelab.thingsinjars.com/web-audio-tutorial/hello.mp3)</p>
      <br/>
      <br/>
      <p>Video URL:
        <input type="text" id="video-url" />
        <br/>( Example: http://vimeo.com/73605534)</p>
      <br/>
      <br/>
      <button id="doit">Do It!</button>
    </div>
    <div id="dopop">
      <button id="toggle">Play/Pause</button>
      <br/>
      <br/>
      <input type="range" min="0" max="100" name="range" id="range" />
      <br/>
      <div id="source1">
        <p> <span class="gain">Source 1 Gain: 1.0</span>
    
            <br/>
            <div id="audio"></div>
        </p>
      </div>
      <hr/>
      <div id="source2">
        <p><span class="gain">Source 2 Gain: 1.0</span>
    
            <br/>
            <div id="video"></div>
        </p>
      </div>
    </div>
    

    inline script:

    function doPop() {
      $("#choose").hide();
      $("#dopop").show();
      // create an instance of popcorn
      var popcorn = Popcorn.smart("#audio", $("#audio-url").val());
      var popcorn2 = Popcorn.smart("#video", $("#video-url").val());
    
      popcorn.on('play', function () {
        popcorn2.play();
      });
    
      popcorn.on('pause', function () {
        popcorn2.pause();
      });
    
      popcorn2.on('play', function () {
        popcorn.play();
      });
    
      popcorn2.on('pause', function () {
        popcorn.pause();
      });
    
      var clicked = false;
    
      $("#toggle").click(function () {
        if (clicked) {
            popcorn.pause();
            clicked = false;
        } else {
            popcorn.play();
            clicked = true;
        }
      });
    
      $("#range").change(function () {
        var x = parseInt($(this).val()) / 100;
        // Use an equal-power crossfading curve:
        var gain1 = Math.cos(x * 0.5 * Math.PI);
        var gain2 = Math.cos((1.0 - x) * 0.5 * Math.PI);
        popcorn.volume(gain1);
        popcorn2.volume(gain2);
        $("#source1 .gain").text("Source 1 Gain: " + gain1);
        $("#source2 .gain").text("Source 2 Gain: " + gain2);
      });
    
    }
    
    $("#doit").click(function () {
      doPop();
    });