handbrake 0.0.1

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/handbrake.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "handbrake/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "handbrake"
7
+ s.version = HandBrake::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Rhett Sutphin"]
10
+ s.email = ["rhett@detailedbalance.net"]
11
+ s.homepage = "https://github.com/rsutphin/handbrake-ruby"
12
+ s.summary = %q{A ruby wrapper for HandBrakeCLI}
13
+ s.description = %q{A lightweight literate ruby wrapper for HandBrakeCLI, the command-line interface for the HandBrake video transcoder.}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency 'rubytree', '~> 0.8.1'
21
+
22
+ s.add_development_dependency 'rspec', '~> 2.5'
23
+ s.add_development_dependency 'rake', '~> 0.9.0'
24
+ s.add_development_dependency 'yard', '~> 0.7.0'
25
+ end
data/hrirb ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ######
4
+ # Run irb for interactive fiddling with this library from the source
5
+
6
+ require 'irb'
7
+
8
+ $LOAD_PATH << File.expand_path('../lib', __FILE__)
9
+ require 'handbrake'
10
+
11
+ $cli = HandBrake::CLI.new(:trace => true)
12
+
13
+ puts "`$cli` is a HandBrake::CLI instance with tracing on"
14
+
15
+ IRB.start(__FILE__)
@@ -0,0 +1,206 @@
1
+ require 'handbrake'
2
+
3
+ module HandBrake
4
+ ##
5
+ # The main entry point for this API. See {file:README.md} for usage
6
+ # examples.
7
+ class CLI
8
+ ##
9
+ # The full path (including filename) to the HandBrakeCLI
10
+ # executable to use.
11
+ #
12
+ # @return [String]
13
+ attr_accessor :bin_path
14
+
15
+ ##
16
+ # Set whether trace is enabled.
17
+ #
18
+ # @return [Boolean]
19
+ attr_writer :trace
20
+
21
+ ##
22
+ # @param [Hash] options
23
+ # @option options [String] :bin_path ('HandBrakeCLI') the full
24
+ # path to the executable to use
25
+ # @option options [Boolean] :trace (false) whether {#trace?} is
26
+ # enabled
27
+ # @option options [#run] :runner (a PopenRunner instance) the class
28
+ # encapsulating the execution method for HandBrakeCLI. You
29
+ # shouldn't usually need to replace this.
30
+ def initialize(options={})
31
+ @bin_path = options[:bin_path] || 'HandBrakeCLI'
32
+ @trace = options[:trace].nil? ? false : options[:trace]
33
+ @runner = options[:runner] || PopenRunner.new(self)
34
+
35
+ @args = []
36
+ end
37
+
38
+ ##
39
+ # Ensures that `#dup` produces a separate copy.
40
+ #
41
+ # @return [void]
42
+ def initialize_copy(original)
43
+ @args = original.instance_eval { @args }.collect { |bit| bit.dup }
44
+ end
45
+
46
+ ##
47
+ # Is trace enabled?
48
+ #
49
+ # If it is enabled, all output from HandBrakeCLI will be streamed
50
+ # to standard error. If not, the output from HandBrakeCLI will
51
+ # only be printed if there is a detectable error.
52
+ #
53
+ # @return [Boolean]
54
+ def trace?
55
+ @trace
56
+ end
57
+
58
+ ##
59
+ # Performs a conversion. This method immediately begins the
60
+ # transcoding process; set all other options first.
61
+ #
62
+ # @return [void]
63
+ def output(filename)
64
+ run('--output', filename)
65
+ end
66
+
67
+ ##
68
+ # Performs a title scan. Unlike HandBrakeCLI, if you do not
69
+ # specify a title, this method will return information for all
70
+ # titles. (HandBrakeCLI defaults to only returning information for
71
+ # title 1.)
72
+ #
73
+ # @return [Titles]
74
+ def scan
75
+ if arguments.include?('--title')
76
+ result = run('--scan')
77
+ Titles.from_output(result.output)
78
+ else
79
+ title(0).scan
80
+ end
81
+ end
82
+
83
+ ##
84
+ # Checks to see if the `HandBrakeCLI` instance designated by
85
+ # {#bin_path} is the current version.
86
+ #
87
+ # Note that `HandBrakeCLI` will always report that it is up to
88
+ # date if it can't connect to the update server, so this is not
89
+ # terribly reliable.
90
+ #
91
+ # @return [Boolean]
92
+ def update
93
+ result = run('--update')
94
+ result.output =~ /Your version of HandBrake is up to date./i
95
+ end
96
+
97
+ ##
98
+ # Returns a structure describing the presets that the current
99
+ # HandBrake install knows about. The structure is a two-level
100
+ # hash. The keys in the first level are the preset categories. The
101
+ # keys in the second level are the preset names and the values are
102
+ # string representations of the arguments for that preset.
103
+ #
104
+ # (This method is included for completeness only. This library does
105
+ # not provide a mechanism to translate the argument lists returned
106
+ # here into the configuration for a {HandBrake::CLI} instance.)
107
+ #
108
+ # @return [Hash]
109
+ def preset_list
110
+ result = run('--preset-list')
111
+ result.output.scan(%r{\< (.*?)\n(.*?)\>}m).inject({}) { |h1, (cat, block)|
112
+ h1[cat.strip] = block.scan(/\+(.*?):(.*?)\n/).inject({}) { |h2, (name, args)|
113
+ h2[name.strip] = args.strip
114
+ h2
115
+ }
116
+ h1
117
+ }
118
+ end
119
+
120
+ ##
121
+ # @private
122
+ def arguments
123
+ @args.collect { |req, *rest| ["--#{req.to_s.gsub('_', '-')}", *rest] }.flatten
124
+ end
125
+
126
+ private
127
+
128
+ def run(*more_args)
129
+ @runner.run(arguments.push(*more_args)).tap do |result|
130
+ unless result.status == 0
131
+ unless trace?
132
+ $stderr.puts result.output
133
+ end
134
+ raise "HandBrakeCLI execution failed (#{result.status.inspect})"
135
+ end
136
+ end
137
+ end
138
+
139
+ ##
140
+ # Copies this CLI instance and appends another command line switch
141
+ # plus optional arguments.
142
+ #
143
+ # This method does not do any validation of the switch name; if
144
+ # you use an invalid one, HandBrakeCLI will fail when it is
145
+ # ultimately invoked.
146
+ #
147
+ # @return [CLI]
148
+ def method_missing(name, *args)
149
+ copy = self.dup
150
+ copy.instance_eval { @args << [name, *(args.collect { |a| a.to_s })] }
151
+ copy
152
+ end
153
+
154
+ ##
155
+ # @private
156
+ # The default runner. Uses `IO.popen` to spawn
157
+ # HandBrakeCLI. General use of this library does not require
158
+ # monkeying with this class.
159
+ class PopenRunner
160
+ ##
161
+ # @param [CLI] cli_instance the {CLI} instance whose configuration to share
162
+ def initialize(cli_instance)
163
+ @cli = cli_instance
164
+ end
165
+
166
+ # Some notes on popen options
167
+ # - IO.popen on 1.9.2 is much more elegant than on 1.8.7
168
+ # (it lets you pass spawn args directly instead of using a
169
+ # subshell, so you can more cleanly pass args to the
170
+ # executable and redirect streams)
171
+ # - Open3.popen3 does not let you get the status
172
+ # - Open4.popen4 does not seem to stream the output and error
173
+ # and hangs when the child process fills some buffer
174
+ # Hence, this implementation:
175
+
176
+ ##
177
+ # @param [Array<String>] arguments the arguments to pass to HandBrakeCLI
178
+ # @return [RunnerResult]
179
+ def run(arguments)
180
+ output = ''
181
+
182
+ cmd = "'" + arguments.unshift(@cli.bin_path).join("' '") + "' 2>&1"
183
+
184
+ $stderr.puts "Spawning HandBrakeCLI using #{cmd.inspect}" if @cli.trace?
185
+ IO.popen(cmd) do |io|
186
+ while line = io.gets
187
+ output << line
188
+ $stderr.puts(line.chomp) if @cli.trace?
189
+ end
190
+ end
191
+ RunnerResult.new(output, $?)
192
+ end
193
+ end
194
+
195
+ ##
196
+ # @private
197
+ # The raw result of one execution of HandBrakeCLI.
198
+ #
199
+ # General use of the library will not require use of this class.
200
+ #
201
+ # @attr [String] output a string containing the combined output
202
+ # and error streams from the run
203
+ # @attr [#to_i] status the process exit status for the run
204
+ RunnerResult = Struct.new(:output, :status)
205
+ end
206
+ end
@@ -0,0 +1,181 @@
1
+ require 'tree'
2
+
3
+ require 'handbrake'
4
+
5
+ module HandBrake
6
+ ##
7
+ # And enhanced `Hash` which can self-parse the output from
8
+ # HandBrakeCLI's `--scan` mode. The keys of this hash will be title
9
+ # numbers and the values will be {Title} instances.
10
+ #
11
+ # @see Title
12
+ # @see Chapter
13
+ class Titles < Hash
14
+ ##
15
+ # The HandBrakeCLI scan output from which this instance was
16
+ # parsed, if available.
17
+ #
18
+ # @return [String,nil]
19
+ attr_reader :raw_output
20
+
21
+ ##
22
+ # A tree representing the indented output at the end of the
23
+ # HandBrakeCLI scan output, if available.
24
+ #
25
+ # @return [String,nil]
26
+ attr_reader :raw_tree
27
+
28
+ ##
29
+ # Builds a new {Titles} instance from the output of `HandBrakeCLI
30
+ # --scan`.
31
+ #
32
+ # @param [String] output the raw contents from the scan
33
+ # @return [Titles] a new, completely initialized title catalog
34
+ def self.from_output(output)
35
+ self.new.tap do |titles|
36
+ titles.raw_output = output
37
+ titles.raw_tree.children.
38
+ collect { |title_node| Title.from_tree(title_node) }.
39
+ each { |title| titles[title.number] = title }
40
+ end
41
+ end
42
+
43
+ ##
44
+ # Initializes the {#raw_output} and {#raw_tree} attributes from
45
+ # the given HandBrakeCLI output. Does not modify the contents of
46
+ # the hash.
47
+ #
48
+ # @param [String] output raw contents from a HandBrakeCLI title
49
+ # scan
50
+ # @return [void]
51
+ def raw_output=(output)
52
+ @raw_output = output
53
+ @raw_tree = extract_tree
54
+ end
55
+
56
+ private
57
+
58
+ def extract_tree
59
+ split_blocks(
60
+ raw_output.split("\n").grep(/^\s*\+/), ''
61
+ ).inject(Tree::TreeNode.new('__root__')) do |root, block|
62
+ root << read_node(block, '')
63
+ root
64
+ end
65
+ end
66
+
67
+ def split_blocks(lines, indent_level)
68
+ lines.inject([]) do |blocks, line|
69
+ blocks << [] if line =~ /^#{indent_level}\+/
70
+
71
+ blocks.last << line
72
+ blocks
73
+ end
74
+ end
75
+
76
+ def read_node(node_lines, indent_level)
77
+ next_indent = indent_level + ' '
78
+ split_blocks(
79
+ node_lines[1..-1], next_indent
80
+ ).inject(Tree::TreeNode.new(node_lines.first[(2 + indent_level.size)..-1])) do |node, block|
81
+ node << read_node(block, next_indent)
82
+ node
83
+ end
84
+ end
85
+ end
86
+
87
+ ##
88
+ # Provides a {#seconds} method for an object which has a `duration`
89
+ # property whose value is a string of the format "hh:mm:ss"
90
+ module DurationAsSeconds
91
+ ##
92
+ # The number of seconds described by the duration. E.g., if the
93
+ # duration were `"1:02:42"`, this method would return `3762`.
94
+ #
95
+ # @return [Fixnum]
96
+ def seconds
97
+ @seconds ||= duration.split(':').collect(&:to_i).reverse.
98
+ inject([1, 0]) { |(m, sum), i| [m * 60, sum + i * m] }.last
99
+ end
100
+ end
101
+
102
+ ##
103
+ # Metadata about a single DVD title.
104
+ class Title
105
+ include DurationAsSeconds
106
+
107
+ ##
108
+ # @return [Fixnum] The title number of this title (a positive integer).
109
+ attr_accessor :number
110
+
111
+ ##
112
+ # @return [String] The duration of the title in the format
113
+ # "hh:mm:ss"
114
+ attr_accessor :duration
115
+
116
+ ##
117
+ # @return [Array<Chapter>] The chapters into which the title is
118
+ # divided.
119
+ attr_writer :chapters
120
+
121
+ ##
122
+ # @return [Boolean] Whether HandBrake considers this title the
123
+ # "main feature".
124
+ attr_writer :main_feature
125
+
126
+ ##
127
+ # Creates a new instance from the given scan subtree.
128
+ #
129
+ # @see Titles.from_output
130
+ # @param [Tree::TreeNode] title_node
131
+ # @return [Title] a new, fully initialized instance
132
+ def self.from_tree(title_node)
133
+ self.new.tap do |title|
134
+ title.number = title_node.name.scan(/title (\d+)/).first.first.to_i
135
+ title.duration = title_node.children.
136
+ detect { |c| c.name =~ /duration/ }.name.
137
+ scan(/duration: (\d\d:\d\d:\d\d)/).first.first
138
+ title.chapters = title_node['chapters:'].children.
139
+ collect { |ch_node| Chapter.from_tree(ch_node) }
140
+ title.main_feature = title_node.children.detect { |c| c.name =~ /Main Feature/ }
141
+ end
142
+ end
143
+
144
+ ##
145
+ # @return [Boolean] Whether HandBrake considers this title the
146
+ # "main feature".
147
+ def main_feature?
148
+ @main_feature
149
+ end
150
+
151
+ ##
152
+ # @return [Array<Chapter>] The chapters into which the title is
153
+ # divided.
154
+ def chapters
155
+ @chapters ||= []
156
+ end
157
+ end
158
+
159
+ ##
160
+ # The metadata about a single chapter in a title of a DVD.
161
+ class Chapter
162
+ include DurationAsSeconds
163
+
164
+ ##
165
+ # @return [String] The duration of the title in the format
166
+ # "hh:mm:ss"
167
+ attr_accessor :duration
168
+
169
+ ##
170
+ # Creates a new instance from the given title subtree.
171
+ #
172
+ # @see Title.from_tree
173
+ # @param [Tree::TreeNode] chapter_node
174
+ # @return [Chapter] a new, fully initialized instance
175
+ def self.from_tree(chapter_node)
176
+ self.new.tap do |ch|
177
+ ch.duration = chapter_node.name.scan(/duration (\d\d:\d\d:\d\d)/).first.first
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,5 @@
1
+ module HandBrake
2
+ ##
3
+ # The current version
4
+ VERSION = "0.0.1"
5
+ end
data/lib/handbrake.rb ADDED
@@ -0,0 +1,11 @@
1
+ ##
2
+ # @see file:README.md
3
+ # @see CLI The main class
4
+ module HandBrake
5
+ autoload :VERSION, 'handbrake/version'
6
+
7
+ autoload :CLI, 'handbrake/cli'
8
+ autoload :Titles, 'handbrake/titles'
9
+ autoload :Title, 'handbrake/titles'
10
+ autoload :Chapter, 'handbrake/titles'
11
+ end
@@ -0,0 +1,162 @@
1
+ require File.expand_path('../../spec_helper.rb', __FILE__)
2
+
3
+ module HandBrake
4
+ describe CLI do
5
+ describe "#bin_path" do
6
+ it "looks on the path by default" do
7
+ HandBrake::CLI.new.bin_path.should == "HandBrakeCLI"
8
+ end
9
+
10
+ it "is the specified value when specified" do
11
+ HandBrake::CLI.new(:bin_path => '/Applications/HandBrakeCLI').bin_path.
12
+ should == '/Applications/HandBrakeCLI'
13
+ end
14
+ end
15
+
16
+ describe "#trace?" do
17
+ it "is false by default" do
18
+ HandBrake::CLI.new.trace?.should == false
19
+ end
20
+
21
+ it "can be set" do
22
+ HandBrake::CLI.new(:trace => true).trace?.should == true
23
+ end
24
+ end
25
+
26
+ describe "building a command" do
27
+ let(:cli) { HandBrake::CLI.new }
28
+
29
+ it "works for a parameter without an argument" do
30
+ cli.markers.arguments.should == %w(--markers)
31
+ end
32
+
33
+ it "works for a parameter with an argument" do
34
+ cli.quality('0.8').arguments.should == %w(--quality 0.8)
35
+ end
36
+
37
+ it "works with a parameter with a dashed name" do
38
+ cli.native_language('eng').arguments.should == %w(--native-language eng)
39
+ end
40
+
41
+ it "can chain parameters" do
42
+ cli.previews('15').format('avi').large_file.title('3').arguments.should ==
43
+ %w(--previews 15 --format avi --large-file --title 3)
44
+ end
45
+
46
+ it "stringifies arguments" do
47
+ cli.previews(18).arguments.should == %w(--previews 18)
48
+ end
49
+
50
+ it "can produce separate forks of the command" do
51
+ base = cli.input('/foo/bar')
52
+ base.quality('0.53').format('avi').arguments.should ==
53
+ %w(--input /foo/bar --quality 0.53 --format avi)
54
+ base.title('6').ipod_atom.arguments.should ==
55
+ %w(--input /foo/bar --title 6 --ipod-atom)
56
+ end
57
+ end
58
+
59
+ describe 'execution' do
60
+ let(:cli) { HandBrake::CLI.new(:runner => runner) }
61
+ let(:runner) { HandBrake::Spec::StaticRunner.new }
62
+
63
+ describe 'default runner' do
64
+ let(:cli) { HandBrake::CLI.new }
65
+
66
+ before do
67
+ `which HandBrakeCLI`
68
+ unless $? == 0
69
+ pending 'HandBrakeCLI is not on the path'
70
+ end
71
+ end
72
+
73
+ it 'works' do
74
+ lambda { cli.update }.should_not raise_error
75
+ end
76
+ end
77
+
78
+ describe '#output' do
79
+ it 'uses the --output argument' do
80
+ cli.output('/foo/bar.m4v')
81
+ runner.actual_arguments.should == %w(--output /foo/bar.m4v)
82
+ end
83
+ end
84
+
85
+ describe '#scan' do
86
+ let(:sample_scan) { File.read(File.expand_path('../sample-titles-scan.err', __FILE__)) }
87
+
88
+ before do
89
+ runner.output = sample_scan
90
+ end
91
+
92
+ it 'uses the --scan argument' do
93
+ cli.scan
94
+ runner.actual_arguments.last.should == '--scan'
95
+ end
96
+
97
+ it 'defaults to scanning all titles' do
98
+ cli.scan
99
+ runner.actual_arguments.should == %w(--title 0 --scan)
100
+ end
101
+
102
+ it 'only scans the specified title if one is specified' do
103
+ cli.title(3).scan
104
+ runner.actual_arguments.should == %w(--title 3 --scan)
105
+ end
106
+
107
+ it 'does not permanently modify the argument list when using the default title setting' do
108
+ cli.scan
109
+ cli.arguments.should_not include('--title')
110
+ end
111
+
112
+ it 'returns titles from the output' do
113
+ # The details for this are tested in titles_spec
114
+ cli.scan.size.should == 5
115
+ end
116
+ end
117
+
118
+ describe '#update' do
119
+ it 'uses the --update argument' do
120
+ cli.update
121
+ runner.actual_arguments.should == %w(--update)
122
+ end
123
+
124
+ it 'returns true if the thing is up to date' do
125
+ runner.output = 'Your version of HandBrake is up to date.'
126
+ cli.update.should be_true
127
+ end
128
+
129
+ it 'returns false if the executable is out of date' do
130
+ runner.output = 'You are using an old version of HandBrake.'
131
+ cli.update.should be_false
132
+ end
133
+ end
134
+
135
+ describe '#preset_list' do
136
+ let(:sample_presets) { File.read(File.expand_path('../sample-preset-list.out', __FILE__)) }
137
+
138
+ before do
139
+ runner.output = sample_presets
140
+ end
141
+
142
+ it 'uses the --preset-list argument' do
143
+ cli.preset_list
144
+ runner.actual_arguments.should == %w(--preset-list)
145
+ end
146
+
147
+ it 'returns a hash containing all the categories' do
148
+ cli.preset_list.keys.sort.should == %w(Apple Legacy Regular)
149
+ end
150
+
151
+ it 'returns a hash containing the presets in each category' do
152
+ cli.preset_list['Regular'].keys.sort.should == ['High Profile', 'Normal']
153
+ end
154
+
155
+ it 'returns a hash containing the actual args for a particular preset' do
156
+ cli.preset_list['Regular']['Normal'].should ==
157
+ '-e x264 -q 20.0 -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4 --strict-anamorphic -m -x ref=2:bframes=2:subme=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0'
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,38 @@
1
+
2
+ < Apple
3
+
4
+ + Universal: -e x264 -q 20.0 -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,auto -R Auto,Auto -D 0.0,0.0 -f mp4 -X 720 --loose-anamorphic -m -x cabac=0:ref=2:me=umh:bframes=0:weightp=0:8x8dct=0:trellis=0:subme=6
5
+
6
+ + iPod: -e x264 -b 700 -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4 -I -X 320 -m -x level=30:bframes=0:weightp=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:subme=6:8x8dct=0:trellis=0
7
+
8
+ + iPhone & iPod Touch: -e x264 -q 20.0 -a 1 -E faac -B 128 -6 dpl2 -R Auto -D 0.0 -f mp4 -X 480 -m -x cabac=0:ref=2:me=umh:bframes=0:weightp=0:subme=6:8x8dct=0:trellis=0
9
+
10
+ + iPhone 4: -e x264 -q 20.0 -r 29.97 --pfr -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4 -4 -X 960 --loose-anamorphic -m
11
+
12
+ + iPad: -e x264 -q 20.0 -r 29.97 --pfr -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4 -4 -X 1024 --loose-anamorphic -m
13
+
14
+ + AppleTV: -e x264 -q 20.0 -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,auto -R Auto,Auto -D 0.0,0.0 -f mp4 -4 -X 960 --loose-anamorphic -m -x cabac=0:ref=2:me=umh:b-pyramid=none:b-adapt=2:weightb=0:trellis=0:weightp=0:vbv-maxrate=9500:vbv-bufsize=9500
15
+
16
+ + AppleTV 2: -e x264 -q 20.0 -r 29.97 --pfr -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,auto -R Auto,Auto -D 0.0,0.0 -f mp4 -4 -X 1280 --loose-anamorphic -m
17
+
18
+ >
19
+
20
+ < Regular
21
+
22
+ + Normal: -e x264 -q 20.0 -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4 --strict-anamorphic -m -x ref=2:bframes=2:subme=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0
23
+
24
+ + High Profile: -e x264 -q 20.0 -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,auto -R Auto,Auto -D 0.0,0.0 -f mp4 --detelecine --decomb --loose-anamorphic -m -x b-adapt=2:rc-lookahead=50
25
+
26
+ >
27
+
28
+ < Legacy
29
+
30
+ + Classic: -b 1000 -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4
31
+
32
+ + AppleTV Legacy: -e x264 -b 2500 -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,auto -R Auto,Auto -D 0.0,0.0 -f mp4 -4 --strict-anamorphic -m -x ref=1:b-pyramid=none:weightp=0:subme=5:me=umh:no-fast-pskip=1:cabac=0:weightb=0:8x8dct=0:trellis=0
33
+
34
+ + iPhone Legacy: -e x264 -b 960 -a 1 -E faac -B 128 -6 dpl2 -R Auto -D 0.0 -f mp4 -I -X 480 -m -x level=30:cabac=0:ref=1:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0:bframes=0:weightp=0:subme=6:8x8dct=0:trellis=0
35
+
36
+ + iPod Legacy: -e x264 -b 1500 -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 -f mp4 -I -X 640 -m -x level=30:bframes=0:weightp=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0:subme=6:8x8dct=0:trellis=0
37
+
38
+ >