carrierwave-video 0.2.3 → 0.3.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/README.rdoc +26 -3
- data/carrierwave-video.gemspec +1 -1
- data/lib/carrierwave-video/version.rb +1 -1
- data/lib/carrierwave/video.rb +8 -8
- data/lib/carrierwave/video/ffmpeg_options.rb +51 -49
- data/spec/lib/carrierwave_video_spec.rb +60 -2
- metadata +6 -4
data/README.rdoc
CHANGED
@@ -15,7 +15,7 @@ Using bundler:
|
|
15
15
|
= Usage
|
16
16
|
|
17
17
|
class VideoUploader < CarrierWave::Uploader::Base
|
18
|
-
include CarrierWave::
|
18
|
+
include CarrierWave::Video
|
19
19
|
|
20
20
|
process encode_video: [:mp4, callbacks: { after_transcode: :set_success } ]
|
21
21
|
end
|
@@ -63,7 +63,30 @@ Logging:
|
|
63
63
|
logger: :method #returns object that behaves like Logger
|
64
64
|
|
65
65
|
Custom:
|
66
|
-
|
66
|
+
streamio-ffmpeg accepts custom params. You may pass these in but keep in mind the watermarking params will be appended if there were any.
|
67
|
+
custom: '-b 1500k'
|
68
|
+
|
69
|
+
= Dynamic Configuration
|
70
|
+
|
71
|
+
class VideoUploader < CarrierWave::Uploader::Base
|
72
|
+
include CarrierWave::Video
|
73
|
+
|
74
|
+
DEFAULTS = {
|
75
|
+
watermark: {
|
76
|
+
path: Rails.root.join('watermark-large.png')
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
process :encode
|
81
|
+
|
82
|
+
def encode
|
83
|
+
encode_video(:mp4, DEFAULTS) do |movie, params|
|
84
|
+
if movie.height < 720
|
85
|
+
params[:watermark][:path] = Rails.root.join('watermark-small.png')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
67
90
|
|
68
91
|
= OGG/OGV & Theora
|
69
92
|
|
@@ -80,7 +103,7 @@ If you need support for this it shouldn't be too hard to add. (Use streamio-ffmp
|
|
80
103
|
Example:
|
81
104
|
|
82
105
|
class VideoUploader < CarrierWave::Uploader::Base
|
83
|
-
include CarrierWave::
|
106
|
+
include CarrierWave::Video
|
84
107
|
|
85
108
|
version :mp4 do
|
86
109
|
process :encode_video => [:mp4, {...}]
|
data/carrierwave-video.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
21
|
# specify any dependencies here; for example:
|
22
|
-
s.add_development_dependency "rspec"
|
22
|
+
s.add_development_dependency "rspec", ">= 2.10.0"
|
23
23
|
s.add_development_dependency "rake"
|
24
24
|
|
25
25
|
s.add_runtime_dependency 'streamio-ffmpeg'
|
data/lib/carrierwave/video.rb
CHANGED
@@ -44,17 +44,17 @@ module CarrierWave
|
|
44
44
|
cache_stored_file! if !cached?
|
45
45
|
|
46
46
|
@options = CarrierWave::Video::FfmpegOptions.new(format, opts)
|
47
|
-
tmp_path
|
47
|
+
tmp_path = File.join( File.dirname(current_path), "tmpfile.#{format}" )
|
48
|
+
file = ::FFMPEG::Movie.new(current_path)
|
48
49
|
|
50
|
+
if opts[:resolution] == :same
|
51
|
+
@options.format_options[:resolution] = file.resolution
|
52
|
+
end
|
49
53
|
|
50
|
-
|
51
|
-
file = ::FFMPEG::Movie.new(current_path)
|
54
|
+
yield(file, @options.format_options) if block_given?
|
52
55
|
|
53
|
-
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
file.transcode(tmp_path, @options.format_options, @options.encoder_options)
|
56
|
+
with_trancoding_callbacks do
|
57
|
+
file.transcode(tmp_path, @options.format_params, @options.encoder_options)
|
58
58
|
File.rename tmp_path, current_path
|
59
59
|
end
|
60
60
|
end
|
@@ -1,23 +1,17 @@
|
|
1
1
|
module CarrierWave
|
2
2
|
module Video
|
3
3
|
class FfmpegOptions
|
4
|
-
attr_reader :
|
5
|
-
:format, :resolution, :custom, :callbacks
|
4
|
+
attr_reader :format, :resolution, :custom, :callbacks
|
6
5
|
|
7
6
|
def initialize(format, options)
|
8
7
|
@format = format.to_s
|
9
|
-
@watermark = options[:watermark].present?
|
10
8
|
@resolution = options[:resolution] || "640x360"
|
11
9
|
@custom = options[:custom]
|
12
10
|
@callbacks = options[:callbacks] || {}
|
13
11
|
@logger = options[:logger]
|
14
12
|
@unparsed = options
|
15
13
|
|
16
|
-
|
17
|
-
@watermark_path = options[:watermark][:path]
|
18
|
-
@watermark_position = options[:watermark][:position].to_s || :bottom_right
|
19
|
-
@watermark_pixels = options[:watermark][:pixels_from_edge] || 10
|
20
|
-
end
|
14
|
+
@format_options = defaults.merge(options)
|
21
15
|
end
|
22
16
|
|
23
17
|
def raw
|
@@ -29,59 +23,67 @@ module CarrierWave
|
|
29
23
|
end
|
30
24
|
|
31
25
|
def encoder_options
|
32
|
-
{preserve_aspect_ratio: :width}
|
26
|
+
{ preserve_aspect_ratio: :width }
|
33
27
|
end
|
34
28
|
|
29
|
+
# input
|
35
30
|
def format_options
|
36
|
-
@format_options
|
37
|
-
|
38
|
-
when "mp4"
|
39
|
-
{
|
40
|
-
video_codec: 'libx264',
|
41
|
-
audio_codec: 'libfaac',
|
42
|
-
custom: "-qscale 0 -vpre slow -vpre baseline -g 30 #{watermark_params}"
|
43
|
-
}
|
44
|
-
when "webm"
|
45
|
-
{
|
46
|
-
video_codec: 'libvpx',
|
47
|
-
audio_codec: 'libvorbis',
|
48
|
-
custom: "-b 1500k -ab 160000 -f webm -g 30 #{watermark_params}"
|
49
|
-
}
|
50
|
-
when "ogv"
|
51
|
-
{
|
52
|
-
video_codec: 'libtheora',
|
53
|
-
audio_codec: 'libvorbis',
|
54
|
-
custom: "-b 1500k -ab 160000 -g 30 #{watermark_params}"
|
55
|
-
}
|
56
|
-
else
|
57
|
-
{}
|
58
|
-
end
|
31
|
+
@format_options
|
32
|
+
end
|
59
33
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
34
|
+
# output
|
35
|
+
def format_params
|
36
|
+
params = @format_options.dup
|
37
|
+
params[:custom] = [params[:custom], watermark_params].compact.join(' ')
|
38
|
+
params
|
64
39
|
end
|
65
40
|
|
66
41
|
def watermark?
|
67
|
-
@watermark
|
42
|
+
@format_options[:watermark].present?
|
68
43
|
end
|
69
44
|
|
70
45
|
def watermark_params
|
71
|
-
return
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
46
|
+
return nil unless watermark?
|
47
|
+
|
48
|
+
@watermark_params ||= begin
|
49
|
+
path = @format_options[:watermark][:path]
|
50
|
+
position = @format_options[:watermark][:position].to_s || :bottom_right
|
51
|
+
margin = @format_options[:watermark][:pixels_from_edge] || @format_options[:watermark][:margin] || 10
|
52
|
+
positioning = case position
|
53
|
+
when 'bottom_left'
|
54
|
+
"#{margin}:main_h-overlay_h-#{margin}"
|
55
|
+
when 'bottom_right'
|
56
|
+
"main_w-overlay_w-#{margin}:main_h-overlay_h-#{margin}"
|
57
|
+
when 'top_left'
|
58
|
+
"#{margin}:#{margin}"
|
59
|
+
when 'top_right'
|
60
|
+
"main_w-overlay_w-#{margin}:#{margin}"
|
61
|
+
end
|
82
62
|
|
83
|
-
|
63
|
+
"-vf \"movie=#{path} [logo]; [in][logo] overlay=#{positioning} [out]\""
|
64
|
+
end
|
84
65
|
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def defaults
|
70
|
+
@defaults ||= { resolution: '640x360', watermark: {} }.tap do |h|
|
71
|
+
case format
|
72
|
+
when 'mp4'
|
73
|
+
h[:video_codec] = 'libx264'
|
74
|
+
h[:audio_codec] = 'libfaac'
|
75
|
+
h[:custom] = '-qscale 0 -vpre slow -vpre baseline -g 30'
|
76
|
+
when 'ogv'
|
77
|
+
h[:video_codec] = 'libtheora'
|
78
|
+
h[:audio_codec] = 'libvorbis'
|
79
|
+
h[:custom] = '-b 1500k -ab 160000 -g 30'
|
80
|
+
when 'webm'
|
81
|
+
h[:video_codec] = 'libvpx'
|
82
|
+
h[:audio_codec] = 'libvorbis'
|
83
|
+
h[:custom] = '-b 1500k -ab 160000 -f webm -g 30'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
85
87
|
end
|
86
88
|
end
|
87
89
|
end
|
@@ -57,7 +57,7 @@ describe CarrierWave::Video do
|
|
57
57
|
|
58
58
|
opts[:video_codec].should == 'libvpx'
|
59
59
|
opts[:audio_codec].should == 'libvorbis'
|
60
|
-
opts[:custom].should == '-b 1500k -ab 160000 -f webm -g 30
|
60
|
+
opts[:custom].should == '-b 1500k -ab 160000 -f webm -g 30'
|
61
61
|
|
62
62
|
path.should == "video/path/tmpfile.#{format}"
|
63
63
|
end
|
@@ -226,8 +226,66 @@ describe CarrierWave::Video do
|
|
226
226
|
})
|
227
227
|
end
|
228
228
|
end
|
229
|
-
end
|
230
229
|
|
230
|
+
context "given a block" do
|
231
|
+
let(:movie) { mock }
|
232
|
+
let(:opts) { {} }
|
233
|
+
let(:params) { { resolution: "640x360", watermark: {}, video_codec: "libvpx", audio_codec: "libvorbis", custom: "-b 1500k -ab 160000 -f webm -g 30" } }
|
234
|
+
|
235
|
+
before do
|
236
|
+
File.should_receive(:rename)
|
237
|
+
movie.stub(:resolution).and_return('1280x720')
|
238
|
+
end
|
239
|
+
|
240
|
+
it "calls the block, with the movie file and params" do
|
241
|
+
movie.should_receive(:transcode) do |path, format_opts, codec_opts|
|
242
|
+
format_opts[:video_codec].should == 'libvpx'
|
243
|
+
format_opts[:audio_codec].should == 'libvorbis'
|
244
|
+
end
|
245
|
+
|
246
|
+
expect {
|
247
|
+
|block| converter.encode_video(format, opts, &block)
|
248
|
+
}.to yield_with_args(movie, params)
|
249
|
+
end
|
250
|
+
|
251
|
+
it "allows the block to modify the params" do
|
252
|
+
block = Proc.new { |input, params| params[:custom] = '-preset slow' }
|
253
|
+
|
254
|
+
movie.should_receive(:transcode) do |path, format_opts, codec_opts|
|
255
|
+
format_opts[:custom].should == '-preset slow'
|
256
|
+
end
|
257
|
+
|
258
|
+
converter.encode_video(format, opts, &block)
|
259
|
+
end
|
260
|
+
|
261
|
+
it "evaluates the final params after any modifications" do
|
262
|
+
block = Proc.new do |input, params|
|
263
|
+
params[:custom] = '-preset slow'
|
264
|
+
params[:watermark][:path] = 'customized/path'
|
265
|
+
end
|
266
|
+
|
267
|
+
movie.should_receive(:transcode) do |path, format_opts, codec_opts|
|
268
|
+
format_opts[:custom].should == '-preset slow -vf "movie=customized/path [logo]; [in][logo] overlay= [out]"'
|
269
|
+
end
|
270
|
+
|
271
|
+
converter.encode_video(format, opts, &block)
|
272
|
+
end
|
273
|
+
|
274
|
+
it "gives preference to the block-provided settings" do
|
275
|
+
opts = { resolution: :same }
|
276
|
+
|
277
|
+
block = Proc.new do |input, params|
|
278
|
+
params[:resolution] = '1x1'
|
279
|
+
end
|
280
|
+
|
281
|
+
movie.should_receive(:transcode) do |path, format_opts, codec_opts|
|
282
|
+
format_opts[:resolution].should == '1x1'
|
283
|
+
end
|
284
|
+
|
285
|
+
converter.encode_video(format, opts, &block)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
231
289
|
|
232
290
|
describe "#encode_ogv" do
|
233
291
|
let(:movie) { mock }
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
- 2
|
8
7
|
- 3
|
9
|
-
|
8
|
+
- 0
|
9
|
+
version: 0.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- rheaton
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2012-
|
17
|
+
date: 2012-08-02 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -26,8 +26,10 @@ dependencies:
|
|
26
26
|
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
segments:
|
29
|
+
- 2
|
30
|
+
- 10
|
29
31
|
- 0
|
30
|
-
version:
|
32
|
+
version: 2.10.0
|
31
33
|
type: :development
|
32
34
|
version_requirements: *id001
|
33
35
|
- !ruby/object:Gem::Dependency
|