streamio-ffmpeg 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b2f7f026d79edbb50b3cc2a727970b24ddc14e35
4
- data.tar.gz: 1eb3016af722ac698e9ffa27515b515f7683bf7a
3
+ metadata.gz: 6f7d05b3e4d5f1e43f04cea131e8f5f7e3772dec
4
+ data.tar.gz: 645f8fcfd8691bb62c27e4182374316512b78de9
5
5
  SHA512:
6
- metadata.gz: bd2bde719ec750a394f4a9143d117355e615d7302d9da8c02d58300b59fed78c7e7e85c2d8b4821221cc21fc402c6bc94982596db37df85f121915aa3b889265
7
- data.tar.gz: 448a6304a0c99eb13a1540bf8a99f45db9d8a08f12d7430a08a6f4b7a6a0a12746f9b1211587ff226a5c37184d81438ab3fd18780a393ba7439c9e30a44a472b
6
+ metadata.gz: 5ec0c612684983472f87288d1f8216c1762969ab4271f53a092d5e34141d975ec3121e9f54667467fc5e11364517d54fef17a9d858c04b1c042c8494b0b727b6
7
+ data.tar.gz: f362e03fcc8c05558e46cda6b6f4ab62ab3b9aadb5f67e030806403a29f6ffca3a0d5e58dc6f1dea175005e42094f20e2a1a7fc4fcfde136d1ecc17b7ac332b9
data/CHANGELOG CHANGED
@@ -1,3 +1,19 @@
1
+ == Master
2
+
3
+ Current with 2.0.0
4
+
5
+ == 2.0.0 2016-01-14
6
+
7
+ New:
8
+ * Support watermarking (thanks smoothdvd)
9
+ * Bumped target ffmpeg version to 2.8
10
+
11
+ Improvements:
12
+ * Allow parenthesis in colorspace (thanks walterdavis for initial code and rociiu for finding a bug with it)
13
+ * Width and height now switched if video is filmed in portrait mode. ffmpeg 2.7 or later now automatically rotates output
14
+ * Movie metadata now provided with ffprobe (#114). Thanks to Ryan Lovelett for the contributions!
15
+ * Ability to create multiple screenshots at consistent intervals in one pass (#113)
16
+
1
17
  == 1.0.0 2013-07-08
2
18
 
3
19
  New:
data/README.md CHANGED
@@ -23,7 +23,9 @@ Will not work in jruby until they fix: http://goo.gl/Z4UcX (should work in the u
23
23
 
24
24
  ### ffmpeg
25
25
 
26
- The current gem is tested against ffmpeg 1.2.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.
26
+ The current gem is tested against ffmpeg 2.8.4. So no guarantees with earlier (or much later)
27
+ versions. Output and input standards have inconveniently changed rather a lot between versions
28
+ of ffmpeg. My goal is to keep this library in sync with new versions of ffmpeg as they come along.
27
29
 
28
30
  Usage
29
31
  -----
@@ -85,7 +87,7 @@ Use the EncodingOptions parser for humanly readable transcoding options. Below y
85
87
  ``` ruby
86
88
  options = {video_codec: "libx264", frame_rate: 10, resolution: "320x240", video_bitrate: 300, video_bitrate_tolerance: 100,
87
89
  aspect: 1.333333, keyframe_interval: 90,
88
- x264_profile: "high", x264_preset: "slow",
90
+ x264_vprofile: "high", x264_preset: "slow",
89
91
  audio_codec: "libfaac", audio_bitrate: 32, audio_sample_rate: 22050, audio_channels: 1,
90
92
  threads: 2,
91
93
  custom: "-vf crop=60:60:10:10"}
@@ -128,6 +130,16 @@ options = {video_min_bitrate: 600, video_max_bitrate: 600, buffer_size: 2000}
128
130
  movie.transcode("movie.flv", options)
129
131
  ```
130
132
 
133
+ Add watermark image on the video.
134
+
135
+ For example, you want to add a watermark on the video at right top corner with 10px padding.
136
+
137
+ ``` ruby
138
+ options = { watermark: "full_path_of_watermark.png", resolution: "640x360", watermark_filter: { position: "RT", padding_x: 10, padding_y: 10 } }
139
+ ```
140
+
141
+ Position can be "LT" (Left Top Corner), "RT" (Right Top Corner), "LB" (Left Bottom Corner), "RB" (Right Bottom Corner).
142
+
131
143
  ### Taking Screenshots
132
144
 
133
145
  You can use the screenshot method to make taking screenshots a bit simpler.
@@ -142,6 +154,20 @@ The screenshot method has the very same API as transcode so the same options wil
142
154
  movie.screenshot("screenshot.bmp", seek_time: 5, resolution: '320x240')
143
155
  ```
144
156
 
157
+ To generate multiple screenshots in a single pass, specify `vframes`. The following code
158
+ generates up to 20 screenshots every 10 seconds:
159
+
160
+ ``` ruby
161
+ movie.screenshot("screenshot.jpg", vframes: 20, frame_rate: '1/6')
162
+ ```
163
+
164
+ To specify the quality when generating compressed screenshots (.jpg), use `quality` which specifies
165
+ ffmpeg `-v:q` option. Quality is an integer between 1 and 31, where lower is better quality:
166
+
167
+ ``` ruby
168
+ movie.screenshot("screenshot.jpg", quality: 3)
169
+ ```
170
+
145
171
  You can preserve aspect ratio the same way as when using transcode.
146
172
 
147
173
  ``` ruby
@@ -151,7 +177,7 @@ movie.screenshot("screenshot.png", { seek_time: 2, resolution: '200x120' }, pres
151
177
  Specify the path to ffmpeg
152
178
  --------------------------
153
179
 
154
- By default, streamio assumes that the ffmpeg binary is available in the execution path and named ffmpeg and so will run commands that look something like "ffmpeg -i /path/to/input.file ...". Use the FFMPEG.ffmpeg_binary setter to specify the full path to the binary if necessary:
180
+ By default, the gem assumes that the ffmpeg binary is available in the execution path and named ffmpeg and so will run commands that look something like "ffmpeg -i /path/to/input.file ...". Use the FFMPEG.ffmpeg_binary setter to specify the full path to the binary if necessary:
155
181
 
156
182
  ``` ruby
157
183
  FFMPEG.ffmpeg_binary = '/usr/local/bin/ffmpeg'
@@ -163,7 +189,7 @@ This will cause the same command to run as "/usr/local/bin/ffmpeg -i /path/to/in
163
189
  Automatically kill hung processes
164
190
  ---------------------------------
165
191
 
166
- By default, streamio will wait for 30 seconds between IO feedback from the FFMPEG process. After which an error is logged and the process killed.
192
+ By default, the gem will wait for 30 seconds between IO feedback from the FFMPEG process. After which an error is logged and the process killed.
167
193
  It is possible to modify this behaviour by setting a new default:
168
194
 
169
195
  ``` ruby
@@ -13,8 +13,9 @@ module FFMPEG
13
13
  # all other parameters go after so that we can override whatever is in the preset
14
14
  codecs = params.select { |p| p =~ /codec/ }
15
15
  presets = params.select { |p| p =~ /\-.pre/ }
16
- other = params - codecs - presets
17
- params = codecs + presets + other
16
+ watermarkoptions = params.select { |p| p =~ /i / || p=~ /filter_complex/ }
17
+ other = params - codecs - presets - watermarkoptions
18
+ params = watermarkoptions + codecs + presets + other
18
19
 
19
20
  params_string = params.join(" ")
20
21
  params_string << " #{convert_aspect(calculate_aspect)}" if calculate_aspect?
@@ -100,6 +101,10 @@ module FFMPEG
100
101
  "-threads #{value}"
101
102
  end
102
103
 
104
+ def convert_target(value)
105
+ "-target #{value}"
106
+ end
107
+
103
108
  def convert_duration(value)
104
109
  "-t #{value}"
105
110
  end
@@ -125,7 +130,16 @@ module FFMPEG
125
130
  end
126
131
 
127
132
  def convert_screenshot(value)
128
- value ? "-vframes 1 -f image2" : ""
133
+ vframes = '-vframes 1 ' unless self[:vframes]
134
+ value ? "#{vframes}-f image2" : ""
135
+ end
136
+
137
+ def convert_quality(value)
138
+ "-q:v #{value}"
139
+ end
140
+
141
+ def convert_vframes(value)
142
+ "-vframes #{value}"
129
143
  end
130
144
 
131
145
  def convert_x264_vprofile(value)
@@ -136,6 +150,23 @@ module FFMPEG
136
150
  "-preset #{value}"
137
151
  end
138
152
 
153
+ def convert_watermark(value)
154
+ "-i #{value}"
155
+ end
156
+
157
+ def convert_watermark_filter(value)
158
+ case value[:position].to_s
159
+ when "LT"
160
+ "-filter_complex 'scale=#{self[:resolution]},overlay=x=#{value[:padding_x]}:y=#{value[:padding_y]}'"
161
+ when "RT"
162
+ "-filter_complex 'scale=#{self[:resolution]},overlay=x=main_w-overlay_w-#{value[:padding_x]}:y=#{value[:padding_y]}'"
163
+ when "LB"
164
+ "-filter_complex 'scale=#{self[:resolution]},overlay=x=#{value[:padding_x]}:y=main_h-overlay_h-#{value[:padding_y]}'"
165
+ when "RB"
166
+ "-filter_complex 'scale=#{self[:resolution]},overlay=x=main_w-overlay_w-#{value[:padding_x]}:y=main_h-overlay_h-#{value[:padding_y]}'"
167
+ end
168
+ end
169
+
139
170
  def convert_custom(value)
140
171
  value
141
172
  end
@@ -1,63 +1,98 @@
1
1
  require 'time'
2
+ require 'multi_json'
2
3
 
3
4
  module FFMPEG
4
5
  class Movie
5
6
  attr_reader :path, :duration, :time, :bitrate, :rotation, :creation_time
6
- attr_reader :video_stream, :video_codec, :video_bitrate, :colorspace, :resolution, :dar
7
- attr_reader :audio_stream, :audio_codec, :audio_bitrate, :audio_sample_rate
7
+ attr_reader :video_stream, :video_codec, :video_bitrate, :colorspace, :width, :height, :sar, :dar, :frame_rate
8
+ attr_reader :audio_stream, :audio_codec, :audio_bitrate, :audio_sample_rate, :audio_channels
8
9
  attr_reader :container
9
10
 
10
11
  def initialize(path)
11
- raise Errno::ENOENT, "the file '#{path}' does not exist" unless File.exists?(path)
12
+ raise Errno::ENOENT, "the file '#{path}' does not exist" unless File.exist?(path)
12
13
 
13
14
  @path = path
14
15
 
15
16
  # ffmpeg will output to stderr
16
- command = "#{FFMPEG.ffmpeg_binary} -i #{Shellwords.escape(path)}"
17
- output = Open3.popen3(command) { |stdin, stdout, stderr| stderr.read }
17
+ command = "#{FFMPEG.ffprobe_binary} -i #{Shellwords.escape(path)} -print_format json -show_format -show_streams -show_error"
18
+ std_output = ''
19
+ std_error = ''
18
20
 
19
- fix_encoding(output)
21
+ Open3.popen3(command) do |stdin, stdout, stderr|
22
+ std_output = stdout.read unless stdout.nil?
23
+ std_error = stderr.read unless stderr.nil?
24
+ end
20
25
 
21
- output[/Input \#\d+\,\s*(\S+),\s*from/]
22
- @container = $1
26
+ fix_encoding(std_output)
23
27
 
24
- output[/Duration: (\d{2}):(\d{2}):(\d{2}\.\d{2})/]
25
- @duration = ($1.to_i*60*60) + ($2.to_i*60) + $3.to_f
28
+ metadata = MultiJson.load(std_output, symbolize_keys: true)
26
29
 
27
- output[/start: (\d*\.\d*)/]
28
- @time = $1 ? $1.to_f : 0.0
30
+ if metadata.key?(:error)
29
31
 
30
- output[/creation_time {1,}: {1,}(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/]
31
- @creation_time = $1 ? Time.parse("#{$1}") : nil
32
+ @duration = 0
32
33
 
33
- output[/bitrate: (\d*)/]
34
- @bitrate = $1 ? $1.to_i : nil
34
+ else
35
35
 
36
- output[/rotate\ {1,}:\ {1,}(\d*)/]
37
- @rotation = $1 ? $1.to_i : nil
36
+ video_streams = metadata[:streams].select { |stream| stream.key?(:codec_type) and stream[:codec_type] === 'video' }
37
+ audio_streams = metadata[:streams].select { |stream| stream.key?(:codec_type) and stream[:codec_type] === 'audio' }
38
38
 
39
- output[/Video:\ (.*)/]
40
- @video_stream = $1
39
+ @container = metadata[:format][:format_name]
41
40
 
42
- output[/Audio:\ (.*)/]
43
- @audio_stream = $1
41
+ @duration = metadata[:format][:duration].to_f
44
42
 
45
- if video_stream
46
- @video_codec, @colorspace, resolution, video_bitrate = video_stream.split(/\s?,\s?/)
47
- @video_bitrate = video_bitrate =~ %r(\A(\d+) kb/s\Z) ? $1.to_i : nil
48
- @resolution = resolution.split(" ").first rescue nil # get rid of [PAR 1:1 DAR 16:9]
49
- @dar = $1 if video_stream[/DAR (\d+:\d+)/]
50
- end
43
+ @time = metadata[:format][:start_time].to_f
44
+
45
+ @creation_time = if metadata[:format].key?(:tags) and metadata[:format][:tags].key?(:creation_time)
46
+ Time.parse(metadata[:format][:tags][:creation_time])
47
+ else
48
+ nil
49
+ end
50
+
51
+ @bitrate = metadata[:format][:bit_rate].to_i
52
+
53
+ unless video_streams.empty?
54
+ # TODO: Handle multiple video codecs (is that possible?)
55
+ video_stream = video_streams.first
56
+ @video_codec = video_stream[:codec_name]
57
+ @colorspace = video_stream[:pix_fmt]
58
+ @width = video_stream[:width]
59
+ @height = video_stream[:height]
60
+ @video_bitrate = video_stream[:bit_rate].to_i
61
+ @sar = video_stream[:sample_aspect_ratio]
62
+ @dar = video_stream[:display_aspect_ratio]
63
+
64
+ @frame_rate = unless video_stream[:avg_frame_rate] == '0/0'
65
+ Rational(video_stream[:avg_frame_rate])
66
+ else
67
+ nil
68
+ end
69
+
70
+ @video_stream = "#{video_stream[:codec_name]} (#{video_stream[:profile]}) (#{video_stream[:codec_tag_string]} / #{video_stream[:codec_tag]}), #{colorspace}, #{resolution} [SAR #{sar} DAR #{dar}]"
71
+
72
+ @rotation = if video_stream.key?(:tags) and video_stream[:tags].key?(:rotate)
73
+ video_stream[:tags][:rotate].to_i
74
+ else
75
+ nil
76
+ end
77
+ end
78
+
79
+ unless audio_streams.empty?
80
+ # TODO: Handle multiple audio codecs
81
+ audio_stream = audio_streams.first
82
+ @audio_channels = audio_stream[:channels].to_i
83
+ @audio_codec = audio_stream[:codec_name]
84
+ @audio_sample_rate = audio_stream[:sample_rate].to_i
85
+ @audio_bitrate = audio_stream[:bit_rate].to_i
86
+ @audio_channel_layout = audio_stream[:channel_layout]
87
+ @audio_stream = "#{audio_codec} (#{audio_stream[:codec_tag_string]} / #{audio_stream[:codec_tag]}), #{audio_sample_rate} Hz, #{audio_channel_layout}, #{audio_stream[:sample_fmt]}, #{audio_bitrate} bit/s"
88
+ end
51
89
 
52
- if audio_stream
53
- @audio_codec, audio_sample_rate, @audio_channels, unused, audio_bitrate = audio_stream.split(/\s?,\s?/)
54
- @audio_bitrate = audio_bitrate =~ %r(\A(\d+) kb/s\Z) ? $1.to_i : nil
55
- @audio_sample_rate = audio_sample_rate[/\d*/].to_i
56
90
  end
57
91
 
58
- @invalid = true if @video_stream.to_s.empty? && @audio_stream.to_s.empty?
59
- @invalid = true if output.include?("is not supported")
60
- @invalid = true if output.include?("could not find codec parameters")
92
+ @invalid = true if metadata.key?(:error)
93
+ @invalid = true if std_error.include?("Unsupported codec")
94
+ @invalid = true if std_error.include?("is not supported")
95
+ @invalid = true if std_error.include?("could not find codec parameters")
61
96
  end
62
97
 
63
98
  def valid?
@@ -65,32 +100,43 @@ module FFMPEG
65
100
  end
66
101
 
67
102
  def width
68
- resolution.split("x")[0].to_i rescue nil
103
+ rotation.nil? || rotation == 180 ? @width : @height;
69
104
  end
70
105
 
71
106
  def height
72
- resolution.split("x")[1].to_i rescue nil
107
+ rotation.nil? || rotation == 180 ? @height : @width;
108
+ end
109
+
110
+ def resolution
111
+ unless width.nil? or height.nil?
112
+ "#{width}x#{height}"
113
+ end
73
114
  end
74
115
 
75
116
  def calculated_aspect_ratio
76
117
  aspect_from_dar || aspect_from_dimensions
77
118
  end
78
119
 
79
- def size
80
- File.size(@path)
120
+ def calculated_pixel_aspect_ratio
121
+ aspect_from_sar || 1
81
122
  end
82
123
 
83
- def audio_channels
84
- return nil unless @audio_channels
85
- return @audio_channels[/\d*/].to_i if @audio_channels["channels"]
86
- return 1 if @audio_channels["mono"]
87
- return 2 if @audio_channels["stereo"]
88
- return 6 if @audio_channels["5.1"]
124
+ def size
125
+ File.size(@path)
89
126
  end
90
127
 
91
- def frame_rate
92
- return nil unless video_stream
93
- video_stream[/(\d*\.?\d*)\s?fps/] ? $1.to_f : nil
128
+ def audio_channel_layout
129
+ # TODO Whenever support for ffmpeg/ffprobe 1.2.1 is dropped this is no longer needed
130
+ @audio_channel_layout || case(audio_channels)
131
+ when 1
132
+ 'stereo'
133
+ when 2
134
+ 'stereo'
135
+ when 6
136
+ '5.1'
137
+ else
138
+ 'unknown'
139
+ end
94
140
  end
95
141
 
96
142
  def transcode(output_file, options = EncodingOptions.new, transcoder_options = {}, &block)
@@ -109,6 +155,13 @@ module FFMPEG
109
155
  aspect.zero? ? nil : aspect
110
156
  end
111
157
 
158
+ def aspect_from_sar
159
+ return nil unless sar
160
+ w, h = sar.split(":")
161
+ aspect = w.to_f / h.to_f
162
+ aspect.zero? ? nil : aspect
163
+ end
164
+
112
165
  def aspect_from_dimensions
113
166
  aspect = width.to_f / height.to_f
114
167
  aspect.nan? ? nil : aspect
@@ -42,7 +42,7 @@ module FFMPEG
42
42
  end
43
43
 
44
44
  def encoding_succeeded?
45
- @errors << "no output file created" and return false unless File.exists?(@output_file)
45
+ @errors << "no output file created" and return false unless File.exist?(@output_file)
46
46
  @errors << "encoded file is invalid" and return false unless encoded.valid?
47
47
  true
48
48
  end
@@ -58,7 +58,7 @@ module FFMPEG
58
58
  FFMPEG.logger.info("Running transcoding...\n#{@command}\n")
59
59
  @output = ""
60
60
 
61
- Open3.popen3(@command) do |stdin, stdout, stderr, wait_thr|
61
+ Open3.popen3(@command) do |_stdin, _stdout, stderr, wait_thr|
62
62
  begin
63
63
  yield(0.0) if block_given?
64
64
  next_line = Proc.new do |line|
@@ -1,3 +1,3 @@
1
1
  module FFMPEG
2
- VERSION = "1.0.0"
2
+ VERSION = '2.0.0'
3
3
  end
@@ -35,14 +35,56 @@ module FFMPEG
35
35
  #
36
36
  # @param [String] path to the ffmpeg binary
37
37
  # @return [String] the path you set
38
+ # @raise Errno::ENOENT if the ffmpeg binary cannot be found
38
39
  def self.ffmpeg_binary=(bin)
40
+ if bin.is_a?(String) && !File.executable?(bin)
41
+ raise Errno::ENOENT, "the ffmpeg binary, \'#{bin}\', is not executable"
42
+ end
39
43
  @ffmpeg_binary = bin
40
44
  end
41
45
 
42
46
  # Get the path to the ffmpeg binary, defaulting to 'ffmpeg'
43
47
  #
44
48
  # @return [String] the path to the ffmpeg binary
49
+ # @raise Errno::ENOENT if the ffmpeg binary cannot be found
45
50
  def self.ffmpeg_binary
46
- @ffmpeg_binary || 'ffmpeg'
51
+ @ffmpeg_binary || which('ffmpeg')
47
52
  end
53
+
54
+ # Get the path to the ffprobe binary, defaulting to what is on ENV['PATH']
55
+ #
56
+ # @return [String] the path to the ffprobe binary
57
+ # @raise Errno::ENOENT if the ffprobe binary cannot be found
58
+ def self.ffprobe_binary
59
+ @ffprobe_binary || which('ffprobe')
60
+ end
61
+
62
+ # Set the path of the ffprobe binary.
63
+ # Can be useful if you need to specify a path such as /usr/local/bin/ffprobe
64
+ #
65
+ # @param [String] path to the ffprobe binary
66
+ # @return [String] the path you set
67
+ # @raise Errno::ENOENT if the ffprobe binary cannot be found
68
+ def self.ffprobe_binary=(bin)
69
+ if bin.is_a?(String) && !File.executable?(bin)
70
+ raise Errno::ENOENT, "the ffprobe binary, \'#{bin}\', is not executable"
71
+ end
72
+ @ffprobe_binary = bin
73
+ end
74
+
75
+ # Cross-platform way of finding an executable in the $PATH.
76
+ #
77
+ # which('ruby') #=> /usr/bin/ruby
78
+ # see: http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
79
+ def self.which(cmd)
80
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
81
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
82
+ exts.each { |ext|
83
+ exe = File.join(path, "#{cmd}#{ext}")
84
+ return exe if File.executable? exe
85
+ }
86
+ end
87
+ raise Errno::ENOENT, "the #{cmd} binary could not be found in #{ENV['PATH']}"
88
+ end
89
+
48
90
  end
metadata CHANGED
@@ -1,50 +1,68 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: streamio-ffmpeg
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - David Backeus
7
+ - Rackfish AB
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-08 00:00:00.000000000 Z
11
+ date: 2016-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: multi_json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rspec
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - ~>
31
+ - - "~>"
18
32
  - !ruby/object:Gem::Version
19
33
  version: '2.14'
20
34
  type: :development
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - ~>
38
+ - - "~>"
25
39
  - !ruby/object:Gem::Version
26
40
  version: '2.14'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - ~>
45
+ - - "~>"
32
46
  - !ruby/object:Gem::Version
33
47
  version: '10.1'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - ~>
52
+ - - "~>"
39
53
  - !ruby/object:Gem::Version
40
54
  version: '10.1'
41
55
  description:
42
56
  email:
43
- - david@streamio.com
57
+ - support@rackfish.com
58
+ - bikeath1337.com
44
59
  executables: []
45
60
  extensions: []
46
61
  extra_rdoc_files: []
47
62
  files:
63
+ - CHANGELOG
64
+ - LICENSE
65
+ - README.md
48
66
  - lib/ffmpeg/encoding_options.rb
49
67
  - lib/ffmpeg/errors.rb
50
68
  - lib/ffmpeg/io_monkey.rb
@@ -52,9 +70,6 @@ files:
52
70
  - lib/ffmpeg/transcoder.rb
53
71
  - lib/ffmpeg/version.rb
54
72
  - lib/streamio-ffmpeg.rb
55
- - README.md
56
- - LICENSE
57
- - CHANGELOG
58
73
  homepage: http://github.com/streamio/streamio-ffmpeg
59
74
  licenses: []
60
75
  metadata: {}
@@ -64,17 +79,17 @@ require_paths:
64
79
  - lib
65
80
  required_ruby_version: !ruby/object:Gem::Requirement
66
81
  requirements:
67
- - - '>='
82
+ - - ">="
68
83
  - !ruby/object:Gem::Version
69
84
  version: '0'
70
85
  required_rubygems_version: !ruby/object:Gem::Requirement
71
86
  requirements:
72
- - - '>='
87
+ - - ">="
73
88
  - !ruby/object:Gem::Version
74
89
  version: '0'
75
90
  requirements: []
76
91
  rubyforge_project:
77
- rubygems_version: 2.0.3
92
+ rubygems_version: 2.4.3
78
93
  signing_key:
79
94
  specification_version: 4
80
95
  summary: Wraps ffmpeg to read metadata and transcodes videos.