streamio-ffmpeg 0.8.5 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +24 -0
- data/README.md +36 -7
- data/lib/ffmpeg/encoding_options.rb +6 -18
- data/lib/ffmpeg/errors.rb +4 -0
- data/lib/ffmpeg/io_monkey.rb +59 -0
- data/lib/ffmpeg/movie.rb +17 -9
- data/lib/ffmpeg/transcoder.rb +44 -46
- data/lib/ffmpeg/version.rb +1 -1
- data/lib/streamio-ffmpeg.rb +3 -1
- metadata +21 -9
data/CHANGELOG
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
== 0.9.0 2012-07-24
|
2
|
+
|
3
|
+
New:
|
4
|
+
* Bumped target ffmpeg version to 0.11.1
|
5
|
+
* Add hung process detection with configurable timeout (thanks stakach)
|
6
|
+
* Raise FFMPEG::Error instead of generic RuntimeError on failed transcodings
|
7
|
+
* Movie#screenshot for more intuitive screenshotting (README has details)
|
8
|
+
* Movie#creation_time and Movie#rotation attributes when metadata is available (thanks Innonate)
|
9
|
+
|
10
|
+
Bugs:
|
11
|
+
* Fixed too many open files bug (thanks to akicho8)
|
12
|
+
* Fixed missing path escaping (thanks to mikesager)
|
13
|
+
* Fixed README typo (thanks to Linutux)
|
14
|
+
* Files outputing "could not find codec parameters" are now recognized as invalid
|
15
|
+
|
16
|
+
Deprecations:
|
17
|
+
* Removed Movie#uncertain_duration?
|
18
|
+
* Removed all the deprecated crop options (use :custom => '-vf crop=x:x:x:x' if you need it)
|
19
|
+
|
20
|
+
Refactorings:
|
21
|
+
* Removed the deprecated duration validation code
|
22
|
+
* Polish on the transcoder class
|
23
|
+
* Polish on the spec suite
|
24
|
+
|
1
25
|
== 0.8.5 2011-03-05
|
2
26
|
|
3
27
|
* If a clip has a DAR that doesn't make sense fall back to calculating aspect ratio from dimensions
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ Installation
|
|
12
12
|
|
13
13
|
(sudo) gem install streamio-ffmpeg
|
14
14
|
|
15
|
-
This version is tested against ffmpeg 0.
|
15
|
+
This version is tested against ffmpeg 0.11.1. So no guarantees with earlier (or much later) versions. Output and input standards have inconveniently changed rather a lot between versions of ffmpeg. My goal is to keep this library in sync with new versions of ffmpeg as they come along.
|
16
16
|
|
17
17
|
Usage
|
18
18
|
-----
|
@@ -60,7 +60,7 @@ movie.transcode("tmp/movie.mp4") # Default ffmpeg settings for mp4 format
|
|
60
60
|
Keep track of progress with an optional block.
|
61
61
|
|
62
62
|
``` ruby
|
63
|
-
movie.transcode(movie.mp4") { |progress| puts progress } # 0.2 ... 0.5 ... 1.0
|
63
|
+
movie.transcode("movie.mp4") { |progress| puts progress } # 0.2 ... 0.5 ... 1.0
|
64
64
|
```
|
65
65
|
|
66
66
|
Give custom command line options with a string.
|
@@ -73,10 +73,10 @@ Use the EncodingOptions parser for humanly readable transcoding options. Below y
|
|
73
73
|
|
74
74
|
``` ruby
|
75
75
|
options = {:video_codec => "libx264", :frame_rate => 10, :resolution => "320x240", :video_bitrate => 300, :video_bitrate_tolerance => 100,
|
76
|
-
:
|
76
|
+
:aspect => 1.333333, :keyframe_interval => 90,
|
77
77
|
:audio_codec => "libfaac", :audio_bitrate => 32, :audio_sample_rate => 22050, :audio_channels => 1,
|
78
78
|
:threads => 2,
|
79
|
-
:custom => "-
|
79
|
+
:custom => "-vf crop=60:60:10:10"}
|
80
80
|
movie.transcode("movie.mp4", options)
|
81
81
|
```
|
82
82
|
|
@@ -116,11 +116,24 @@ options = {:video_min_bitrate => 600, :video_max_bitrate => 600, :buffer_size =>
|
|
116
116
|
movie.transcode("movie.flv", options)
|
117
117
|
```
|
118
118
|
|
119
|
-
|
119
|
+
### Taking Screenshots
|
120
|
+
|
121
|
+
You can use the screenshot method to make taking screenshots a bit simpler.
|
122
|
+
|
123
|
+
``` ruby
|
124
|
+
movie.screenshot("screenshot.jpg")
|
125
|
+
```
|
126
|
+
|
127
|
+
The screenshot method has the very same API as transcode so the same options will work.
|
128
|
+
|
129
|
+
``` ruby
|
130
|
+
movie.screenshot("screenshot.bmp", :seek_time => 5, :resolution => '320x240')
|
131
|
+
```
|
132
|
+
|
133
|
+
You can preserve aspect ratio the same way as when using transcode.
|
120
134
|
|
121
135
|
``` ruby
|
122
|
-
|
123
|
-
movie.transcode("movie.mp4", options) # encodes video using libx264-medium.ffpreset
|
136
|
+
movie.screenshot("screenshot.png", {:seek_time => 2, :resolution => '200x120'}, :preserve_aspect_ratio => :width)
|
124
137
|
```
|
125
138
|
|
126
139
|
Specify the path to ffmpeg
|
@@ -134,6 +147,22 @@ FFMPEG.ffmpeg_binary = '/usr/local/bin/ffmpeg'
|
|
134
147
|
|
135
148
|
This will cause the same command to run as "/usr/local/bin/ffmpeg -i /path/to/input.file ..." instead.
|
136
149
|
|
150
|
+
|
151
|
+
Automatically kill hung processes
|
152
|
+
---------------------------------
|
153
|
+
|
154
|
+
By default, streamio will wait for 200 seconds between IO feedback from the FFMPEG process. After which an error is logged and the process killed.
|
155
|
+
It is possible to modify this behaviour by setting a new default:
|
156
|
+
|
157
|
+
``` ruby
|
158
|
+
# Change the timeout
|
159
|
+
Transcoder.timeout = 30
|
160
|
+
|
161
|
+
# Disable the timeout altogether
|
162
|
+
Transcoder.timeout = false
|
163
|
+
```
|
164
|
+
|
165
|
+
|
137
166
|
Copyright
|
138
167
|
---------
|
139
168
|
|
@@ -48,22 +48,6 @@ module FFMPEG
|
|
48
48
|
self[:aspect].nil? && self[:resolution]
|
49
49
|
end
|
50
50
|
|
51
|
-
def convert_croptop(value)
|
52
|
-
"-croptop #{value}"
|
53
|
-
end
|
54
|
-
|
55
|
-
def convert_cropbottom(value)
|
56
|
-
"-cropbottom #{value}"
|
57
|
-
end
|
58
|
-
|
59
|
-
def convert_cropleft(value)
|
60
|
-
"-cropleft #{value}"
|
61
|
-
end
|
62
|
-
|
63
|
-
def convert_cropright(value)
|
64
|
-
"-cropright #{value}"
|
65
|
-
end
|
66
|
-
|
67
51
|
def convert_video_codec(value)
|
68
52
|
"-vcodec #{value}"
|
69
53
|
end
|
@@ -77,7 +61,7 @@ module FFMPEG
|
|
77
61
|
end
|
78
62
|
|
79
63
|
def convert_video_bitrate(value)
|
80
|
-
"-b #{k_format(value)}"
|
64
|
+
"-b:v #{k_format(value)}"
|
81
65
|
end
|
82
66
|
|
83
67
|
def convert_audio_codec(value)
|
@@ -85,7 +69,7 @@ module FFMPEG
|
|
85
69
|
end
|
86
70
|
|
87
71
|
def convert_audio_bitrate(value)
|
88
|
-
"-
|
72
|
+
"-b:a #{k_format(value)}"
|
89
73
|
end
|
90
74
|
|
91
75
|
def convert_audio_sample_rate(value)
|
@@ -140,6 +124,10 @@ module FFMPEG
|
|
140
124
|
"-ss #{value}"
|
141
125
|
end
|
142
126
|
|
127
|
+
def convert_screenshot(value)
|
128
|
+
value ? "-vframes 1 -f image2" : ""
|
129
|
+
end
|
130
|
+
|
143
131
|
def convert_custom(value)
|
144
132
|
value
|
145
133
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
if RUBY_VERSION =~ /1\.8/
|
2
|
+
# Useful when `timeout.rb`, which, on M.R.I 1.8, relies on green threads, does not work consistently.
|
3
|
+
begin
|
4
|
+
require 'system_timer'
|
5
|
+
FFMPEG::Timer = SystemTimer
|
6
|
+
rescue LoadError
|
7
|
+
require 'timeout'
|
8
|
+
FFMPEG::Timer = Timeout
|
9
|
+
end
|
10
|
+
else
|
11
|
+
require 'timeout'
|
12
|
+
FFMPEG::Timer = Timeout
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'win32/process' if RUBY_PLATFORM =~ /(win|w)(32|64)$/
|
16
|
+
|
17
|
+
#
|
18
|
+
# Monkey Patch timeout support into the IO class
|
19
|
+
#
|
20
|
+
class IO
|
21
|
+
def each_with_timeout(pid, seconds, sep_string=$/)
|
22
|
+
sleeping_queue = Queue.new
|
23
|
+
thread = nil
|
24
|
+
|
25
|
+
timer_set = lambda do
|
26
|
+
thread = new_thread(pid) { FFMPEG::Timer.timeout(seconds) { sleeping_queue.pop } }
|
27
|
+
end
|
28
|
+
|
29
|
+
timer_cancel = lambda do
|
30
|
+
thread.kill if thread rescue nil
|
31
|
+
end
|
32
|
+
|
33
|
+
timer_set.call
|
34
|
+
each(sep_string) do |buffer|
|
35
|
+
timer_cancel.call
|
36
|
+
yield buffer
|
37
|
+
timer_set.call
|
38
|
+
end
|
39
|
+
ensure
|
40
|
+
timer_cancel.call
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def new_thread(pid, &block)
|
45
|
+
current_thread = Thread.current
|
46
|
+
Thread.new do
|
47
|
+
begin
|
48
|
+
block.call
|
49
|
+
rescue Exception => e
|
50
|
+
current_thread.raise e
|
51
|
+
if RUBY_PLATFORM =~ /(win|w)(32|64)$/
|
52
|
+
Process.kill(1, pid)
|
53
|
+
else
|
54
|
+
Process.kill('SIGKILL', pid)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/ffmpeg/movie.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
1
3
|
module FFMPEG
|
2
4
|
class Movie
|
3
|
-
attr_reader :path, :duration, :time, :bitrate
|
5
|
+
attr_reader :path, :duration, :time, :bitrate, :rotation, :creation_time
|
4
6
|
attr_reader :video_stream, :video_codec, :video_bitrate, :colorspace, :resolution, :dar
|
5
7
|
attr_reader :audio_stream, :audio_codec, :audio_bitrate, :audio_sample_rate
|
6
8
|
|
@@ -9,8 +11,9 @@ module FFMPEG
|
|
9
11
|
|
10
12
|
@path = path
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
# ffmpeg will output to stderr
|
15
|
+
command = "#{FFMPEG.ffmpeg_binary} -i #{Shellwords.escape(path)}"
|
16
|
+
output = Open3.popen3(command) { |stdin, stdout, stderr| stderr.read }
|
14
17
|
|
15
18
|
fix_encoding(output)
|
16
19
|
|
@@ -19,18 +22,22 @@ module FFMPEG
|
|
19
22
|
|
20
23
|
output[/start: (\d*\.\d*)/]
|
21
24
|
@time = $1 ? $1.to_f : 0.0
|
25
|
+
|
26
|
+
output[/creation_time {1,}: {1,}(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/]
|
27
|
+
@creation_time = $1 ? Time.parse("#{$1}") : nil
|
22
28
|
|
23
29
|
output[/bitrate: (\d*)/]
|
24
30
|
@bitrate = $1 ? $1.to_i : nil
|
25
31
|
|
32
|
+
output[/rotate\ {1,}:\ {1,}(\d*)/]
|
33
|
+
@rotation = $1 ? $1.to_i : nil
|
34
|
+
|
26
35
|
output[/Video: (.*)/]
|
27
36
|
@video_stream = $1
|
28
37
|
|
29
38
|
output[/Audio: (.*)/]
|
30
39
|
@audio_stream = $1
|
31
40
|
|
32
|
-
@uncertain_duration = true #output.include?("Estimating duration from bitrate, this may be inaccurate") || @time > 0
|
33
|
-
|
34
41
|
if video_stream
|
35
42
|
@video_codec, @colorspace, resolution, video_bitrate = video_stream.split(/\s?,\s?/)
|
36
43
|
@video_bitrate = video_bitrate =~ %r(\A(\d+) kb/s\Z) ? $1.to_i : nil
|
@@ -46,16 +53,13 @@ module FFMPEG
|
|
46
53
|
|
47
54
|
@invalid = true if @video_stream.to_s.empty? && @audio_stream.to_s.empty?
|
48
55
|
@invalid = true if output.include?("is not supported")
|
56
|
+
@invalid = true if output.include?("could not find codec parameters")
|
49
57
|
end
|
50
58
|
|
51
59
|
def valid?
|
52
60
|
not @invalid
|
53
61
|
end
|
54
62
|
|
55
|
-
def uncertain_duration?
|
56
|
-
@uncertain_duration
|
57
|
-
end
|
58
|
-
|
59
63
|
def width
|
60
64
|
resolution.split("x")[0].to_i rescue nil
|
61
65
|
end
|
@@ -88,6 +92,10 @@ module FFMPEG
|
|
88
92
|
Transcoder.new(self, output_file, options, transcoder_options).run &block
|
89
93
|
end
|
90
94
|
|
95
|
+
def screenshot(output_file, options = EncodingOptions.new, transcoder_options = {}, &block)
|
96
|
+
Transcoder.new(self, output_file, options.merge(:screenshot => true), transcoder_options).run &block
|
97
|
+
end
|
98
|
+
|
91
99
|
protected
|
92
100
|
def aspect_from_dar
|
93
101
|
return nil unless dar
|
data/lib/ffmpeg/transcoder.rb
CHANGED
@@ -3,6 +3,16 @@ require 'shellwords'
|
|
3
3
|
|
4
4
|
module FFMPEG
|
5
5
|
class Transcoder
|
6
|
+
@@timeout = 200
|
7
|
+
|
8
|
+
def self.timeout=(time)
|
9
|
+
@@timeout = time
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.timeout
|
13
|
+
@@timeout
|
14
|
+
end
|
15
|
+
|
6
16
|
def initialize(movie, output_file, options = EncodingOptions.new, transcoder_options = {})
|
7
17
|
@movie = movie
|
8
18
|
@output_file = output_file
|
@@ -24,30 +34,42 @@ module FFMPEG
|
|
24
34
|
# ffmpeg < 0.8: frame= 413 fps= 48 q=31.0 size= 2139kB time=16.52 bitrate=1060.6kbits/s
|
25
35
|
# ffmpeg >= 0.8: frame= 4855 fps= 46 q=31.0 size= 45306kB time=00:02:42.28 bitrate=2287.0kbits/
|
26
36
|
def run
|
27
|
-
command = "#{FFMPEG.ffmpeg_binary} -y -i #{Shellwords.escape(@movie.path)} #{@raw_options}
|
37
|
+
command = "#{FFMPEG.ffmpeg_binary} -y -i #{Shellwords.escape(@movie.path)} #{@raw_options} #{Shellwords.escape(@output_file)}"
|
28
38
|
FFMPEG.logger.info("Running transcoding...\n#{command}\n")
|
29
39
|
output = ""
|
30
40
|
last_output = nil
|
31
|
-
Open3.popen3(command) do |stdin, stdout, stderr|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
if line
|
38
|
-
time
|
39
|
-
|
40
|
-
time
|
41
|
-
|
42
|
-
|
41
|
+
Open3.popen3(command) do |stdin, stdout, stderr, wait_thr|
|
42
|
+
begin
|
43
|
+
yield(0.0) if block_given?
|
44
|
+
next_line = Proc.new do |line|
|
45
|
+
fix_encoding(line)
|
46
|
+
output << line
|
47
|
+
if line.include?("time=")
|
48
|
+
if line =~ /time=(\d+):(\d+):(\d+.\d+)/ # ffmpeg 0.8 and above style
|
49
|
+
time = ($1.to_i * 3600) + ($2.to_i * 60) + $3.to_f
|
50
|
+
elsif line =~ /time=(\d+.\d+)/ # ffmpeg 0.7 and below style
|
51
|
+
time = $1.to_f
|
52
|
+
else # better make sure it wont blow up in case of unexpected output
|
53
|
+
time = 0.0
|
54
|
+
end
|
55
|
+
progress = time / @movie.duration
|
56
|
+
yield(progress) if block_given?
|
57
|
+
end
|
58
|
+
if line =~ /Unsupported codec/
|
59
|
+
FFMPEG.logger.error "Failed encoding...\nCommand\n#{command}\nOutput\n#{output}\n"
|
60
|
+
raise "Failed encoding: #{line}"
|
43
61
|
end
|
44
|
-
progress = time / @movie.duration
|
45
|
-
yield(progress) if block_given?
|
46
62
|
end
|
47
|
-
|
48
|
-
|
49
|
-
|
63
|
+
|
64
|
+
if @@timeout
|
65
|
+
stderr.each_with_timeout(wait_thr.pid, @@timeout, "r", &next_line)
|
66
|
+
else
|
67
|
+
stderr.each("r", &next_line)
|
50
68
|
end
|
69
|
+
|
70
|
+
rescue Timeout::Error => e
|
71
|
+
FFMPEG.logger.error "Process hung...\nCommand\n#{command}\nOutput\n#{output}\n"
|
72
|
+
raise FFMPEG::Error, "Process hung. Full output: #{output}"
|
51
73
|
end
|
52
74
|
end
|
53
75
|
|
@@ -55,34 +77,17 @@ module FFMPEG
|
|
55
77
|
yield(1.0) if block_given?
|
56
78
|
FFMPEG.logger.info "Transcoding of #{@movie.path} to #{@output_file} succeeded\n"
|
57
79
|
else
|
58
|
-
errors =
|
80
|
+
errors = "Errors: #{@errors.join(", ")}. "
|
59
81
|
FFMPEG.logger.error "Failed encoding...\n#{command}\n\n#{output}\n#{errors}\n"
|
60
|
-
raise "Failed encoding.#{errors}Full output: #{output}"
|
82
|
+
raise FFMPEG::Error, "Failed encoding.#{errors}Full output: #{output}"
|
61
83
|
end
|
62
84
|
|
63
85
|
encoded
|
64
86
|
end
|
65
87
|
|
66
88
|
def encoding_succeeded?
|
67
|
-
unless File.exists?(@output_file)
|
68
|
-
|
69
|
-
return false
|
70
|
-
end
|
71
|
-
|
72
|
-
unless encoded.valid?
|
73
|
-
@errors << "encoded file is invalid"
|
74
|
-
return false
|
75
|
-
end
|
76
|
-
|
77
|
-
if validate_duration?
|
78
|
-
precision = @raw_options[:duration] ? 1.5 : 1.1
|
79
|
-
desired_duration = @raw_options[:duration] && @raw_options[:duration] < @movie.duration ? @raw_options[:duration] : @movie.duration
|
80
|
-
if (encoded.duration >= (desired_duration * precision) or encoded.duration <= (desired_duration / precision))
|
81
|
-
@errors << "encoded file duration differed from original/specified duration (wanted: #{desired_duration}sec, got: #{encoded.duration}sec)"
|
82
|
-
return false
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
89
|
+
@errors << "no output file created" and return false unless File.exists?(@output_file)
|
90
|
+
@errors << "encoded file is invalid" and return false unless encoded.valid?
|
86
91
|
true
|
87
92
|
end
|
88
93
|
|
@@ -107,13 +112,6 @@ module FFMPEG
|
|
107
112
|
end
|
108
113
|
end
|
109
114
|
|
110
|
-
def validate_duration?
|
111
|
-
return false if @movie.uncertain_duration?
|
112
|
-
return false if %w(.jpg .png).include?(File.extname(@output_file))
|
113
|
-
return false if @raw_options.is_a?(String)
|
114
|
-
true
|
115
|
-
end
|
116
|
-
|
117
115
|
def fix_encoding(output)
|
118
116
|
output[/test/]
|
119
117
|
rescue ArgumentError
|
data/lib/ffmpeg/version.rb
CHANGED
data/lib/streamio-ffmpeg.rb
CHANGED
@@ -4,10 +4,12 @@ require 'logger'
|
|
4
4
|
require 'stringio'
|
5
5
|
|
6
6
|
require 'ffmpeg/version'
|
7
|
+
require 'ffmpeg/errors'
|
7
8
|
require 'ffmpeg/movie'
|
9
|
+
require 'ffmpeg/io_monkey'
|
8
10
|
require 'ffmpeg/transcoder'
|
9
11
|
require 'ffmpeg/encoding_options'
|
10
|
-
|
12
|
+
|
11
13
|
module FFMPEG
|
12
14
|
# FFMPEG logs information about its progress when it's transcoding.
|
13
15
|
# Jack in your own logger through this method if you wish to.
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: streamio-ffmpeg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-07-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '2.7'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.7'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rake
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ~>
|
@@ -32,7 +37,12 @@ dependencies:
|
|
32
37
|
version: 0.9.2
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.9.2
|
36
46
|
description: Simple yet powerful wrapper around ffmpeg to get metadata from movies
|
37
47
|
and do transcoding.
|
38
48
|
email:
|
@@ -42,6 +52,8 @@ extensions: []
|
|
42
52
|
extra_rdoc_files: []
|
43
53
|
files:
|
44
54
|
- lib/ffmpeg/encoding_options.rb
|
55
|
+
- lib/ffmpeg/errors.rb
|
56
|
+
- lib/ffmpeg/io_monkey.rb
|
45
57
|
- lib/ffmpeg/movie.rb
|
46
58
|
- lib/ffmpeg/transcoder.rb
|
47
59
|
- lib/ffmpeg/version.rb
|
@@ -63,7 +75,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
63
75
|
version: '0'
|
64
76
|
segments:
|
65
77
|
- 0
|
66
|
-
hash:
|
78
|
+
hash: 190048295991981084
|
67
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
80
|
none: false
|
69
81
|
requirements:
|
@@ -72,10 +84,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
84
|
version: '0'
|
73
85
|
segments:
|
74
86
|
- 0
|
75
|
-
hash:
|
87
|
+
hash: 190048295991981084
|
76
88
|
requirements: []
|
77
89
|
rubyforge_project:
|
78
|
-
rubygems_version: 1.8.
|
90
|
+
rubygems_version: 1.8.24
|
79
91
|
signing_key:
|
80
92
|
specification_version: 3
|
81
93
|
summary: Reads metadata and transcodes movies.
|