streamio-ffmpeg 0.8.5 → 0.9.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/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.
|