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.
- Chrome Extension content script
- Web Audio
- The pitch shift is done using a delay based pitch shifter by Chris Wilso.
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...