See Practice Tube in action!
Description:

This app allows you to loop parts of YouTube videos at half speed to make it easier to learn your favorite songs on your instrument. It was created as a useful tool for musicians and music teachers.

I like practicing guitar with YouTube rather than just audio because there is a ton of music on there, and when watching live videos sometimes one can see what a guitarist's fingers are doing without any studio trickery. But it can be hard to try to get the details by repeatedly clicking around to certain points in the video. Sometimes one needs to hear difficult parts several times and that's inconvenient with a guitar over your shoulder - especially if you're trying to focus on a difficult rhythm.

So, I wanted to make something that would loop videos with the simple click of a couple buttons. The YouTube Data API lets me search for videos, and the IFrame Player API lets me manipulate videos while they play.

  1. Search for a video in the search bar such as "The Trooper by Iron Maiden".
  2. Click on a video under "Results".
  3. When the song gets to the beginning of your favorite riff, click "Start Loop".
  4. When the song gets to the end of the part you want to practice, click "End Loop" and it will begin to loop.
  5. Click "Half Speed" to slow it down.
  6. To resume normal playback, unclick the "Looping" button.
  7. To resume normal speed, unclick the "Half Speed" button.
  8. For convenience, if you just want to hear the last ten or thirty seconds of the song again, click either of the "Rewind :10" or "Rewind :30" buttons.
Favorite Features:

I enjoyed creating the controls for the half time and looping features because I got to think like a musician, a music teacher, and a programmer at the same time. When the user selects the loop's end point, the video automatically starts looping and lights up the button. When they click the 'looping' button a second time to turn it off, normal playback resumes. But they can still turn it back on and return to the same loop points, at the same playback rate (if the video supports it). It was very satisfying to see this snap into place for the first time. 

Code Sample:

After the user has been authenticated and they have chosen a video to watch, these are the functions at the heart of the program which control playback looping at different rates through the YouTube IFrame Player API. 

 

// When the API is ready, create the player object.
function onYouTubeIframeAPIReady() {
  player = new YT.Player('existing-iframe-example', {
      events: {
        'onReady': onPlayerReady,
        'onStateChange': onPlayerStateChange
      }
  });
}

// When the user has chosen a video by clicking one, cue it up and start playing it.
function loadVideoById(id) {
  player.cueVideoById({'videoId': id});
  player.playVideo();
}

// When they click the 'start loop' button, store the current playback time.
function getLoopStartTime() {
  startTime = player.getCurrentTime();
}

// When they click the 'end loop' button, store the current playback time as the endpoint and call the startLooping() function.
function getLoopEndTime() {
  endTime = player.getCurrentTime();
  startLooping();
}

// Get current video id and re-cue the video, this time with an start and end points in seconds.
// Start the video and set the playback rate. 
function startLooping() {
  var currentVideoId = player.getVideoData()['video_id'];
  player.cueVideoById({
    'videoId': currentVideoId,
    'startSeconds': startTime,
    'endSeconds': endTime
  });
  player.playVideo();
  setPlaybackRate();

  // If the 'looping' button hasn't been pressed yet - the user just set the endpoint the first time - then automatically toggle the 'looping' button to 'clicked' for visual feedback. 
  // This way they can turn it off to resume normal playback and stop looping.
  if ($('.loopSwitch').hasClass('clicked') === false) {
    $('.loopSwitch').addClass('clicked');
    loopingOn = true;
  };
}

// If the user wants slow playback, set playback rate to half speed. 
// This is not supported on all videos.
// Otherwise, set playback rate to normal, which is 1.
function setPlaybackRate() {
  if (halfOn) {
    player.setPlaybackRate('.5');
  } else {
    player.setPlaybackRate('1');
  }
}

// Stop looping and play video in its entirety from the current time until 'looping' button is pressed again.
// Call 'setPlaybackRate()' to keep current speed when not looping in case someone still wants it slow.
function resumePlayback() {
  var duration = player.getDuration();
  var currentTime = player.getCurrentTime();
  var currentVideoId = player.getVideoData()['video_id'];
  player.cueVideoById({
    'videoId': currentVideoId,
    'startSeconds': currentTime,
    'endSeconds': duration
  });
  player.playVideo();
  setPlaybackRate();
}

// Rewind 10 seconds or 30 seconds from current time.
function back10() {
  var currentTime = player.getCurrentTime();
  player.seekTo(currentTime - 10);
}
function back30() {
  var currentTime = player.getCurrentTime();
  player.seekTo(currentTime - 30);
}

 

 

Challenges:

Getting the authentication to work was the most difficult part. I had to make sure my site was validated by google, and that the API was correctly enabled on the google developer's console. In general, I found that the documentation was not very clear on all the details for this process.

Technologies Used:
JavaScript, API, OAuth