puremotion 0.0.1 → 0.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/.yardopts +1 -0
- data/README.md +69 -0
- data/Rakefile +23 -11
- data/examples/progress_reporting.rb +26 -0
- data/examples/simple.rb +22 -0
- data/ext/puremotion/audio.c +38 -0
- data/ext/puremotion/extconf.rb +34 -0
- data/ext/puremotion/frame.c +176 -0
- data/ext/puremotion/media.c +175 -0
- data/ext/puremotion/puremotion.c +26 -0
- data/ext/puremotion/puremotion.h +38 -0
- data/ext/puremotion/stream.c +128 -0
- data/ext/puremotion/stream_collection.c +44 -0
- data/ext/puremotion/utils.c +81 -0
- data/ext/puremotion/utils.h +6 -0
- data/ext/puremotion/video.c +141 -0
- data/lib/{puremotion/events → events}/event.rb +0 -0
- data/lib/{puremotion/events → events}/generator.rb +0 -0
- data/lib/media.rb +89 -0
- data/lib/preset/audio/audio.rb +42 -0
- data/lib/preset/file.rb +19 -0
- data/lib/preset/general.rb +28 -0
- data/lib/preset/metadata.rb +41 -0
- data/lib/preset/preset.rb +120 -0
- data/lib/preset/video/crop.rb +29 -0
- data/lib/preset/video/pad.rb +31 -0
- data/lib/preset/video/video.rb +130 -0
- data/lib/puremotion.rb +20 -12
- data/lib/puremotion_native.so +0 -0
- data/lib/threading.rb +54 -0
- data/lib/{puremotion/tools → tools}/ffmpeg.rb +12 -50
- data/lib/transcode/transcode.rb +142 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/units/media_spec.rb +13 -0
- data/spec/units/preset_spec.rb +91 -0
- metadata +52 -44
- data/.document +0 -5
- data/.gitignore +0 -21
- data/README.rdoc +0 -18
- data/VERSION +0 -1
- data/lib/puremotion/codecs.rb +0 -59
- data/lib/puremotion/media.rb +0 -490
- data/lib/puremotion/media/stream.rb +0 -4
- data/lib/puremotion/media/stream/audio.rb +0 -0
- data/lib/puremotion/media/stream/base.rb +0 -7
- data/lib/puremotion/media/stream/collection.rb +0 -5
- data/lib/puremotion/media/stream/video.rb +0 -61
- data/lib/puremotion/recipes/ipod.yml +0 -12
- data/lib/puremotion/thread.rb +0 -153
- data/lib/puremotion/transcode/recipe.rb +0 -250
- data/lib/puremotion/transcode/transcode.rb +0 -153
- data/puremotion.gemspec +0 -68
- data/test/helper.rb +0 -10
- data/test/test_puremotion.rb +0 -7
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puremotion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Ominiom
|
@@ -9,53 +14,51 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-03-25 00:00:00 +00:00
|
13
18
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
- !ruby/object:Gem::Dependency
|
16
|
-
name: thoughtbot-shoulda
|
17
|
-
type: :development
|
18
|
-
version_requirement:
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">="
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: "0"
|
24
|
-
version:
|
25
|
-
description: A Ruby wrapper for analysis and conversion of media using FFmpeg
|
26
|
-
email: iain.iw.wilson@googlemail.com
|
27
|
-
executables: []
|
19
|
+
dependencies: []
|
28
20
|
|
29
|
-
|
21
|
+
description: A Ruby wrapper for FFmpeg
|
22
|
+
email: iain@ominiom.com
|
23
|
+
executables: []
|
30
24
|
|
25
|
+
extensions:
|
26
|
+
- ext/puremotion/extconf.rb
|
31
27
|
extra_rdoc_files:
|
32
28
|
- LICENSE
|
33
|
-
- README.
|
29
|
+
- README.md
|
34
30
|
files:
|
35
|
-
- .
|
36
|
-
- .gitignore
|
31
|
+
- .yardopts
|
37
32
|
- LICENSE
|
38
|
-
- README.
|
33
|
+
- README.md
|
39
34
|
- Rakefile
|
40
|
-
-
|
35
|
+
- ext/puremotion/audio.c
|
36
|
+
- ext/puremotion/extconf.rb
|
37
|
+
- ext/puremotion/frame.c
|
38
|
+
- ext/puremotion/media.c
|
39
|
+
- ext/puremotion/puremotion.c
|
40
|
+
- ext/puremotion/puremotion.h
|
41
|
+
- ext/puremotion/stream.c
|
42
|
+
- ext/puremotion/stream_collection.c
|
43
|
+
- ext/puremotion/utils.c
|
44
|
+
- ext/puremotion/utils.h
|
45
|
+
- ext/puremotion/video.c
|
46
|
+
- lib/events/event.rb
|
47
|
+
- lib/events/generator.rb
|
48
|
+
- lib/media.rb
|
49
|
+
- lib/preset/audio/audio.rb
|
50
|
+
- lib/preset/file.rb
|
51
|
+
- lib/preset/general.rb
|
52
|
+
- lib/preset/metadata.rb
|
53
|
+
- lib/preset/preset.rb
|
54
|
+
- lib/preset/video/crop.rb
|
55
|
+
- lib/preset/video/pad.rb
|
56
|
+
- lib/preset/video/video.rb
|
41
57
|
- lib/puremotion.rb
|
42
|
-
- lib/
|
43
|
-
- lib/
|
44
|
-
- lib/
|
45
|
-
- lib/
|
46
|
-
- lib/puremotion/media/stream.rb
|
47
|
-
- lib/puremotion/media/stream/audio.rb
|
48
|
-
- lib/puremotion/media/stream/base.rb
|
49
|
-
- lib/puremotion/media/stream/collection.rb
|
50
|
-
- lib/puremotion/media/stream/video.rb
|
51
|
-
- lib/puremotion/recipes/ipod.yml
|
52
|
-
- lib/puremotion/thread.rb
|
53
|
-
- lib/puremotion/tools/ffmpeg.rb
|
54
|
-
- lib/puremotion/transcode/recipe.rb
|
55
|
-
- lib/puremotion/transcode/transcode.rb
|
56
|
-
- puremotion.gemspec
|
57
|
-
- test/helper.rb
|
58
|
-
- test/test_puremotion.rb
|
58
|
+
- lib/puremotion_native.so
|
59
|
+
- lib/threading.rb
|
60
|
+
- lib/tools/ffmpeg.rb
|
61
|
+
- lib/transcode/transcode.rb
|
59
62
|
has_rdoc: true
|
60
63
|
homepage: http://github.com/ominiom/puremotion
|
61
64
|
licenses: []
|
@@ -69,21 +72,26 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
72
|
requirements:
|
70
73
|
- - ">="
|
71
74
|
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 0
|
72
77
|
version: "0"
|
73
|
-
version:
|
74
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
79
|
requirements:
|
76
80
|
- - ">="
|
77
81
|
- !ruby/object:Gem::Version
|
82
|
+
segments:
|
83
|
+
- 0
|
78
84
|
version: "0"
|
79
|
-
version:
|
80
85
|
requirements: []
|
81
86
|
|
82
87
|
rubyforge_project:
|
83
|
-
rubygems_version: 1.3.
|
88
|
+
rubygems_version: 1.3.6
|
84
89
|
signing_key:
|
85
90
|
specification_version: 3
|
86
91
|
summary: PureMotion
|
87
92
|
test_files:
|
88
|
-
-
|
89
|
-
-
|
93
|
+
- spec/units/media_spec.rb
|
94
|
+
- spec/units/preset_spec.rb
|
95
|
+
- spec/spec_helper.rb
|
96
|
+
- examples/progress_reporting.rb
|
97
|
+
- examples/simple.rb
|
data/.document
DELETED
data/.gitignore
DELETED
data/README.rdoc
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
= puremotion
|
2
|
-
|
3
|
-
Description goes here.
|
4
|
-
|
5
|
-
== Note on Patches/Pull Requests
|
6
|
-
|
7
|
-
* Fork the project.
|
8
|
-
* Make your feature addition or bug fix.
|
9
|
-
* Add tests for it. This is important so I don't break it in a
|
10
|
-
future version unintentionally.
|
11
|
-
* Commit, do not mess with rakefile, version, or history.
|
12
|
-
(if you want to have your own version, that is fine but
|
13
|
-
bump version in a commit by itself I can ignore when I pull)
|
14
|
-
* Send me a pull request. Bonus points for topic branches.
|
15
|
-
|
16
|
-
== Copyright
|
17
|
-
|
18
|
-
Copyright (c) 2009 Ominiom. See LICENSE for details.
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.0.1
|
data/lib/puremotion/codecs.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
module PureMotion::Codecs
|
2
|
-
|
3
|
-
@@Codec = Struct.new(:audio, :video, :ffmpeg_name)
|
4
|
-
|
5
|
-
@@codecs = {
|
6
|
-
'aac' => {
|
7
|
-
:ffmpeg_name => 'libfaac',
|
8
|
-
:audio => true
|
9
|
-
},
|
10
|
-
'mp3' => {
|
11
|
-
:ffmpeg_name => 'libmp3lame',
|
12
|
-
:audio => true
|
13
|
-
},
|
14
|
-
'vorbis' => {
|
15
|
-
:ffmpeg_name => 'libvorbis',
|
16
|
-
:audio => true
|
17
|
-
},
|
18
|
-
'theora' => {
|
19
|
-
:ffmpeg_name => 'libtheora',
|
20
|
-
:video => true
|
21
|
-
},
|
22
|
-
'divx' => {
|
23
|
-
:ffmpeg_name => 'libxvid',
|
24
|
-
:video => true
|
25
|
-
},
|
26
|
-
'h264' => {
|
27
|
-
:ffmpeg_name => 'libx264',
|
28
|
-
:video => true
|
29
|
-
},
|
30
|
-
'flv' => {
|
31
|
-
:ffmpeg_name => 'flv',
|
32
|
-
:video => true
|
33
|
-
}
|
34
|
-
}
|
35
|
-
|
36
|
-
def self.find name, type = nil
|
37
|
-
codec = @@codecs[name]
|
38
|
-
if not type.nil? and not codec.nil? then
|
39
|
-
if not codec[type] then return false end
|
40
|
-
end
|
41
|
-
return build(codec) unless codec.nil?
|
42
|
-
nil
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.valid? name, type = nil
|
46
|
-
codec = find name, type
|
47
|
-
return false if codec.nil?
|
48
|
-
true
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.build codec
|
52
|
-
c = @@Codec.new
|
53
|
-
codec.each_pair do |key, value|
|
54
|
-
c[key] = value
|
55
|
-
end
|
56
|
-
c
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
data/lib/puremotion/media.rb
DELETED
@@ -1,490 +0,0 @@
|
|
1
|
-
module PureMotion
|
2
|
-
|
3
|
-
class Media
|
4
|
-
|
5
|
-
event :analysed
|
6
|
-
|
7
|
-
attr_accessor :file
|
8
|
-
|
9
|
-
@analysed = false
|
10
|
-
|
11
|
-
@unknown_format = false
|
12
|
-
@invalid_file = false
|
13
|
-
|
14
|
-
@streams = nil
|
15
|
-
|
16
|
-
def self.analyse(input, options = {})
|
17
|
-
return self.new(input)
|
18
|
-
end
|
19
|
-
|
20
|
-
def analysed?
|
21
|
-
@analysed
|
22
|
-
end
|
23
|
-
|
24
|
-
def initialize(file)
|
25
|
-
@file = file
|
26
|
-
|
27
|
-
@output = ''
|
28
|
-
raise ArgumentError, "File does not exist" unless File.exists? @file
|
29
|
-
|
30
|
-
@ffmpeg = Tools::FFmpeg.new :options => "-i #{file}"
|
31
|
-
|
32
|
-
@ffmpeg.line + lambda do |ffmpeg, line|
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
@ffmpeg.complete + lambda do | ffmpeg, out |
|
37
|
-
@output = @ffmpeg.output.join("\n")
|
38
|
-
|
39
|
-
metadata = /(Input \#.*)\n.+\n\Z/m.match(@output)
|
40
|
-
|
41
|
-
@unknown_format = has(/Unknown format/i)
|
42
|
-
@invalid_file = has(/Duration: N\/A|bitrate: N\/A/im)
|
43
|
-
|
44
|
-
@analysed = true
|
45
|
-
analysed(true)
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
# Raw output of FFmpeg
|
51
|
-
#
|
52
|
-
# Returns:
|
53
|
-
#
|
54
|
-
# * Nil: If the video is still being analysed - unless the parameter :so_far is passed
|
55
|
-
# * String: Raw output
|
56
|
-
def output(opt)
|
57
|
-
|
58
|
-
return nil unless valid?
|
59
|
-
|
60
|
-
if status(:analysing) then return nil unless opt == :so_far end
|
61
|
-
|
62
|
-
return output.join('\n')
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
def transcode(params)
|
67
|
-
return Transcode::Transcode.new(self, params)
|
68
|
-
end
|
69
|
-
|
70
|
-
# Returns:
|
71
|
-
# * nil if not yet analysed
|
72
|
-
# * false if the media is an unknown format
|
73
|
-
# * false if the file is not media or is corrupt
|
74
|
-
# * true otherwise
|
75
|
-
def valid?
|
76
|
-
return nil unless @analysed
|
77
|
-
return false if @unknown_format || @invalid_file
|
78
|
-
has /Input #\d*.\d*/
|
79
|
-
end
|
80
|
-
|
81
|
-
def invalid?
|
82
|
-
!valid?
|
83
|
-
end
|
84
|
-
|
85
|
-
|
86
|
-
def unknown_format?
|
87
|
-
@unknown_format
|
88
|
-
end
|
89
|
-
|
90
|
-
# If true then either:
|
91
|
-
# * The media is a valid format but corrupted and cannot be read
|
92
|
-
# or
|
93
|
-
# * The file isn't media!
|
94
|
-
def invalid_file?
|
95
|
-
@invalid_file
|
96
|
-
end
|
97
|
-
|
98
|
-
# Container bitrate:
|
99
|
-
#
|
100
|
-
# Returns:
|
101
|
-
# * Nil: If the bitrate could not be detected
|
102
|
-
# * String: "xxx kb/s" if _fmt_ is :raw
|
103
|
-
# * Integer: bitrate in kb/s otherwise
|
104
|
-
def bitrate(fmt = nil)
|
105
|
-
br = bitrate_match
|
106
|
-
return nil if br.nil?
|
107
|
-
|
108
|
-
mbr = {
|
109
|
-
:value => br[1].to_i,
|
110
|
-
:unit => br[2]
|
111
|
-
}
|
112
|
-
|
113
|
-
return mbr[:value] unless fmt == :raw
|
114
|
-
|
115
|
-
br
|
116
|
-
|
117
|
-
end
|
118
|
-
|
119
|
-
# Boolean: Whether media has a video stream or not
|
120
|
-
def video?
|
121
|
-
return nil if not @analysed
|
122
|
-
return false if not valid?
|
123
|
-
!video_match.nil?
|
124
|
-
end
|
125
|
-
|
126
|
-
# Boolean: Whether media has an audio stream or not
|
127
|
-
def audio?
|
128
|
-
return nil if not @analysed
|
129
|
-
has /Stream\s*(.*?)[,|:|\(|\[].*?\s*Video:\s*(.*?),\s*(.*?),\s*(\d*)x(\d*)/
|
130
|
-
end
|
131
|
-
|
132
|
-
# Returns a hash with all sorts of details about the first video stream
|
133
|
-
# Nil if no video stream
|
134
|
-
def video
|
135
|
-
return nil unless video?
|
136
|
-
{
|
137
|
-
:codec => detail(:video, :codec),
|
138
|
-
:colorspace => detail(:video, :colorspace),
|
139
|
-
:resolution => {
|
140
|
-
:width => detail(:video, :resolution, :width),
|
141
|
-
:height => detail(:video, :resolution, :height)
|
142
|
-
},
|
143
|
-
:fps => detail(:video, :fps),
|
144
|
-
:bitrate => detail(:video, :bitrate, :raw),
|
145
|
-
:duration => detail(:duration, :seconds)
|
146
|
-
}
|
147
|
-
end
|
148
|
-
|
149
|
-
def audio
|
150
|
-
return nil unless audio?
|
151
|
-
{
|
152
|
-
:codec => detail(:audio, :codec),
|
153
|
-
:sample_rate => detail(:audio, :sample, :rate),
|
154
|
-
:sample_size => detail(:audio, :sample, :size),
|
155
|
-
:channels => detail(:audio, :channels),
|
156
|
-
:bitrate => detail(:audio, :bitrate)
|
157
|
-
}
|
158
|
-
end
|
159
|
-
|
160
|
-
# Big messy function that allows things like:
|
161
|
-
# * detail :video, :resolution, :height
|
162
|
-
# * detail :video, :fps
|
163
|
-
# * detail :video, :duration
|
164
|
-
def detail(*args)
|
165
|
-
|
166
|
-
return nil unless valid?
|
167
|
-
|
168
|
-
case args[0]
|
169
|
-
when :video
|
170
|
-
|
171
|
-
# Main Video handler
|
172
|
-
|
173
|
-
case args[1]
|
174
|
-
when :codec
|
175
|
-
|
176
|
-
# Find video codec
|
177
|
-
return video_match[2]
|
178
|
-
|
179
|
-
when :colorspace
|
180
|
-
|
181
|
-
# Find colorspace
|
182
|
-
return video_match[3]
|
183
|
-
|
184
|
-
when :resolution
|
185
|
-
|
186
|
-
# Handle resolution
|
187
|
-
|
188
|
-
case args[2]
|
189
|
-
when :width
|
190
|
-
|
191
|
-
# Frame width
|
192
|
-
return video_match[4]
|
193
|
-
|
194
|
-
when :height
|
195
|
-
|
196
|
-
# Frame height
|
197
|
-
return video_match[5]
|
198
|
-
|
199
|
-
end
|
200
|
-
|
201
|
-
# Default resolution output format
|
202
|
-
return video_match[4] + "x" + video_match[5]
|
203
|
-
|
204
|
-
when :fps
|
205
|
-
|
206
|
-
# Frame Rate
|
207
|
-
fps = video_frame_rate_match[1].to_f
|
208
|
-
|
209
|
-
# Handle undected frame rates
|
210
|
-
if fps == 0 then fps = nil end
|
211
|
-
|
212
|
-
return fps
|
213
|
-
|
214
|
-
when :bitrate
|
215
|
-
|
216
|
-
# Captue bitrate via regex
|
217
|
-
br = video_bitrate_match[1].to_i
|
218
|
-
|
219
|
-
# Decide if bitrate is in kb/s or b/s
|
220
|
-
case video_bitrate_match[2]
|
221
|
-
when 'b/s'
|
222
|
-
|
223
|
-
# If in b/s divide to get kb/s
|
224
|
-
return (br / 1024).to_i
|
225
|
-
|
226
|
-
end
|
227
|
-
|
228
|
-
# Otherwise send raw bitrate
|
229
|
-
return br
|
230
|
-
|
231
|
-
when :duration
|
232
|
-
|
233
|
-
# Redirect to overall file duration
|
234
|
-
return detail(:duration, args[1])
|
235
|
-
|
236
|
-
end
|
237
|
-
|
238
|
-
# End video section
|
239
|
-
|
240
|
-
return nil
|
241
|
-
|
242
|
-
when :audio
|
243
|
-
|
244
|
-
# Audio section
|
245
|
-
|
246
|
-
case args[1]
|
247
|
-
when :codec
|
248
|
-
|
249
|
-
# Find the codec
|
250
|
-
codec = audio_match[2]
|
251
|
-
|
252
|
-
if codec =~ /\dx[\d a-f]*/ then
|
253
|
-
codec = :unidentifed
|
254
|
-
end
|
255
|
-
|
256
|
-
return codec
|
257
|
-
|
258
|
-
when :sample
|
259
|
-
|
260
|
-
case args[2]
|
261
|
-
when :rate
|
262
|
-
return audio_match[3].to_i
|
263
|
-
end
|
264
|
-
|
265
|
-
return nil
|
266
|
-
|
267
|
-
when :channels
|
268
|
-
|
269
|
-
case audio_match[5]
|
270
|
-
when 'stereo'
|
271
|
-
return 2
|
272
|
-
when 'mono'
|
273
|
-
return 1
|
274
|
-
end
|
275
|
-
|
276
|
-
return nil
|
277
|
-
when :bitrate
|
278
|
-
return audio_bitrate_match[1].to_i
|
279
|
-
end
|
280
|
-
|
281
|
-
return nil
|
282
|
-
|
283
|
-
when :duration
|
284
|
-
|
285
|
-
d = dur
|
286
|
-
secs = (d[:h] * 60 * 60) + (d[:m] * 60) + (d[:s]) * 1.00
|
287
|
-
|
288
|
-
case args[1]
|
289
|
-
when :seconds
|
290
|
-
return secs
|
291
|
-
when :frames
|
292
|
-
return (secs * video_frame_rate_match[1].to_f).to_i
|
293
|
-
end
|
294
|
-
|
295
|
-
return d[:raw]
|
296
|
-
|
297
|
-
end
|
298
|
-
|
299
|
-
nil
|
300
|
-
end
|
301
|
-
|
302
|
-
# * Float: Frame rate of video stream
|
303
|
-
# * Nil: If no video stream, undectable or invalid media
|
304
|
-
def fps
|
305
|
-
return nil unless valid?
|
306
|
-
return nil unless video?
|
307
|
-
begin
|
308
|
-
return video_frame_rate_match[1].to_f
|
309
|
-
rescue
|
310
|
-
return nil
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
private
|
315
|
-
|
316
|
-
def bitrate_match
|
317
|
-
/bitrate: ([0-9\.]+)\s*(.*)\s+/.match(@raw_metadata)
|
318
|
-
end
|
319
|
-
|
320
|
-
def audio_match
|
321
|
-
return nil unless valid?
|
322
|
-
|
323
|
-
match = /Stream\s*(.*?)[,|:|\(|\[].*?\s*Audio:\s*(.*?),\s*([0-9\.]*) (\w*),\s*([a-zA-Z:]*)/.match(@output)
|
324
|
-
|
325
|
-
match
|
326
|
-
end
|
327
|
-
|
328
|
-
def audio_bitrate_match
|
329
|
-
return nil if not valid?
|
330
|
-
|
331
|
-
match = /Stream\s*.*?[,|:|\(|\[].*?\s*Audio:\s*.*?,\s*[0-9\.]* \w*,\s*[a-zA-Z:]*,[^,]*,\s*(\d*)\s*([a-zA-Z]*\/s)/.match(@output)
|
332
|
-
|
333
|
-
match
|
334
|
-
end
|
335
|
-
|
336
|
-
def video_match
|
337
|
-
return nil unless valid?
|
338
|
-
|
339
|
-
match = /Stream\s*(.*?)[,|:|\(|\[].*?\s*Video:\s*(.*?),\s*(.*?),\s*(\d*)x(\d*)/.match(@output)
|
340
|
-
|
341
|
-
/#
|
342
|
-
|
343
|
-
1 => stream id
|
344
|
-
2 => codec
|
345
|
-
3 => colorspace
|
346
|
-
4 => width
|
347
|
-
5 => height
|
348
|
-
|
349
|
-
|
350
|
-
/
|
351
|
-
|
352
|
-
match
|
353
|
-
end
|
354
|
-
|
355
|
-
def video_bitrate_match
|
356
|
-
match = /Stream\s*.*?[,|:|\(|\[].*?\s*Video:\s*.*?,\s*.*?,\s*\d*x\d*[^,]*,\s*([0-9\.]+)\s*(.*\/.),/.match(@output)
|
357
|
-
match
|
358
|
-
end
|
359
|
-
|
360
|
-
def video_frame_rate_match
|
361
|
-
match = /Stream\s*.*?[,|:|\(|\[].*?\s*Video:\s\S*,\s\S*,\s\d+x\d+[^,]+,\s\S*\s\S*,\s([^,\s]*)/.match(@output)
|
362
|
-
|
363
|
-
match
|
364
|
-
end
|
365
|
-
|
366
|
-
def raw_duration
|
367
|
-
return nil unless valid?
|
368
|
-
|
369
|
-
/Duration:\s*([0-9\:\.]+),/.match(@output)[1]
|
370
|
-
end
|
371
|
-
|
372
|
-
def dur
|
373
|
-
return nil unless valid?
|
374
|
-
|
375
|
-
bits = /(\d*):(\d{2}):(\d{2}.\d*)/.match(raw_duration)
|
376
|
-
{
|
377
|
-
:raw => bits[0],
|
378
|
-
:h => bits[1].to_i,
|
379
|
-
:m => bits[2].to_i,
|
380
|
-
:s => bits[3].to_f
|
381
|
-
}
|
382
|
-
end
|
383
|
-
|
384
|
-
def has(regexp)
|
385
|
-
if @output =~ regexp then
|
386
|
-
true
|
387
|
-
else
|
388
|
-
false
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
def find(regexp)
|
393
|
-
m = regexp.match(@output)
|
394
|
-
return m[1] if m
|
395
|
-
nil
|
396
|
-
end
|
397
|
-
|
398
|
-
end
|
399
|
-
|
400
|
-
class Stream
|
401
|
-
|
402
|
-
def initialize(raw)
|
403
|
-
@raw = raw
|
404
|
-
end
|
405
|
-
|
406
|
-
def kind
|
407
|
-
m = /:\s*(\S*):/.match(@raw)
|
408
|
-
m[1]
|
409
|
-
end
|
410
|
-
|
411
|
-
end
|
412
|
-
|
413
|
-
class Input
|
414
|
-
|
415
|
-
attr_accessor :streams
|
416
|
-
|
417
|
-
def initialize(raw)
|
418
|
-
@raw = raw
|
419
|
-
@streams = []
|
420
|
-
detect_streams
|
421
|
-
end
|
422
|
-
|
423
|
-
def container
|
424
|
-
/Input \#\d+\,\s*(\S+),\s*from/.match(@raw)[1]
|
425
|
-
end
|
426
|
-
|
427
|
-
def file
|
428
|
-
/from '(\S+)'/.match(@raw)[1]
|
429
|
-
end
|
430
|
-
|
431
|
-
protected
|
432
|
-
|
433
|
-
def detect_streams
|
434
|
-
@raw.each_line do |line|
|
435
|
-
@streams << Stream.new(line) if line =~ /\s*Stream/
|
436
|
-
end
|
437
|
-
end
|
438
|
-
|
439
|
-
end
|
440
|
-
|
441
|
-
class Analysis
|
442
|
-
|
443
|
-
attr_accessor :info, :inputs
|
444
|
-
|
445
|
-
def initialize(options = {})
|
446
|
-
analyse
|
447
|
-
@inputs[0] unless @inputs.empty?
|
448
|
-
end
|
449
|
-
|
450
|
-
def analyse
|
451
|
-
@inputs = []
|
452
|
-
@fio = IO.popen('ffmpeg -i C:/ffmpeg/test.wmv 2>&1')
|
453
|
-
|
454
|
-
prev_indent = -1
|
455
|
-
indent = 0
|
456
|
-
lines = []
|
457
|
-
|
458
|
-
begin
|
459
|
-
f = @fio.gets
|
460
|
-
|
461
|
-
indent = f.length - f.lstrip.length
|
462
|
-
|
463
|
-
if indent < prev_indent then
|
464
|
-
add(lines.join)
|
465
|
-
lines = []
|
466
|
-
end
|
467
|
-
|
468
|
-
prev_indent = indent
|
469
|
-
|
470
|
-
#puts "Indent: " + indent.to_s + " - " + f
|
471
|
-
|
472
|
-
if f =~ /Input #\d*/ then
|
473
|
-
|
474
|
-
end
|
475
|
-
|
476
|
-
lines << f
|
477
|
-
|
478
|
-
end while not @fio.eof?
|
479
|
-
|
480
|
-
end
|
481
|
-
|
482
|
-
def add(block)
|
483
|
-
if m = /^Input #(\d+),/.match(block) then
|
484
|
-
@inputs[m[0].to_i] = Input.new block
|
485
|
-
end
|
486
|
-
end
|
487
|
-
|
488
|
-
end
|
489
|
-
|
490
|
-
end
|