greatseth-rvideo 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/CHANGELOG +70 -0
  2. data/ENV +100 -0
  3. data/ENV2 +129 -0
  4. data/LICENSE +20 -0
  5. data/Manifest +74 -0
  6. data/README +91 -0
  7. data/RULES +11 -0
  8. data/Rakefile +50 -0
  9. data/config/boot.rb +25 -0
  10. data/lib/rvideo.rb +43 -0
  11. data/lib/rvideo/errors.rb +24 -0
  12. data/lib/rvideo/float.rb +7 -0
  13. data/lib/rvideo/frame_capturer.rb +127 -0
  14. data/lib/rvideo/inspector.rb +469 -0
  15. data/lib/rvideo/reporter.rb +176 -0
  16. data/lib/rvideo/reporter/views/index.html.erb +27 -0
  17. data/lib/rvideo/reporter/views/report.css +27 -0
  18. data/lib/rvideo/reporter/views/report.html.erb +81 -0
  19. data/lib/rvideo/reporter/views/report.js +9 -0
  20. data/lib/rvideo/string.rb +5 -0
  21. data/lib/rvideo/tools/abstract_tool.rb +393 -0
  22. data/lib/rvideo/tools/ffmpeg.rb +273 -0
  23. data/lib/rvideo/tools/ffmpeg2theora.rb +42 -0
  24. data/lib/rvideo/tools/flvtool2.rb +50 -0
  25. data/lib/rvideo/tools/mencoder.rb +103 -0
  26. data/lib/rvideo/tools/mp4box.rb +21 -0
  27. data/lib/rvideo/tools/mp4creator.rb +35 -0
  28. data/lib/rvideo/tools/mplayer.rb +31 -0
  29. data/lib/rvideo/tools/yamdi.rb +44 -0
  30. data/lib/rvideo/transcoder.rb +120 -0
  31. data/lib/rvideo/version.rb +9 -0
  32. data/rvideo.gemspec +37 -0
  33. data/scripts/txt2html +67 -0
  34. data/setup.rb +1585 -0
  35. data/spec/files/boat.avi +0 -0
  36. data/spec/files/kites.mp4 +0 -0
  37. data/spec/fixtures/ffmpeg_builds.yml +28 -0
  38. data/spec/fixtures/ffmpeg_results.yml +608 -0
  39. data/spec/fixtures/files.yml +398 -0
  40. data/spec/fixtures/recipes.yml +58 -0
  41. data/spec/integrations/formats_spec.rb +315 -0
  42. data/spec/integrations/frame_capturer_spec.rb +26 -0
  43. data/spec/integrations/inspection_spec.rb +112 -0
  44. data/spec/integrations/recipes_spec.rb +0 -0
  45. data/spec/integrations/rvideo_spec.rb +17 -0
  46. data/spec/integrations/transcoder_integration_spec.rb +29 -0
  47. data/spec/integrations/transcoding_spec.rb +9 -0
  48. data/spec/spec.opts +1 -0
  49. data/spec/spec_helper.rb +16 -0
  50. data/spec/support.rb +36 -0
  51. data/spec/units/abstract_tool_spec.rb +111 -0
  52. data/spec/units/ffmpeg_spec.rb +311 -0
  53. data/spec/units/flvtool2_spec.rb +324 -0
  54. data/spec/units/frame_capturer_spec.rb +72 -0
  55. data/spec/units/inspector_spec.rb +59 -0
  56. data/spec/units/mencoder_spec.rb +4994 -0
  57. data/spec/units/mp4box_spec.rb +34 -0
  58. data/spec/units/mp4creator_spec.rb +34 -0
  59. data/spec/units/mplayer_spec.rb +34 -0
  60. data/spec/units/string_spec.rb +8 -0
  61. data/spec/units/transcoder_spec.rb +156 -0
  62. data/tasks/deployment.rake +5 -0
  63. data/tasks/testing.rake +27 -0
  64. data/tasks/transcoding.rake +40 -0
  65. data/tasks/website.rake +8 -0
  66. data/website/index.html +219 -0
  67. data/website/index.txt +142 -0
  68. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  69. metadata +181 -0
@@ -0,0 +1,273 @@
1
+ module RVideo
2
+ module Tools
3
+ class Ffmpeg
4
+ RESOLUTION_ABBREVIATIONS = {
5
+ "sqcif" => "128x96",
6
+ "qcif" => "176x144",
7
+ "cif" => "352x288",
8
+ "4cif" => "704x576",
9
+ "qqvga" => "160x120",
10
+ "qvga" => "320x240",
11
+ "vga" => "640x480",
12
+ "svga" => "800x600",
13
+ "xga" => "1024x768",
14
+ "uxga" => "1600x1200",
15
+ "qxga" => "2048x1536",
16
+ "sxga" => "1280x1024",
17
+ "qsxga" => "2560x2048",
18
+ "hsxga" => "5120x4096",
19
+ "wvga" => "852x480",
20
+ "wxga" => "1366x768",
21
+ "wsxga" => "1600x1024",
22
+ "wuxga" => "1920x1200",
23
+ "woxga" => "2560x1600",
24
+ "wqsxga" => "3200x2048",
25
+ "wquxga" => "3840x2400",
26
+ "whsxga" => "6400x4096",
27
+ "whuxga" => "7680x4800",
28
+ "cga" => "320x200",
29
+ "ega" => "640x350",
30
+ "hd480" => "852x480",
31
+ "hd720" => "1280x720",
32
+ "hd1080" => "1920x1080"
33
+ }
34
+
35
+ VALID_ASPECT_STRINGS = ["4:3", "16:9"]
36
+ VALID_ASPECT_FLOATS = [1.3333, 1.7777]
37
+
38
+ # The flag used to set video bitrate has apparently changed between
39
+ # different ffmpeg versions. In the latest builds -b is used.
40
+ # In older builds it was -v which is now used to set verbosity of logging.
41
+ DEFAULT_VIDEO_BIT_RATE_PARAMETER = "b"
42
+ cattr_accessor :video_bit_rate_parameter
43
+ self.video_bit_rate_parameter = DEFAULT_VIDEO_BIT_RATE_PARAMETER
44
+
45
+ include AbstractTool::InstanceMethods
46
+
47
+ attr_reader :frame, :q, :size, :time, :output_bitrate, :video_size, :audio_size, :header_size, :overhead, :psnr, :output_fps
48
+
49
+ # Not sure if this is needed anymore...
50
+ def tool_command
51
+ 'ffmpeg'
52
+ end
53
+
54
+ def format_fps(params={})
55
+ "-r #{params[:fps]}"
56
+ end
57
+
58
+ def format_video_bit_rate(params = {})
59
+ "-#{video_bit_rate_parameter} #{params[:video_bit_rate]}k"
60
+ end
61
+
62
+ def format_video_bit_rate_tolerance(params = {})
63
+ "-bt #{params[:video_bit_rate_tolerance]}k"
64
+ end
65
+
66
+ def format_video_bit_rate_min(params = {})
67
+ "-minrate #{params[:video_bit_rate_min]}k"
68
+ end
69
+
70
+ def format_video_bit_rate_max(params = {})
71
+ "-maxrate #{params[:video_bit_rate_max]}k"
72
+ end
73
+
74
+ def format_video_quality(params={})
75
+ bitrate = params[:video_bit_rate].blank? ? nil : params[:video_bit_rate]
76
+
77
+ params.merge! get_original_fps unless params[:fps]
78
+
79
+ factor = params[:scale][:width].to_f * params[:scale][:height].to_f * params[:fps].to_f
80
+
81
+ case params[:video_quality]
82
+ when 'low'
83
+ bitrate ||= (factor / 12000).to_i
84
+ params[:video_bit_rate] = bitrate
85
+ "#{format_video_bit_rate params} -crf 30 -me zero -subq 1 -refs 1 -threads auto"
86
+ when 'medium'
87
+ bitrate ||= (factor / 9000).to_i
88
+ params[:video_bit_rate] = bitrate
89
+ "#{format_video_bit_rate params} -crf 22 -flags +loop -cmp +sad -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me hex -subq 3 -trellis 1 -refs 2 -bf 3 -b_strategy 1 -coder 1 -me_range 16 -g 250"
90
+ when 'high'
91
+ bitrate ||= (factor / 3600).to_i
92
+ params[:video_bit_rate] = bitrate
93
+ "#{format_video_bit_rate params} -crf 18 -flags +loop -cmp +sad -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me full -subq 6 -trellis 1 -refs 3 -bf 3 -b_strategy 1 -coder 1 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71"
94
+ end
95
+ end
96
+
97
+ def format_resolution(params={})
98
+ p = "-s #{params[:scale][:width]}x#{params[:scale][:height]}"
99
+ if params[:letterbox]
100
+ plr = ((params[:letterbox][:width] - params[:scale][:width]) / 2).to_i
101
+ ptb = ((params[:letterbox][:height] - params[:scale][:height]) / 2).to_i
102
+ p += " -padtop #{ptb} -padbottom #{ptb} -padleft #{plr} -padright #{plr} "
103
+ end
104
+ p
105
+ end
106
+
107
+ def format_audio_channels(params={})
108
+ "-ac #{params[:channels]}"
109
+ end
110
+
111
+ def format_audio_bit_rate(params={})
112
+ "-ab #{params[:bit_rate]}k"
113
+ end
114
+
115
+ def format_audio_sample_rate(params={})
116
+ "-ar #{params[:sample_rate]}"
117
+ end
118
+
119
+
120
+ private
121
+
122
+ # Turns the temp log file into a useful string, from which we can parse the
123
+ # transcoding results.
124
+ # These log files can be enormous, so pulling the whole thing into memory is not an
125
+ # option.
126
+ def populate_raw_result(temp_file_name)
127
+ @raw_result = ""
128
+
129
+ # Is the log file exceptionally long? It's really not a big deal to pull in a thousand lines or so
130
+ # into memory. It's the gigantic files that cause problems. If the files isn't too large,
131
+ # just pull it in.
132
+ line_count = 0
133
+ if m = /^\s*(\d+)/.match(`wc -l #{temp_file_name}`)
134
+ line_count = m[1].to_i
135
+ end
136
+
137
+ if line_count > 500
138
+ # Find the message indicating that the command is actually running.
139
+ running_string = "Press .* to stop encoding"
140
+ @raw_result << `grep "#{running_string}" #{temp_file_name}`
141
+ end
142
+
143
+ # Append the bottom of the log file, where the interesting bits live.
144
+ @raw_result << `tail -n 500 #{temp_file_name}`
145
+ end
146
+
147
+ def parse_result(result)
148
+ if m = /Expected .+ for (.+) but found: (.+)/.match(result)
149
+ raise TranscoderError::InvalidCommand, m.to_s
150
+ end
151
+
152
+ if m = /Unable for find a suitable output format for.*$/.match(result)
153
+ raise TranscoderError::InvalidCommand, m[0]
154
+ end
155
+
156
+ if m = /Unknown codec \'(.*)\'/.match(result)
157
+ raise TranscoderError::InvalidFile, "Codec #{m[1]} not supported by this build of ffmpeg"
158
+ end
159
+
160
+ if m = /could not find codec parameters/.match(result)
161
+ raise TranscoderError::InvalidFile, "Codec not supported by this build of ffmpeg"
162
+ end
163
+
164
+ if m = /I\/O error occured\n(.*)$/.match(result)
165
+ raise TranscoderError::InvalidFile, "I/O error: #{m[1].strip}"
166
+ end
167
+
168
+ if m = /\n(.*)Unknown Format$/.match(result)
169
+ raise TranscoderError::InvalidFile, "unknown format (#{m[1]})"
170
+ end
171
+
172
+ if m = /\nERROR.*/m.match(result)
173
+ raise TranscoderError::InvalidFile, m[0]
174
+ end
175
+
176
+ if m = /[(\S+) @ \d+x\d+]error, (.+?)/.match(result)
177
+ raise TranscoderError::InvalidFile, "#{m[1]}: #{m[2]}"
178
+ end
179
+
180
+ if result =~ /usage: ffmpeg/
181
+ raise TranscoderError::InvalidCommand, "must pass a command to ffmpeg"
182
+ end
183
+
184
+ if result =~ /Output file does not contain.*stream/
185
+ raise TranscoderError, "Output file does not contain any video or audio streams."
186
+ end
187
+
188
+ if m = /Unsupported codec.*id=(.*)\).*for input stream\s*(.*)\s*/.match(result)
189
+ inspect_original if @original.nil?
190
+ case m[2]
191
+ when @original.audio_stream_id
192
+ codec_type = "audio"
193
+ codec = @original.audio_codec
194
+ when @original.video_stream_id
195
+ codec_type = "video"
196
+ codec = @original.video_codec
197
+ else
198
+ codec_type = "video or audio"
199
+ codec = "unknown"
200
+ end
201
+
202
+ raise TranscoderError::InvalidFile, "Unsupported #{codec_type} codec: #{codec} (id=#{m[1]}, stream=#{m[2]})"
203
+ #raise TranscoderError, "Codec #{m[1]} not supported (in stream #{m[2]})"
204
+ end
205
+
206
+ # Could not open './spec/../config/../tmp/processed/1/kites-1.avi'
207
+ if result =~ /Could not open .#{@output_file}.\Z/
208
+ raise TranscoderError, "Could not write output file to #{@output_file}"
209
+ end
210
+
211
+ full_details = /Press .* to stop encoding\n(.*)/m.match(result)
212
+ raise TranscoderError, "Unexpected result details (#{result})" if full_details.nil?
213
+ details = full_details[1].strip.gsub(/\s*\n\s*/," - ")
214
+
215
+ if details =~ /Could not write header/
216
+ raise TranscoderError, details
217
+ end
218
+
219
+ #frame= 584 q=6.0 Lsize= 708kB time=19.5 bitrate= 297.8kbits/s
220
+ #video:49kB audio:153kB global headers:0kB muxing overhead 250.444444%
221
+
222
+ #frame= 4126 q=31.0 Lsize= 5917kB time=69.1 bitrate= 702.0kbits/s
223
+ #video:2417kB audio:540kB global headers:0kB muxing overhead 100.140277%
224
+
225
+ #frame= 273 fps= 31 q=10.0 Lsize= 398kB time=5.9 bitrate= 551.8kbits/s
226
+ #video:284kB audio:92kB global headers:0kB muxing overhead 5.723981%
227
+
228
+ #mdb:94, lastbuf:0 skipping granule 0
229
+ #size= 1080kB time=69.1 bitrate= 128.0kbits /s
230
+ #video:0kB audio:1080kB global headers:0kB muxing overhead 0.002893%
231
+
232
+ #size= 80kB time=5.1 bitrate= 128.0kbits/s ^Msize= 162kB time=10.3 bitrate= 128.0kbits/s ^Msize= 241kB time=15.4 bitrate= 128.0kbits/s ^Msize= 329kB time=21.1 bitrate= 128.0kbits/s ^Msize= 413kB time=26.4 bitrate= 128.0kbits/s ^Msize= 506kB time=32.4 bitrate= 128.0kbits/s ^Msize= 591kB time=37.8 bitrate= 128.0kbits/s ^Msize= 674kB time=43.2 bitrate= 128.0kbits/s ^Msize= 771kB time=49.4 bitrate= 128.0kbits/s ^Msize= 851kB time=54.5 bitrate= 128.0kbits/s ^Msize= 932kB time=59.6 bitrate= 128.0kbits/s ^Msize= 1015kB time=64.9 bitrate= 128.0kbits/s ^Msize= 1094kB time=70.0 bitrate= 128.0kbits/s ^Msize= 1175kB time=75.2 bitrate= 128.0kbits/s ^Msize= 1244kB time=79.6 bitrate= 128.0kbits/s ^Msize= 1335kB time=85.4 bitrate= 128.0kbits/s ^Msize= 1417kB time=90.7 bitrate= 128.0kbits/s ^Msize= 1508kB time=96.5 bitrate= 128.0kbits/s ^Msize= 1589kB time=101.7 bitrate= 128.0kbits/s ^Msize= 1671kB time=106.9 bitrate= 128.0kbits/s ^Msize= 1711kB time=109.5 bitrate= 128.0kbits/s - video:0kB audio:1711kB global headers:0kB muxing overhead 0.001826%
233
+
234
+ #mdb:14, lastbuf:0 skipping granule 0 - overread, skip -5 enddists: -2 -2 - overread, skip -5 enddists: -2 -2 - size= 90kB time=5.7 bitrate= 128.0kbits/s \nsize= 189kB time=12.1 bitrate= 128.0kbits/s
235
+
236
+ #size= 59kB time=20.2 bitrate= 24.0kbits/s \nsize= 139kB time=47.4 bitrate= 24.0kbits/s \nsize= 224kB time=76.5 bitrate= 24.0kbits/s \nsize= 304kB time=103.7 bitrate= 24.0kbits/s \nsi
237
+
238
+ #mdb:14, lastbuf:0 skipping granule 0 - overread, skip -5 enddists: -2 -2 - overread, skip -5 enddists: -2 -2 - size= 81kB time=10.3 bitrate= 64.0kbits/s \nsize= 153kB time=19.6 bitrate= 64.0kbits/s
239
+
240
+ #size= 65kB time=4.1 bitrate= 128.1kbits/s \nsize= 119kB time=7.6 bitrate= 128.0kbits/s \nsize= 188kB time=12.0 bitrate= 128.0kbits/s \nsize= 268kB time=17.1 bitrate= 128.0kbits/s \nsize=
241
+
242
+ #Error while decoding stream #0.1 [mpeg4aac @ 0xb7d089f0]faac: frame decoding failed: Gain control not yet implementedError while decoding stream #0.1frame= 2143 fps= 83 q=4.0 size= 4476kB time=71.3 bitrate= 514.5kbits/s ^M[mpeg4aac @ 0xb7d089f0]faac: frame decoding failed: Gain control not yet implementedError while decoding stream #0.1
243
+
244
+ # NOTE: had to remove "\s" from "\s.*L.*size=" from this regexp below.
245
+ # Not sure why. Unit tests were succeeding, but hand tests weren't.
246
+ if details =~ /video:/
247
+ #success = /^frame=\s*(\S*)\s*q=(\S*).*L.*size=\s*(\S*)\s*time=\s*(\S*)\s*bitrate=\s*(\S*)\s*/m.match(details)
248
+ @frame = details[/frame=\s*(\S*)/, 1]
249
+ @output_fps = details[/fps=\s*(\S*)/, 1]
250
+ @q = details[/\s+q=\s*(\S*)/, 1]
251
+ @size = details[/size=\s*(\S*)/, 1]
252
+ @time = details[/time=\s*(\S*)/, 1]
253
+ @output_bitrate = details[/bitrate=\s*(\S*)/, 1]
254
+
255
+ @video_size = details[/video:\s*(\S*)/, 1]
256
+ @audio_size = details[/audio:\s*(\S*)/, 1]
257
+ @header_size = details[/headers:\s*(\S*)/, 1]
258
+ @overhead = details[/overhead[:]*\s*(\S*)/, 1]
259
+
260
+ psnr_match = /PSNR=(.*)\s*size=/.match(details)
261
+ @psnr = psnr_match[1].strip if psnr_match
262
+ return true
263
+ end
264
+
265
+ #[mp3 @ 0x54340c]flv doesnt support that sample rate, choose from (44100, 22050, 11025)
266
+ #Could not write header for output file #0 (incorrect codec parameters ?)
267
+
268
+ raise TranscoderError::UnexpectedResult, details
269
+ end
270
+
271
+ end
272
+ end
273
+ end
@@ -0,0 +1,42 @@
1
+ module RVideo
2
+ module Tools
3
+ class Ffmpeg2theora
4
+ include AbstractTool::InstanceMethods
5
+
6
+ attr_reader :raw_metadata
7
+
8
+ def tool_command
9
+ 'ffmpeg2theora'
10
+ end
11
+
12
+ def format_video_quality(params={})
13
+ bitrate = params[:video_bit_rate].blank? ? nil : params[:video_bit_rate]
14
+ factor = (params[:scale][:width].to_f * params[:scale][:height].to_f * params[:fps].to_f)
15
+ case params[:video_quality]
16
+ when 'low'
17
+ " -v 1 "
18
+ when 'medium'
19
+ "-v 5 "
20
+ when 'high'
21
+ "-v 10 "
22
+ else
23
+ ""
24
+ end
25
+ end
26
+
27
+ def parse_result(result)
28
+ if m = /does not exist or has an unknown data format/.match(result)
29
+ raise TranscoderError::InvalidFile, "I/O error"
30
+ end
31
+
32
+ if m = /General output options/.match(result)
33
+ raise TranscoderError::InvalidCommand, "no command passed to ffmpeg2theora, or no output file specified"
34
+ end
35
+
36
+ @raw_metadata = result.empty? ? "No Results" : result
37
+ return true
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,50 @@
1
+ # Warning: If you're dealing with large files, you should consider using yamdi instead.
2
+ module RVideo
3
+ module Tools
4
+ class Flvtool2
5
+ include AbstractTool::InstanceMethods
6
+
7
+ attr_reader :raw_metadata
8
+
9
+ #attr_reader :has_key_frames, :cue_points, :audiodatarate, :has_video, :stereo, :can_seek_to_end, :framerate, :audiosamplerate, :videocodecid, :datasize, :lasttimestamp,
10
+ # :audiosamplesize, :audiosize, :has_audio, :audiodelay, :videosize, :metadatadate, :metadatacreator, :lastkeyframetimestamp, :height, :filesize, :has_metadata, :audiocodecid,
11
+ # :duration, :videodatarate, :has_cue_points, :width
12
+
13
+ def tool_command
14
+ 'flvtool2'
15
+ end
16
+
17
+ private
18
+
19
+ def parse_result(result)
20
+ if result.empty?
21
+ return true
22
+ end
23
+
24
+ if m = /ERROR: No such file or directory(.*)\n/.match(result)
25
+ raise TranscoderError::InputFileNotFound, m[0]
26
+ end
27
+
28
+ if m = /ERROR: IO is not a FLV stream/.match(result)
29
+ raise TranscoderError::InvalidFile, "input must be a valid FLV file"
30
+ end
31
+
32
+ if m = /Copyright.*Norman Timmler/i.match(result)
33
+ raise TranscoderError::InvalidCommand, "command printed flvtool2 help text (and presumably didn't execute)"
34
+ end
35
+
36
+ if m = /ERROR: undefined method .?timestamp.? for nil/.match(result)
37
+ raise TranscoderError::InvalidFile, "Output file was empty (presumably)"
38
+ end
39
+
40
+ if m = /\A---(.*)...\Z/m.match(result)
41
+ @raw_metadata = m[0]
42
+ return true
43
+ end
44
+
45
+ raise TranscoderError::UnexpectedResult, result
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,103 @@
1
+ module RVideo
2
+ module Tools
3
+ class Mencoder
4
+ include AbstractTool::InstanceMethods
5
+
6
+ attr_reader :frame, :size, :time, :bitrate, :video_size, :audio_size, :output_fps
7
+
8
+ def tool_command
9
+ 'mencoder'
10
+ end
11
+
12
+ def format_fps(params={})
13
+ " -ofps #{params[:fps]}"
14
+ end
15
+
16
+ def format_resolution(params={})
17
+ p = " -vf scale=#{params[:scale][:width]}:#{params[:scale][:height]}"
18
+ if params[:letterbox]
19
+ p += ",expand=#{params[:letterbox][:width]}:#{params[:letterbox][:height]}"
20
+ end
21
+ p += ",harddup"
22
+ end
23
+
24
+ def format_audio_channels(params={})
25
+ " -channels #{params[:channels]}"
26
+ end
27
+
28
+ def format_audio_bit_rate(params={})
29
+ " br=#{params[:bit_rate]}:"
30
+ end
31
+
32
+ def format_audio_sample_rate(params={})
33
+ " -srate #{params[:sample_rate]}"
34
+ end
35
+
36
+ def format_video_quality(params={})
37
+ bitrate = params[:video_bit_rate].blank? ? nil : params[:video_bit_rate]
38
+ factor = (params[:scale][:width].to_f * params[:scale][:height].to_f * params[:fps].to_f)
39
+ case params[:video_quality]
40
+ when 'low'
41
+ bitrate ||= (factor / 12000).to_i
42
+ " -x264encopts threads=auto:subq=1:me=dia:frameref=1:crf=30:bitrate=#{bitrate} "
43
+ when 'medium'
44
+ bitrate ||= (factor / 9000).to_i
45
+ " -x264encopts threads=auto:subq=3:me=hex:frameref=2:crf=22:bitrate=#{bitrate} "
46
+ when 'high'
47
+ bitrate ||= (factor / 3600).to_i
48
+ " -x264encopts threads=auto:subq=6:me=dia:frameref=3:crf=18:bitrate=#{bitrate} "
49
+ else
50
+ ""
51
+ end
52
+ end
53
+
54
+
55
+
56
+ private
57
+
58
+ def parse_result(result)
59
+ if m = /Exiting.*No output file specified/.match(result)
60
+ raise TranscoderError::InvalidCommand, "no command passed to mencoder, or no output file specified"
61
+ end
62
+
63
+ if m = /counldn't set specified parameters, exiting/.match(result)
64
+ raise TranscoderError::InvalidCommand, "a combination of the recipe parameters is invalid: #{result}"
65
+ end
66
+
67
+ if m = /Sorry, this file format is not recognized\/supported/.match(result)
68
+ raise TranscoderError::InvalidFile, "unknown format"
69
+ end
70
+
71
+ if m = /Cannot open file\/device./.match(result)
72
+ raise TranscoderError::InvalidFile, "I/O error"
73
+ end
74
+
75
+ if m = /File not found:$/.match(result)
76
+ raise TranscoderError::InvalidFile, "I/O error"
77
+ end
78
+
79
+ video_details = result.match /Video stream:(.*)$/
80
+ if video_details
81
+ @bitrate = video_details[0][/Video stream:\s*([0-9.]*)/, 1]
82
+ @video_size = video_details[0][/size:\s*(\d*)\s*(\S*)/, 1]
83
+ @time = video_details[0][/bytes\s*([0-9.]*)/, 1]
84
+ @frame = video_details[0][/secs\s*(\d*)/, 1]
85
+ @output_fps = (@frame.to_f / @time.to_f).round_to(3)
86
+
87
+ elsif result =~ /Video stream is mandatory/
88
+ raise TranscoderError::InvalidFile,
89
+ "Video stream required, and no video stream found"
90
+ end
91
+
92
+ audio_details = result.match /Audio stream:(.*)$/
93
+ if audio_details
94
+ @audio_size = audio_details[0][/size:\s*(\d*)\s*\S*/, 1]
95
+ else
96
+ @audio_size = 0
97
+ end
98
+ @size = (@video_size.to_i + @audio_size.to_i).to_s
99
+ end
100
+
101
+ end
102
+ end
103
+ end