vcs_ruby 1.0.1 → 1.1.0
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 +4 -4
- data/lib/FFmpeg/ffmpeg.rb +141 -0
- data/lib/FFmpeg/ffmpeg_audio_stream.rb +38 -0
- data/lib/FFmpeg/ffmpeg_meta_info.rb +37 -0
- data/lib/FFmpeg/ffmpeg_video_stream.rb +52 -0
- data/lib/{mplayer.rb → MPlayer/mplayer.rb} +48 -63
- data/lib/MPlayer/mplayer_audio_stream.rb +35 -0
- data/lib/MPlayer/mplayer_meta_info.rb +40 -0
- data/lib/MPlayer/mplayer_video_stream.rb +44 -0
- data/lib/capturer.rb +17 -21
- data/lib/command.rb +4 -2
- data/lib/configuration.rb +18 -7
- data/lib/contact_sheet.rb +106 -127
- data/lib/defaults.yml +4 -4
- data/lib/font.rb +12 -12
- data/lib/{thumbnail.rb → frame.rb} +45 -24
- data/lib/libAV/libav.rb +143 -0
- data/lib/libAV/libav_audio_stream.rb +38 -0
- data/lib/libAV/libav_meta_info.rb +37 -0
- data/lib/libAV/libav_video_stream.rb +52 -0
- data/lib/stream.rb +24 -0
- data/lib/tools.rb +13 -20
- data/lib/vcs.rb +16 -4
- data/lib/version.info +1 -1
- data/lib/version.rb +2 -2
- data/lib/video.rb +89 -0
- metadata +37 -8
- data/lib/ffmpeg.rb +0 -183
- data/lib/libav.rb +0 -181
data/bin/vcs.rb
CHANGED
@@ -74,12 +74,12 @@ optparse = OptionParser.new do|opts|
|
|
74
74
|
opts.on('-C [CAPTURER]', '--capture [CAPTURER]', arguments['--capturer'], 'Capturer: ' + Tools::list_arguments(arguments["--capturer"])) do |capturer|
|
75
75
|
options[:capturer] = capturer
|
76
76
|
end
|
77
|
-
opts.on( '-T [TITLE]', '--title [TITLE]', 'Set
|
77
|
+
opts.on( '-T [TITLE]', '--title [TITLE]', 'Set Title') do |title|
|
78
78
|
options[:title] = title
|
79
79
|
end
|
80
80
|
opts.on( '-o [FILE]', '--output [FILE]', 'File name of output. When ommited will be derived from the input filename. Can be repeated for multiple files.') do |file|
|
81
81
|
options[:output] << file
|
82
|
-
end
|
82
|
+
end
|
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
|
@@ -141,8 +141,8 @@ optparse.parse!
|
|
141
141
|
|
142
142
|
Tools::print_help optparse if options[:help] || ARGV.empty?
|
143
143
|
|
144
|
-
|
145
|
-
|
144
|
+
Configuration.instance.verbose = options[:verbose]
|
145
|
+
Configuration.instance.quiet = options[:quiet]
|
146
146
|
|
147
147
|
# Invoke ContactSheet
|
148
148
|
|
@@ -0,0 +1,141 @@
|
|
1
|
+
#
|
2
|
+
# FFmpeg Abstraction
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'capturer'
|
6
|
+
require 'command'
|
7
|
+
|
8
|
+
module VCSRuby
|
9
|
+
class FFmpeg < Capturer
|
10
|
+
|
11
|
+
HEADER = 10
|
12
|
+
ENCODING_SUPPORT = 2
|
13
|
+
VIDEO_CODEC = 3
|
14
|
+
NAME = 8
|
15
|
+
|
16
|
+
attr_reader :info, :video_streams, :audio_streams
|
17
|
+
|
18
|
+
def initialize video
|
19
|
+
@video = video
|
20
|
+
@ffmpeg = Command.new :ffmpeg, 'ffmpeg'
|
21
|
+
@ffprobe = Command.new :ffmpeg, 'ffprobe'
|
22
|
+
|
23
|
+
detect_version if available?
|
24
|
+
end
|
25
|
+
|
26
|
+
def file_valid?
|
27
|
+
return probe_meta_information
|
28
|
+
end
|
29
|
+
|
30
|
+
def name
|
31
|
+
:ffmpeg
|
32
|
+
end
|
33
|
+
|
34
|
+
def available?
|
35
|
+
@ffmpeg.available? && !libav?
|
36
|
+
end
|
37
|
+
|
38
|
+
def libav?
|
39
|
+
@libav
|
40
|
+
end
|
41
|
+
|
42
|
+
def detect_version
|
43
|
+
info = @ffmpeg.execute('-version')
|
44
|
+
match = /avconv ([\d|.|-|:]*)/.match(info)
|
45
|
+
@libav = !!match
|
46
|
+
match = /ffmpeg version ([\d|.]*)/.match(info)
|
47
|
+
if match
|
48
|
+
@version = match[1]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def grab time, image_path
|
53
|
+
@ffmpeg.execute "-y -ss #{time.total_seconds} -i \"#{@video.full_path}\" -an -dframes 1 -vframes 1 -vcodec #{format} -f rawvideo \"#{image_path}\""
|
54
|
+
end
|
55
|
+
|
56
|
+
def available_formats
|
57
|
+
# Ordered by priority
|
58
|
+
image_formats = ['png', 'tiff', 'bmp', 'mjpeg']
|
59
|
+
formats = []
|
60
|
+
|
61
|
+
list = @ffprobe.execute "-codecs"
|
62
|
+
list.lines.drop(HEADER).each do |codec|
|
63
|
+
name, e, v = format_split(codec)
|
64
|
+
formats << name if image_formats.include?(name) && e && v
|
65
|
+
end
|
66
|
+
|
67
|
+
image_formats.select{ |format| formats.include?(format) }.map(&:to_sym)
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_s
|
71
|
+
"FFmpeg #{@version}"
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
def format_split line
|
76
|
+
e = line[ENCODING_SUPPORT] == 'E'
|
77
|
+
v = line[VIDEO_CODEC] == 'V'
|
78
|
+
|
79
|
+
name = line[NAME..-1].split(' ', 2).first
|
80
|
+
return name, e, v
|
81
|
+
rescue
|
82
|
+
return nil, false, false
|
83
|
+
end
|
84
|
+
|
85
|
+
def probe_meta_information
|
86
|
+
check_cache
|
87
|
+
parse_meta_info
|
88
|
+
return true
|
89
|
+
rescue Exception => e
|
90
|
+
puts e
|
91
|
+
return false
|
92
|
+
end
|
93
|
+
|
94
|
+
def check_cache
|
95
|
+
unless @cache
|
96
|
+
@cache = @ffprobe.execute("\"#{@video.full_path}\" -show_format -show_streams", "2>&1")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def get_hash defines
|
101
|
+
result = {}
|
102
|
+
defines.lines.each do |line|
|
103
|
+
kv = line.split("=")
|
104
|
+
result[kv[0].strip] = kv[1].strip if kv.count == 2
|
105
|
+
end
|
106
|
+
result
|
107
|
+
end
|
108
|
+
|
109
|
+
def parse_meta_info
|
110
|
+
parse_format
|
111
|
+
parse_audio_streams
|
112
|
+
parse_video_streams
|
113
|
+
end
|
114
|
+
|
115
|
+
def parse_format
|
116
|
+
@cache.scan(/\[FORMAT\](.*?)\[\/FORMAT\]/m) do |format|
|
117
|
+
@info = FFmpegMetaInfo.new(get_hash(format[0]))
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def parse_audio_streams
|
122
|
+
@audio_streams = []
|
123
|
+
@cache.scan(/\[STREAM\](.*?)\[\/STREAM\]/m) do |stream|
|
124
|
+
info = get_hash(stream[0])
|
125
|
+
if info['codec_type'] == 'audio'
|
126
|
+
@audio_streams << FFmpegAudioStream.new(info)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def parse_video_streams
|
132
|
+
@video_streams = []
|
133
|
+
@cache.scan(/\[STREAM\](.*?)\[\/STREAM\]/m) do |stream|
|
134
|
+
info = get_hash(stream[0])
|
135
|
+
if info['codec_type'] == 'video'
|
136
|
+
@video_streams << FFmpegVideoStream.new(info)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#
|
2
|
+
# Implementes AudioStream Interface for FFmpeg
|
3
|
+
#
|
4
|
+
|
5
|
+
# AudioStream = Struct.new(:codec, :channels, :channel_layout, :sample_rate, :bit_rate, :raw)
|
6
|
+
module VCSRuby
|
7
|
+
class FFmpegAudioStream
|
8
|
+
attr_reader :raw
|
9
|
+
|
10
|
+
def initialize audio_stream
|
11
|
+
@raw = audio_stream
|
12
|
+
end
|
13
|
+
|
14
|
+
def codec short = false
|
15
|
+
if short
|
16
|
+
@raw['codec_name']
|
17
|
+
else
|
18
|
+
@raw['codec_long_name']
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def channels
|
23
|
+
@raw['channels'].to_i
|
24
|
+
end
|
25
|
+
|
26
|
+
def channel_layout
|
27
|
+
@raw['channel_layout']
|
28
|
+
end
|
29
|
+
|
30
|
+
def sample_rate
|
31
|
+
@raw['sample_rate'].to_i
|
32
|
+
end
|
33
|
+
|
34
|
+
def bit_rate
|
35
|
+
@raw['bit_rate'].to_i
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# Implementes MetaInfo Interface for FFmpeg
|
3
|
+
#
|
4
|
+
|
5
|
+
# MetaInformation = Struct.new(:duration, :bit_rate, :size, :format, :extension, :raw)
|
6
|
+
|
7
|
+
require_relative '../time_index'
|
8
|
+
|
9
|
+
module VCSRuby
|
10
|
+
class FFmpegMetaInfo
|
11
|
+
attr_reader :raw
|
12
|
+
|
13
|
+
def initialize meta_info
|
14
|
+
@raw = meta_info
|
15
|
+
end
|
16
|
+
|
17
|
+
def duration
|
18
|
+
TimeIndex.new(@raw['duration'].to_f)
|
19
|
+
end
|
20
|
+
|
21
|
+
def bit_rate
|
22
|
+
@raw['bit_rate'].to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
def size
|
26
|
+
@raw['size'].to_i
|
27
|
+
end
|
28
|
+
|
29
|
+
def format
|
30
|
+
@raw['format_long_name']
|
31
|
+
end
|
32
|
+
|
33
|
+
def extension
|
34
|
+
@raw['format_name']
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#
|
2
|
+
# Implementes VideoStream Interface for FFmpeg
|
3
|
+
#
|
4
|
+
|
5
|
+
# VideoStream = Struct.new(:width, :height, :codec, :color_space, :bit_rate, :frame_rate, :aspect_ratio, :raw)
|
6
|
+
|
7
|
+
module VCSRuby
|
8
|
+
class FFmpegVideoStream
|
9
|
+
attr_reader :raw
|
10
|
+
|
11
|
+
def initialize video_stream
|
12
|
+
@raw = video_stream
|
13
|
+
end
|
14
|
+
|
15
|
+
def width
|
16
|
+
@raw['width'].to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
def height
|
20
|
+
@raw['height'].to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
def codec short = false
|
24
|
+
if short
|
25
|
+
@raw['codec_name']
|
26
|
+
else
|
27
|
+
@raw['codec_long_name']
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def color_space
|
32
|
+
if ["unknown", "", nil].include? @raw['color_space']
|
33
|
+
@raw['pix_fmt']
|
34
|
+
else
|
35
|
+
@raw['color_space']
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def bit_rate
|
40
|
+
@raw['bit_rate'].to_i
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def frame_rate
|
45
|
+
Rational(@raw['r_frame_rate'])
|
46
|
+
end
|
47
|
+
|
48
|
+
def aspect_ratio
|
49
|
+
@raw['display_aspect_ratio']
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -2,15 +2,15 @@
|
|
2
2
|
# MPlayer Abstraction
|
3
3
|
#
|
4
4
|
|
5
|
-
require 'command'
|
6
5
|
require 'capturer'
|
7
|
-
require '
|
6
|
+
require 'command'
|
8
7
|
|
9
8
|
module VCSRuby
|
10
9
|
class MPlayer < Capturer
|
11
10
|
|
12
11
|
HEADER = 2
|
13
12
|
|
13
|
+
attr_reader :info, :video_streams, :audio_streams
|
14
14
|
def initialize video
|
15
15
|
@video = video
|
16
16
|
@mplayer = Command.new :mplayer, 'mplayer'
|
@@ -18,6 +18,10 @@ module VCSRuby
|
|
18
18
|
detect_version if available?
|
19
19
|
end
|
20
20
|
|
21
|
+
def file_valid?
|
22
|
+
return probe_meta_information
|
23
|
+
end
|
24
|
+
|
21
25
|
def name
|
22
26
|
:mplayer
|
23
27
|
end
|
@@ -25,55 +29,16 @@ module VCSRuby
|
|
25
29
|
def available?
|
26
30
|
@mplayer.available?
|
27
31
|
end
|
28
|
-
|
32
|
+
|
29
33
|
def detect_version
|
30
34
|
info = @mplayer.execute('')
|
31
35
|
match = /MPlayer (.*),/.match(info)
|
32
36
|
@version = match[1] if match
|
33
37
|
end
|
34
38
|
|
35
|
-
def length
|
36
|
-
load_probe
|
37
|
-
@length
|
38
|
-
end
|
39
|
-
|
40
|
-
def width
|
41
|
-
load_probe
|
42
|
-
@width
|
43
|
-
end
|
44
|
-
|
45
|
-
def height
|
46
|
-
load_probe
|
47
|
-
@height
|
48
|
-
end
|
49
|
-
|
50
|
-
def video_codec
|
51
|
-
load_probe
|
52
|
-
@video_codec
|
53
|
-
end
|
54
|
-
|
55
|
-
def audio_codec
|
56
|
-
load_probe
|
57
|
-
@audio_codec
|
58
|
-
end
|
59
|
-
|
60
|
-
def fps
|
61
|
-
load_probe
|
62
|
-
@fps
|
63
|
-
end
|
64
|
-
|
65
|
-
def file_pattern n
|
66
|
-
if format == :jpeg
|
67
|
-
"#{"%08d" % n}.jpg"
|
68
|
-
else
|
69
|
-
"#{"%08d" % n}.#{format.to_s}"
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
39
|
def grab time, image_path
|
74
|
-
@mplayer.execute "-
|
75
|
-
|
76
|
-
FileUtils.mv(file_pattern(5), image_path)
|
40
|
+
@mplayer.execute "-vo png -ss #{time.total_seconds} -endpos 0 \"#{@video.full_path}\""
|
41
|
+
FileUtils.mv(file_pattern(1), image_path)
|
77
42
|
end
|
78
43
|
|
79
44
|
def available_formats
|
@@ -90,35 +55,55 @@ module VCSRuby
|
|
90
55
|
image_formats.select{ |format| formats.include?(format) }.map(&:to_sym)
|
91
56
|
end
|
92
57
|
|
93
|
-
def format_split line
|
94
|
-
name = line.strip.split(' ', 2).first
|
95
|
-
end
|
96
|
-
|
97
58
|
def to_s
|
98
59
|
"MPlayer #{@version}"
|
99
60
|
end
|
61
|
+
|
100
62
|
private
|
101
|
-
def
|
102
|
-
|
63
|
+
def format_split line
|
64
|
+
name = line.strip.split(' ', 2).first
|
65
|
+
end
|
66
|
+
def probe_meta_information
|
67
|
+
check_cache
|
68
|
+
parse_meta_info
|
69
|
+
return true
|
70
|
+
rescue Exception => e
|
71
|
+
puts e
|
72
|
+
return false
|
103
73
|
end
|
104
74
|
|
105
|
-
def
|
106
|
-
unless
|
107
|
-
|
75
|
+
def check_cache
|
76
|
+
unless @cache
|
77
|
+
@cache = @mplayer.execute("-ao null -vo null -identify -frames 0 -really-quiet \"#{@video.full_path}\"")
|
108
78
|
end
|
109
79
|
end
|
110
80
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
81
|
+
def get_hash defines
|
82
|
+
result = {}
|
83
|
+
defines.lines.each do |line|
|
84
|
+
kv = line.split("=")
|
85
|
+
result[kv[0].strip] = kv[1].strip if kv.count == 2
|
86
|
+
end
|
87
|
+
result
|
88
|
+
end
|
89
|
+
|
90
|
+
def parse_meta_info
|
91
|
+
mplayer_hash = get_hash(@cache)
|
92
|
+
@info = MPlayerMetaInfo.new(mplayer_hash, File.size(@video.full_path))
|
93
|
+
|
94
|
+
# Todo: Handling of multiple streams
|
95
|
+
@video_streams = []
|
96
|
+
@video_streams << MPlayerVideoStream.new(mplayer_hash)
|
97
|
+
@audio_streams = []
|
98
|
+
@audio_streams << MPlayerAudioStream.new(mplayer_hash)
|
99
|
+
end
|
100
|
+
|
101
|
+
def file_pattern n
|
102
|
+
if format == :jpeg
|
103
|
+
"#{"%08d" % n}.jpg"
|
104
|
+
else
|
105
|
+
"#{"%08d" % n}.#{format.to_s}"
|
120
106
|
end
|
121
|
-
@parsed = true
|
122
107
|
end
|
123
108
|
end
|
124
109
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#
|
2
|
+
# Implementes AudioStream Interface for MPlayer
|
3
|
+
#
|
4
|
+
|
5
|
+
# AudioStream = Struct.new(:codec, :channels, :channel_layout, :sample_rate, :bit_rate, :raw)
|
6
|
+
module VCSRuby
|
7
|
+
class MPlayerAudioStream
|
8
|
+
attr_reader :raw
|
9
|
+
|
10
|
+
def initialize audio_stream
|
11
|
+
@raw = audio_stream
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
def codec short = false
|
16
|
+
@raw['ID_AUDIO_CODEC']
|
17
|
+
end
|
18
|
+
|
19
|
+
def channels
|
20
|
+
@raw['ID_AUDIO_NCH'].to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
def channel_layout
|
24
|
+
''
|
25
|
+
end
|
26
|
+
|
27
|
+
def sample_rate
|
28
|
+
@raw['ID_AUDIO_RATE'].to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
def bit_rate
|
32
|
+
@raw['ID_AUDIO_BITRATE'].to_i
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
# Implementes MetaInfo Interface for MPlayer
|
3
|
+
#
|
4
|
+
|
5
|
+
# MetaInformation = Struct.new(:duration, :bit_rate, :size, :format, :extension, :raw)
|
6
|
+
|
7
|
+
require_relative '../time_index'
|
8
|
+
|
9
|
+
module VCSRuby
|
10
|
+
class MPlayerMetaInfo
|
11
|
+
attr_reader :raw
|
12
|
+
|
13
|
+
def initialize meta_info, filesize
|
14
|
+
@raw = meta_info
|
15
|
+
@filesize = filesize
|
16
|
+
end
|
17
|
+
|
18
|
+
def duration
|
19
|
+
TimeIndex.new(@raw['ID_LENGTH'].to_f)
|
20
|
+
end
|
21
|
+
|
22
|
+
def bit_rate
|
23
|
+
@raw['ID_AUDIO_BITRATE'].to_i + @raw['ID_VIDEO_BITRATE'].to_i
|
24
|
+
end
|
25
|
+
|
26
|
+
def size
|
27
|
+
@filesize
|
28
|
+
end
|
29
|
+
|
30
|
+
def format
|
31
|
+
extension
|
32
|
+
end
|
33
|
+
|
34
|
+
def extension
|
35
|
+
ext = File.extname(@raw['ID_FILENAME'])
|
36
|
+
ext[0] = ''
|
37
|
+
ext
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#
|
2
|
+
# Implementes VideoStream Interface for MPlayer
|
3
|
+
#
|
4
|
+
|
5
|
+
# VideoStream = Struct.new(:width, :height, :codec, :color_space, :bit_rate, :frame_rate, :aspect_ratio, :raw)
|
6
|
+
|
7
|
+
module VCSRuby
|
8
|
+
class MPlayerVideoStream
|
9
|
+
attr_reader :raw
|
10
|
+
|
11
|
+
def initialize video_stream
|
12
|
+
@raw = video_stream
|
13
|
+
end
|
14
|
+
|
15
|
+
def width
|
16
|
+
@raw['ID_VIDEO_WIDTH'].to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
def height
|
20
|
+
@raw['ID_VIDEO_HEIGHT'].to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
def codec short = false
|
24
|
+
@raw['ID_VIDEO_FORMAT']
|
25
|
+
end
|
26
|
+
|
27
|
+
def color_space
|
28
|
+
''
|
29
|
+
end
|
30
|
+
|
31
|
+
def bit_rate
|
32
|
+
@raw['ID_VIDEO_BITRATE'].to_i
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def frame_rate
|
37
|
+
@raw['ID_VIDEO_FPS'].to_f
|
38
|
+
end
|
39
|
+
|
40
|
+
def aspect_ratio
|
41
|
+
''
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/capturer.rb
CHANGED
@@ -2,42 +2,38 @@
|
|
2
2
|
# Capturer Baseclass
|
3
3
|
#
|
4
4
|
|
5
|
+
require 'vcs'
|
6
|
+
|
5
7
|
module VCSRuby
|
6
8
|
class Capturer
|
9
|
+
$formats = { :png => 'png', :bmp => 'bmp', :tiff => 'tif', :mjpeg => 'jpg', :jpeg => 'jpg', :jpg => 'jpg' }
|
10
|
+
|
7
11
|
def available?
|
8
12
|
false
|
9
13
|
end
|
10
14
|
|
11
|
-
def
|
12
|
-
|
13
|
-
end
|
15
|
+
def self.initialize_capturers video
|
16
|
+
capturers = []
|
14
17
|
|
15
|
-
|
16
|
-
raise "NotImplementedException"
|
18
|
+
puts "Available capturers: #{available_capturers.map{ |c| c.to_s }.join(', ')}" if Tools.verbose?
|
17
19
|
end
|
18
20
|
|
19
|
-
def
|
20
|
-
|
21
|
-
end
|
21
|
+
def self.create
|
22
|
+
capturers = []
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
capturers << LibAV.new(video)
|
25
|
+
capturers << MPlayer.new(video)
|
26
|
+
capturers << FFmpeg.new(video)
|
26
27
|
|
27
|
-
|
28
|
-
raise "NotImplementedException"
|
28
|
+
return capturers.first
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
def available_formats
|
36
|
-
raise "NotImplementedException"
|
31
|
+
def format
|
32
|
+
@format || available_formats.first
|
37
33
|
end
|
38
34
|
|
39
|
-
def
|
40
|
-
|
35
|
+
def format_extension
|
36
|
+
$formats[format]
|
41
37
|
end
|
42
38
|
|
43
39
|
def format= format
|
data/lib/command.rb
CHANGED
@@ -17,7 +17,7 @@ module VCSRuby
|
|
17
17
|
|
18
18
|
def execute parameter, streams = 0, no_error = false
|
19
19
|
raise "Command '#{name}' not available" unless available?
|
20
|
-
puts "#{@command} #{parameter}
|
20
|
+
puts "#{@command} #{parameter}" if Configuration.instance.verbose?
|
21
21
|
result = nil
|
22
22
|
if Tools::windows?
|
23
23
|
streams = '2> nul' if streams === 0
|
@@ -40,7 +40,9 @@ private
|
|
40
40
|
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
41
41
|
exts.each do |ext|
|
42
42
|
exe = File.join(path, "#{cmd}#{ext}")
|
43
|
-
|
43
|
+
if File.executable?(exe) && !File.directory?(exe)
|
44
|
+
return exe
|
45
|
+
end
|
44
46
|
end
|
45
47
|
end
|
46
48
|
return nil
|