Created
February 11, 2010 01:40
-
-
Save mrrooijen/301111 to your computer and use it in GitHub Desktop.
A simple class that enables you to directly download a video from YouTube by simply providing the full YouTube URL.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'json' | |
require 'open-uri' | |
require 'progressbar' | |
# YouTube | |
# This class allows you to directly download videos straight from YouTube | |
# All you have to do is provide the full URL to a video on YouTube.com | |
# See the examples below! | |
class YouTube | |
BASE_URI = "http://www.youtube.com/" | |
def self.read_video_from(url, &block) | |
download_video(parse_video_url(url), &block) | |
end | |
def self.read_video_from_and_download_to(url, path = Dir.pwd) | |
full_path = File.expand_path(File.join(path, parse_video_title(url) + '.flv')) | |
read_video_from(url) do |youtube| | |
File.open(full_path, "w") do |video| | |
video.write(youtube.read) | |
end | |
end | |
end | |
def self.parse_video_title(url) | |
open(url) do |file| | |
file.each_line do |line| | |
return $1 if line =~ /<h1 >(.*)<\/h1>/ | |
end | |
end | |
false | |
end | |
private | |
def self.parse_video_url(url) | |
url =~ /watch\?v=(.*)/ | |
video_id = $1.split("&")[0] | |
video_url = nil | |
open("#{BASE_URI}watch\?v=#{video_id}") do |page| | |
page.each_line do |line| | |
if line =~ /.SWF_ARGS.:(.*),\n$/ | |
params = JSON.parse($1) | |
video_url = "#{BASE_URI}get_video?video_id=#{params['video_id']}&t=#{params['t']}" | |
break | |
end | |
end | |
end | |
video_url || could_not_locate_video_file | |
end | |
def self.could_not_locate_video_file | |
puts "Could not locate video file for the given URL!" | |
exit | |
end | |
def self.download_video(url, &block) | |
puts "Downloading Video From YouTube..." | |
progress_bar = nil | |
open(url, :proxy => nil, :content_length_proc => lambda { |length| | |
if length && 0 < length | |
progress_bar = ProgressBar.new(url, length) | |
end | |
}, | |
:progress_proc => lambda { |progress| | |
progress_bar.set(progress) if progress_bar | |
}, &block) | |
puts "" | |
puts "Finished downloading video!" | |
end | |
end | |
## EXAMPLES | |
## URL | |
# All you need is "a very awesome video" | |
url = 'http://www.youtube.com/watch?v=oHg5SJYRHA0' | |
## METHOD 1 | |
# Then you can simply invoke the following "One Line Command" to download | |
# and directly save the video to the filesystem | |
YouTube::read_video_from_and_download_to(url, 'youtube') | |
## METHOD 2 | |
# If you wish to do something else before writing the YouTube video you can | |
# also use the following method to read from YouTube and then later store it on the filesystem | |
# To manually fetch the "video title" from YouTube, use: YouTube::parse_video_title(url) | |
# be sure to append the ".flv" extension to it, as it of course isn't stored in the YouTube video title | |
YouTube::read_video_from(url) do |youtube| | |
File.open("/Users/Michael/Desktop/#{YouTube::parse_video_title(url)}.flv", "w") do |video| | |
video.write(youtube.read) | |
end | |
end | |
## METHOD 3 | |
# Basically like method 2, except that we're not using the YouTube::parse_video_title(url) method here | |
# which means you have 100% control over what the output file must be called. | |
YouTube::read_video_from(url) do |youtube| | |
File.open("/Users/Michael/Desktop/my_video.flv", "w") do |video| | |
video.write(youtube.read) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment