mhs-rvideo 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,154 @@
1
+ module RVideo
2
+ module Tools
3
+ class Ffmpeg
4
+ include AbstractTool::InstanceMethods
5
+
6
+ attr_reader :frame, :q, :size, :time, :output_bitrate, :video_size, :audio_size, :header_size, :overhead, :psnr, :output_fps
7
+
8
+ # Not sure if this is needed anymore...
9
+ def tool_command
10
+ 'ffmpeg'
11
+ end
12
+
13
+ #
14
+ # Return -r and the frame rate of the original file. E.g.:
15
+ #
16
+ # -r 29.97
17
+ #
18
+ # If the original frame rate can't be determined, return an empty
19
+ # string.
20
+ def original_fps
21
+ inspect_original if @original.nil?
22
+ if @original.fps
23
+ "-r #{@original.fps}"
24
+ else
25
+ ""
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def parse_result(result)
32
+
33
+ if m = /Unable for find a suitable output format for.*$/.match(result)
34
+ raise TranscoderError::InvalidCommand, m[0]
35
+ end
36
+
37
+ if m = /Unknown codec \'(.*)\'/.match(result)
38
+ raise TranscoderError::InvalidFile, "Codec #{m[1]} not supported by this build of ffmpeg"
39
+ end
40
+
41
+ if m = /could not find codec parameters/.match(result)
42
+ raise TranscoderError::InvalidFile, "Codec not supported by this build of ffmpeg"
43
+ end
44
+
45
+ if m = /I\/O error occured\n(.*)$/.match(result)
46
+ raise TranscoderError::InvalidFile, "I/O error: #{m[1].strip}"
47
+ end
48
+
49
+ if m = /\n(.*)Unknown Format$/.match(result)
50
+ raise TranscoderError::InvalidFile, "unknown format (#{m[1]})"
51
+ end
52
+
53
+ if m = /\nERROR.*/m.match(result)
54
+ raise TranscoderError::InvalidFile, m[0]
55
+ end
56
+
57
+ if result =~ /usage: ffmpeg/
58
+ raise TranscoderError::InvalidCommand, "must pass a command to ffmpeg"
59
+ end
60
+
61
+ if result =~ /Output file does not contain.*stream/
62
+ raise TranscoderError, "Output file does not contain any video or audio streams."
63
+ end
64
+
65
+ if m = /Unsupported codec.*id=(.*)\).*for input stream\s*(.*)\s*/.match(result)
66
+ inspect_original if @original.nil?
67
+ case m[2]
68
+ when @original.audio_stream_id
69
+ codec_type = "audio"
70
+ codec = @original.audio_codec
71
+ when @original.video_stream_id
72
+ codec_type = "video"
73
+ codec = @original.video_codec
74
+ else
75
+ codec_type = "video or audio"
76
+ codec = "unknown"
77
+ end
78
+
79
+ raise TranscoderError::InvalidFile, "Unsupported #{codec_type} codec: #{codec} (id=#{m[1]}, stream=#{m[2]})"
80
+ #raise TranscoderError, "Codec #{m[1]} not supported (in stream #{m[2]})"
81
+ end
82
+
83
+ # Could not open './spec/../config/../tmp/processed/1/kites-1.avi'
84
+ if result =~ /Could not open .#{@output_file}.\Z/
85
+ raise TranscoderError, "Could not write output file to #{@output_file}"
86
+ end
87
+
88
+ full_details = /Press .* to stop encoding\n(.*)/m.match(result)
89
+ raise TranscoderError, "Unexpected result details (#{result})" if full_details.nil?
90
+ details = full_details[1].strip.gsub(/\s*\n\s*/," - ")
91
+
92
+ if details =~ /Could not write header/
93
+ raise TranscoderError, details
94
+ end
95
+
96
+ #frame= 584 q=6.0 Lsize= 708kB time=19.5 bitrate= 297.8kbits/s
97
+ #video:49kB audio:153kB global headers:0kB muxing overhead 250.444444%
98
+
99
+ #frame= 4126 q=31.0 Lsize= 5917kB time=69.1 bitrate= 702.0kbits/s
100
+ #video:2417kB audio:540kB global headers:0kB muxing overhead 100.140277%
101
+
102
+ #frame= 273 fps= 31 q=10.0 Lsize= 398kB time=5.9 bitrate= 551.8kbits/s
103
+ #video:284kB audio:92kB global headers:0kB muxing overhead 5.723981%
104
+
105
+ #mdb:94, lastbuf:0 skipping granule 0
106
+ #size= 1080kB time=69.1 bitrate= 128.0kbits /s
107
+ #video:0kB audio:1080kB global headers:0kB muxing overhead 0.002893%
108
+
109
+ #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%
110
+
111
+ #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
112
+
113
+ #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
114
+
115
+ #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
116
+
117
+ #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=
118
+
119
+ #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
120
+
121
+ # NOTE: had to remove "\s" from "\s.*L.*size=" from this regexp below.
122
+ # Not sure why. Unit tests were succeeding, but hand tests weren't.
123
+ if details =~ /video:/
124
+ #success = /^frame=\s*(\S*)\s*q=(\S*).*L.*size=\s*(\S*)\s*time=\s*(\S*)\s*bitrate=\s*(\S*)\s*/m.match(details)
125
+ @frame = sanitary_match(/frame=\s*(\S*)/, details)
126
+ @output_fps = sanitary_match(/fps=\s*(\S*)/, details)
127
+ @q = sanitary_match(/\s+q=\s*(\S*)/, details)
128
+ @size = sanitary_match(/size=\s*(\S*)/, details)
129
+ @time = sanitary_match(/time=\s*(\S*)/, details)
130
+ @output_bitrate = sanitary_match(/bitrate=\s*(\S*)/, details)
131
+
132
+ @video_size = /video:\s*(\S*)/.match(details)[1]
133
+ @audio_size = /audio:\s*(\S*)/.match(details)[1]
134
+ @header_size = /headers:\s*(\S*)/.match(details)[1]
135
+ @overhead = /overhead[:]*\s*(\S*)/.match(details)[1]
136
+ psnr_match = /PSNR=(.*)\s*size=/.match(details)
137
+ @psnr = psnr_match[1].strip if psnr_match
138
+ return true
139
+ end
140
+
141
+ #[mp3 @ 0x54340c]flv doesnt support that sample rate, choose from (44100, 22050, 11025)
142
+ #Could not write header for output file #0 (incorrect codec parameters ?)
143
+
144
+ raise TranscoderError::UnexpectedResult, details
145
+ end
146
+
147
+ def sanitary_match(regexp, string)
148
+ match = regexp.match(string)
149
+ return match[1] if match
150
+ end
151
+
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,49 @@
1
+ module RVideo
2
+ module Tools
3
+ class Flvtool2
4
+ include AbstractTool::InstanceMethods
5
+
6
+ attr_reader :raw_metadata
7
+
8
+ #attr_reader :has_key_frames, :cue_points, :audiodatarate, :has_video, :stereo, :can_seek_to_end, :framerate, :audiosamplerate, :videocodecid, :datasize, :lasttimestamp,
9
+ # :audiosamplesize, :audiosize, :has_audio, :audiodelay, :videosize, :metadatadate, :metadatacreator, :lastkeyframetimestamp, :height, :filesize, :has_metadata, :audiocodecid,
10
+ # :duration, :videodatarate, :has_cue_points, :width
11
+
12
+ def tool_command
13
+ 'flvtool2'
14
+ end
15
+
16
+ private
17
+
18
+ def parse_result(result)
19
+ if result.empty?
20
+ return true
21
+ end
22
+
23
+ if m = /ERROR: No such file or directory(.*)\n/.match(result)
24
+ raise TranscoderError::InputFileNotFound, m[0]
25
+ end
26
+
27
+ if m = /ERROR: IO is not a FLV stream/.match(result)
28
+ raise TranscoderError::InvalidFile, "input must be a valid FLV file"
29
+ end
30
+
31
+ if m = /Copyright.*Norman Timmler/i.match(result)
32
+ raise TranscoderError::InvalidCommand, "command printed flvtool2 help text (and presumably didn't execute)"
33
+ end
34
+
35
+ if m = /ERROR: undefined method .?timestamp.? for nil/.match(result)
36
+ raise TranscoderError::InvalidFile, "Output file was empty (presumably)"
37
+ end
38
+
39
+ if m = /\A---(.*)...\Z/m.match(result)
40
+ @raw_metadata = m[0]
41
+ return true
42
+ end
43
+
44
+ raise TranscoderError::UnexpectedResult, result
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,65 @@
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, :fps
7
+
8
+ def tool_command
9
+ 'mencoder'
10
+ end
11
+
12
+ def original_fps
13
+ inspect_original if @original.nil?
14
+ if @original.fps
15
+ "-ofps #{@original.fps}"
16
+ else
17
+ ""
18
+ end
19
+ end
20
+
21
+ def parse_result(result)
22
+ if m = /Exiting.*No output file specified/.match(result)
23
+ raise TranscoderError::InvalidCommand, "no command passed to mencoder, or no output file specified"
24
+ end
25
+
26
+ if m = /Sorry, this file format is not recognized\/supported/.match(result)
27
+ raise TranscoderError::InvalidFile, "unknown format"
28
+ end
29
+
30
+ if m = /Cannot open file\/device./.match(result)
31
+ raise TranscoderError::InvalidFile, "I/O error"
32
+ end
33
+
34
+ if m = /File not found:$/.match(result)
35
+ raise TranscoderError::InvalidFile, "I/O error"
36
+ end
37
+
38
+ video_details = result.match /Video stream:(.*)$/
39
+ if video_details
40
+ @bitrate = sanitary_match(/Video stream:\s*([0-9.]*)/, video_details[0])
41
+ @video_size = sanitary_match(/size:\s*(\d*)\s*(\S*)/, video_details[0])
42
+ @time = sanitary_match(/bytes\s*([0-9.]*)/, video_details[0])
43
+ @frame = sanitary_match(/secs\s*(\d*)/, video_details[0])
44
+ @fps = (@frame.to_f / @time.to_f).round_to(3)
45
+ elsif result =~ /Video stream is mandatory/
46
+ raise TranscoderError::InvalidFile, "Video stream required, and no video stream found"
47
+ end
48
+
49
+ audio_details = result.match /Audio stream:(.*)$/
50
+ if audio_details
51
+ @audio_size = sanitary_match(/size:\s*(\d*)\s*(\S*)/, audio_details[0])
52
+ else
53
+ @audio_size = 0
54
+ end
55
+ @size = (@video_size.to_i + @audio_size.to_i).to_s
56
+ end
57
+
58
+ def sanitary_match(regexp, string)
59
+ match = regexp.match(string)
60
+ return match[1] if match
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,21 @@
1
+ module RVideo
2
+ module Tools
3
+ class Mp4box
4
+ include AbstractTool::InstanceMethods
5
+ attr_reader :raw_metadata
6
+
7
+ def tool_command
8
+ 'MP4Box'
9
+ end
10
+
11
+ private
12
+
13
+ def parse_result(result)
14
+ #currently, no useful info returned in result to determine if successful or not
15
+ @raw_metadata = result.empty? ? "No Results" : result
16
+ return true
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,36 @@
1
+ module RVideo
2
+ module Tools
3
+ class Mp4creator
4
+ include AbstractTool::InstanceMethods
5
+
6
+ attr_reader :raw_metadata
7
+
8
+ def tool_command
9
+ 'mp4creator'
10
+ end
11
+
12
+ def original_fps
13
+ inspect_original if @original.nil?
14
+ if @original.fps
15
+ "-rate=#{@original.fps}"
16
+ else
17
+ ""
18
+ end
19
+ end
20
+
21
+ def parse_result(result)
22
+ if m = /can't open file/.match(result)
23
+ raise TranscoderError::InvalidFile, "I/O error"
24
+ end
25
+
26
+ if m = /unknown file type/.match(result)
27
+ raise TranscoderError::InvalidFile, "I/O error"
28
+ end
29
+
30
+ @raw_metadata = result.empty? ? "No Results" : result
31
+ return true
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,31 @@
1
+ module RVideo
2
+ module Tools
3
+ class Mplayer
4
+ include AbstractTool::InstanceMethods
5
+
6
+ attr_reader :raw_metadata
7
+
8
+ def tool_command
9
+ 'mplayer'
10
+ end
11
+
12
+ def parse_result(result)
13
+ if m = /This will likely crash/.match(result)
14
+ raise TranscoderError::InvalidFile, "unknown format"
15
+ end
16
+
17
+ if m = /Failed to open/.match(result)
18
+ raise TranscoderError::InvalidFile, "I/O error"
19
+ end
20
+
21
+ if m = /File not found/.match(result)
22
+ raise TranscoderError::InvalidFile, "I/O error"
23
+ end
24
+
25
+ @raw_metadata = result.empty? ? "No Results" : result
26
+ return true
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,138 @@
1
+ module RVideo # :nodoc:
2
+ class Transcoder
3
+
4
+ attr_reader :executed_commands, :processed, :errors, :warnings, :total_time
5
+
6
+ #
7
+ # To transcode a video, initialize a Transcoder object:
8
+ #
9
+ # transcoder = RVideo::Transcoder.new("/path/to/input.mov")
10
+ #
11
+ # Then pass a recipe and valid options to the execute method
12
+ #
13
+ # recipe = "ffmpeg -i $input_file$ -ar 22050 -ab 64 -f flv -r 29.97 -s"
14
+ # recipe += " $resolution$ -y $output_file$"
15
+ # recipe += "\nflvtool2 -U $output_file$"
16
+ # begin
17
+ # transcoder.execute(recipe, {:output_file => "/path/to/output.flv",
18
+ # :resolution => "640x360"})
19
+ # rescue TranscoderError => e
20
+ # puts "Unable to transcode file: #{e.class} - #{e.message}"
21
+ # end
22
+ #
23
+ # If the job succeeds, you can access the metadata of the input and output
24
+ # files with:
25
+ #
26
+ # transcoder.original # RVideo::Inspector object
27
+ # transcoder.processed # RVideo::Inspector object
28
+ #
29
+ # If the transcoding succeeds, the file may still have problems. RVideo
30
+ # will populate an errors array if the duration of the processed video
31
+ # differs from the duration of the original video, or if the processed
32
+ # file is unreadable.
33
+ #
34
+
35
+ def initialize(input_file = nil)
36
+ # Allow a nil input_file for backwards compatibility. (Change at 1.0?)
37
+ check_input_file(input_file)
38
+
39
+ @input_file = input_file
40
+ @executed_commands = []
41
+ @errors = []
42
+ @warnings = []
43
+ end
44
+
45
+ def original
46
+ @original ||= Inspector.new(:file => @input_file)
47
+ end
48
+
49
+ #
50
+ # Configure logging. Pass a valid Ruby logger object.
51
+ #
52
+ # logger = Logger.new(STDOUT)
53
+ # RVideo::Transcoder.logger = logger
54
+ #
55
+
56
+ def self.logger=(l)
57
+ @logger = l
58
+ end
59
+
60
+ def self.logger
61
+ if @logger.nil?
62
+ @logger = Logger.new('/dev/null')
63
+ end
64
+
65
+ @logger
66
+ end
67
+
68
+ #
69
+ # Requires a command and a hash of various interpolated options. The
70
+ # command should be one or more lines of transcoder tool commands (e.g.
71
+ # ffmpeg, flvtool2). Interpolate options by adding $option_key$ to the
72
+ # recipe, and passing :option_key => "value" in the options hash.
73
+ #
74
+ # recipe = "ffmpeg -i $input_file$ -ar 22050 -ab 64 -f flv -r 29.97
75
+ # recipe += "-s $resolution$ -y $output_file$"
76
+ # recipe += "\nflvtool2 -U $output_file$"
77
+ #
78
+ # transcoder = RVideo::Transcoder.new("/path/to/input.mov")
79
+ # begin
80
+ # transcoder.execute(recipe, {:output_file => "/path/to/output.flv", :resolution => "320x240"})
81
+ # rescue TranscoderError => e
82
+ # puts "Unable to transcode file: #{e.class} - #{e.message}"
83
+ # end
84
+ #
85
+
86
+ def execute(task, options = {})
87
+ t1 = Time.now
88
+
89
+ if @input_file.nil?
90
+ @input_file = options[:input_file]
91
+ end
92
+
93
+ Transcoder.logger.info("\nNew transcoder job\n================\nTask: #{task}\nOptions: #{options.inspect}")
94
+ parse_and_execute(task, options)
95
+ @processed = Inspector.new(:file => options[:output_file])
96
+ result = check_integrity
97
+ Transcoder.logger.info("\nFinished task. Total errors: #{@errors.size}\n")
98
+ @total_time = Time.now - t1
99
+ result
100
+ rescue TranscoderError => e
101
+ raise e
102
+ rescue Exception => e
103
+ Transcoder.logger.error("[ERROR] Unhandled RVideo exception: #{e.class} - #{e.message}\n#{e.backtrace}")
104
+ raise TranscoderError::UnknownError, "Unexpected RVideo error: #{e.message} (#{e.class})"
105
+ end
106
+
107
+ private
108
+
109
+ def check_input_file(input_file)
110
+ if input_file and !FileTest.exist?(input_file.gsub("\"",""))
111
+ raise TranscoderError::InputFileNotFound, "File not found (#{input_file})"
112
+ end
113
+ end
114
+
115
+ def check_integrity
116
+ precision = 1.1
117
+ if @processed.invalid?
118
+ @errors << "Output file invalid"
119
+ elsif (@processed.duration >= (original.duration * precision) or @processed.duration <= (original.duration / precision))
120
+ @errors << "Original file has a duration of #{original.duration}, but processed file has a duration of #{@processed.duration}"
121
+ end
122
+ return @errors.size == 0
123
+ end
124
+
125
+ def parse_and_execute(task, options = {})
126
+ raise TranscoderError::ParameterError, "Expected a recipe class (as a string), but got a #{task.class.to_s} (#{task})" unless task.is_a? String
127
+ options = options.merge(:input_file => @input_file)
128
+
129
+ commands = task.split("\n").compact
130
+ commands.each do |c|
131
+ tool = Tools::AbstractTool.assign(c, options)
132
+ tool.original = @original
133
+ tool.execute
134
+ executed_commands << tool
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,9 @@
1
+ module Rvideo #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 9
5
+ TINY = 4
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
data/lib/rvideo.rb ADDED
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/rvideo'
2
+
3
+ require 'inspector'
4
+ require 'float'
5
+ require 'tools/abstract_tool'
6
+ require 'tools/ffmpeg'
7
+ require 'tools/mencoder'
8
+ require 'tools/flvtool2'
9
+ require 'tools/mp4box'
10
+ require 'tools/mplayer'
11
+ require 'tools/mp4creator'
12
+ require 'errors'
13
+ require 'transcoder'
14
+ require 'active_support'
15
+
16
+ TEMP_PATH = File.expand_path(File.dirname(__FILE__) + '/../tmp')
17
+ FIXTURE_PATH = File.expand_path(File.dirname(__FILE__) + '/../spec/fixtures')
18
+ TEST_FILE_PATH = File.expand_path(File.dirname(__FILE__) + '/../spec/files')
19
+ REPORT_PATH = File.expand_path(File.dirname(__FILE__) + '/../report')
20
+
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mhs-rvideo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.4
5
+ platform: ruby
6
+ authors:
7
+ - Jonathan Dahl (Slantwise Design)
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-27 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Inspect and process video or audio files.
17
+ email: jon@slantwisedesign.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - History.txt
24
+ - License.txt
25
+ - README.txt
26
+ files:
27
+ - History.txt
28
+ - License.txt
29
+ - README.txt
30
+ - RULES
31
+ - Rakefile
32
+ - lib/rvideo.rb
33
+ - lib/rvideo/errors.rb
34
+ - lib/rvideo/float.rb
35
+ - lib/rvideo/inspector.rb
36
+ - lib/rvideo/tools/abstract_tool.rb
37
+ - lib/rvideo/tools/ffmpeg.rb
38
+ - lib/rvideo/tools/flvtool2.rb
39
+ - lib/rvideo/tools/mencoder.rb
40
+ - lib/rvideo/tools/mp4box.rb
41
+ - lib/rvideo/tools/mp4creator.rb
42
+ - lib/rvideo/tools/mplayer.rb
43
+ - lib/rvideo/transcoder.rb
44
+ - lib/rvideo/version.rb
45
+ has_rdoc: true
46
+ homepage: http://github.com/mhs/rvideo
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --main
52
+ - README.txt
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ requirements: []
68
+
69
+ rubyforge_project: rvideo
70
+ rubygems_version: 1.3.5
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Inspect and process video or audio files.
74
+ test_files: []
75
+