rvideo 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/ENV +100 -0
  2. data/ENV2 +129 -0
  3. data/History.txt +3 -0
  4. data/License.txt +20 -0
  5. data/Manifest.txt +44 -0
  6. data/README.txt +91 -0
  7. data/RULES +11 -0
  8. data/Rakefile +163 -0
  9. data/config/boot.rb +16 -0
  10. data/lib/rvideo.rb +19 -0
  11. data/lib/rvideo/errors.rb +21 -0
  12. data/lib/rvideo/inspector.rb +486 -0
  13. data/lib/rvideo/reporter.rb +176 -0
  14. data/lib/rvideo/reporter/views/index.html.erb +27 -0
  15. data/lib/rvideo/reporter/views/report.css +27 -0
  16. data/lib/rvideo/reporter/views/report.html.erb +81 -0
  17. data/lib/rvideo/reporter/views/report.js +9 -0
  18. data/lib/rvideo/tools/abstract_tool.rb +79 -0
  19. data/lib/rvideo/tools/ffmpeg.rb +111 -0
  20. data/lib/rvideo/tools/flvtool2.rb +45 -0
  21. data/lib/rvideo/transcoder.rb +113 -0
  22. data/lib/rvideo/version.rb +9 -0
  23. data/scripts/txt2html +67 -0
  24. data/setup.rb +1585 -0
  25. data/spec/files/kites.mp4 +0 -0
  26. data/spec/fixtures/ffmpeg_builds.yml +28 -0
  27. data/spec/fixtures/files.yml +374 -0
  28. data/spec/fixtures/recipes.yml +6 -0
  29. data/spec/integrations/files/files.yml +361 -0
  30. data/spec/integrations/formats_spec.rb +287 -0
  31. data/spec/integrations/inspection_spec.rb +15 -0
  32. data/spec/integrations/recipes_spec.rb +0 -0
  33. data/spec/integrations/rvideo_spec.rb +17 -0
  34. data/spec/integrations/transcoding_spec.rb +9 -0
  35. data/spec/spec.opts +1 -0
  36. data/spec/spec_helper.rb +11 -0
  37. data/spec/units/abstract_tool_spec.rb +112 -0
  38. data/spec/units/ffmpeg_spec.rb +703 -0
  39. data/spec/units/flvtool2_spec.rb +314 -0
  40. data/spec/units/inspector_spec.rb +41 -0
  41. data/spec/units/transcoder_spec.rb +140 -0
  42. data/website/index.html +219 -0
  43. data/website/index.txt +142 -0
  44. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  45. metadata +94 -0
@@ -0,0 +1,314 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ module RVideo
4
+ module Tools
5
+
6
+ describe Flvtool2 do
7
+ before do
8
+ setup_flvtool2_spec
9
+ end
10
+
11
+ it "should initialize with valid arguments" do
12
+ @flvtool2.class.should == Flvtool2
13
+ end
14
+
15
+ it "should have the correct tool_command" do
16
+ @flvtool2.tool_command.should == 'flvtool2'
17
+ end
18
+
19
+ it "should call parse_result on execute, with a result string" do
20
+ @flvtool2.should_receive(:parse_result).once.with /\AERROR: No such file or directory/
21
+ @flvtool2.execute
22
+ end
23
+
24
+ it "should mixin AbstractTool" do
25
+ Flvtool2.included_modules.include?(AbstractTool::InstanceMethods).should be_true
26
+ end
27
+
28
+ it "should set supported options successfully" do
29
+ @flvtool2.options[:temp_file].should == @options[:temp_file]
30
+ @flvtool2.options[:output_file].should == @options[:output_file]
31
+ end
32
+
33
+ end
34
+
35
+ describe Flvtool2, " when parsing a result" do
36
+ before do
37
+ setup_flvtool2_spec
38
+ end
39
+
40
+ it "should set metadata if called with -P option" do
41
+ @flvtool2.send(:parse_result, @metadata_result).should be_true
42
+ @flvtool2.raw_metadata.should == @metadata_result
43
+ end
44
+
45
+ it "should succeed but not set metadata without -P option" do
46
+ @flvtool2.send(:parse_result,"").should be_true
47
+ end
48
+ end
49
+
50
+ context Flvtool2, " result parsing should raise an exception" do
51
+
52
+ setup do
53
+ setup_flvtool2_spec
54
+ end
55
+
56
+ specify "when not passed a command" do
57
+ lambda {
58
+ @flvtool2.send(:parse_result, @helptext)
59
+ }.should raise_error(TranscoderError::InvalidCommand, /flvtool2 help text/)
60
+ end
61
+
62
+ specify "when passed an invalid input file" do
63
+ lambda {
64
+ @flvtool2.send(:parse_result, @non_flv_input)
65
+ }.should raise_error(TranscoderError::InvalidFile, "input must be a valid FLV file")
66
+ end
67
+
68
+ specify "when input file not found" do
69
+ lambda {
70
+ @flvtool2.send(:parse_result, @no_input_file)
71
+ }.should raise_error(TranscoderError::InputFileNotFound, /^ERROR: No such file or directory/)
72
+ end
73
+
74
+ specify "when receiving unexpected results" do
75
+ lambda {
76
+ @flvtool2.send(:parse_result, @unexpected_results)
77
+ }.should raise_error(TranscoderError::UnexpectedResult, /ffmpeg/i)
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ def setup_flvtool2_spec
84
+ @options = {:temp_file => "foo", :output_file => "bar"}
85
+ @command = "flvtool2 -U $temp_file$ $output_file$"
86
+ @flvtool2 = RVideo::Tools::Flvtool2.new(@command, @options)
87
+
88
+ @helptext = "FLVTool2 1.0.6
89
+ Copyright (c) 2005-2007 Norman Timmler (inlet media e.K., Hamburg, Germany)
90
+ Get the latest version from http://www.inlet-media.de/flvtool2
91
+ This program is published under the BSD license.
92
+
93
+ Usage: flvtool2 [-ACDPUVaciklnoprstvx]... [-key:value]... in-path|stdin [out-path|stdout]
94
+
95
+ If out-path is omitted, in-path will be overwritten.
96
+ In-path can be a single file, or a directory. If in-path is a directory,
97
+ out-path has to be likewise, or can be omitted. Directory recursion
98
+ is controlled by the -r switch. You can use stdin and stdout keywords
99
+ as in- and out-path for piping or redirecting.
100
+
101
+ Chain commands like that: -UP (updates FLV file than prints out meta data)
102
+
103
+ Commands:
104
+ -A Adds tags from -t tags-file
105
+ -C Cuts file using -i inpoint and -o outpoint
106
+ -D Debugs file (writes a lot to stdout)
107
+ -H Helpscreen will be shown
108
+ -P Prints out meta data to stdout
109
+ -U Updates FLV with an onMetaTag event
110
+
111
+ Switches:
112
+ -a Collapse space between cutted regions
113
+ -c Compatibility mode calculates some onMetaTag values different
114
+ -key:value Key-value-pair for onMetaData tag (overwrites generated values)
115
+ -i timestamp Inpoint for cut command in miliseconds
116
+ -k Keyframe mode slides onCuePoint(navigation) tags added by the
117
+ add command to nearest keyframe position
118
+ -l Logs FLV stream reading to stream.log in current directory
119
+ -n Number of tag to debug
120
+ -o timestamp Outpoint for cut command in miliseconds
121
+ -p Preserve mode only updates FLVs that have not been processed
122
+ before
123
+ -r Recursion for directory processing
124
+ -s Simulation mode never writes FLV data to out-path
125
+ -t path Tagfile (MetaTags written in XML)
126
+ -v Verbose mode
127
+ -x XML mode instead of YAML mode
128
+
129
+ REPORT BUGS at http://projects.inlet-media.de/flvtool2
130
+ Powered by Riva VX, http://rivavx.com"
131
+
132
+ @non_flv_input = "ERROR: IO is not a FLV stream. Wrong signature.
133
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flv/stream.rb:393:in `read_header'
134
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flv/stream.rb:57:in `initialize'
135
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:272:in `new'
136
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:272:in `open_stream'
137
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:238:in `process_files'
138
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:225:in `each'
139
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:225:in `process_files'
140
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:44:in `execute!'
141
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2.rb:168:in `execute!'
142
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2.rb:228
143
+ ERROR: /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
144
+ ERROR: /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:27:in `require'
145
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/bin/flvtool2:2
146
+ ERROR: /opt/local/bin/flvtool2:18:in `load'
147
+ ERROR: /opt/local/bin/flvtool2:18"
148
+
149
+ @no_input_file = "ERROR: No such file or directory - /Users/jon/code/spinoza/rvideo/foobar
150
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:259:in `initialize'
151
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:259:in `open'
152
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:259:in `open_stream'
153
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:238:in `process_files'
154
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:225:in `each'
155
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:225:in `process_files'
156
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2/base.rb:44:in `execute!'
157
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2.rb:168:in `execute!'
158
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/lib/flvtool2.rb:228
159
+ ERROR: /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
160
+ ERROR: /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:27:in `require'
161
+ ERROR: /opt/local/lib/ruby/gems/1.8/gems/flvtool2-1.0.6/bin/flvtool2:2
162
+ ERROR: /opt/local/bin/flvtool2:18:in `load'
163
+ ERROR: /opt/local/bin/flvtool2:18"
164
+
165
+ @unexpected_results = "FFmpeg version CVS, Copyright (c) 2000-2004 Fabrice Bellard
166
+ Mac OSX universal build for ffmpegX
167
+ configuration: --enable-memalign-hack --enable-mp3lame --enable-gpl --disable-vhook --disable-ffplay --disable-ffserver --enable-a52 --enable-xvid --enable-faac --enable-faad --enable-amr_nb --enable-amr_wb --enable-pthreads --enable-x264
168
+ libavutil version: 49.0.0
169
+ libavcodec version: 51.9.0
170
+ libavformat version: 50.4.0
171
+ built on Apr 15 2006 04:58:19, gcc: 4.0.1 (Apple Computer, Inc. build 5250)
172
+
173
+ Seems that stream 1 comes from film source: 600.00 (600/1) -> 59.75 (239/4)
174
+ Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'jobjob2.mov':
175
+ Duration: 00:01:09.0, start: 0.000000, bitrate: 28847 kb/s
176
+ Stream #0.0(eng): Audio: aac, 44100 Hz, stereo
177
+ Stream #0.1(eng), 59.75 fps(r): Video: dvvideo, yuv411p, 720x480
178
+ Stream mapping:
179
+ Stream #0.1 -> #0.0
180
+ Stream #0.0 -> #0.1
181
+ Press [q] to stop encoding"
182
+
183
+ @metadata_result = "---
184
+ /Users/jon/code/spinoza/rvideo/temp.flv:
185
+ hasKeyframes: true
186
+ cuePoints:
187
+ audiodatarate: 64.8512825785226
188
+ hasVideo: true
189
+ stereo: false
190
+ canSeekToEnd: false
191
+ framerate: 30
192
+ audiosamplerate: 44000
193
+ videocodecid: 2
194
+ datasize: 992710
195
+ lasttimestamp: 19.453
196
+ audiosamplesize: 16
197
+ audiosize: 165955
198
+ hasAudio: true
199
+ audiodelay: 0
200
+ videosize: 825165
201
+ metadatadate: Fri Sep 14 13:25:58 GMT-0500 2007
202
+ metadatacreator: inlet media FLVTool2 v1.0.6 - http://www.inlet-media.de/flvtool2
203
+ lastkeyframetimestamp: 19.219
204
+ height: 240
205
+ filesize: 998071
206
+ hasMetadata: true
207
+ keyframes:
208
+ times:
209
+ - 0
210
+ - 0.4
211
+ - 0.801
212
+ - 1.201
213
+ - 1.602
214
+ - 2.002
215
+ - 2.402
216
+ - 2.803
217
+ - 3.203
218
+ - 3.604
219
+ - 4.004
220
+ - 4.404
221
+ - 4.805
222
+ - 5.205
223
+ - 5.606
224
+ - 6.006
225
+ - 6.406
226
+ - 6.807
227
+ - 7.207
228
+ - 7.608
229
+ - 8.008
230
+ - 8.408
231
+ - 8.809
232
+ - 9.209
233
+ - 9.61
234
+ - 10.01
235
+ - 10.41
236
+ - 10.811
237
+ - 11.211
238
+ - 11.612
239
+ - 12.012
240
+ - 12.412
241
+ - 12.813
242
+ - 13.213
243
+ - 13.614
244
+ - 14.014
245
+ - 14.414
246
+ - 14.815
247
+ - 15.215
248
+ - 15.616
249
+ - 16.016
250
+ - 16.416
251
+ - 16.817
252
+ - 17.217
253
+ - 17.618
254
+ - 18.018
255
+ - 18.418
256
+ - 18.819
257
+ - 19.219
258
+ filepositions:
259
+ - 1573
260
+ - 24627
261
+ - 56532
262
+ - 90630
263
+ - 137024
264
+ - 185134
265
+ - 225110
266
+ - 262990
267
+ - 291508
268
+ - 330947
269
+ - 370739
270
+ - 398621
271
+ - 426203
272
+ - 448515
273
+ - 468895
274
+ - 488660
275
+ - 508208
276
+ - 523991
277
+ - 541463
278
+ - 558463
279
+ - 572248
280
+ - 590480
281
+ - 604788
282
+ - 620959
283
+ - 632658
284
+ - 645806
285
+ - 655949
286
+ - 668266
287
+ - 684172
288
+ - 697064
289
+ - 713306
290
+ - 728607
291
+ - 746615
292
+ - 760836
293
+ - 774867
294
+ - 790766
295
+ - 804779
296
+ - 821676
297
+ - 843681
298
+ - 857278
299
+ - 873427
300
+ - 888404
301
+ - 900958
302
+ - 914336
303
+ - 927537
304
+ - 941037
305
+ - 958188
306
+ - 974841
307
+ - 988796
308
+ audiocodecid: 2
309
+ videodatarate: 336.705289672544
310
+ duration: 19.486
311
+ hasCuePoints: false
312
+ width: 320
313
+ ..."
314
+ end
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ module RVideo
4
+ describe Inspector do
5
+ it "should raise an error if ffmpeg cannot be found" do
6
+ lambda {
7
+ file = Inspector.new(:file => "#{TEST_FILE_PATH}/kites.mp4", :ffmpeg_binary => "ffmpeg-nonexistant")
8
+ }.should raise_error(RuntimeError, /^ffmpeg could not be found/)
9
+ end
10
+
11
+ it "should raise an error if it doesn't recognize a file format" do
12
+ unrecognized_format(:text)
13
+ end
14
+
15
+ def unrecognized_format(format)
16
+ file = Inspector.new(:raw_response => files(format))
17
+ file.unknown_format?.should be_true
18
+ end
19
+ end
20
+
21
+ describe Inspector, " parsing ffmpeg info" do
22
+
23
+ it "should read ffmpeg build data successfully (with a darwinports build)" do
24
+ file = Inspector.new(:raw_response => ffmpeg('darwinports'))
25
+ file.ffmpeg_configuration.should == "--prefix=/opt/local --prefix=/opt/local --disable-vhook --mandir=/opt/local/share/man --extra-cflags=-DHAVE_LRINTF --extra-ldflags=-d -L/opt/local/lib --enable-gpl --enable-mp3lame --enable-libogg --enable-vorbis --enable-faac --enable-faad --enable-xvid --enable-x264 --enable-a52 --enable-dts"
26
+ file.ffmpeg_version.should == "SVN-r6399"
27
+ file.ffmpeg_libav.should == ["libavutil version: 49.0.1", "libavcodec version: 51.16.0", "libavformat version: 50.5.0"]
28
+ file.ffmpeg_build.should == "built on Mar 29 2007 17:18:04, gcc: 4.0.1 (Apple Computer, Inc. build 5367)"
29
+ file.raw_metadata.should =~ /^Input #/
30
+ end
31
+
32
+ it "should read ffmpeg build data successfully (with a compiled build)" do
33
+ file = Inspector.new(:raw_response => ffmpeg(:osx_intel_1))
34
+ file.ffmpeg_configuration.should == "--enable-memalign-hack --enable-mp3lame --enable-gpl --disable-vhook --disable-ffplay --disable-ffserver --enable-a52 --enable-xvid --enable-faac --enable-faad --enable-amr_nb --enable-amr_wb --enable-pthreads --enable-x264"
35
+ file.ffmpeg_version.should == "CVS"
36
+ file.ffmpeg_libav.should == ["libavutil version: 49.0.0", "libavcodec version: 51.9.0", "libavformat version: 50.4.0"]
37
+ file.ffmpeg_build.should == "built on Apr 15 2006 04:58:19, gcc: 4.0.1 (Apple Computer, Inc. build 5250)"
38
+ file.raw_metadata.should =~ /^Input #/
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,140 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ def setup_spec
4
+ @options = {:input_file => "foo", :output_file => "bar", :resolution => "baz"}
5
+ @simple_avi = "ffmpeg -i $input_file$ -ar 44100 -ab 64 -vcodec xvid -acodec mp3 -r 29.97 -s $resolution$ -y $output_file$"
6
+ @transcoder = RVideo::Transcoder.new
7
+ @mock_original_file = mock(:original)
8
+ @mock_original_file.stub!(:raw_response)
9
+ RVideo::Inspector.stub!(:new).and_return(@mock_original_file)
10
+ end
11
+
12
+ module RVideo
13
+
14
+ describe Transcoder, " when the execute method receives valid parameters" do
15
+ before do
16
+ setup_spec
17
+ @transcoder.stub!(:check_integrity).and_return(true)
18
+ end
19
+
20
+ it "should pass a string as-is, along with options" do
21
+ @transcoder.stub!(:parse_and_execute)
22
+ @simple_avi = "ffmpeg -i foo"
23
+ @transcoder.execute(@simple_avi, @options)
24
+ end
25
+
26
+ it "should store a Tool object at transcoder.executed_commands" do
27
+ @mock_ffmpeg = mock("ffmpeg")
28
+ Tools::AbstractTool.stub!(:assign).and_return(@mock_ffmpeg)
29
+ @mock_ffmpeg.should_receive(:execute)
30
+ @transcoder.execute(@simple_avi, @options)
31
+ @transcoder.executed_commands.size.should == 1
32
+ @transcoder.executed_commands.first.should == @mock_ffmpeg
33
+ end
34
+
35
+ end
36
+
37
+ describe Transcoder, " file integrity checks" do
38
+
39
+ before do
40
+ setup_spec
41
+ @transcoder.stub!(:parse_and_execute)
42
+ @mock_processed_file = mock("processed")
43
+ @mock_original_file.stub!(:duration).and_return 10
44
+ @mock_processed_file.stub!(:duration).and_return 10
45
+ @mock_processed_file.stub!(:invalid?).and_return false
46
+ Inspector.should_receive(:new).once.with(:file => "foo").and_return(@mock_original_file)
47
+ Inspector.should_receive(:new).once.with(:file => "bar").and_return(@mock_processed_file)
48
+ end
49
+
50
+ it "should call the inspector twice on a successful job, and should set @original and @processed" do
51
+ @transcoder.original.should be_nil
52
+ @transcoder.processed.should be_nil
53
+
54
+ @transcoder.execute(@simple_avi, @options)
55
+ @transcoder.original.should == @mock_original_file
56
+ @transcoder.processed.should == @mock_processed_file
57
+ end
58
+
59
+ it "should check integrity" do
60
+ @transcoder.should_receive(:check_integrity).once.and_return true
61
+ @transcoder.execute(@simple_avi, @options).should be_true
62
+ @transcoder.errors.should be_empty
63
+ end
64
+
65
+ it "should fail if output duration is more than 10% different than the original" do
66
+ @mock_original_file.should_receive(:duration).twice.and_return(10)
67
+ @mock_processed_file.should_receive(:duration).twice.and_return(13)
68
+ @transcoder.execute(@simple_avi, @options).should be_false
69
+ @transcoder.errors.should == ["Original file has a duration of 10, but processed file has a duration of 13"]
70
+ end
71
+
72
+ it "should fail if the processed file is invalid" do
73
+ @mock_processed_file.should_receive(:invalid?).and_return(true)
74
+ @transcoder.execute(@simple_avi, @options).should be_false
75
+ @transcoder.errors.should_not be_empty
76
+ end
77
+
78
+ end
79
+
80
+ describe Transcoder, "#parse_and_execute" do
81
+ before do
82
+ @options = {:input_file => "foo", :output_file => "bar", :resolution => "baz"}
83
+ @simple_avi = "ffmpeg -i $input_file$ -ar 44100 -ab 64 -vcodec xvid -acodec mp3 -r 29.97 -s $resolution$ -y $output_file$"
84
+ @mock_tool = mock("tool")
85
+ @mock_tool.stub!(:execute)
86
+ @transcoder = Transcoder.new
87
+ Inspector.stub!(:new)
88
+ end
89
+
90
+ it "should assign a command via AbstractTool.assign, and pass the right options" do
91
+ Tools::AbstractTool.should_receive(:assign).with(@simple_avi, @options).and_return(@mock_tool)
92
+ @transcoder.send(:parse_and_execute, @simple_avi, @options)
93
+ end
94
+
95
+ it "should call Tools::AbstractTool once with a one-line recipe" do
96
+ Tools::AbstractTool.should_receive(:assign).once.and_return(@mock_tool)
97
+ @transcoder.send(:parse_and_execute, @simple_avi, @options)
98
+ end
99
+
100
+ it "should call twice with a two-line recipe" do
101
+ two_line = "ffmpeg -i foo \n ffmpeg -i bar"
102
+ Tools::AbstractTool.should_receive(:assign).twice.and_return(@mock_tool)
103
+ @transcoder.send(:parse_and_execute, two_line, @options)
104
+ end
105
+
106
+ it "should call five times with a five-line recipe" do
107
+ five_line = "ffmpeg -i foo \n ffmpeg -i bar \n flvtool -i foo \n mp4box \n qt tools 8"
108
+ Tools::AbstractTool.should_receive(:assign).exactly(5).and_return(@mock_tool)
109
+ @transcoder.send(:parse_and_execute, five_line, @options)
110
+ end
111
+
112
+ it "should pass an exception from the abstract tool" do
113
+ Tools::AbstractTool.should_receive(:assign).and_raise(TranscoderError::UnexpectedResult)
114
+
115
+ lambda {
116
+ @transcoder.send(:parse_and_execute, @simple_avi, @options)
117
+ }.should raise_error(TranscoderError::UnexpectedResult)
118
+ end
119
+ end
120
+
121
+ describe Transcoder, " when the execute method receives invalid parameters" do
122
+ before do
123
+ setup_spec
124
+ end
125
+
126
+ it "should raise an exception when trying to call a tool that doesn't exist" do
127
+ lambda {
128
+ @transcoder.send(:parse_and_execute, "foo -i bar")
129
+ }.should raise_error(NameError, "uninitialized constant RVideo::Tools::Foo")
130
+ end
131
+
132
+ it "should raise an exception when the first argument is not a string" do
133
+ [String, 1, 1.0, true, nil, :foo].each do |obj|
134
+ lambda {
135
+ @transcoder.execute(obj)
136
+ }.should raise_error(ArgumentError, /first argument must either be/)
137
+ end
138
+ end
139
+ end
140
+ end