vidibus-mp4_encoder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 André Pankratz
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # Vidibus::Mp4Encoder
2
+
3
+ This is an encoder class for generating H.264 videos in a mp4 container.
4
+
5
+ This gem is part of [Vidibus](http://vidibus.org), an open source toolset for building distributed (video) applications.
6
+
7
+ **Beware:** Work in progress!
8
+
9
+
10
+ ## Notes
11
+
12
+ x264 FFmpeg Options Guide:
13
+ https://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping
14
+
15
+
16
+ ## Copyright
17
+
18
+ © 2012 André Pankratz See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ $:.unshift File.expand_path('../lib/', __FILE__)
2
+
3
+ require 'bundler'
4
+ require 'rdoc/task'
5
+ require 'rspec'
6
+ require 'rspec/core/rake_task'
7
+
8
+ Bundler::GemHelper.install_tasks
9
+
10
+ RSpec::Core::RakeTask.new(:rcov) do |t|
11
+ t.pattern = 'spec/**/*_spec.rb'
12
+ t.rcov = true
13
+ t.rcov_opts = ['--exclude', '^spec,/gems/']
14
+ end
15
+
16
+ Rake::RDocTask.new do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'Vidibus::Mp4Encoder'
19
+ rdoc.rdoc_files.include('README*')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ rdoc.options << '--charset=utf-8'
22
+ end
23
+
24
+ task :default => :rcov
@@ -0,0 +1,189 @@
1
+ module Vidibus
2
+ class Mp4Encoder < Vidibus::Encoder::Base
3
+ class ProfileError < Vidibus::Encoder::ProfileError; end
4
+
5
+ VERSION = '0.1.0'
6
+
7
+ DEFAULT_AUDIO_CODEC = 'aac'
8
+ DEFAULT_VIDEO_CODEC = 'h264'
9
+ DEFAULT_VIDEO_PROFILE = 'main'
10
+ DEFAULT_VIDEO_CODEC_LEVEL = '3.1'
11
+ DEFAULT_PRESETS = {
12
+ :baseline => 'coder=0 bf=0 flags2=-wpred-dct8x8',
13
+ :main => 'coder=1 flags=+loop cmp=+chroma partitions=+parti8x8+parti4x4+partp8x8+partb8x8 me_method=hex subq=7 i_qfactor=0.71 directpred=1 flags2=+wpred+fastpskip-dct8x8'
14
+ }
15
+
16
+ # Common profile settings.
17
+ def self.profile_presets
18
+ @profile_presets ||= begin
19
+ {
20
+ :p192 => {
21
+ :video_profile => 'baseline',
22
+ :constant_bit_rate => true,
23
+ :video_bit_rate => 90000,
24
+ :audio_bit_rate => 32000,
25
+ :audio_sample_rate => 32000,
26
+ :audio_channels => 1,
27
+ :width => 192,
28
+ :dimensions_modulus => 4,
29
+ :frame_rate => 10
30
+ },
31
+ :p480 => {
32
+ :video_profile => 'baseline',
33
+ :constant_bit_rate => true,
34
+ :video_bit_rate => 400000,
35
+ :audio_bit_rate => 32000,
36
+ :audio_sample_rate => 32000,
37
+ :audio_channels => 1,
38
+ :width => 480,
39
+ :dimensions_modulus => 4,
40
+ :frame_rate => [29.97, 25]
41
+ },
42
+ :t960 => {
43
+ :video_profile => 'baseline',
44
+ :constant_bit_rate => true,
45
+ :video_bit_rate => 1800000,
46
+ :audio_bit_rate => 96000,
47
+ :audio_sample_rate => 32000,
48
+ :width => 960,
49
+ :frame_rate => [29.97, 25]
50
+ },
51
+ :t1280 => {
52
+ :video_profile => 'baseline',
53
+ :video_bit_rate => 2800000,
54
+ :audio_bit_rate => 128000,
55
+ :audio_sample_rate => 32000,
56
+ :width => 1280,
57
+ :frame_rate => [29.97, 25]
58
+ },
59
+ :w620 => {
60
+ :video_bit_rate => 1000000,
61
+ :audio_bit_rate => 96000,
62
+ :audio_sample_rate => 48000,
63
+ :width => 620,
64
+ :dimensions_modulus => 4,
65
+ :frame_rate => [29.97, 25]
66
+ },
67
+ :w768 => {
68
+ :video_bit_rate => 1400000,
69
+ :audio_bit_rate => 128000,
70
+ :audio_sample_rate => 48000,
71
+ :width => 768,
72
+ :frame_rate => [29.97, 25]
73
+ },
74
+ :w1280 => {
75
+ :video_bit_rate => 2800000,
76
+ :audio_bit_rate => 192000,
77
+ :audio_sample_rate => 48000,
78
+ :width => 1280,
79
+ :frame_rate => [29.97, 25]
80
+ },
81
+ :w1920 => {
82
+ :video_bit_rate => 4500000,
83
+ :audio_bit_rate => 192000,
84
+ :audio_sample_rate => 48000,
85
+ :width => 1920,
86
+ :frame_rate => [29.97, 25]
87
+ }
88
+ }.tap do |p|
89
+ p[:default] = p[:w768]
90
+ end
91
+ end
92
+ end
93
+
94
+ def self.file_extension
95
+ 'mp4'
96
+ end
97
+
98
+ private
99
+
100
+ flag(:audio_bit_rate) { |value| "-ab #{value}" }
101
+ flag(:audio_channels) { |value| "-ac #{value}" }
102
+ flag(:audio_sample_rate) { |value| "-ar #{value}" }
103
+ flag(:aspect_ratio) { |value| "-aspect #{value}" }
104
+ flag(:video_profile) { |value| "-profile #{value}" }
105
+ flag(:video_codec_level) { |value| "-level #{value}" }
106
+
107
+ flag(:video_bit_rate) do |value|
108
+ output = "-b #{value} "
109
+ if profile.constant_bit_rate
110
+ output << " -vmaxrate #{value} -vbufsize #{value}"
111
+ end
112
+ output
113
+ end
114
+
115
+ # Set dimensions and aspect ratio to remove anamorphosis.
116
+ flag(:dimensions) do
117
+ modulus = profile.dimensions_modulus || 8
118
+ value = profile.dimensions(modulus)
119
+ "-s #{value} -aspect #{profile.aspect_ratio(modulus)}"
120
+ end
121
+
122
+ # Try to find a matching frame rate, if several ones are given. If no
123
+ # matching frame rate can be found, the first one will be used.
124
+ # Unless a gop duration is given, a keyframe will be set every 4 seconds.
125
+ flag(:frame_rate) do |value|
126
+ if value.is_a?(Array)
127
+ value = matching_frame_rate(value) || value.first
128
+ end
129
+ gop_duration = profile.try!(:gop_duration) || 4000
130
+ gop = gop_duration/1000*value
131
+ "-r #{value} -g #{gop} -keyint_min #{gop}"
132
+ end
133
+
134
+ # Convert the preset args
135
+ flag(:preset) do |value|
136
+ '-' + value.gsub(/\s+/, ' -').gsub(/\=/, ' ')
137
+ end
138
+
139
+ flag(:audio_codec) do |value|
140
+ if value == 'aac'
141
+ 'libfaac'
142
+ else
143
+ raise 'aac is the only audio codec supported right now'
144
+ end
145
+ end
146
+
147
+ flag(:video_codec) do |value|
148
+ if value == 'h264'
149
+ 'libx264'
150
+ else
151
+ raise 'h264 is the only video codec supported right now'
152
+ end
153
+ end
154
+
155
+ # Set default options for current profile:
156
+ #
157
+ # audio_codec: 'aac'
158
+ # video_codec: 'h264'
159
+ # video_profile: 'main'
160
+ # video_codec_level: '3.1'
161
+ # preset: [the :main present]
162
+ def preprocess
163
+ profile.settings[:audio_codec] ||= DEFAULT_AUDIO_CODEC
164
+ profile.settings[:video_codec] ||= DEFAULT_VIDEO_CODEC
165
+ profile.settings[:video_profile] ||= DEFAULT_VIDEO_PROFILE
166
+ profile.settings[:video_codec_level] ||= begin
167
+ profile.video_profile.to_s == 'baseline' ? '3.0': DEFAULT_VIDEO_CODEC_LEVEL
168
+ end
169
+ profile.settings[:preset] ||= DEFAULT_PRESETS[profile.video_profile.to_sym]
170
+ super
171
+ end
172
+
173
+ # Log encoding errors.
174
+ def handle_response(stdout, stderr)
175
+ stderr.each("\r") do |line|
176
+ if line =~ /error/i
177
+ logger.error("Encoder error:\n#{line}")
178
+ end
179
+ end
180
+ end
181
+
182
+ # The encoding recipe.
183
+ def recipe
184
+ audio = %(-acodec %{audio_codec} %{audio_sample_rate} %{audio_bit_rate} %{audio_channels} -async 2)
185
+ video = %(-vcodec %{video_codec} %{dimensions} %{video_bit_rate} %{frame_rate} %{video_profile} %{video_codec_level} %{preset})
186
+ "ffmpeg -i %{input} #{audio} #{video} -y -threads 0 %{output}"
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,5 @@
1
+ require 'vidibus-encoder'
2
+
3
+ require 'vidibus/mp4_encoder'
4
+
5
+ Vidibus::Encoder.register_format(:mp4, Vidibus::Mp4Encoder)
metadata ADDED
@@ -0,0 +1,172 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vidibus-mp4_encoder
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - "Andr\xC3\xA9 Pankratz"
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-04-20 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: vidibus-encoder
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: bundler
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 23
44
+ segments:
45
+ - 1
46
+ - 0
47
+ - 0
48
+ version: 1.0.0
49
+ type: :development
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: rake
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ type: :development
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: rdoc
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ type: :development
78
+ version_requirements: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ name: rcov
81
+ prerelease: false
82
+ requirement: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ type: :development
92
+ version_requirements: *id005
93
+ - !ruby/object:Gem::Dependency
94
+ name: rspec
95
+ prerelease: false
96
+ requirement: &id006 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ hash: 7
102
+ segments:
103
+ - 2
104
+ version: "2"
105
+ type: :development
106
+ version_requirements: *id006
107
+ - !ruby/object:Gem::Dependency
108
+ name: rr
109
+ prerelease: false
110
+ requirement: &id007 !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ hash: 3
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ type: :development
120
+ version_requirements: *id007
121
+ description: MP4 (H.264) Encoder
122
+ email: andre@vidibus.com
123
+ executables: []
124
+
125
+ extensions: []
126
+
127
+ extra_rdoc_files: []
128
+
129
+ files:
130
+ - lib/vidibus/mp4_encoder.rb
131
+ - lib/vidibus-mp4_encoder.rb
132
+ - LICENSE
133
+ - README.md
134
+ - Rakefile
135
+ has_rdoc: true
136
+ homepage: https://github.com/vidibus/vidibus-mp4_encoder
137
+ licenses: []
138
+
139
+ post_install_message:
140
+ rdoc_options: []
141
+
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ hash: 3
150
+ segments:
151
+ - 0
152
+ version: "0"
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ none: false
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ hash: 23
159
+ segments:
160
+ - 1
161
+ - 3
162
+ - 6
163
+ version: 1.3.6
164
+ requirements: []
165
+
166
+ rubyforge_project: vidibus-mp4_encoder
167
+ rubygems_version: 1.3.7
168
+ signing_key:
169
+ specification_version: 3
170
+ summary: MP4 (H.264) Encoder
171
+ test_files: []
172
+