Pitch Shifter: Video audio meddler chrome extension

October 23, 2015

Pitch Shifter screenshot

Change the pitch of videos on the web, cool!

You can start doing it right now by adding our Chrome Extension: Pitch Shifter.

Also the source code is on GitHub.

It should work with any HTML5 video, but we really only tested it with YouTube as that's the player we use the most. Some videos, like those on Facebook or in YouTube ads, are delivered from a different domain and don't output audio due to CORS (more on CORS later).

We use several technologies to grab the video on the page and then route its audio through FX.

But how dow we get at the videos on a YouTube page?

We tried looking at methods of accessing the video without using a Chrome Extension (which would be a true web cool thing), however none of our approaches quite worked.

You can't access an embedded YouTube video via <iframe>

Cross-origin resource sharing (CORS) stops you here. CORS allows a server to tell the broswer that the content it is returning is meant to be accessed by a certain domain only, in the case of an embedded YouTube video, it would have to be a youtube.com subdomain.

You can't access the URLs of the raw videos in javascript

We found endlesshack/youtube-video Github project and thought that maybe we could do a cheeky hack and grab the URLs ourselves (like YouTube's own player does). However, CORS again prevents this as their API does not allow XHR requests from other domains.

Boo! So a chrome extension it is.

Chrome Extensions let you do what the flute you want. By using a "content script" you can be run after a page loads and access all the content within it.

A Chrome Extension requires a Manifest file, here's one for a simple plugin that runs a script after the page has loaded (called content_script.js in this).

{
  "manifest_version": 2,
  "name": "My bad boy extension",
  "version": "1.0",
  "description": "Does a cool thing",
  "icons": {
    "16": "icon16.png",
    "48": "icon48.png",
    "128": "icon128.png"
  },
  "content_scripts": [
    {
      "matches": ["*://*/*"],
      "js": [
        "content_script.js"
      ],
      "run_at": "document_end"
    }
  ]
}

Getting the video audio

We wrote a content script that ran

With Web Audio we can add video tags as nodes in our audio graph using a MediaElementAudioSourceNode.

The pattern is

var audioCtx = new AudioContext();
var videoEl = document.querySelector('video');
var source = audioCtx.createMediaElementSource(videoEl);

// Now we can connect it to another node in the graph...

See the source code for the extension on Github.