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
metadata
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: viddl-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 113
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
-
|
8
|
-
version: "0.
|
8
|
+
- 61
|
9
|
+
version: "0.61"
|
9
10
|
platform: ruby
|
10
11
|
authors:
|
11
12
|
- Marc Seeger
|
@@ -13,84 +14,65 @@ autorequire:
|
|
13
14
|
bindir: bin
|
14
15
|
cert_chain: []
|
15
16
|
|
16
|
-
date:
|
17
|
-
default_executable:
|
17
|
+
date: 2012-04-15 00:00:00 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: nokogiri
|
21
21
|
prerelease: false
|
22
22
|
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
23
24
|
requirements:
|
24
|
-
- -
|
25
|
+
- - ">="
|
25
26
|
- !ruby/object:Gem::Version
|
27
|
+
hash: 3
|
26
28
|
segments:
|
27
|
-
- 1
|
28
|
-
- 5
|
29
29
|
- 0
|
30
|
-
version:
|
30
|
+
version: "0"
|
31
31
|
type: :runtime
|
32
32
|
version_requirements: *id001
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
34
|
+
name: rake
|
35
35
|
prerelease: false
|
36
36
|
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
37
38
|
requirements:
|
38
39
|
- - ">="
|
39
40
|
- !ruby/object:Gem::Version
|
41
|
+
hash: 3
|
40
42
|
segments:
|
41
43
|
- 0
|
42
44
|
version: "0"
|
43
|
-
type: :
|
45
|
+
type: :development
|
44
46
|
version_requirements: *id002
|
45
47
|
- !ruby/object:Gem::Dependency
|
46
|
-
name:
|
48
|
+
name: minitest
|
47
49
|
prerelease: false
|
48
50
|
requirement: &id003 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
49
52
|
requirements:
|
50
53
|
- - ">="
|
51
54
|
- !ruby/object:Gem::Version
|
55
|
+
hash: 3
|
52
56
|
segments:
|
53
57
|
- 0
|
54
58
|
version: "0"
|
55
|
-
type: :
|
59
|
+
type: :development
|
56
60
|
version_requirements: *id003
|
57
61
|
- !ruby/object:Gem::Dependency
|
58
|
-
name:
|
62
|
+
name: rest-client
|
59
63
|
prerelease: false
|
60
64
|
requirement: &id004 !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
61
66
|
requirements:
|
62
67
|
- - ">="
|
63
68
|
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
64
70
|
segments:
|
65
71
|
- 0
|
66
72
|
version: "0"
|
67
73
|
type: :development
|
68
74
|
version_requirements: *id004
|
69
|
-
|
70
|
-
name: rest-client
|
71
|
-
prerelease: false
|
72
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
73
|
-
requirements:
|
74
|
-
- - ">="
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
segments:
|
77
|
-
- 0
|
78
|
-
version: "0"
|
79
|
-
type: :development
|
80
|
-
version_requirements: *id005
|
81
|
-
- !ruby/object:Gem::Dependency
|
82
|
-
name: minitest
|
83
|
-
prerelease: false
|
84
|
-
requirement: &id006 !ruby/object:Gem::Requirement
|
85
|
-
requirements:
|
86
|
-
- - ">="
|
87
|
-
- !ruby/object:Gem::Version
|
88
|
-
segments:
|
89
|
-
- 0
|
90
|
-
version: "0"
|
91
|
-
type: :development
|
92
|
-
version_requirements: *id006
|
93
|
-
description: An extendable commandline video downloader for flash video sites. Includes plugins for vimeo, youtube, dailymotion and more
|
75
|
+
description: An extendable commandline video downloader for flash video sites. Includes plugins for vimeo, youtube and megavideo
|
94
76
|
email: mail@marc-seeger.de
|
95
77
|
executables:
|
96
78
|
- viddl-rb
|
@@ -99,28 +81,20 @@ extensions: []
|
|
99
81
|
extra_rdoc_files: []
|
100
82
|
|
101
83
|
files:
|
102
|
-
- bin/helper/downloader.rb
|
103
|
-
- bin/helper/driver.rb
|
104
|
-
- bin/helper/parameter-parser.rb
|
105
84
|
- bin/viddl-rb
|
106
|
-
- lib/viddl-rb.rb
|
107
|
-
- helper/audio-helper.rb
|
108
85
|
- helper/download-helper.rb
|
109
86
|
- helper/plugin-helper.rb
|
110
|
-
- helper/utility-helper.rb
|
111
87
|
- plugins/blip.rb
|
112
|
-
- plugins/dailymotion.rb
|
113
88
|
- plugins/metacafe.rb
|
114
89
|
- plugins/soundcloud.rb
|
115
90
|
- plugins/veoh.rb
|
116
91
|
- plugins/vimeo.rb
|
117
92
|
- plugins/youtube.rb
|
93
|
+
- CHANGELOG.txt
|
118
94
|
- Gemfile
|
119
95
|
- Gemfile.lock
|
120
96
|
- Rakefile
|
121
97
|
- README.md
|
122
|
-
- TODO.txt
|
123
|
-
has_rdoc: true
|
124
98
|
homepage: https://github.com/rb2k/viddl-rb
|
125
99
|
licenses: []
|
126
100
|
|
@@ -128,18 +102,22 @@ post_install_message:
|
|
128
102
|
rdoc_options: []
|
129
103
|
|
130
104
|
require_paths:
|
131
|
-
-
|
105
|
+
- .
|
132
106
|
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
133
108
|
requirements:
|
134
109
|
- - ">="
|
135
110
|
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
136
112
|
segments:
|
137
113
|
- 0
|
138
114
|
version: "0"
|
139
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
140
117
|
requirements:
|
141
118
|
- - ">="
|
142
119
|
- !ruby/object:Gem::Version
|
120
|
+
hash: 19
|
143
121
|
segments:
|
144
122
|
- 1
|
145
123
|
- 3
|
@@ -148,9 +126,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
126
|
requirements: []
|
149
127
|
|
150
128
|
rubyforge_project: viddl-rb
|
151
|
-
rubygems_version: 1.
|
129
|
+
rubygems_version: 1.8.21
|
152
130
|
signing_key:
|
153
131
|
specification_version: 3
|
154
132
|
summary: An extendable commandline video downloader for flash video sites.
|
155
133
|
test_files: []
|
156
134
|
|
135
|
+
has_rdoc: false
|
data/TODO.txt
DELETED
data/bin/helper/downloader.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
|
2
|
-
# Downloader iterates over a download queue and downloads and saves each video in the queue.
|
3
|
-
class Downloader
|
4
|
-
class DownloadFailedError < StandardError; end
|
5
|
-
|
6
|
-
def download(download_queue, params)
|
7
|
-
download_queue.each do |url_name|
|
8
|
-
url = url_name[:url]
|
9
|
-
name = url_name[:name]
|
10
|
-
|
11
|
-
result = ViddlRb::DownloadHelper.save_file(url, name, :save_dir => params[:save_dir], :tool => params[:tool])
|
12
|
-
unless result
|
13
|
-
raise DownloadFailedError, "Download for #{name} failed."
|
14
|
-
else
|
15
|
-
puts "Download for #{name} successful."
|
16
|
-
ViddlRb::AudioHelper.extract(name, params[:save_dir]) if params[:extract_audio]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/bin/helper/driver.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
|
2
|
-
# The Driver class drives the application logic in the viddl-rb utility.
|
3
|
-
# It gets the correct plugin for the given url and passes a download queue
|
4
|
-
# (that it gets from the plugin) to the Downloader object which downloads the videos.
|
5
|
-
class Driver
|
6
|
-
|
7
|
-
def initialize(param_hash)
|
8
|
-
@params = param_hash
|
9
|
-
@downloader = Downloader.new
|
10
|
-
end
|
11
|
-
|
12
|
-
#starts the downloading process or print just the urls or names.
|
13
|
-
def start
|
14
|
-
queue = get_download_queue
|
15
|
-
|
16
|
-
if @params[:url_only]
|
17
|
-
queue.each { |url_name| puts url_name[:url] }
|
18
|
-
elsif @params[:title_only]
|
19
|
-
queue.each { |url_name| puts url_name[:name] }
|
20
|
-
else
|
21
|
-
@downloader.download(queue, @params)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
#finds the right plugins and returns the download queue.
|
28
|
-
def get_download_queue
|
29
|
-
url = @params[:url]
|
30
|
-
plugin = ViddlRb::PluginBase.registered_plugins.find { |p| p.matches_provider?(url) }
|
31
|
-
raise "ERROR: No plugin seems to feel responsible for this URL." unless plugin
|
32
|
-
puts "Using plugin: #{plugin}"
|
33
|
-
|
34
|
-
begin
|
35
|
-
#we'll end up with an array of hashes with they keys :url and :name
|
36
|
-
plugin.get_urls_and_filenames(url, @params)
|
37
|
-
|
38
|
-
rescue ViddlRb::PluginBase::CouldNotDownloadVideoError => e
|
39
|
-
raise "ERROR: The video could not be downloaded.\n" +
|
40
|
-
"Reason: #{e.message}"
|
41
|
-
rescue StandardError => e
|
42
|
-
raise "Error while running the #{plugin.name.inspect} plugin. Maybe it has to be updated?\n" +
|
43
|
-
"Error: #{e.message}.\n" +
|
44
|
-
"Backtrace:\n#{e.backtrace.join("\n")}"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,109 +0,0 @@
|
|
1
|
-
|
2
|
-
# ParameterParser parses the program parameters.
|
3
|
-
# If the parameters are not valid in some way an exception is raised.
|
4
|
-
# The exceptions raised by this class are handeled in the bin program.
|
5
|
-
|
6
|
-
class ParameterParser
|
7
|
-
|
8
|
-
DEFAULT_SAVE_DIR = "."
|
9
|
-
|
10
|
-
#returns a hash with the parameters in it:
|
11
|
-
# :url => the video url
|
12
|
-
# :extract_audio => should attempt to extract audio? (true/false)
|
13
|
-
# :url_only => do not download, only print the urls to stdout
|
14
|
-
# :title_only => do not download, only print the titles to stdout
|
15
|
-
# :playlist_filter => a regular expression used to filter playlists
|
16
|
-
# :save_dir => the directory where the videos are saved
|
17
|
-
# :tool => the download tool (wget, curl, net/http) to use
|
18
|
-
# :quality => the resolution and format to download
|
19
|
-
def self.parse_app_parameters(args)
|
20
|
-
|
21
|
-
# Default option values are set here
|
22
|
-
options = {
|
23
|
-
:extract_audio => false,
|
24
|
-
:url_only => false,
|
25
|
-
:title_only => false,
|
26
|
-
:playlist_filter => nil,
|
27
|
-
:save_dir => DEFAULT_SAVE_DIR,
|
28
|
-
:tool => nil,
|
29
|
-
:quality => nil
|
30
|
-
}
|
31
|
-
|
32
|
-
optparse = OptionParser.new do |opts|
|
33
|
-
opts.banner = "Usage: viddl-rb URL [options]"
|
34
|
-
|
35
|
-
opts.on("-e", "--extract-audio", "Save video audio to file") do
|
36
|
-
if ViddlRb::UtilityHelper.os_has?("ffmpeg")
|
37
|
-
options[:extract_audio] = true
|
38
|
-
else
|
39
|
-
raise OptionParser::ParseError.new("to extract audio you need to have ffmpeg on your PATH")
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
opts.on("-u", "--url-only", "Prints url without downloading") do
|
44
|
-
options[:url_only] = true
|
45
|
-
end
|
46
|
-
|
47
|
-
opts.on("-t", "--title-only", "Prints title without downloading") do
|
48
|
-
options[:title_only] = true
|
49
|
-
end
|
50
|
-
|
51
|
-
opts.on("-f", "--filter REGEX", Regexp, "Filters a video playlist according to the regex") do |regex|
|
52
|
-
options[:filter] = regex
|
53
|
-
end
|
54
|
-
|
55
|
-
opts.on("-s", "--save-dir DIRECTORY", "Specifies the directory where videos should be saved") do |dir|
|
56
|
-
if File.directory?(dir)
|
57
|
-
options[:save_dir] = dir
|
58
|
-
else
|
59
|
-
raise OptionParser::InvalidArgument.new("'#{dir}' is not a valid directory")
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
opts.on("-d", "--downloader TOOL", "Specifies the tool to download with. Supports 'wget', 'curl' and 'net-http'") do |tool|
|
64
|
-
if tool =~ /(^wget$)|(^curl$)|(^net-http$)/
|
65
|
-
options[:tool] = tool
|
66
|
-
else
|
67
|
-
raise OptionParser::InvalidArgument.new("'#{tool}' is not a valid tool.")
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
opts.on("-q", "--quality QUALITY",
|
72
|
-
"Specifies the video format and resolution in the following way => resolution:extension (e.g. 720:mp4)") do |quality|
|
73
|
-
if match = quality.match(/(\d+):(.*)/)
|
74
|
-
res = match[1]
|
75
|
-
ext = match[2]
|
76
|
-
elsif match = quality.match(/\d+/)
|
77
|
-
res = match[0]
|
78
|
-
ext = nil
|
79
|
-
else
|
80
|
-
raise OptionParse.InvalidArgument.new("#{quality} is not a valid argument.")
|
81
|
-
end
|
82
|
-
options[:quality] = {:extension => ext, :resolution => res}
|
83
|
-
end
|
84
|
-
|
85
|
-
opts.on_tail('-h', '--help', 'Display this screen') do
|
86
|
-
print_help_and_exit(opts)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
optparse.parse!(args) # removes all options from args
|
91
|
-
print_help_and_exit(optparse) if args.empty? # exit if no video url
|
92
|
-
url = args.first # the url is the only element left
|
93
|
-
validate_url!(url) # raise exception if invalid url
|
94
|
-
options[:url] = url
|
95
|
-
options
|
96
|
-
end
|
97
|
-
|
98
|
-
def self.print_help_and_exit(opts)
|
99
|
-
puts opts
|
100
|
-
exit(0)
|
101
|
-
end
|
102
|
-
|
103
|
-
def self.validate_url!(url)
|
104
|
-
unless url =~ /^http/
|
105
|
-
raise OptionParser::InvalidArgument.new(
|
106
|
-
"please include 'http' with your URL e.g. http://www.youtube.com/watch?v=QH2-TGUlwu4")
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
data/helper/audio-helper.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
module ViddlRb
|
2
|
-
|
3
|
-
# This class is responsible for extracting audio from video files using ffmpeg.
|
4
|
-
class AudioHelper
|
5
|
-
|
6
|
-
def self.extract(file_path, save_dir)
|
7
|
-
no_ext_filename = file_path.split('.')[0..-1][0]
|
8
|
-
#capture stderr because ffmpeg expects an output param and will error out
|
9
|
-
puts "Gathering information about the downloaded file."
|
10
|
-
file_info = Open3.popen3("ffmpeg -i #{file_path}") {|stdin, stdout, stderr, wait_thr| stderr.read }
|
11
|
-
puts "Done gathering information about the downloaded file."
|
12
|
-
|
13
|
-
if !file_info.to_s.empty?
|
14
|
-
audio_format_matches = file_info.match(/Audio: (\w*)/)
|
15
|
-
if audio_format_matches
|
16
|
-
audio_format = audio_format_matches[1]
|
17
|
-
puts "detected audio format: #{audio_format}"
|
18
|
-
else
|
19
|
-
raise "ERROR: Couldn't find any audio:\n#{file_info.inspect}"
|
20
|
-
end
|
21
|
-
|
22
|
-
extension_mapper = {
|
23
|
-
'aac' => 'm4a',
|
24
|
-
'mp3' => 'mp3',
|
25
|
-
'vorbis' => 'ogg'
|
26
|
-
}
|
27
|
-
|
28
|
-
if extension_mapper.key?(audio_format)
|
29
|
-
output_extension = extension_mapper[audio_format]
|
30
|
-
else
|
31
|
-
#lame fallback
|
32
|
-
puts "Unknown audio format: #{audio_format}, using name as extension: '.#{audio_format}'."
|
33
|
-
output_extension = audio_format
|
34
|
-
end
|
35
|
-
output_filename = File.join(save_dir, "#{no_ext_filename}.#{output_extension}")
|
36
|
-
if File.exist?(output_filename)
|
37
|
-
puts "Audio file seems to exist already, removing it before extraction."
|
38
|
-
File.delete(output_filename)
|
39
|
-
end
|
40
|
-
Open3.popen3("ffmpeg -i #{file_path} -vn -acodec copy #{output_filename}") { |stdin, stdout, stderr, wait_thr| stdout.read }
|
41
|
-
puts "Done extracting audio to #{output_filename}"
|
42
|
-
else
|
43
|
-
raise "ERROR: Error while checking audio track of #{file_path}"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
data/helper/utility-helper.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
# This class contains utility methods that are used by both the bin utility and the library.
|
2
|
-
|
3
|
-
module ViddlRb
|
4
|
-
|
5
|
-
class UtilityHelper
|
6
|
-
#loads all plugins in the plugin directory.
|
7
|
-
#the plugin classes are dynamically added to the ViddlRb module.
|
8
|
-
def self.load_plugins
|
9
|
-
Dir[File.join(File.dirname(__FILE__), "../plugins/*.rb")].each do |plugin|
|
10
|
-
ViddlRb.class_eval(File.read(plugin))
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
#checks to see whether the os has a certain utility like wget or curl
|
15
|
-
#`` returns the standard output of the process
|
16
|
-
#system returns the exit code of the process
|
17
|
-
def self.os_has?(utility)
|
18
|
-
windows = ENV['OS'] =~ /windows/i
|
19
|
-
|
20
|
-
unless windows
|
21
|
-
`which #{utility}`.include?(utility.to_s)
|
22
|
-
else
|
23
|
-
if !system("where /q where").nil? #if Windows has the where utility
|
24
|
-
system("where /q #{utility}") #/q is the quiet mode flag
|
25
|
-
else
|
26
|
-
begin #as a fallback we just run the utility itself
|
27
|
-
system(utility)
|
28
|
-
rescue Errno::ENOENT
|
29
|
-
false
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
#recursively get the final location (after following all redirects) for an url.
|
36
|
-
def self.get_final_location(url)
|
37
|
-
Net::HTTP.get_response(URI(url)) do |res|
|
38
|
-
location = res["location"]
|
39
|
-
return url if location.nil?
|
40
|
-
return get_final_location(location)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
end
|