vcs_ruby 0.8.4 → 0.8.5
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/bin/vcs.rb +17 -17
- data/lib/capturer.rb +2 -2
- data/lib/command.rb +2 -2
- data/lib/contact_sheet.rb +36 -23
- data/lib/ffmpeg.rb +3 -2
- data/lib/font.rb +52 -8
- data/lib/libav.rb +3 -2
- data/lib/mplayer.rb +5 -0
- data/lib/thumbnail.rb +4 -2
- data/lib/time_index.rb +1 -1
- data/lib/tools.rb +1 -1
- data/lib/vcs.rb +2 -2
- data/lib/version.info +1 -1
- metadata +34 -2
data/bin/vcs.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
-
# Video Contact Sheet Ruby:
|
3
|
+
# Video Contact Sheet Ruby:
|
4
4
|
# ----------------------
|
5
5
|
#
|
6
6
|
# Generates contact sheets of videos
|
@@ -19,10 +19,10 @@ include VCSRuby
|
|
19
19
|
|
20
20
|
|
21
21
|
# Configuration can Override options
|
22
|
-
options =
|
23
|
-
{
|
24
|
-
quiet: false,
|
25
|
-
verbose: false,
|
22
|
+
options =
|
23
|
+
{
|
24
|
+
quiet: false,
|
25
|
+
verbose: false,
|
26
26
|
capturer: :any,
|
27
27
|
format: nil,
|
28
28
|
output: []
|
@@ -35,10 +35,10 @@ arguments =
|
|
35
35
|
'--capturer' => [:ffmpeg, :libav, :mplayer, :any],
|
36
36
|
'--format' => [:png, :jpg, :jpeg, :tiff],
|
37
37
|
'--funky' => [:polaroid, :photos, :overlap, :rotate, :photoframe, :polaroidframe, :film, :random]
|
38
|
-
}
|
38
|
+
}
|
39
39
|
|
40
40
|
# Command Line Parameters
|
41
|
-
optparse = OptionParser.new do|opts|
|
41
|
+
optparse = OptionParser.new do|opts|
|
42
42
|
opts.separator $vcs_ruby_name + ' ' + $vcs_ruby_version.to_s
|
43
43
|
opts.separator ''
|
44
44
|
opts.on( '-i [INTERVAL]', '--interval [INTERVAL]', 'Set the interval [INTERVAL]') do |interval|
|
@@ -83,7 +83,7 @@ optparse = OptionParser.new do|opts|
|
|
83
83
|
opts.on( '-s [SIGNATURE]', '--signature [SIGNATURE]', 'Change the image signature to your preference.') do |signature|
|
84
84
|
options[:signature] = signature
|
85
85
|
end
|
86
|
-
opts.on( '--no-signature', 'Remove footer with signature') do
|
86
|
+
opts.on( '--no-signature', 'Remove footer with signature') do
|
87
87
|
options[:no_signature] = true
|
88
88
|
end
|
89
89
|
opts.on( '-l [HIGHLIGHT]', '--highlight [HIGHLIGHT]' 'Add the frame found at timestamp [HIGHLIGHT] as a highlight.') do |highlight|
|
@@ -95,14 +95,14 @@ optparse = OptionParser.new do|opts|
|
|
95
95
|
opts.on("-V", "--verbose", "More verbose Output.") do
|
96
96
|
options[:verbose] = true
|
97
97
|
end
|
98
|
-
opts.on( '-v', '--version', 'Version' ) do
|
98
|
+
opts.on( '-v', '--version', 'Version' ) do
|
99
99
|
puts $vcs_ruby_name + ' ' + $vcs_ruby_version.to_s
|
100
|
-
exit 0
|
101
|
-
end
|
102
|
-
|
103
|
-
opts.on( '-h', '--help', 'Prints help' ) do
|
100
|
+
exit 0
|
101
|
+
end
|
102
|
+
|
103
|
+
opts.on( '-h', '--help', 'Prints help' ) do
|
104
104
|
options[:help] = true
|
105
|
-
end
|
105
|
+
end
|
106
106
|
|
107
107
|
opts.separator ''
|
108
108
|
opts.separator 'Examples:'
|
@@ -121,7 +121,7 @@ optparse = OptionParser.new do|opts|
|
|
121
121
|
end
|
122
122
|
|
123
123
|
Tools::print_help optparse if ARGV.empty?
|
124
|
-
|
124
|
+
|
125
125
|
optparse.parse!
|
126
126
|
|
127
127
|
Tools::print_help optparse if options[:help] || ARGV.empty?
|
@@ -137,7 +137,7 @@ begin
|
|
137
137
|
sheet.initialize_filename(options[:output][index]) if options[:output][index]
|
138
138
|
sheet.build
|
139
139
|
end
|
140
|
-
|
141
|
-
|
140
|
+
rescue Exception => e
|
141
|
+
STDERR.puts "ERROR: #{e.message}"
|
142
142
|
end
|
143
143
|
|
data/lib/capturer.rb
CHANGED
data/lib/command.rb
CHANGED
@@ -20,11 +20,11 @@ module VCSRuby
|
|
20
20
|
result = nil
|
21
21
|
if Tools::windows?
|
22
22
|
streams = '2> nul' if streams === 0
|
23
|
-
|
23
|
+
|
24
24
|
result = `cmd /C #{@command} #{parameter} #{streams}`
|
25
25
|
else
|
26
26
|
streams = "2> /dev/null" if streams === 0
|
27
|
-
|
27
|
+
|
28
28
|
result =`#{@command} #{parameter} #{streams}`
|
29
29
|
end
|
30
30
|
|
data/lib/contact_sheet.rb
CHANGED
@@ -9,11 +9,11 @@ require 'yaml'
|
|
9
9
|
require 'vcs'
|
10
10
|
|
11
11
|
module VCSRuby
|
12
|
-
class ContactSheet
|
12
|
+
class ContactSheet
|
13
13
|
attr_accessor :capturer, :format, :signature, :title, :highlight
|
14
14
|
attr_reader :thumbnail_width, :thumbnail_height
|
15
15
|
attr_reader :length, :from, :to
|
16
|
-
|
16
|
+
|
17
17
|
def initialize video, capturer = :any
|
18
18
|
@capturer = capturer
|
19
19
|
@configuration = Configuration.new
|
@@ -22,7 +22,7 @@ module VCSRuby
|
|
22
22
|
initialize_filename(File.basename(@video, '.*'))
|
23
23
|
puts "Processing #{File.basename(video)}..." unless Tools.quiet?
|
24
24
|
detect_video_properties
|
25
|
-
|
25
|
+
|
26
26
|
@thumbnails = []
|
27
27
|
|
28
28
|
@tempdir = Dir.mktmpdir
|
@@ -56,7 +56,7 @@ module VCSRuby
|
|
56
56
|
@interval = interval
|
57
57
|
end
|
58
58
|
|
59
|
-
def rows
|
59
|
+
def rows
|
60
60
|
@rows
|
61
61
|
end
|
62
62
|
|
@@ -105,7 +105,7 @@ module VCSRuby
|
|
105
105
|
raise "Invalid To Time"
|
106
106
|
end
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
109
|
|
110
110
|
def self.finalize(tempdir)
|
111
111
|
proc do
|
@@ -117,7 +117,7 @@ module VCSRuby
|
|
117
117
|
def build
|
118
118
|
initialize_thumbnails
|
119
119
|
capture_thumbnails
|
120
|
-
|
120
|
+
|
121
121
|
puts "Composing standard contact sheet..." unless Tools.quiet?
|
122
122
|
s = splice_montage(montage_thumbs)
|
123
123
|
|
@@ -135,24 +135,27 @@ private
|
|
135
135
|
def selected_capturer
|
136
136
|
result = nil
|
137
137
|
if @capturer == nil || @capturer == :any
|
138
|
-
result =
|
138
|
+
result = available_capturers.first
|
139
139
|
else
|
140
|
-
result =
|
140
|
+
result = available_capturers.select{ |c| c.name == @capturer }.first
|
141
141
|
end
|
142
|
-
raise "Selected Capturer (#{@capturer.to_s}) not available" unless result
|
142
|
+
raise "Selected Capturer (#{@capturer.to_s}) not available. Install one of these: #{@capturers.map{ |c| c.name }.join(', ')}" unless result
|
143
143
|
return result
|
144
144
|
end
|
145
145
|
|
146
146
|
def initialize_capturers video
|
147
|
-
capturers = []
|
148
|
-
capturers << LibAV.new(video)
|
149
|
-
capturers << MPlayer.new(video)
|
150
|
-
capturers << FFmpeg.new(video)
|
147
|
+
@capturers = []
|
148
|
+
@capturers << LibAV.new(video)
|
149
|
+
@capturers << MPlayer.new(video)
|
150
|
+
@capturers << FFmpeg.new(video)
|
151
151
|
|
152
152
|
@video = video
|
153
|
-
@capturers = capturers.select{ |c| c.available? }
|
154
153
|
|
155
|
-
puts "Available capturers: #{
|
154
|
+
puts "Available capturers: #{available_capturers.map{ |c| c.to_s }.join(', ')}" if Tools.verbose?
|
155
|
+
end
|
156
|
+
|
157
|
+
def available_capturers
|
158
|
+
@capturers.select{ |c| c.available? }
|
156
159
|
end
|
157
160
|
|
158
161
|
def initialize_thumbnails
|
@@ -209,7 +212,7 @@ private
|
|
209
212
|
end
|
210
213
|
montage.geometry "+#{@configuration.padding}+#{@configuration.padding}"
|
211
214
|
# rows or columns can be nil (auto fit)
|
212
|
-
montage.tile "#{@columns}x#{@rows}"
|
215
|
+
montage.tile "#{@columns}x#{@rows}"
|
213
216
|
montage << file_path
|
214
217
|
end
|
215
218
|
return file_path
|
@@ -220,9 +223,9 @@ private
|
|
220
223
|
MiniMagick::Tool::Convert.new do |convert|
|
221
224
|
convert << montage_path
|
222
225
|
convert.background @configuration.contact_background
|
223
|
-
convert.splice '5x10'
|
226
|
+
convert.splice '5x10'
|
224
227
|
convert << file_path
|
225
|
-
end
|
228
|
+
end
|
226
229
|
file_path
|
227
230
|
end
|
228
231
|
|
@@ -232,7 +235,9 @@ private
|
|
232
235
|
convert.stack do |ul|
|
233
236
|
ul.size "#{montage.width}x#{@configuration.title_font.line_height}"
|
234
237
|
ul.xc @configuration.title_background
|
235
|
-
|
238
|
+
if @configuration.title_font.exists?
|
239
|
+
ul.font @configuration.title_font.path
|
240
|
+
end
|
236
241
|
ul.pointsize @configuration.title_font.size
|
237
242
|
ul.background @configuration.title_background
|
238
243
|
ul.fill @configuration.title_color
|
@@ -285,7 +290,9 @@ private
|
|
285
290
|
a.size "#{montage.width - 18}x1"
|
286
291
|
a.xc @configuration.header_background
|
287
292
|
a.size.+
|
288
|
-
|
293
|
+
if @configuration.header_font.exists?
|
294
|
+
a.font @configuration.header_font.path
|
295
|
+
end
|
289
296
|
a.pointsize @configuration.header_font.size
|
290
297
|
a.background @configuration.header_background
|
291
298
|
a.fill 'Black'
|
@@ -293,11 +300,15 @@ private
|
|
293
300
|
b.gravity 'West'
|
294
301
|
b.stack do |c|
|
295
302
|
c.label 'Filename: '
|
296
|
-
|
303
|
+
if @configuration.header_font.exists?
|
304
|
+
c.font @configuration.header_font.path
|
305
|
+
end
|
297
306
|
c.label File.basename(@video)
|
298
307
|
c.append.+
|
299
308
|
end
|
300
|
-
|
309
|
+
if @configuration.header_font.exists?
|
310
|
+
b.font @configuration.header_font.path
|
311
|
+
end
|
301
312
|
b.label "File size: #{Tools.to_human_size(File.size(@video))}"
|
302
313
|
b.label "Length: #{@length.to_timestamp}"
|
303
314
|
b.append
|
@@ -323,7 +334,9 @@ private
|
|
323
334
|
a.size "#{montage.width}x#{signature_height}"
|
324
335
|
a.gravity 'Center'
|
325
336
|
a.xc @configuration.signature_background
|
326
|
-
|
337
|
+
if @configuration.signature_font.exists?
|
338
|
+
a.font @configuration.signature_font.path
|
339
|
+
end
|
327
340
|
a.pointsize @configuration.signature_font.size
|
328
341
|
a.fill @configuration.signature_color
|
329
342
|
a.annotate(0, @signature)
|
data/lib/ffmpeg.rb
CHANGED
@@ -17,7 +17,8 @@ module VCSRuby
|
|
17
17
|
@video = video
|
18
18
|
@ffmpeg = Command.new :ffmpeg, 'ffmpeg'
|
19
19
|
@ffprobe = Command.new :ffmpeg, 'ffprobe'
|
20
|
-
|
20
|
+
|
21
|
+
detect_version if available?
|
21
22
|
end
|
22
23
|
|
23
24
|
def name
|
@@ -108,7 +109,7 @@ private
|
|
108
109
|
video_stream = split_stream_line(is_stream?(@cache, /Video/).first)
|
109
110
|
|
110
111
|
dimensions = /(\d*)x(\d*) \[PAR (\d*:\d*) DAR (\d*:\d*)\]/.match(video_stream[DIMENSION])
|
111
|
-
|
112
|
+
|
112
113
|
if dimensions
|
113
114
|
@par = dimensions[3]
|
114
115
|
@dar = dimensions[4]
|
data/lib/font.rb
CHANGED
@@ -3,30 +3,74 @@
|
|
3
3
|
#
|
4
4
|
|
5
5
|
require 'mini_magick'
|
6
|
+
require 'pp'
|
6
7
|
|
7
8
|
module VCSRuby
|
9
|
+
IMFont = Struct.new(:name, :family, :style, :stretch, :weight, :glyphs)
|
10
|
+
|
8
11
|
class Font
|
9
12
|
attr_reader :name, :path, :size
|
10
13
|
|
14
|
+
@@fonts = {}
|
15
|
+
|
11
16
|
def initialize name, size
|
12
17
|
@name = name
|
13
18
|
@path = find_path
|
14
19
|
@size = size
|
15
20
|
end
|
16
|
-
|
21
|
+
|
22
|
+
def exists?
|
23
|
+
load_font_cache if @@fonts.length == 0
|
24
|
+
|
25
|
+
!!font_by_name(@name)
|
26
|
+
end
|
27
|
+
|
17
28
|
def find_path
|
18
|
-
if
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
29
|
+
load_font_cache if @@fonts.length == 0
|
30
|
+
|
31
|
+
if exists?
|
32
|
+
font_by_name(@name).glyphs
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def font_by_name name
|
39
|
+
if name =~ /\./
|
40
|
+
key, font = @@fonts.select{ |key, f| f.glyphs =~ /#{name}\z/ }.first
|
41
|
+
return font
|
42
|
+
else
|
43
|
+
@@fonts[name]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def load_font_cache
|
48
|
+
|
49
|
+
fonts = MiniMagick::Tool::Identify.new(whiny: false) do |identify|
|
50
|
+
identify.list 'font'
|
51
|
+
end
|
52
|
+
|
53
|
+
parse_fonts(fonts)
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_fonts(fonts)
|
57
|
+
font = nil
|
58
|
+
fonts.lines.each do |line|
|
59
|
+
key, value = line.strip.split(':', 2).map(&:strip)
|
60
|
+
|
61
|
+
next if ['Path'].include? key
|
62
|
+
|
63
|
+
if key == 'Font'
|
64
|
+
@@fonts[value] = font = IMFont.new(value)
|
65
|
+
else
|
66
|
+
font.send(key + '=', value)
|
67
|
+
end
|
24
68
|
end
|
25
69
|
end
|
26
70
|
|
27
71
|
def line_height
|
28
72
|
MiniMagick::Tool::Convert.new do |convert|
|
29
|
-
convert.font path
|
73
|
+
convert.font path if exists?
|
30
74
|
convert.pointsize size
|
31
75
|
convert << 'label:F'
|
32
76
|
convert.format '%h'
|
data/lib/libav.rb
CHANGED
@@ -17,7 +17,8 @@ module VCSRuby
|
|
17
17
|
@video = video
|
18
18
|
@avconv = Command.new :libav, 'avconv'
|
19
19
|
@avprobe = Command.new :libav, 'avprobe'
|
20
|
-
|
20
|
+
|
21
|
+
detect_version if available?
|
21
22
|
end
|
22
23
|
|
23
24
|
def name
|
@@ -100,7 +101,7 @@ private
|
|
100
101
|
video_stream = split_stream_line(is_stream?(@cache, /Video/).first)
|
101
102
|
|
102
103
|
dimensions = /(\d*)x(\d*) \[PAR (\d*:\d*) DAR (\d*:\d*)\]/.match(video_stream[DIMENSION])
|
103
|
-
|
104
|
+
|
104
105
|
if dimensions
|
105
106
|
@par = dimensions[3]
|
106
107
|
@dar = dimensions[4]
|
data/lib/mplayer.rb
CHANGED
data/lib/thumbnail.rb
CHANGED
@@ -17,7 +17,7 @@ module VCSRuby
|
|
17
17
|
@filters = [ method(:resize_filter), method(:timestamp_filter), method(:softshadow_filter) ]
|
18
18
|
end
|
19
19
|
|
20
|
-
def capture
|
20
|
+
def capture
|
21
21
|
@capper.grab @time, @image_path
|
22
22
|
end
|
23
23
|
|
@@ -65,7 +65,9 @@ private
|
|
65
65
|
box.fill @configuration.timestamp_color
|
66
66
|
box.pointsize @configuration.timestamp_font.size
|
67
67
|
box.gravity 'SouthEast'
|
68
|
-
|
68
|
+
if @configuration.timestamp_font.exists?
|
69
|
+
box.font @configuration.timestamp_font.path
|
70
|
+
end
|
69
71
|
box.annotate('+10+10', " #{@time.to_timestamp} ")
|
70
72
|
end
|
71
73
|
convert.flatten
|
data/lib/time_index.rb
CHANGED
data/lib/tools.rb
CHANGED
@@ -61,7 +61,7 @@ module VCSRuby
|
|
61
61
|
|
62
62
|
def self.to_human_size size
|
63
63
|
powers = { 'B' => 1 << 10, 'KiB' => 1 << 20, 'MiB' => 1 << 30, 'GiB' => 1 << 40, 'TiB' => 1 << 50 }
|
64
|
-
powers.each_pair do |prefix, power|
|
64
|
+
powers.each_pair do |prefix, power|
|
65
65
|
if size < power
|
66
66
|
return format('%.2f',size.to_f / (power >> 10)) + ' ' + prefix
|
67
67
|
end
|
data/lib/vcs.rb
CHANGED
data/lib/version.info
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.6
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vcs_ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-05-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mini_magick
|
@@ -27,6 +27,38 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 4.0.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.5.0
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.5.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 10.0.0
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 10.0.0
|
30
62
|
description: Creates a contact sheet, a preview, of a video, usable as library or
|
31
63
|
as a script. Based on VCS *NIX. Creating Thumbnails with libav, ffmpeg or mplayer
|
32
64
|
and compose it with ImageMagick into nice looking sheets.
|