video_transcoding 0.23.0 → 0.25.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +547 -0
- data/LICENSE +1 -1
- data/README.md +7 -497
- data/bin/convert-video +17 -2
- data/bin/detect-crop +3 -3
- data/bin/query-handbrake-log +2 -2
- data/bin/transcode-video +130 -34
- data/lib/video_transcoding.rb +1 -1
- data/lib/video_transcoding/cli.rb +1 -1
- data/lib/video_transcoding/console.rb +1 -1
- data/lib/video_transcoding/copyright.rb +2 -2
- data/lib/video_transcoding/crop.rb +1 -1
- data/lib/video_transcoding/errors.rb +1 -1
- data/lib/video_transcoding/ffmpeg.rb +1 -1
- data/lib/video_transcoding/handbrake.rb +1 -1
- data/lib/video_transcoding/media.rb +1 -1
- data/lib/video_transcoding/mkvpropedit.rb +1 -1
- data/lib/video_transcoding/mp4track.rb +1 -1
- data/lib/video_transcoding/tool.rb +1 -1
- data/lib/video_transcoding/version.rb +2 -2
- metadata +4 -3
data/bin/convert-video
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# convert-video
|
4
4
|
#
|
5
|
-
# Copyright (c) 2013-
|
5
|
+
# Copyright (c) 2013-2020 Don Melton
|
6
6
|
#
|
7
7
|
|
8
8
|
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
@@ -436,8 +436,23 @@ HERE
|
|
436
436
|
Process.kill 'INT', io.pid
|
437
437
|
end
|
438
438
|
|
439
|
+
buffer = ''
|
440
|
+
|
439
441
|
io.each_char do |char|
|
440
|
-
|
442
|
+
if (char.bytes[0] & 0x80) != 0
|
443
|
+
buffer << char
|
444
|
+
else
|
445
|
+
if not buffer.empty?
|
446
|
+
print buffer
|
447
|
+
buffer = ''
|
448
|
+
end
|
449
|
+
|
450
|
+
print char
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
if not buffer.empty?
|
455
|
+
print buffer
|
441
456
|
end
|
442
457
|
end
|
443
458
|
rescue SystemCallError => e
|
data/bin/detect-crop
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# detect-crop
|
4
4
|
#
|
5
|
-
# Copyright (c) 2013-
|
5
|
+
# Copyright (c) 2013-2020 Don Melton
|
6
6
|
#
|
7
7
|
|
8
8
|
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
@@ -90,8 +90,8 @@ HERE
|
|
90
90
|
|
91
91
|
print_all = ->(crop) do
|
92
92
|
puts
|
93
|
-
puts "mpv --no-audio --vf
|
94
|
-
puts "mpv --no-audio --vf
|
93
|
+
puts "mpv --no-audio --vf=\"lavfi=[drawbox=#{Crop.drawbox_string(crop, width, height)}:invert:1]\" #{shell_path}"
|
94
|
+
puts "mpv --no-audio --vf=crop=#{Crop.player_string(crop, width, height)} #{shell_path}"
|
95
95
|
print_transcode.call crop
|
96
96
|
end
|
97
97
|
|
data/bin/query-handbrake-log
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# query-handbrake-log
|
4
4
|
#
|
5
|
-
# Copyright (c) 2013-
|
5
|
+
# Copyright (c) 2013-2020 Don Melton
|
6
6
|
#
|
7
7
|
|
8
8
|
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
@@ -137,7 +137,7 @@ HERE
|
|
137
137
|
File.foreach(log) do |line|
|
138
138
|
found = true if not found and line =~ /^HandBrake/
|
139
139
|
count += 1
|
140
|
-
fail "not a HandBrake-generated `.log` file: #{log}" if count >
|
140
|
+
fail "not a HandBrake-generated `.log` file: #{log}" if count > 10 and not found
|
141
141
|
duration_line = line if duration_line.nil? and line =~ /\+ duration: /
|
142
142
|
rate_line = line if line =~ /\+ frame rate: /
|
143
143
|
|
data/bin/transcode-video
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# transcode-video
|
4
4
|
#
|
5
|
-
# Copyright (c) 2013-
|
5
|
+
# Copyright (c) 2013-2020 Don Melton
|
6
6
|
#
|
7
7
|
|
8
8
|
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
@@ -89,8 +89,10 @@ Video options:
|
|
89
89
|
(use `--crop auto` for `HandBrakeCLI` behavior)
|
90
90
|
--constrain-crop
|
91
91
|
constrain `--crop detect` to optimal shape
|
92
|
-
--fallback-crop handbrake|ffmpeg|none
|
92
|
+
--fallback-crop handbrake|ffmpeg|minimal|none
|
93
93
|
select fallback crop values if `--crop detect` fails
|
94
|
+
(`minimal` uses the smallest possible crop values
|
95
|
+
combining results from `HandBrakeCLI` and `ffmpeg`)
|
94
96
|
--720p fit video within 1280x720 pixel bounds
|
95
97
|
--max-width WIDTH, --max-height HEIGHT
|
96
98
|
fit video within horizontal and/or vertical pixel bounds
|
@@ -134,18 +136,21 @@ Audio options:
|
|
134
136
|
(can be used multiple times)
|
135
137
|
--reverse-double-order
|
136
138
|
reverse order of `double` width audio output tracks
|
137
|
-
--
|
138
|
-
|
139
|
-
(
|
139
|
+
--audio-format surround|stereo|all=ac3|aac
|
140
|
+
set audio format for specific or all output tracks
|
141
|
+
(default for surround: ac3; default for stereo: aac)
|
142
|
+
--keep-ac3-stereo
|
143
|
+
copy rather than transcode AC-3 stereo or mono audio tracks
|
144
|
+
even when the current stereo format is AAC
|
140
145
|
--ac3-encoder ac3|eac3
|
141
146
|
set AC-3 audio encoder (default: ac3)
|
142
147
|
--ac3-bitrate 384|448|640|768|1536
|
143
|
-
set AC-3 audio bitrate (default: 640)
|
148
|
+
set AC-3 surround audio bitrate (default: 640)
|
144
149
|
--pass-ac3-bitrate 384|448|640|768|1536
|
145
|
-
set AC-3
|
150
|
+
set AC-3 surround pass-through bitrate (default: 640)
|
146
151
|
--copy-audio TRACK|all
|
147
152
|
try to copy track selected by number in its original format
|
148
|
-
falling back to
|
153
|
+
falling back to surround format if original not allowed
|
149
154
|
or try to copy all tracks in same manner
|
150
155
|
(only applies to main and explicitly added audio tracks)
|
151
156
|
(can be used multiple times)
|
@@ -157,8 +162,10 @@ Audio options:
|
|
157
162
|
(can be used multiple times)
|
158
163
|
--aac-encoder NAME
|
159
164
|
use named AAC audio encoder (default: platform dependent)
|
160
|
-
--mixdown dpl2
|
161
|
-
set mixdown
|
165
|
+
--mixdown stereo|dpl2
|
166
|
+
set mixdown for stereo audio output tracks
|
167
|
+
to regular stereo or Dolby Pro Logic II format
|
168
|
+
(default: stereo)
|
162
169
|
--no-audio disable all audio output
|
163
170
|
|
164
171
|
Subtitle options:
|
@@ -253,14 +260,16 @@ HERE
|
|
253
260
|
@audio_language = []
|
254
261
|
@audio_width = {:main => :double, :other => :stereo}
|
255
262
|
@reverse_double_order = false
|
256
|
-
@
|
263
|
+
@surround_format = 'ac3'
|
264
|
+
@stereo_format = 'aac'
|
265
|
+
@keep_ac3_stereo = false
|
257
266
|
@ac3_encoder = 'ac3'
|
258
267
|
@ac3_bitrate = 640
|
259
268
|
@pass_ac3_bitrate = 640
|
260
269
|
@copy_audio = []
|
261
270
|
@copy_audio_name = []
|
262
271
|
@aac_encoder = nil
|
263
|
-
@mixdown = '
|
272
|
+
@mixdown = 'stereo'
|
264
273
|
@burn_subtitle = nil
|
265
274
|
@force_subtitle = nil
|
266
275
|
@extra_subtitle = []
|
@@ -430,7 +439,7 @@ HERE
|
|
430
439
|
|
431
440
|
opts.on '--fallback-crop ARG' do |arg|
|
432
441
|
@fallback_crop = case arg
|
433
|
-
when 'handbrake', 'ffmpeg', 'mplayer', 'none'
|
442
|
+
when 'handbrake', 'ffmpeg', 'mplayer', 'minimal', 'none'
|
434
443
|
arg.to_sym
|
435
444
|
else
|
436
445
|
fail UsageError, "invalid fallback crop argument: #{arg}"
|
@@ -557,10 +566,35 @@ HERE
|
|
557
566
|
|
558
567
|
opts.on('--reverse-double-order') { @reverse_double_order = true }
|
559
568
|
|
569
|
+
opts.on '--audio-format ARG' do |arg|
|
570
|
+
if arg =~ /^(surround|stereo|all)=(ac3|aac)$/
|
571
|
+
case $1
|
572
|
+
when 'surround'
|
573
|
+
@surround_format = $2
|
574
|
+
when 'stereo'
|
575
|
+
@stereo_format = $2
|
576
|
+
else
|
577
|
+
@surround_format = $2
|
578
|
+
@stereo_format = $2
|
579
|
+
end
|
580
|
+
else
|
581
|
+
fail UsageError, "invalid audio format argument: #{arg}"
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
opts.on '--keep-ac3-stereo' do
|
586
|
+
@keep_ac3_stereo = true
|
587
|
+
end
|
588
|
+
|
560
589
|
opts.on '--prefer-ac3' do
|
561
|
-
|
590
|
+
Console.warn '**********'
|
591
|
+
Console.warn 'Using deprecated option: --prefer-ac3'
|
592
|
+
Console.warn "Replace with: --audio-width all=surround --audio-format all=ac3"
|
593
|
+
Console.warn '**********'
|
562
594
|
@audio_width[:main] = :surround
|
563
595
|
@audio_width[:other] = :surround
|
596
|
+
@surround_format = 'ac3'
|
597
|
+
@stereo_format = 'ac3'
|
564
598
|
end
|
565
599
|
|
566
600
|
opts.on '--ac3-encoder ARG' do |arg|
|
@@ -620,7 +654,7 @@ HERE
|
|
620
654
|
|
621
655
|
opts.on '--mixdown ARG' do |arg|
|
622
656
|
@mixdown = case arg
|
623
|
-
when '
|
657
|
+
when 'stereo', 'dpl2'
|
624
658
|
arg
|
625
659
|
else
|
626
660
|
fail UsageError, "invalid mixdown: #{arg}"
|
@@ -843,6 +877,7 @@ HERE
|
|
843
877
|
adjust_metadata(handbrake_options['output'])
|
844
878
|
|
845
879
|
unless @dry_run
|
880
|
+
puts "Completed: #{handbrake_options['output']}"
|
846
881
|
seconds = Time.now.tv_sec - seconds
|
847
882
|
hours = seconds / (60 * 60)
|
848
883
|
minutes = (seconds / 60) % 60
|
@@ -1053,6 +1088,13 @@ HERE
|
|
1053
1088
|
hb_crop
|
1054
1089
|
when :ffmpeg, :mplayer
|
1055
1090
|
ff_crop
|
1091
|
+
when :minimal
|
1092
|
+
{
|
1093
|
+
:top => [hb_crop[:top], ff_crop[:top]].min,
|
1094
|
+
:bottom => [hb_crop[:bottom], ff_crop[:bottom]].min,
|
1095
|
+
:left => [hb_crop[:left], ff_crop[:left]].min,
|
1096
|
+
:right => [hb_crop[:right], ff_crop[:right]].min
|
1097
|
+
}
|
1056
1098
|
when :none
|
1057
1099
|
{:top => 0, :bottom => 0, :left => 0, :right => 0}
|
1058
1100
|
else
|
@@ -1094,41 +1136,78 @@ HERE
|
|
1094
1136
|
end
|
1095
1137
|
|
1096
1138
|
tracks, encoders, bitrates, mixdowns, names = [], [], [], [], []
|
1139
|
+
@aac_encoder ||= HandBrake.aac_encoder
|
1140
|
+
surround_encoder = @surround_format == 'ac3' ? @ac3_encoder : @aac_encoder
|
1141
|
+
stereo_encoder = @stereo_format == 'ac3' ? @ac3_encoder : @aac_encoder
|
1097
1142
|
|
1098
1143
|
add_surround = ->(info, copy) do
|
1099
1144
|
bitrate = info[:bps].nil? ? 640 : info[:bps] / 1000
|
1100
1145
|
|
1101
|
-
if
|
1102
|
-
(
|
1103
|
-
|
1104
|
-
|
1146
|
+
if copy or
|
1147
|
+
(@surround_format == 'ac3' and
|
1148
|
+
((@ac3_encoder == 'ac3' and info[:format] == 'AC3') or
|
1149
|
+
(@ac3_encoder == 'eac3' and info[:format] =~ /^(?:E-)?AC3$/)) and
|
1150
|
+
bitrate <= @pass_ac3_bitrate) or
|
1151
|
+
(@surround_format == 'aac' and info[:format] =~ /^AAC/)
|
1105
1152
|
encoders << 'copy'
|
1106
1153
|
bitrates << ''
|
1154
|
+
mixdowns << ''
|
1107
1155
|
else
|
1108
|
-
encoders <<
|
1156
|
+
encoders << surround_encoder
|
1109
1157
|
|
1110
|
-
if
|
1111
|
-
|
1112
|
-
|
1158
|
+
if @surround_format == 'ac3'
|
1159
|
+
if (@ac3_encoder == 'ac3' and @ac3_bitrate >= 640) or
|
1160
|
+
(@ac3_encoder == 'eac3' and @ac3_bitrate == 1536)
|
1161
|
+
bitrates << ''
|
1162
|
+
else
|
1163
|
+
bitrates << @ac3_bitrate.to_s
|
1164
|
+
end
|
1165
|
+
|
1166
|
+
mixdowns << ''
|
1113
1167
|
else
|
1114
|
-
bitrates <<
|
1168
|
+
bitrates << ''
|
1169
|
+
mixdowns << '5point1'
|
1115
1170
|
end
|
1116
1171
|
end
|
1117
|
-
|
1118
|
-
mixdowns << ''
|
1119
1172
|
end
|
1120
1173
|
|
1121
1174
|
add_stereo = ->(info, copy) do
|
1122
|
-
if copy or
|
1175
|
+
if copy or
|
1176
|
+
(info[:channels] <= 2.0 and
|
1177
|
+
((@stereo_format == 'aac' and info[:format] =~ /^AAC/) or
|
1178
|
+
(((@ac3_encoder == 'ac3' and info[:format] == 'AC3') or
|
1179
|
+
(@ac3_encoder == 'eac3' and info[:format] =~ /^(?:E-)?AC3$/)) and
|
1180
|
+
(@keep_ac3_stereo or @stereo_format == 'ac3'))))
|
1123
1181
|
encoders << 'copy'
|
1182
|
+
bitrates << ''
|
1124
1183
|
mixdowns << ''
|
1125
1184
|
else
|
1126
|
-
|
1127
|
-
|
1185
|
+
encoders << stereo_encoder
|
1186
|
+
|
1187
|
+
if stereo_encoder == 'eac3'
|
1188
|
+
if @ac3_bitrate == 1536
|
1189
|
+
bitrates << ''
|
1190
|
+
else
|
1191
|
+
if (info[:channels] > 1.0)
|
1192
|
+
if @ac3_bitrate == 768
|
1193
|
+
bitrates << '384'
|
1194
|
+
else
|
1195
|
+
bitrates << '224'
|
1196
|
+
end
|
1197
|
+
else
|
1198
|
+
if @ac3_bitrate == 768
|
1199
|
+
bitrates << '192'
|
1200
|
+
else
|
1201
|
+
bitrates << '96'
|
1202
|
+
end
|
1203
|
+
end
|
1204
|
+
end
|
1205
|
+
else
|
1206
|
+
bitrates << ''
|
1207
|
+
end
|
1208
|
+
|
1128
1209
|
mixdowns << (info[:channels] > 2.0 ? @mixdown : '')
|
1129
1210
|
end
|
1130
|
-
|
1131
|
-
bitrates << ''
|
1132
1211
|
end
|
1133
1212
|
|
1134
1213
|
track_order.each do |track|
|
@@ -1138,6 +1217,7 @@ HERE
|
|
1138
1217
|
|
1139
1218
|
if @copy_audio_name.first == :all or @copy_audio_name.include? track
|
1140
1219
|
name = info.fetch(:name, '')
|
1220
|
+
name ||= ''
|
1141
1221
|
else
|
1142
1222
|
name = ''
|
1143
1223
|
end
|
@@ -1162,7 +1242,7 @@ HERE
|
|
1162
1242
|
add_stereo.call info, copy
|
1163
1243
|
end
|
1164
1244
|
when :surround
|
1165
|
-
if
|
1245
|
+
if (info[:channels] > 2.0)
|
1166
1246
|
add_surround.call info, copy
|
1167
1247
|
else
|
1168
1248
|
add_stereo.call info, copy
|
@@ -1175,7 +1255,7 @@ HERE
|
|
1175
1255
|
handbrake_options['audio'] = tracks.join(',')
|
1176
1256
|
encoders = encoders.join(',')
|
1177
1257
|
handbrake_options['aencoder'] = encoders if encoders.gsub(/,/, '') != ''
|
1178
|
-
handbrake_options['audio-fallback'] =
|
1258
|
+
handbrake_options['audio-fallback'] = surround_encoder unless @copy_audio.empty?
|
1179
1259
|
bitrates = bitrates.join(',')
|
1180
1260
|
handbrake_options['ab'] = bitrates if bitrates.gsub(/,/, '') != ''
|
1181
1261
|
mixdowns = mixdowns.join(',')
|
@@ -1336,10 +1416,26 @@ HERE
|
|
1336
1416
|
Process.kill 'INT', io.pid
|
1337
1417
|
end
|
1338
1418
|
|
1419
|
+
buffer = ''
|
1420
|
+
|
1339
1421
|
io.each_char do |char|
|
1340
|
-
|
1422
|
+
if (char.bytes[0] & 0x80) != 0
|
1423
|
+
buffer << char
|
1424
|
+
else
|
1425
|
+
if not buffer.empty?
|
1426
|
+
print buffer
|
1427
|
+
buffer = ''
|
1428
|
+
end
|
1429
|
+
|
1430
|
+
print char
|
1431
|
+
end
|
1432
|
+
|
1341
1433
|
log_file.print char unless log_file.nil?
|
1342
1434
|
end
|
1435
|
+
|
1436
|
+
if not buffer.empty?
|
1437
|
+
print buffer
|
1438
|
+
end
|
1343
1439
|
end
|
1344
1440
|
rescue SystemCallError => e
|
1345
1441
|
raise "transcoding failed: #{e}"
|
data/lib/video_transcoding.rb
CHANGED