viddl-rb 0.73 → 0.74
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/README.md +7 -6
- data/bin/helper/downloader.rb +1 -6
- data/bin/helper/parameter-parser.rb +14 -6
- data/bin/viddl-rb +2 -2
- data/helper/download-helper.rb +72 -35
- data/helper/utility-helper.rb +11 -2
- data/lib/viddl-rb.rb +1 -11
- metadata +19 -5
data/README.md
CHANGED
@@ -10,7 +10,7 @@ gem install viddl-rb
|
|
10
10
|
__Usage:__
|
11
11
|
|
12
12
|
Download a video:
|
13
|
-
viddl-rb http://www.youtube.com/watch?v=QH2-TGUlwu4
|
13
|
+
```viddl-rb http://www.youtube.com/watch?v=QH2-TGUlwu4```
|
14
14
|
|
15
15
|
Viddl-rb supports the following command line options:
|
16
16
|
```
|
@@ -19,16 +19,17 @@ Viddl-rb supports the following command line options:
|
|
19
19
|
-t, --title-only Prints title without downloading
|
20
20
|
-f, --filter REGEX Filters a video playlist according to the regex (Youtube only right now)
|
21
21
|
-s, --save-dir DIRECTORY Specifies the directory where videos should be saved
|
22
|
+
-d, --downloader TOOL Specifies the tool to download with. Supports 'wget', 'curl' and 'net-http'
|
22
23
|
-h, --help Displays the help screen
|
23
24
|
```
|
24
25
|
|
25
26
|
Download a video and extract the audio:
|
26
|
-
viddl-rb http://www.youtube.com/watch?v=QH2-TGUlwu4 --extract-audio
|
27
|
+
```viddl-rb http://www.youtube.com/watch?v=QH2-TGUlwu4 --extract-audio```
|
27
28
|
|
28
29
|
In both cases we'll name the output file according to the video title.
|
29
30
|
|
30
31
|
Setting the video save directory:
|
31
|
-
viddl-rb http://vimeo.com/38372260 --save-dir C:/myvideos
|
32
|
+
```viddl-rb http://vimeo.com/38372260 --save-dir C:/myvideos```
|
32
33
|
|
33
34
|
The --save-dir option works with both absolute and relative paths (relative based on the directory viddl-rb is run from).
|
34
35
|
If you want to save to a folder with spaces in it, you have to quote the path like this: --save-dir "C:/my videos"
|
@@ -36,13 +37,13 @@ If you want to save to a folder with spaces in it, you have to quote the path li
|
|
36
37
|
__Youtube plugin specifics:__
|
37
38
|
|
38
39
|
Download all videos on a playlist:
|
39
|
-
viddl-rb http://www.youtube.com/playlist?list=PL7E8DA0A515924126
|
40
|
+
```viddl-rb http://www.youtube.com/playlist?list=PL7E8DA0A515924126```
|
40
41
|
|
41
42
|
Download all videos from a user:
|
42
|
-
viddl-rb http://www.youtube.com/user/tedtalksdirector
|
43
|
+
```viddl-rb http://www.youtube.com/user/tedtalksdirector```
|
43
44
|
|
44
45
|
Filter videos to download from a user/playlist:
|
45
|
-
viddl-rb http://www.youtube.com/user/tedtalksdirector --filter /internet/i
|
46
|
+
```viddl-rb http://www.youtube.com/user/tedtalksdirector --filter /internet/i```
|
46
47
|
|
47
48
|
The --filter argument accepts a regular expression and will only download videos where the title matches the regex.
|
48
49
|
It uses the same syntax as Ruby regular expression literals do.
|
data/bin/helper/downloader.rb
CHANGED
@@ -8,7 +8,7 @@ class Downloader
|
|
8
8
|
url = url_name[:url]
|
9
9
|
name = url_name[:name]
|
10
10
|
|
11
|
-
result = save_file(url, name, params[:save_dir])
|
11
|
+
result = ViddlRb::DownloadHelper.save_file(url, name, :save_dir => params[:save_dir], :tool => params[:tool])
|
12
12
|
unless result
|
13
13
|
raise DownloadFailedError, "Download for #{name} failed."
|
14
14
|
else
|
@@ -17,9 +17,4 @@ class Downloader
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
21
|
-
# TODO save_dir is not used yet
|
22
|
-
def save_file(url, name, save_dir)
|
23
|
-
ViddlRb::DownloadHelper.save_file(url, name, save_dir)
|
24
|
-
end
|
25
20
|
end
|
@@ -22,7 +22,8 @@ class ParameterParser
|
|
22
22
|
:url_only => false,
|
23
23
|
:title_only => false,
|
24
24
|
:playlist_filter => nil,
|
25
|
-
:save_dir => DEFAULT_SAVE_DIR
|
25
|
+
:save_dir => DEFAULT_SAVE_DIR,
|
26
|
+
:tool => nil
|
26
27
|
}
|
27
28
|
|
28
29
|
optparse = OptionParser.new do |opts|
|
@@ -56,6 +57,14 @@ class ParameterParser
|
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
60
|
+
opts.on("-d", "--downloader TOOL", "Specifies the tool to download with. Supports 'wget', 'curl' and 'net-http'") do |tool|
|
61
|
+
if tool =~ /(^wget$)|(^curl$)|(^net-http$)/
|
62
|
+
options[:tool] = tool
|
63
|
+
else
|
64
|
+
raise OptionParser::InvalidArgument.new("'#{tool}' is not a valid tool.")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
59
68
|
opts.on_tail('-h', '--help', 'Display this screen') do
|
60
69
|
print_help_and_exit(opts)
|
61
70
|
end
|
@@ -63,7 +72,8 @@ class ParameterParser
|
|
63
72
|
|
64
73
|
optparse.parse!(args) # removes all options from args
|
65
74
|
print_help_and_exit(optparse) if args.empty? # exit if no video url
|
66
|
-
url =
|
75
|
+
url = args.first # the url is the only element left
|
76
|
+
validate_url!(url) # raise exception if invalid url
|
67
77
|
options[:url] = url
|
68
78
|
options
|
69
79
|
end
|
@@ -73,10 +83,8 @@ class ParameterParser
|
|
73
83
|
exit(0)
|
74
84
|
end
|
75
85
|
|
76
|
-
def self.validate_url(url)
|
77
|
-
|
78
|
-
url
|
79
|
-
else
|
86
|
+
def self.validate_url!(url)
|
87
|
+
unless url =~ /^http/
|
80
88
|
raise OptionParser::InvalidArgument.new(
|
81
89
|
"please include 'http' with your URL e.g. http://www.youtube.com/watch?v=QH2-TGUlwu4")
|
82
90
|
end
|
data/bin/viddl-rb
CHANGED
@@ -25,7 +25,7 @@ begin
|
|
25
25
|
|
26
26
|
puts "Loading Plugins"
|
27
27
|
ViddlRb::UtilityHelper.load_plugins
|
28
|
-
"Plugins loaded: #{ViddlRb::PluginBase.registered_plugins.inspect}"
|
28
|
+
puts "Plugins loaded: #{ViddlRb::PluginBase.registered_plugins.inspect}"
|
29
29
|
|
30
30
|
puts "Will try to extract audio: #{params[:extract_audio] == true}."
|
31
31
|
puts "Analyzing URL: #{params[:url]}"
|
@@ -33,7 +33,7 @@ begin
|
|
33
33
|
app = Driver.new(params)
|
34
34
|
app.start # starts the download process
|
35
35
|
|
36
|
-
rescue OptionParser::ParseError => e
|
36
|
+
rescue OptionParser::ParseError, ViddlRb::RequirementError => e
|
37
37
|
puts "Error: #{e.message}"
|
38
38
|
exit(1)
|
39
39
|
|
data/helper/download-helper.rb
CHANGED
@@ -1,57 +1,94 @@
|
|
1
1
|
module ViddlRb
|
2
2
|
|
3
|
+
class RequirementError < StandardError; end
|
4
|
+
|
3
5
|
class DownloadHelper
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
rescue LoadError
|
9
|
-
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."
|
10
|
-
exit
|
11
|
-
end
|
12
|
-
progress_bar = nil
|
13
|
-
open(uri, :proxy => nil,
|
14
|
-
:content_length_proc => lambda { |length|
|
15
|
-
if length && 0 < length
|
16
|
-
progress_bar = ProgressBar.new(uri.to_s, length)
|
17
|
-
progress_bar.file_transfer_mode #to show download speed and file size
|
18
|
-
end
|
19
|
-
},
|
20
|
-
:progress_proc => lambda { |progress|
|
21
|
-
progress_bar.set(progress) if progress_bar
|
22
|
-
}) {|file| return file.read}
|
23
|
-
end
|
6
|
+
|
7
|
+
#viddl will use the first of these tools it finds on the system to download the video.
|
8
|
+
#if the system does not have any of these tools, net/http is used instead.
|
9
|
+
TOOLS_PRIORITY_LIST = [:wget, :curl]
|
24
10
|
|
25
11
|
#simple helper that will save a file from the web and save it with a progress bar
|
26
|
-
def self.save_file(
|
12
|
+
def self.save_file(file_url, file_name, opts = {})
|
27
13
|
trap("SIGINT") { puts "goodbye"; exit }
|
28
14
|
|
29
|
-
|
15
|
+
#default options
|
16
|
+
options = {:save_dir => ".",
|
17
|
+
:amount_of_retries => 6,
|
18
|
+
:tool => get_tool}
|
19
|
+
|
20
|
+
opts[:tool] = options[:tool] if opts[:tool].nil?
|
21
|
+
options.merge!(opts)
|
22
|
+
|
23
|
+
file_path = File.expand_path(File.join(options[:save_dir], file_name))
|
24
|
+
success = false
|
25
|
+
|
30
26
|
#Some providers seem to flake out every now end then
|
31
|
-
amount_of_retries.times do |i|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
27
|
+
options[:amount_of_retries].times do |i|
|
28
|
+
case options[:tool].to_sym
|
29
|
+
when :wget
|
30
|
+
puts "Using wget"
|
31
|
+
success = system "wget \"#{file_url}\" -O #{file_path.inspect}"
|
32
|
+
when :curl
|
33
|
+
puts "Using curl"
|
37
34
|
#-L means: follow redirects, We set an agent because Vimeo seems to want one
|
38
|
-
|
35
|
+
success = system "curl -A 'Wget/1.8.1' --retry 10 --retry-delay 5 --retry-max-time 4 -L \"#{file_url}\" -o #{file_path.inspect}"
|
39
36
|
else
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
}
|
37
|
+
require_progressbar
|
38
|
+
puts "Using net/http"
|
39
|
+
success = download_and_save_file(file_url, file_path)
|
44
40
|
end
|
45
41
|
#we were successful, we're outta here
|
46
|
-
if
|
42
|
+
if success
|
47
43
|
break
|
48
44
|
else
|
49
45
|
puts "Download seems to have failed (retrying, attempt #{i+1}/#{amount_of_retries})"
|
50
46
|
sleep 2
|
51
47
|
end
|
52
48
|
end
|
53
|
-
|
49
|
+
success
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.get_tool
|
53
|
+
tool = TOOLS_PRIORITY_LIST.find { |tool| ViddlRb::UtilityHelper.os_has?(tool) }
|
54
|
+
tool || :net_http
|
54
55
|
end
|
55
56
|
|
57
|
+
def self.require_progressbar
|
58
|
+
begin
|
59
|
+
require "progressbar"
|
60
|
+
rescue LoadError
|
61
|
+
raise RequirementError,
|
62
|
+
"you don't seem to have curl or wget on your system. In this case you'll need to install the 'progressbar' gem."
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# downloads and saves a file using the net/http streaming api
|
67
|
+
# return true if the download was successful, else returns false
|
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
|
56
93
|
end
|
57
94
|
end
|
data/helper/utility-helper.rb
CHANGED
@@ -18,7 +18,7 @@ module ViddlRb
|
|
18
18
|
windows = ENV['OS'] =~ /windows/i
|
19
19
|
|
20
20
|
unless windows
|
21
|
-
`which #{utility}`.include?(utility)
|
21
|
+
`which #{utility}`.include?(utility.to_s)
|
22
22
|
else
|
23
23
|
if !system("where /q where").nil? #if Windows has the where utility
|
24
24
|
system("where /q #{utility}") #/q is the quiet mode flag
|
@@ -31,6 +31,15 @@ module ViddlRb
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
34
|
-
|
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
|
+
|
35
44
|
end
|
36
45
|
end
|
data/lib/viddl-rb.rb
CHANGED
@@ -95,19 +95,9 @@ module ViddlRb
|
|
95
95
|
def self.follow_all_redirects(urls_filenames)
|
96
96
|
urls_filenames.map do |uf|
|
97
97
|
url = uf[:url]
|
98
|
-
final_location = get_final_location(url)
|
98
|
+
final_location = UtilityHelper.get_final_location(url)
|
99
99
|
{:url => final_location, :name => uf[:name]}
|
100
100
|
end
|
101
101
|
end
|
102
102
|
private_class_method :follow_all_redirects
|
103
|
-
|
104
|
-
#recursively get the final location (after following all redirects) for an url.
|
105
|
-
def self.get_final_location(url)
|
106
|
-
Net::HTTP.get_response(URI(url)) do |res|
|
107
|
-
location = res["location"]
|
108
|
-
return url if location.nil?
|
109
|
-
return get_final_location(location)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
private_class_method :get_final_location
|
113
103
|
end
|
metadata
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: viddl-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 159
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: "0.
|
8
|
+
- 74
|
9
|
+
version: "0.74"
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Marc Seeger
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2012-10-
|
17
|
+
date: 2012-10-07 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -87,7 +87,21 @@ dependencies:
|
|
87
87
|
version: "0"
|
88
88
|
type: :development
|
89
89
|
version_requirements: *id005
|
90
|
-
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: progressbar
|
92
|
+
prerelease: false
|
93
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
hash: 3
|
99
|
+
segments:
|
100
|
+
- 0
|
101
|
+
version: "0"
|
102
|
+
type: :development
|
103
|
+
version_requirements: *id006
|
104
|
+
description: An extendable commandline video downloader for flash video sites. Includes plugins for vimeo, youtube, dailymotion and more
|
91
105
|
email: mail@marc-seeger.de
|
92
106
|
executables:
|
93
107
|
- viddl-rb
|