carrierwave-video 0.0.1.pre

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/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in carrierwave-video.gemspec
4
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,58 @@
1
+ = CarrierWave Video Converter
2
+
3
+ This gem adds a video converter using ffmpeg and the streamio-ffmpeg rubygem.
4
+ Note: for watermarking to work, there a fork of the streamio-ffmpeg gem that must be used.
5
+
6
+ = Installation
7
+
8
+ gem install carrierwave-video
9
+
10
+ Using bundler:
11
+
12
+ gem 'carrierwave-video'
13
+
14
+ = Usage
15
+
16
+ class VideoUploader < CarrierWave::Uploader::Base
17
+ include CarrierWave::VideoConverter
18
+
19
+ process encode_video: [:mp4, after_transcode: :set_success ]
20
+ end
21
+
22
+ class Video
23
+ mount_uploader :file, VideoUploader
24
+
25
+ def set_success
26
+ self.success = true
27
+ end
28
+ end
29
+
30
+ = Possible Options
31
+
32
+ Pass in options to process:
33
+
34
+ process encode_video: [:mp4, resolution: "200x200"]
35
+
36
+ Resolution passed to ffmpeg:
37
+ resolution: "640x360"
38
+
39
+ Watermark:
40
+ watermark: {
41
+ path: File.join(Rails.root, "directory", "file.png"),
42
+ position: :bottom_right, # also: :top_right, :bottom_left, :bottom_right
43
+ pixels_from_edge: 10
44
+ }
45
+
46
+ Callbacks:
47
+ callbacks: {
48
+ before_transcode: :method
49
+ after_transcode: :method
50
+ ensure: :method
51
+ }
52
+
53
+ Logging:
54
+ logger: :method #returns object that behaves like Logger
55
+
56
+ = Upcoming
57
+
58
+ * screengrabs
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "carrierwave-video/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "carrierwave-video"
7
+ s.version = Carrierwave::Video::VERSION
8
+ s.authors = ["rheaton"]
9
+ s.email = ["rachelmheaton@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Carrierwave extension that uses ffmpeg to transcode videos.}
12
+ s.description = %q{Transcodes to html5-friendly videos.}
13
+
14
+ s.rubyforge_project = "carrierwave-video"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec"
23
+
24
+ s.add_runtime_dependency 'streamio-ffmpeg'#, :git => 'git://github.com/stakach/streamio-ffmpeg.git'
25
+ s.add_runtime_dependency 'carrierwave'
26
+ s.requirements << 'ruby, version 1.9 or greater'
27
+ s.requirements << 'ffmpeg, version 0.10 or greater with libx256, libfaac, libtheora, libvorbid, libvpx enabled'
28
+ end
@@ -0,0 +1,5 @@
1
+ module Carrierwave
2
+ module Video
3
+ VERSION = "0.0.1.pre"
4
+ end
5
+ end
@@ -0,0 +1,59 @@
1
+ require 'streamio-ffmpeg'
2
+ require 'carrierwave'
3
+ require 'carrierwave/video/ffmpeg_options'
4
+
5
+ module CarrierWave
6
+ module Video
7
+ extend ActiveSupport::Concern
8
+ module ClassMethods
9
+ def encode_video(target_format, options={})
10
+ process encode_video: [target_format, options]
11
+ end
12
+ end
13
+
14
+ def encode_video(format, opts={})
15
+ # move upload to local cache
16
+ cache_stored_file! if !cached?
17
+
18
+ options = CarrierWave::Video::FfmpegOptions.new(format, opts)
19
+ tmp_path = File.join( File.dirname(current_path), "tmpfile.#{format}" )
20
+
21
+
22
+ with_callbacks(opts) do
23
+ file = ::FFMPEG::Movie.new(current_path)
24
+ file.transcode(tmp_path, options.format_options, options.encoder_options)
25
+ File.rename tmp_path, current_path
26
+ end
27
+ end
28
+
29
+ private
30
+ def with_callbacks(opts, &block)
31
+ callbacks = opts[:callbacks] || {}
32
+ logger_opt = opts[:logger]
33
+ begin
34
+ send_callback(callbacks[:before_transcode])
35
+ setup_logger(logger_opt)
36
+ block.call
37
+ send_callback(callbacks[:after_transcode])
38
+ ensure
39
+ reset_logger
40
+ send_callback(callbacks[:ensure])
41
+ end
42
+ end
43
+
44
+ def send_callback(callback)
45
+ model.send(callback) if callback.present?
46
+ end
47
+
48
+ def setup_logger(opt)
49
+ return unless opt.present?
50
+ @ffmpeg_logger = ::FFMPEG.logger
51
+ ::FFMPEG.logger = model.send(opt)
52
+ end
53
+
54
+ def reset_logger
55
+ return unless @ffmpeg_logger
56
+ ::FFMPEG.logger = @ffmpeg_logger
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,69 @@
1
+ module CarrierWave
2
+ module Video
3
+ class FfmpegOptions
4
+ attr_reader :watermark_path, :watermark_position, :watermark_pixels,
5
+ :format, :resolution
6
+
7
+ def initialize(format, options)
8
+ @format = format.to_s
9
+ @watermark = options[:watermark].present?
10
+ @resolution = options[:resolution] || "640x360"
11
+ if watermark?
12
+ @watermark_path = options[:watermark][:path]
13
+ @watermark_position = options[:watermark][:position].to_s || :bottom_right
14
+ @watermark_pixels = options[:watermark][:pixels_from_edge] || 10
15
+ end
16
+ end
17
+
18
+ def encoder_options
19
+ {preserve_aspect_ratio: :width}
20
+ end
21
+
22
+ def format_options
23
+ format_options = case format
24
+ when "mp4"
25
+ {
26
+ video_codec: 'libx264',
27
+ audio_codec: 'libfaac',
28
+ custom: "-b 1500k -vpre slow -vpre baseline -g 30 #{watermark_params}"
29
+ }
30
+ when "webm"
31
+ {
32
+ video_codec: 'libvpx',
33
+ audio_codec: 'libvorbis',
34
+ custom: "-b 1500k -ab 160000 -f webm -g 30 #{watermark_params}"
35
+ }
36
+ when "ogv"
37
+ {
38
+ video_codec: 'libtheora',
39
+ audio_codec: 'libvorbis',
40
+ custom: "-b 1500k -ab 160000 -g 30 #{watermark_params}"
41
+ }
42
+ else
43
+ {}
44
+ end
45
+ { resolution: resolution }.merge(format_options)
46
+ end
47
+
48
+ def watermark?
49
+ @watermark
50
+ end
51
+
52
+ def watermark_params
53
+ return "" unless watermark?
54
+ positioning = case watermark_position
55
+ when 'bottom_left'
56
+ "#{watermark_pixels}:main_h-overlay_h-#{watermark_pixels}"
57
+ when 'bottom_right'
58
+ "main_w-overlay_w-#{watermark_pixels}:main_h-overlay_h-#{watermark_pixels}"
59
+ when 'top_left'
60
+ "#{watermark_pixels}:#{watermark_pixels}"
61
+ when 'top_right'
62
+ "main_w-overlay_w-#{watermark_pixels}:#{watermark_pixels}"
63
+ end
64
+
65
+ "-vf \"movie=#{watermark_path} [logo]; [in][logo] overlay=#{positioning} [out]\""
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,163 @@
1
+ require 'spec_helper'
2
+
3
+ describe CarrierWave::Video do
4
+ class Video; end
5
+
6
+ class TestVideoUploader
7
+ include CarrierWave::Video
8
+ def cached?; end
9
+ def cache_stored_file!; end
10
+ def model
11
+ @video ||= Video.new
12
+ end
13
+ end
14
+
15
+ let(:converter) { TestVideoUploader.new }
16
+
17
+ describe ".encode_video" do
18
+ it "processes the model" do
19
+ TestVideoUploader.should_receive(:process).with(encode_video: ["format", :opts])
20
+ TestVideoUploader.encode_video("format", :opts)
21
+ end
22
+
23
+ it "does not require options" do
24
+ TestVideoUploader.should_receive(:process).with(encode_video: ["format", {}])
25
+ TestVideoUploader.encode_video("format")
26
+ end
27
+ end
28
+
29
+ describe "#encode_video" do
30
+ let(:format) { 'webm' }
31
+ let(:movie) { mock }
32
+
33
+ before do
34
+ converter.stub(:current_path).and_return('video/path/file.mov')
35
+
36
+ FFMPEG::Movie.should_receive(:new).and_return(movie)
37
+ end
38
+
39
+ context "no options set" do
40
+ before { File.should_receive(:rename) }
41
+ it "is calls transcode with correct format options" do
42
+ movie.should_receive(:transcode) do |path, opts, codec_opts|
43
+ codec_opts.should == {preserve_aspect_ratio: :width}
44
+
45
+ opts[:video_codec].should == 'libvpx'
46
+ opts[:audio_codec].should == 'libvorbis'
47
+ opts[:custom].should == '-b 1500k -ab 160000 -f webm -g 30 '
48
+
49
+ path.should == "video/path/tmpfile.#{format}"
50
+ end
51
+
52
+ converter.encode_video(format)
53
+ end
54
+ end
55
+
56
+ context "callbacks set" do
57
+ before { movie.should_receive(:transcode) }
58
+
59
+ context "no exceptions raised" do
60
+ before { File.should_receive(:rename) }
61
+
62
+ it "calls before_transcode, after_transcode, and ensure" do
63
+ converter.model.should_receive(:method1).ordered
64
+ converter.model.should_receive(:method2).ordered
65
+ converter.model.should_receive(:method3).ordered
66
+
67
+ converter.encode_video(format, callbacks: {
68
+ before_transcode: :method1,
69
+ after_transcode: :method2,
70
+ ensure: :method3
71
+ })
72
+ end
73
+ end
74
+
75
+ context "exception raised" do
76
+ let(:e) { StandardError.new("test error") }
77
+ before { File.should_receive(:rename).and_raise(e) }
78
+
79
+ it "calls before_transcode and ensure" do
80
+ converter.model.should_receive(:method1).ordered
81
+ converter.model.should_not_receive(:method2)
82
+ converter.model.should_receive(:method3).ordered
83
+
84
+ lambda do
85
+ converter.encode_video(format, callbacks: {
86
+ before_transcode: :method1,
87
+ after_transcode: :method2,
88
+ ensure: :method3
89
+ })
90
+ end.should raise_exception(e)
91
+ end
92
+ end
93
+ end
94
+
95
+ context "logger set" do
96
+ let(:logger) { mock }
97
+ before do
98
+ converter.model.stub(:logger).and_return(logger)
99
+ movie.should_receive(:transcode)
100
+ end
101
+
102
+ context "with no exceptions" do
103
+ before { File.should_receive(:rename) }
104
+
105
+ it "sets FFMPEG logger to logger and resets" do
106
+ old_logger = ::FFMPEG.logger
107
+ ::FFMPEG.should_receive(:logger=).with(logger).ordered
108
+ ::FFMPEG.should_receive(:logger=).with(old_logger).ordered
109
+ converter.encode_video(format, logger: :logger)
110
+ end
111
+ end
112
+
113
+ context "with exceptions" do
114
+ let(:e) { StandardError.new("test error") }
115
+ before { File.should_receive(:rename).and_raise(e) }
116
+
117
+ it "logs exception" do
118
+ lambda do
119
+ converter.encode_video(format, logger: :logger)
120
+ end.should raise_exception(e)
121
+ end
122
+ end
123
+ end
124
+
125
+ context "watermark set" do
126
+ before { File.should_receive(:rename) }
127
+
128
+ it "appends watermark params to custom params for ffmpeg" do
129
+ movie.should_receive(:transcode) do |path, opts, codec_opts|
130
+ codec_opts.should == {preserve_aspect_ratio: :width}
131
+
132
+ opts[:video_codec].should == 'libvpx'
133
+ opts[:audio_codec].should == 'libvorbis'
134
+ opts[:custom].should == "-b 1500k -ab 160000 -f webm -g 30 -vf \"movie=path/to/file.png [logo]; [in][logo] overlay=5:main_h-overlay_h-5 [out]\""
135
+
136
+ path.should == "video/path/tmpfile.#{format}"
137
+ end
138
+
139
+ converter.encode_video(format, watermark: {
140
+ path: 'path/to/file.png',
141
+ position: :bottom_left,
142
+ pixels_from_edge: 5
143
+ })
144
+ end
145
+
146
+ it "only requires path watermark parameter" do
147
+ movie.should_receive(:transcode) do |path, opts, codec_opts|
148
+ codec_opts.should == {preserve_aspect_ratio: :width}
149
+
150
+ opts[:video_codec].should == 'libvpx'
151
+ opts[:audio_codec].should == 'libvorbis'
152
+ opts[:custom].should == "-b 1500k -ab 160000 -f webm -g 30 -vf \"movie=path/to/file.png [logo]; [in][logo] overlay= [out]\""
153
+
154
+ path.should == "video/path/tmpfile.#{format}"
155
+ end
156
+
157
+ converter.encode_video(format, watermark: {
158
+ path: 'path/to/file.png'
159
+ })
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,6 @@
1
+ require 'streamio-ffmpeg'
2
+ require 'carrierwave/video'
3
+
4
+ RSpec.configure do |config|
5
+ config.mock_with :rspec
6
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: carrierwave-video
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.pre
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - rheaton
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70335404267560 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70335404267560
25
+ - !ruby/object:Gem::Dependency
26
+ name: streamio-ffmpeg
27
+ requirement: &70335404266960 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70335404266960
36
+ - !ruby/object:Gem::Dependency
37
+ name: carrierwave
38
+ requirement: &70335404266520 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70335404266520
47
+ description: Transcodes to html5-friendly videos.
48
+ email:
49
+ - rachelmheaton@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - Gemfile
56
+ - README.rdoc
57
+ - Rakefile
58
+ - carrierwave-video.gemspec
59
+ - lib/carrierwave-video/version.rb
60
+ - lib/carrierwave/video.rb
61
+ - lib/carrierwave/video/ffmpeg_options.rb
62
+ - spec/lib/carrierwave_video_spec.rb
63
+ - spec/spec_helper.rb
64
+ homepage: ''
65
+ licenses: []
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>'
80
+ - !ruby/object:Gem::Version
81
+ version: 1.3.1
82
+ requirements:
83
+ - ruby, version 1.9 or greater
84
+ - ffmpeg, version 0.10 or greater with libx256, libfaac, libtheora, libvorbid, libvpx
85
+ enabled
86
+ rubyforge_project: carrierwave-video
87
+ rubygems_version: 1.8.17
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Carrierwave extension that uses ffmpeg to transcode videos.
91
+ test_files:
92
+ - spec/lib/carrierwave_video_spec.rb
93
+ - spec/spec_helper.rb