YouTube Downloader
Monday, September 23, 2013
YouTube needs no introduction - it hosts many videos and has a virtual firehose of new content uploaded every second of every day. The primary interface is through a web browser with no easy way to download content for offline viewing. Naturally, “YouTube downloader” plugins have become a popular addition to most web browsers.
I thought it would be fun to implement a basic “YouTube downloader” in Factor.
First, we start by obtaining information about a video using the YouTube API, parsing the response as a query string:
CONSTANT: video-info-url URL" https://www.youtube.com/get_video_info"
: get-video-info ( video-id -- video-info )
video-info-url clone
3 "asv" set-query-param
"detailpage" "el" set-query-param
"en_US" "hl" set-query-param
swap "video_id" set-query-param
http-get nip query>assoc ;
Next, we can get a list of the available video formats:
: video-formats ( video-info -- video-formats )
"url_encoded_fmt_stream_map" of
"," split [ query>assoc ] map ;
A particular video format includes a download URL and a signature that needs to be attached to it to successfully download the video:
: video-download-url ( video-format -- url )
[ "url" of ] [ "sig" of ] bi "&signature=" glue ;
We are going to use the video title to create a filename, but first we want to sanitize it by removing unprintable characters and a few characters which might conflict with your filesystem and making it no more than 200 characters long:
: sanitize ( title -- title' )
[ 0 31 between? not ] filter
[ "\"#$%'*,./:;<>?^|~\\" member? not ] filter
200 short head ;
Finally, to download a video, we lookup its video info, find the first
mp4
formatted video, convert it to a download URL, and then
download-to
a file.
: download-video ( video-id -- )
get-video-info [
video-formats [ "type" of "video/mp4" head? ] find nip
video-download-url
] [
"title" of sanitize ".mp4" append download-to
] bi ;
You can choose a directory to download it to using the with-directory word. For example, downloading a video to your home directory:
IN: scratchpad "~" [ "G8LC8ES6ogw" download-video ] with-directory
The code for this is on my GitHub.