viddl-rb 0.8 → 0.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.txt +14 -0
- data/Gemfile.lock +7 -29
- data/README.md +34 -122
- data/Rakefile +8 -22
- data/bin/viddl-rb +117 -45
- data/helper/download-helper.rb +67 -94
- data/helper/plugin-helper.rb +10 -60
- data/plugins/blip.rb +2 -3
- data/plugins/metacafe.rb +54 -53
- data/plugins/soundcloud.rb +15 -19
- data/plugins/veoh.rb +41 -40
- data/plugins/vimeo.rb +23 -30
- data/plugins/youtube.rb +138 -266
- metadata +29 -50
- data/TODO.txt +0 -3
- data/bin/helper/downloader.rb +0 -20
- data/bin/helper/driver.rb +0 -47
- data/bin/helper/parameter-parser.rb +0 -109
- data/helper/audio-helper.rb +0 -48
- data/helper/utility-helper.rb +0 -45
- data/lib/viddl-rb.rb +0 -103
- data/plugins/dailymotion.rb +0 -44
data/CHANGELOG.txt
ADDED
data/Gemfile.lock
CHANGED
@@ -1,43 +1,21 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
viddl-rb (0.
|
5
|
-
|
6
|
-
nokogiri (~> 1.5.0)
|
7
|
-
progressbar
|
4
|
+
viddl-rb (0.6)
|
5
|
+
nokogiri
|
8
6
|
|
9
7
|
GEM
|
10
8
|
remote: http://rubygems.org/
|
11
9
|
specs:
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
mechanize (2.7.1)
|
17
|
-
domain_name (~> 0.5, >= 0.5.1)
|
18
|
-
http-cookie (~> 1.0.0)
|
19
|
-
mime-types (~> 1.17, >= 1.17.2)
|
20
|
-
net-http-digest_auth (~> 1.1, >= 1.1.1)
|
21
|
-
net-http-persistent (~> 2.5, >= 2.5.2)
|
22
|
-
nokogiri (~> 1.4)
|
23
|
-
ntlm-http (~> 0.1, >= 0.1.1)
|
24
|
-
webrobots (>= 0.0.9, < 0.2)
|
25
|
-
mime-types (1.23)
|
26
|
-
minitest (5.0.4)
|
27
|
-
net-http-digest_auth (1.3)
|
28
|
-
net-http-persistent (2.8)
|
29
|
-
nokogiri (1.5.10)
|
30
|
-
ntlm-http (0.1.1)
|
31
|
-
progressbar (0.20.0)
|
32
|
-
rake (10.0.4)
|
10
|
+
mime-types (1.17.2)
|
11
|
+
minitest (2.11.3)
|
12
|
+
nokogiri (1.5.0)
|
13
|
+
rake (0.9.2.2)
|
33
14
|
rest-client (1.6.7)
|
34
15
|
mime-types (>= 1.16)
|
35
|
-
unf (0.1.1)
|
36
|
-
unf_ext
|
37
|
-
unf_ext (0.0.6)
|
38
|
-
webrobots (0.1.1)
|
39
16
|
|
40
17
|
PLATFORMS
|
18
|
+
java
|
41
19
|
ruby
|
42
20
|
|
43
21
|
DEPENDENCIES
|
data/README.md
CHANGED
@@ -1,122 +1,34 @@
|
|
1
|
-
__viddl-rb:__
|
2
|
-
|
3
|
-
Repo: http://github.com/rb2k/viddl-rb
|
4
|
-
[ gem
|
111
|
-
* [Nokogiri](http://nokogiri.org/)
|
112
|
-
* [Mechanize](http://mechanize.rubyforge.org/)
|
113
|
-
* ffmpeg if you want to extract audio tracks from the videos
|
114
|
-
|
115
|
-
__Co Maintainer:__
|
116
|
-
* [kl](https://github.com/kl): Windows support (who knew!), bug fixes, veoh plugin, metacafe plugin, refactoring it into a library, ...
|
117
|
-
|
118
|
-
__Contributors:__
|
119
|
-
* [divout](https://github.com/divout) aka Ivan K: blip.tv plugin, bugfixes
|
120
|
-
* Sniper: bugfixes
|
121
|
-
* [Serabe](https://github.com/Serabe) aka Sergio Arbeo: packaging viddl as a binary
|
122
|
-
* [laserlemon](https://github.com/laserlemon): Adding gemnasium images to readme
|
1
|
+
__viddl-rb:__
|
2
|
+
Created by Marc Seeger (@rb2k)
|
3
|
+
Repo: http://github.com/rb2k/viddl-rb
|
4
|
+
[](http://travis-ci.org/rb2k/viddl-rb)
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
__Installation:__
|
9
|
+
gem install viddl-rb
|
10
|
+
|
11
|
+
__Usage:__
|
12
|
+
|
13
|
+
Download a video:
|
14
|
+
viddl-rb http://www.youtube.com/watch?v=QH2-TGUlwu4
|
15
|
+
|
16
|
+
Download a video and extract the audio:
|
17
|
+
viddl-rb http://www.youtube.com/watch?v=QH2-TGUlwu4 --extract-audio
|
18
|
+
|
19
|
+
In both cases we'll name the output file according to the video title.
|
20
|
+
|
21
|
+
|
22
|
+
__Requirements:__
|
23
|
+
|
24
|
+
* curl/wget or the [progress bar](http://github.com/nex3/ruby-progressbar/) gem
|
25
|
+
* [Nokogiri](http://nokogiri.org/)
|
26
|
+
* ffmpeg if you want to extract audio tracks from the videos
|
27
|
+
|
28
|
+
|
29
|
+
__Contributors:__
|
30
|
+
|
31
|
+
* [kl](https://github.com/kl): Windows support (who knew!), bug fixes, veoh plugin, metacafe plugin
|
32
|
+
* [divout](https://github.com/divout) aka Ivan K: blip.tv plugin, bugfixes
|
33
|
+
* Sniper: bugfixes
|
34
|
+
* [Serabe](https://github.com/Serabe) aka Sergio Arbeo: packaging viddl as a binary
|
data/Rakefile
CHANGED
@@ -1,22 +1,8 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require '
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
t.test_files = ["spec/lib_spec.rb", "spec/url_extraction_spec.rb", "spec/integration_spec.rb"]
|
10
|
-
end
|
11
|
-
|
12
|
-
Rake::TestTask.new(:test_lib) do |t|
|
13
|
-
t.test_files = FileList["spec/lib_spec.rb"]
|
14
|
-
end
|
15
|
-
|
16
|
-
Rake::TestTask.new(:test_extract) do |t|
|
17
|
-
t.test_files = FileList["spec/url_extraction_spec.rb"]
|
18
|
-
end
|
19
|
-
|
20
|
-
Rake::TestTask.new(:test_integration) do |t|
|
21
|
-
t.test_files = FileList["spec/integration_spec.rb"]
|
22
|
-
end
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
task :default => [:test]
|
5
|
+
|
6
|
+
Rake::TestTask.new do |t|
|
7
|
+
t.pattern = "spec/*_spec.rb"
|
8
|
+
end
|
data/bin/viddl-rb
CHANGED
@@ -1,45 +1,117 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'helper')
|
3
|
-
|
4
|
-
|
5
|
-
require "
|
6
|
-
require "
|
7
|
-
require "
|
8
|
-
require "
|
9
|
-
require "
|
10
|
-
require "
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'helper')
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
require "nokogiri"
|
6
|
+
require "cgi"
|
7
|
+
require "open-uri"
|
8
|
+
require "open3"
|
9
|
+
require "download-helper.rb"
|
10
|
+
require "plugin-helper.rb"
|
11
|
+
|
12
|
+
if ARGV[0].nil?
|
13
|
+
puts "Usage: viddl-rb URL [--extract-audio]"
|
14
|
+
exit
|
15
|
+
end
|
16
|
+
|
17
|
+
puts "Loading Plugins"
|
18
|
+
Dir[File.join(File.dirname(__FILE__),"../plugins/*.rb")].each do |plugin|
|
19
|
+
load plugin
|
20
|
+
end
|
21
|
+
|
22
|
+
puts "Plugins loaded: #{PluginBase.registered_plugins.inspect}"
|
23
|
+
|
24
|
+
url = ARGV[0]
|
25
|
+
extract_audio = ARGV.include?('--extract-audio')
|
26
|
+
url_only = ARGV.include?('--url-only')
|
27
|
+
title_only = ARGV.include?('--title-only')
|
28
|
+
|
29
|
+
puts "Will try to extract audio: #{extract_audio}."
|
30
|
+
|
31
|
+
unless url.match(/^http/)
|
32
|
+
puts "Please include 'http' with your URL e.g. http://www.youtube.com/watch?v=QH2-TGUlwu4"
|
33
|
+
exit(1)
|
34
|
+
end
|
35
|
+
|
36
|
+
puts "Analyzing URL: #{url}"
|
37
|
+
#Check all plugins for a match
|
38
|
+
PluginBase.registered_plugins.each do |plugin|
|
39
|
+
if plugin.matches_provider?(url)
|
40
|
+
puts "#{plugin}: true"
|
41
|
+
begin
|
42
|
+
#we'll end up with an array of hashes with they keys :url and :name
|
43
|
+
download_queue = plugin.get_urls_and_filenames(url)
|
44
|
+
rescue StandardError => e
|
45
|
+
puts "Error while running the #{plugin.name.inspect} plugin. Maybe it has to be updated? Error: #{e.message}."
|
46
|
+
exit(1)
|
47
|
+
end
|
48
|
+
|
49
|
+
if url_only
|
50
|
+
download_queue.each{|url_name| puts url_name[:url]}
|
51
|
+
exit
|
52
|
+
elsif title_only
|
53
|
+
download_queue.each{|url_name| puts url_name[:name]}
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
|
57
|
+
download_queue.each do |url_name|
|
58
|
+
result = DownloadHelper.save_file(url_name[:url], url_name[:name])
|
59
|
+
if result
|
60
|
+
puts "Download for #{url_name[:name]} successful."
|
61
|
+
if extract_audio
|
62
|
+
puts "Extracting audio for #{url_name[:name]}"
|
63
|
+
if DownloadHelper.os_has?('ffmpeg')
|
64
|
+
no_ext_filename = url_name[:name].split('.')[0..-1][0]
|
65
|
+
#capture stderr because ffmpeg expects an output param and will error out
|
66
|
+
puts "Gathering information about the downloaded file."
|
67
|
+
file_info = Open3.popen3("ffmpeg -i #{url_name[:name]}") {|stdin, stdout, stderr, wait_thr| stderr.read }
|
68
|
+
puts "Done gathering information about the downloaded file."
|
69
|
+
if !file_info.to_s.empty?
|
70
|
+
audio_format_matches = file_info.match(/Audio: (\w*)/)
|
71
|
+
if audio_format_matches
|
72
|
+
audio_format = audio_format_matches[1]
|
73
|
+
puts "detected audio format: #{audio_format}"
|
74
|
+
else
|
75
|
+
puts "Couldn't find any audio:\n#{file_info.inspect}"
|
76
|
+
next
|
77
|
+
end
|
78
|
+
|
79
|
+
extension_mapper = {
|
80
|
+
'aac' => 'm4a',
|
81
|
+
'mp3' => 'mp3',
|
82
|
+
'vorbis' => 'ogg'
|
83
|
+
}
|
84
|
+
|
85
|
+
if extension_mapper.key?(audio_format)
|
86
|
+
output_extension = extension_mapper[audio_format]
|
87
|
+
else
|
88
|
+
#lame fallback
|
89
|
+
puts "Unknown audio format: #{audio_format}, using name as extension: '.#{audio_format}'."
|
90
|
+
output_extension = audio_format
|
91
|
+
end
|
92
|
+
output_filename = "#{no_ext_filename}.#{output_extension}"
|
93
|
+
if File.exist?(output_filename)
|
94
|
+
puts "Audio file seems to exist already, removing it before extraction."
|
95
|
+
File.delete(output_filename)
|
96
|
+
end
|
97
|
+
Open3.popen3("ffmpeg -i #{url_name[:name]} -vn -acodec copy #{output_filename}") {|stdin, stdout, stderr, wait_thr| stdout.read }
|
98
|
+
puts "Done extracting audio to #{output_filename}"
|
99
|
+
else
|
100
|
+
puts "Error while checking audio track of #{url_name[:name]}"
|
101
|
+
end
|
102
|
+
else
|
103
|
+
puts "Didn't detect ffmpeg on your system, can't extract audio."
|
104
|
+
end
|
105
|
+
end
|
106
|
+
else
|
107
|
+
puts "Download for #{url_name[:name]} failed."
|
108
|
+
end
|
109
|
+
end
|
110
|
+
#plugin matched and downloaded, we're done
|
111
|
+
exit
|
112
|
+
else
|
113
|
+
puts "#{plugin}: false"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
puts "No plugin seems to feel responsible for this URL."
|
data/helper/download-helper.rb
CHANGED
@@ -1,94 +1,67 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
def self.download_and_save_file(download_url, full_path)
|
69
|
-
final_url = UtilityHelper.get_final_location(download_url) # follow all redirects
|
70
|
-
uri = URI(final_url)
|
71
|
-
file = File.new(full_path, "wb")
|
72
|
-
file_size = 0
|
73
|
-
|
74
|
-
Net::HTTP.start(uri.host, uri.port) do |http|
|
75
|
-
http.request_get(uri.request_uri) do |res|
|
76
|
-
file_size = res.read_header["content-length"].to_i
|
77
|
-
bar = ProgressBar.new(File.basename(full_path), file_size)
|
78
|
-
bar.file_transfer_mode
|
79
|
-
res.read_body do |segment|
|
80
|
-
bar.inc(segment.size)
|
81
|
-
file.write(segment)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
file.close
|
86
|
-
print "\n"
|
87
|
-
download_successful?(full_path, file_size) #because Net::HTTP.start does not throw Net exceptions
|
88
|
-
end
|
89
|
-
|
90
|
-
def self.download_successful?(full_file_path, file_size)
|
91
|
-
File.exist?(full_file_path) && File.size(full_file_path) == file_size
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
1
|
+
class DownloadHelper
|
2
|
+
#usually not called directly
|
3
|
+
def self.fetch_file(uri)
|
4
|
+
|
5
|
+
begin
|
6
|
+
require "progressbar" #http://github.com/nex3/ruby-progressbar
|
7
|
+
rescue LoadError
|
8
|
+
puts "ERROR: You don't seem to have curl or wget on your system. In this case you'll need to install the 'progressbar' gem."
|
9
|
+
exit
|
10
|
+
end
|
11
|
+
progress_bar = nil
|
12
|
+
open(uri, :proxy => nil,
|
13
|
+
:content_length_proc => lambda { |length|
|
14
|
+
if length && 0 < length
|
15
|
+
progress_bar = ProgressBar.new(uri.to_s, length)
|
16
|
+
end
|
17
|
+
},
|
18
|
+
:progress_proc => lambda { |progress|
|
19
|
+
progress_bar.set(progress) if progress_bar
|
20
|
+
}) {|file| return file.read}
|
21
|
+
end
|
22
|
+
|
23
|
+
#simple helper that will save a file from the web and save it with a progress bar
|
24
|
+
def self.save_file(file_uri, file_name)
|
25
|
+
unescaped_uri = CGI::unescape(file_uri)
|
26
|
+
result = false
|
27
|
+
if os_has?("wget")
|
28
|
+
puts "using wget"
|
29
|
+
result = system("wget \"#{unescaped_uri}\" -O #{file_name}")
|
30
|
+
elsif os_has?("curl")
|
31
|
+
puts "using curl"
|
32
|
+
#-L means: follow redirects, We set an agent because Vimeo seems to want one
|
33
|
+
result = system("curl -A 'Wget/1.8.1' -L \"#{unescaped_uri}\" -o #{file_name}")
|
34
|
+
else
|
35
|
+
puts "using net/http"
|
36
|
+
open(file_name, 'wb') { |file|
|
37
|
+
file.write(fetch_file(unescaped_uri)); puts
|
38
|
+
}
|
39
|
+
result = true
|
40
|
+
end
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
#checks to see whether the os has a certain utility like wget or curl
|
45
|
+
def self.os_has?(utility)
|
46
|
+
windows = ENV['OS'] =~ /windows/i
|
47
|
+
return `which #{utility}`.include?(utility) unless windows # if not Windows
|
48
|
+
|
49
|
+
#use where (simliar to which) if present to reduce console clutter
|
50
|
+
begin
|
51
|
+
has_where? ? `where #{utility}` : `#{utility}`
|
52
|
+
return true
|
53
|
+
rescue Errno::ENOENT
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
#checks if Windows has the where utility (Server 2003 and later)
|
59
|
+
def self.has_where?
|
60
|
+
begin
|
61
|
+
`where`
|
62
|
+
true
|
63
|
+
rescue Errno::ENOENT
|
64
|
+
false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|