Skip to content

Instantly share code, notes, and snippets.

@guillermo
Created August 3, 2011 20:04
Show Gist options
  • Save guillermo/1123627 to your computer and use it in GitHub Desktop.
Save guillermo/1123627 to your computer and use it in GitHub Desktop.
Little script to download and convet music
#!/usr/bin/env ruby
=begin
README
======
Download any youtube video, in the original format ogg without
loosing quality, and also convert a mp3 from the ogg.
You have to decide if the mp3 quality is enough for you. Or you
can adjust the parameters of the conversion if you need the mp3
to a better quality.
Buy each downloaded music before download it.
Feel free to fork, or make a rubygem if you want.
Dependencies
============
* ffmpeg (In osx with brew, a just "brew install ffmpeg" is enough).
* Ruby (Tested in 1.8 and 1.9.2)
* Ruby mechanize library (gem install mechanize)
Installation
============
1.- Give it execution permissions.
2.- [Optional] Put it in your path. Maybe ~/bin.
License
=======
----------------------------------------------------------------------------
"THE BEER-WARE LICENSE" (Revision 42):
<guillermo@cientifico.net> wrote this file. As long as you retain this notice
you can do whatever you want with this stuff. If we meet some day, and you
think this stuff is worth it, you can buy me a beer in return Guillermo
Álvarez Fernández
----------------------------------------------------------------------------
=end
require 'rubygems'
require 'mechanize'
require 'cgi'
class Video
attr_reader :title, :url
def initialize(agent, title, url)
@agent, @title, @url = agent, title, url
end
def process!
file = download
extract_audio(file)
end
def inspect
"#<Video:#{title}>"
end
protected
def file_name
title.gsub(/\W+/,'-')
end
def extract_audio(file)
format = `ffmpeg -i #{file} 2>&1`[/Stream.*Audio\: (\w+)/,1]
case format
when "vorbis"
$stderr.puts("Extracting to original format #{file_name}.ogg ...")
system("ffmpeg -i #{file} -vn -acodec copy #{file_name}.ogg 2>&1")
$stderr.puts("Converting to mp3 #{file_name}.mp3 ...")
system("ffmpeg -i #{file} -vn -f mp3 #{file_name}.mp3 2>&1")
when 'aac'
$stderr.puts("Extracting to original format #{file_name}.ogg ...")
system("ffmpeg -i #{file} -vn -acodec copy #{file_name}.aac 2>&1")
$stderr.puts("Converting to mp3 #{file_name}.mp3 ...")
system("ffmpeg -i #{file} -vn -f mp3 #{file_name}.mp3 2>&1")
else
$stderr.puts "Unsoported flv adudio format #{format}"
end
end
def download
flv_path = file_name+".flv"
puts "Downloading #{flv_path} (#{@title}) at #{url} ..."
File.open(flv_path,'w') do |f|
f.write @agent.get(flv_video_url).body
end
flv_path
end
def flv_video_url
return @flv_path if defined?(@flv_path)
flashvars = (video_page / "embed")[0]["flashvars"]
path = flashvars.split("&").find{|var|
var.split("=").first == "url_encoded_fmt_stream_map" rescue false
}.split("=")[1]
video_path = CGI.unescape(path).split("&").first.split("=")[1]
@flv_path = CGI.unescape( video_path )
end
def video_page
@page ||= @agent.get(@url)
end
end
class YouTube
def initialize
@agent = a = Mechanize.new { |agent|
agent.user_agent_alias = 'Mac Safari'
}
end
def search(term)
url = "http://www.youtube.com/results?search_query=#{CGI.escape(term)}&aq=f"
page = @agent.get(url)
videos = (page / "#search-results h3 a").map do |result|
Video.new(@agent, result["title"], "http://www.youtube.com"+result["href"] )
end
end
end
if File.expand_path($0) == File.expand_path(__FILE__)
$stderr.puts "Did you have the rights for doing this? (Yes/no)"
exit(0) unless %w(yes sure! y ye yeah sure).include? ($stdin.gets.strip).downcase
videos = YouTube.new.search(ARGV.join(" "))
puts "Select a video to download"
videos.each_with_index do |video,index|
puts "\t #{index+1} - #{video.title}"
end
selected = $stdin.gets.strip.to_i
unless videos.size < selected || selected == 0
videos[selected].process!
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment