other_video_transcoding 0.8.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +56 -1
- data/LICENSE +1 -1
- data/bin/ask-ffmpeg-log +5 -5
- data/bin/other-transcode +329 -203
- data/other_video_transcoding-0.10.0.gem +0 -0
- data/other_video_transcoding-0.8.0.gem +0 -0
- data/other_video_transcoding-0.9.0.gem +0 -0
- data/other_video_transcoding.gemspec +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a38e8e2bf7937b708b2b024767f266beee682bc92f7377f4e8062dee7babd09
|
4
|
+
data.tar.gz: e3fd2a8a57f2fad558b9a30fcb2fae633b8b7120d9e802f3d08a65de1053b1ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8dd9d8cb3788ec1d17379d167e75dbe506dca39b64a7e18f162021387d9329e0bb874b6a9bf298d866d27e5a47e151e43881708c3efc22730ee0fbc5004addc
|
7
|
+
data.tar.gz: db27d572846d979263b8c5b7286f011849b7b8c6669e18a740bed29db3b1fbf5c0d924a420e2f531f26f4ae97d85f484161adc5a5b006f5b4914415d31cc512c
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,61 @@
|
|
2
2
|
|
3
3
|
This single document contains all of the notes created for each [release](https://github.com/donmelton/other_video_transcoding/releases).
|
4
4
|
|
5
|
+
## [0.11.0](https://github.com/donmelton/other_video_transcoding/releases/tag/0.11.0)
|
6
|
+
|
7
|
+
Saturday, July 16, 2022
|
8
|
+
|
9
|
+
* Modify `other-transcode` to copy 10-bit high-dynamic-range (HDR10) metadata, extracting content light level and mastering display metadata from a HDR10 video frame input and tagging a 10-bit video stream output in Matroska (MKV) format with that information. This will also copy static HDR10 metadata from Dolby Vision and HDR10+ video streams but it will _not_ copy additional dynamic metadata from those formats.
|
10
|
+
* Add a `--overlay-params` option to `other-transcode` to override the `overlay` filter configuration applied when burning subtitles. This is useful when cropping to move a subtitle within the output boundary.
|
11
|
+
* Add a `--fdk-vbr` option to `other-transcode` to set the numeric variable bitrate (VBR) mode for the Fraunhofer `libfdk_aac` audio encoder, disabling constant bitrate (CBR) ratecontrol. VBR mode `1` selects the lowest quality and `5` the highest. Please note that the `libfdk_aac` encoder is not normally included with `ffmpeg` due to licensing restrictions and the `--fdk-vbr` option has no effect if that encoder is not available. Via [ #127](https://github.com/donmelton/other_video_transcoding/issues/127).
|
12
|
+
|
13
|
+
## [0.10.0](https://github.com/donmelton/other_video_transcoding/releases/tag/0.10.0)
|
14
|
+
|
15
|
+
Thursday, January 27, 2022
|
16
|
+
|
17
|
+
* Add a `--nvenc-gpu-only` option to `other-transcode` to keep data on the GPU for greater speed, if possible. Deinterlacing is allowed but cropping, scaling, detelecining, setting frame rates and burning subtitles will prevent this from working and may actually slow things down. Performance can also be affected negatively depending on PC configuration. Please note that the `--nvenc-gpu-only` option requires `ffmpeg` version 5.0 or later.
|
18
|
+
* Add a `--x264-cbr` option to `other-transcode` to simplify access to constant bitrate (CBR) ratecontrol. Despite the name, actual output bitrates from the `x264` encoder are variable and below what might be expected. So, default video bitrate targets are raised to accommodate this.
|
19
|
+
* Enable proper crop detection in `other-transcode` for 4K UHD Blu-ray rips and other media with a 10-bit color depth. This was done by changing the `limit` value passed to the `cropdetect` filter from an integer constant to a floating point equation. Via [ #52](https://github.com/donmelton/other_video_transcoding/issues/52).
|
20
|
+
* Modify `other-transcode` to add a workaround for the mapping of BT.470 M and BT.470 BG color transfer characteristics from values returned from `ffprobe` to values actually used by `ffmpeg`. Via [ #112](https://github.com/donmelton/other_video_transcoding/issues/112).
|
21
|
+
* Modify `other-transcode` to allow parentheses within the argument to the `--yadif-params`, `--x264-params` and `--x265-params` options. Via [ #119](https://github.com/donmelton/other_video_transcoding/issues/119).
|
22
|
+
* Modify `ask-ffmpeg-log` to fix detection of frame counts less than five digits within `.log` files from very short duration videos. Via [ #126](https://github.com/donmelton/other_video_transcoding/issues/126).
|
23
|
+
* Modify `ask-ffmpeg-log` to fix detection of statistics within `.log` files not generated by `other-transcode`.
|
24
|
+
* Remove the deprecated `--nvenc-rc-mode` and `--aac-stereo` options from `other-transcode`.
|
25
|
+
* Update all copyright notices to the year 2022.
|
26
|
+
|
27
|
+
## [0.9.0](https://github.com/donmelton/other_video_transcoding/releases/tag/0.9.0)
|
28
|
+
|
29
|
+
Saturday, June 5, 2021
|
30
|
+
|
31
|
+
Nvidia encoders:
|
32
|
+
|
33
|
+
* Add a `--nvenc-recommended` option to `other-transcode` which easily and optimally configures the Nvidia H.264 and HEVC video encoders, equivalent to using:
|
34
|
+
* `--nvenc-spatial-aq --nvenc-lookahead 32 --nvenc-bframe-refs middle`
|
35
|
+
* The `--nvenc-bframe-refs` option is also new and using `middle` as its argument increases compression efficiency. However, it's not supported on all Nvidia hardware. Which means, neither is the `--nvenc-recommended` option.
|
36
|
+
* So, using `--nvenc-recommended` for H.264 encoding requires at minimum a fourth generation Pascal-based GPU like the GTX 1080. And using it for HEVC encoding requires at minimum a more recent sixth generation Turing-based model like the GTX 1660 or RTX 2070.
|
37
|
+
* Add a `--nvenc-cq` option to `other-transcode` to allow constant quality (CQ) ratecontrol. This option ignores the target video bitrate and takes a single numerical argument between `1` and `51` with lower values indicating higher quality. However, only values between `25` and `30` are really practical for 1080p content. It's recommended to start with `--nvenc-cq 28` and adjust as needed. Fractional values are also supported.
|
38
|
+
* While CQ ratecontrol can adapt better to extremely dynamic content compared to the default average bitrate (ABR) ratecontrol system, the output bitrates produced by CQ can vary significantly and it can be slightly more prone to color banding with the H.264 encoder. So, for now, consider the `--nvenc-cq` option an experimental feature.
|
39
|
+
* Deprecate the `--nvenc-rc-mode` option in `other-transcode` because maximum rate and buffer size values are already specified so an explicit ratecontrol mode is not required.
|
40
|
+
|
41
|
+
Audio:
|
42
|
+
|
43
|
+
* Modify `other-transcode` to no longer explicitly set audio bitrates and instead rely on the defaults from the audio encoders included with `ffmpeg`. This is being done to both simplify the code in `other-transcode` and to leverage the judgement of the audio encoder developers, which means:
|
44
|
+
* AC-3 surround audio is lowered from 640 Kbps to 448 Kbps.
|
45
|
+
* Dolby Digital Plus (Enhanced AC-3) surround audio is raised from 384 Kbps to 448 Kbps.
|
46
|
+
* AAC stereo audio is lowered from 256 Kbps to 128 Kbps when using the native `ffmpeg` or Apple AudioToolbox encoders.
|
47
|
+
* If desired, use the `--surround-bitrate` and `--stereo-bitrate` options to restore the previous default audio bitrates.
|
48
|
+
* Add a `--aac-only` option to `other-transcode` to force transcoding of all audio into AAC format, copying only tracks which are already in that format. Surround tracks are converted to a 5.1-channel AAC format at 341 Kbps when using the native `ffmpeg` encoder. This channel layout is compatible with most playback devices. Allowing more than 5.1 channels would significantly reduce playback compatibility.
|
49
|
+
* Deprecate the `--aac-stereo` option in `other-transcode` and replace with a new `--eac3-aac` option, which uses Dolby Digital Plus format only for surround audio with AAC format for stereo audio. Since the `--aac-stereo` option only made sense when used in combination with the `--eac3` option, this makes `--eac3-aac` more convenient.
|
50
|
+
|
51
|
+
Other changes:
|
52
|
+
|
53
|
+
* Change the default ratecontrol maximum rate and buffer size values in `other-transcode`, as well as how those values increased when the target video bitrate is increased. The default values now also differ depending on whether the output video is in H.264 or HEVC format.
|
54
|
+
* Modify the `--rc-maxrate` and `--rc-bufsize` options in `other-transcode` to allow specific bitrates as arguments and not just multiples of the video bitrate target. These options are most useful for lowering maximum rate and buffer size values. To raise those values, increase the target video bitrate instead.
|
55
|
+
* Change the pixel format and force a Main 10 video profile in `other-transcode` when using the Apple VideoToolbox encoder to create output with a 10-bit color depth. Correct generation of 10-bit output requires macOS Big Sur or later.
|
56
|
+
* Modify `other-transcode` to copy the three basic color properties (primaries, transer and space) from the input to the output when those properties are availabe. Otherwise use some sensible defaults.
|
57
|
+
* Modify `other-transcode` to force a H.264 level when using `--x264` with slower presets. This ensures that the `x264` encoder continues to generate a video stream compatible with most playback devices when those presets are used.
|
58
|
+
* Modify `other-transcode` to remove the hack which avoids using the Matroksa muxer `-disposition` option in old versions of `ffmpeg`. This means version 4.3 or later of `ffmpeg` is now required to run `other-transcode`.
|
59
|
+
|
5
60
|
## [0.8.0](https://github.com/donmelton/other_video_transcoding/releases/tag/0.8.0)
|
6
61
|
|
7
62
|
Saturday, February 13, 2021
|
@@ -59,7 +114,7 @@ Tuesday, December 22, 2020
|
|
59
114
|
* Lower the default target bitrates for 8-bit HEVC video in `other-transcode` to match the defaults for 10-bit HEVC video. This means, for example, the default target for HEVC at a 1080p resolution will be 6000 Kbps no matter the output bit depth.
|
60
115
|
* Modify `other-transcode` to set the video buffer size equal to the maximum video bitrate when using an Nvidia encoder, essentially adding `--rc-bufsize 3` to the command line. Previously the buffer size was never explicitly set so `ffmpeg` would use a default value of twice the target bitrate. Since the maximum bitrate is normally three times the target bitrate this meant the buffer size was actually smaller than the maximum. While this didn't cause any known problems, Nvidia recommends a larger buffer size to improve quality. However, using `--rc-bufsize 0` will restore the old behavior and the default value from `ffmpeg`.
|
61
116
|
* Ignore the `--nvenc-lookahead` option in `other-transcode` when the argument is `0` since such a value won't change the behavior of an Nvidia encoder anyway.
|
62
|
-
* Add a `--limit-ac3-surround` option to `other-transcode` which prevents surround audio in AC-3 or Dolby Digital Plus (Enhanced AC-3) format from being copied instead of transcoded when the orginal bitrate is above the transcoding bitrate. This allows setting a lower target with the `--surround-bitrate` option in order to force higher-bitrate tracks to be transcoded instead of copied.
|
117
|
+
* Add a `--limit-ac3-surround` option to `other-transcode` which prevents surround audio in AC-3 or Dolby Digital Plus (Enhanced AC-3) format from being copied instead of transcoded when the orginal bitrate is above the transcoding bitrate. This allows setting a lower target with the `--surround-bitrate` option in order to force higher-bitrate tracks to be transcoded instead of copied.
|
63
118
|
* Reduce the minimum bitrates for Dolby Digital Plus audio in `other-transcode` from 256, 128 and 64 Kbps for surround, stereo and mono layouts to 192, 96 and 48 Kbps. The default bitrates for Dolby Digital Plus audio remain the same and this change does not affect audio output in AC-3 or AAC formats.
|
64
119
|
|
65
120
|
## [0.5.0](https://github.com/donmelton/other_video_transcoding/releases/tag/0.5.0)
|
data/LICENSE
CHANGED
data/bin/ask-ffmpeg-log
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# ask-ffmpeg-log
|
4
4
|
#
|
5
|
-
# Copyright (c) 2019-
|
5
|
+
# Copyright (c) 2019-2022 Don Melton
|
6
6
|
#
|
7
7
|
|
8
8
|
require 'abbrev'
|
@@ -16,8 +16,8 @@ module Transcoding
|
|
16
16
|
class Command
|
17
17
|
def about
|
18
18
|
<<-HERE
|
19
|
-
ask-ffmpeg-log 0.
|
20
|
-
Copyright (c) 2019-
|
19
|
+
ask-ffmpeg-log 0.11.0
|
20
|
+
Copyright (c) 2019-2022 Don Melton
|
21
21
|
HERE
|
22
22
|
end
|
23
23
|
|
@@ -138,9 +138,9 @@ Options:
|
|
138
138
|
fail "not a ffmpeg-generated `.log` file: #{log}"
|
139
139
|
end
|
140
140
|
|
141
|
-
stats = content.match(/^frame=.*[.0-9]+x */m).to_s.lines.last.to_s.rstrip
|
141
|
+
stats = content.match(/^frame=.* speed= *[.0-9]+x */m).to_s.lines.last.to_s.rstrip
|
142
142
|
|
143
|
-
if stats =~ /frame=([0-9]+) fps=( *[.0-9]+)/
|
143
|
+
if stats =~ /frame=( *[0-9]+) fps=( *[.0-9]+)/
|
144
144
|
frames = $1
|
145
145
|
fps = $2
|
146
146
|
seconds = frames.to_f / fps.lstrip.to_f
|
data/bin/other-transcode
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# other-transcode
|
4
4
|
#
|
5
|
-
# Copyright (c) 2019-
|
5
|
+
# Copyright (c) 2019-2022 Don Melton
|
6
6
|
#
|
7
7
|
|
8
8
|
require 'English'
|
@@ -18,8 +18,8 @@ module Transcoding
|
|
18
18
|
class Command
|
19
19
|
def about
|
20
20
|
<<-HERE
|
21
|
-
other-transcode 0.
|
22
|
-
Copyright (c) 2019-
|
21
|
+
other-transcode 0.11.0
|
22
|
+
Copyright (c) 2019-2022 Don Melton
|
23
23
|
HERE
|
24
24
|
end
|
25
25
|
|
@@ -137,17 +137,25 @@ Video options:
|
|
137
137
|
|
138
138
|
def usage10
|
139
139
|
<<-HERE
|
140
|
+
--overlay-params KEY=VALUE[:KEY=VALUE]...
|
141
|
+
override subtitle overlay filter configuration
|
140
142
|
--yadif-params KEY=VALUE[:KEY=VALUE]...
|
141
143
|
override yadif deinterlace filter configuration
|
142
|
-
--rc-maxrate FACTOR, --rc-bufsize FACTOR
|
144
|
+
--rc-maxrate FACTOR, --rc-bufsize FACTOR|BITRATE
|
143
145
|
set ratecontrol maximum rate and/or buffer size
|
144
|
-
as multiple of video bitrate target
|
146
|
+
as multiple of video bitrate target or specific bitrate
|
145
147
|
--copy-video disable transcoding and copy original video track
|
146
148
|
|
147
149
|
Apple Video Toolbox encoder options:
|
148
150
|
--vt-allow-sw allow software encoding
|
149
151
|
|
150
152
|
Nvidia video encoder options:
|
153
|
+
--nvenc-recommended
|
154
|
+
apply optimal quality settings, equivalent to using:
|
155
|
+
`--nvenc-spatial-aq`
|
156
|
+
`--nvenc-lookahead 32`
|
157
|
+
`--nvenc-bframe-refs middle`
|
158
|
+
(not supported on all Nvidia hardware)
|
151
159
|
--nvenc-spatial-aq
|
152
160
|
enable spatial adaptive quantization (AQ)
|
153
161
|
--nvenc-temporal-aq
|
@@ -160,8 +168,12 @@ Nvidia video encoder options:
|
|
160
168
|
set number of reference frames
|
161
169
|
--nvenc-bframes FRAMES
|
162
170
|
set maximum number of B-frames
|
163
|
-
--nvenc-
|
164
|
-
set
|
171
|
+
--nvenc-bframe-refs each|middle
|
172
|
+
set mode for using B-frames as reference frames
|
173
|
+
--nvenc-cq QUALITY
|
174
|
+
use constant quality (CQ) ratecontrol at target quality
|
175
|
+
--nvenc-gpu-only
|
176
|
+
keep data on GPU for greater speed, if possible
|
165
177
|
|
166
178
|
Intel Quick Sync video encoder options:
|
167
179
|
--qsv-refs FRAMES
|
@@ -185,6 +197,9 @@ Video Acceleration API encoder options:
|
|
185
197
|
set numeric level of compression
|
186
198
|
|
187
199
|
x264 software video encoder options:
|
200
|
+
--x264-cbr use constant bitrate (CBR) ratecontrol
|
201
|
+
with variable bitrate output
|
202
|
+
(raises default video bitrate targets)
|
188
203
|
--x264-avbr use average variable bitrate (AVBR) ratecontrol
|
189
204
|
--x264-mbtree use macroblock-tree ratecontrol (disables AVBR if in use)
|
190
205
|
--x264-quick increase encoding speed by 70-80%
|
@@ -241,35 +256,39 @@ Audio options:
|
|
241
256
|
def usage15
|
242
257
|
<<-HERE
|
243
258
|
--surround-bitrate BITRATE
|
244
|
-
set surround audio bitrate (default:
|
259
|
+
set surround audio bitrate (default: 448)
|
245
260
|
--stereo-bitrate BITRATE
|
246
|
-
set stereo audio bitrate (default:
|
261
|
+
set stereo audio bitrate (default: 128)
|
247
262
|
HERE
|
248
263
|
end
|
249
264
|
|
250
265
|
def usage16
|
251
266
|
<<-HERE
|
252
267
|
--mono-bitrate BITRATE
|
253
|
-
set mono audio bitrate (default: 50% of stereo bitrate)
|
268
|
+
set mono audio bitrate (default: ~50% of stereo bitrate)
|
254
269
|
HERE
|
255
270
|
end
|
256
271
|
|
257
272
|
def usage17
|
258
273
|
<<-HERE
|
259
274
|
--eac3 use Dolby Digital Plus (E-AC-3) format for all audio
|
260
|
-
(default bitrates:
|
275
|
+
(default bitrates: 448 for surround, 192 for stereo)
|
261
276
|
HERE
|
262
277
|
end
|
263
278
|
|
264
279
|
def usage18
|
265
280
|
<<-HERE
|
266
|
-
--aac
|
281
|
+
--eac3-aac use Dolby Digital Plus format only for surround audio
|
282
|
+
with AAC format for stereo audio
|
283
|
+
--aac-only use AAC format for all audio,
|
284
|
+
disabling passthrough of audio in other formats
|
285
|
+
(default bitrates: 341 for surround, 128 for stereo)
|
267
286
|
--limit-ac3-surround
|
268
287
|
don't copy surround audio in AC-3 format
|
269
|
-
when orginal bitrate is above
|
288
|
+
when orginal bitrate is above passthrough bitrate
|
270
289
|
--keep-ac3-stereo
|
271
290
|
copy stereo and mono audio in AC-3 format
|
272
|
-
even when orginal bitrate is above
|
291
|
+
even when orginal bitrate is above passthrough bitrate
|
273
292
|
--pass-dts enable passthrough of audio in DTS and DTS-ES formats
|
274
293
|
HERE
|
275
294
|
end
|
@@ -277,6 +296,14 @@ Audio options:
|
|
277
296
|
def usage19
|
278
297
|
<<-HERE
|
279
298
|
|
299
|
+
Fraunhofer FDK AAC audio encoder options:
|
300
|
+
--fdk-vbr MODE set numeric variable bitrate (VBR) mode, from 1 to 5
|
301
|
+
HERE
|
302
|
+
end
|
303
|
+
|
304
|
+
def usage20
|
305
|
+
<<-HERE
|
306
|
+
|
280
307
|
Subtitle options:
|
281
308
|
--add-subtitle TRACK[=forced]|auto|all|LANGUAGE|STRING
|
282
309
|
add single subtitle track by number
|
@@ -311,7 +338,6 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
311
338
|
@detect = false
|
312
339
|
@preview = false
|
313
340
|
@format = :mkv
|
314
|
-
@mkv_options = []
|
315
341
|
@copy_track_names = false
|
316
342
|
@max_muxing_queue_size = nil
|
317
343
|
@dry_run = false
|
@@ -335,6 +361,7 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
335
361
|
@rate = nil
|
336
362
|
@detelecine = false
|
337
363
|
@enable_filters = true
|
364
|
+
@overlay_params = nil
|
338
365
|
@yadif_params = nil
|
339
366
|
@maxrate = nil
|
340
367
|
@bufsize = nil
|
@@ -345,7 +372,9 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
345
372
|
@nvenc_multipass = nil
|
346
373
|
@nvenc_refs = nil
|
347
374
|
@nvenc_bframes = nil
|
348
|
-
@
|
375
|
+
@nvenc_bframe_refs = nil
|
376
|
+
@nvenc_cq = nil
|
377
|
+
@nvenc_gpu_only = false
|
349
378
|
@qsv_refs = nil
|
350
379
|
@qsv_bframes = nil
|
351
380
|
@amf_quality = nil
|
@@ -370,9 +399,11 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
370
399
|
@mono_bitrate = nil
|
371
400
|
@surround_encoder = 'ac3'
|
372
401
|
@stereo_encoder = nil
|
402
|
+
@aac_fallback_encoder = 'aac'
|
373
403
|
@keep_ac3_surround = true
|
374
404
|
@keep_ac3_stereo = false
|
375
405
|
@pass_dts = false
|
406
|
+
@fdk_vbr_mode = nil
|
376
407
|
@subtitle_selections = []
|
377
408
|
@auto_add_subtitle = false
|
378
409
|
@burn_subtitle_track = 0
|
@@ -389,14 +420,14 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
389
420
|
puts usage1 + usage2 + usage3 + usage4 + usage5 + usage6 +
|
390
421
|
usage7 + usage8 + usage9 + usage10 + usage11 + usage12 +
|
391
422
|
usage13 + usage14 + usage15 + usage16 + usage17 +
|
392
|
-
usage18 + usage19
|
423
|
+
usage18 + usage19 + usage20
|
393
424
|
when 'more'
|
394
425
|
puts usage1 + usage2 + usage3 + usage4 + usage6 + usage7 +
|
395
426
|
usage8 + usage9 + usage11 + usage13 + usage15 + usage16 +
|
396
|
-
usage17 + usage18 +
|
427
|
+
usage17 + usage18 + usage20
|
397
428
|
else
|
398
429
|
puts usage1 + usage3 + usage6 + usage8 + usage11 + usage13 +
|
399
|
-
usage15 + usage17 +
|
430
|
+
usage15 + usage17 + usage20
|
400
431
|
end
|
401
432
|
|
402
433
|
exit
|
@@ -566,6 +597,7 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
566
597
|
@target = [arg.to_i, 1].max
|
567
598
|
end
|
568
599
|
|
600
|
+
@nvenc_cq = nil
|
569
601
|
@encoder = nil if @encoder == 'copy'
|
570
602
|
end
|
571
603
|
|
@@ -636,9 +668,17 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
636
668
|
@enable_filters = false
|
637
669
|
end
|
638
670
|
|
671
|
+
opts.on '--overlay-params ARG' do |arg|
|
672
|
+
arg.split ':' do |param|
|
673
|
+
fail UsageError, "invalid argument: #{arg}" unless param =~ /^[\w\-]+=[\w\-\.,\(\)]+$/
|
674
|
+
end
|
675
|
+
|
676
|
+
@overlay_params = arg
|
677
|
+
end
|
678
|
+
|
639
679
|
opts.on '--yadif-params ARG' do |arg|
|
640
680
|
arg.split ':' do |param|
|
641
|
-
fail UsageError, "invalid argument: #{arg}" unless param =~ /^[\w\-]+=[\w
|
681
|
+
fail UsageError, "invalid argument: #{arg}" unless param =~ /^[\w\-]+=[\w\-\.,\(\)]+$/
|
642
682
|
end
|
643
683
|
|
644
684
|
@yadif_params = arg
|
@@ -672,6 +712,13 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
672
712
|
@vt_allow_sw = true
|
673
713
|
end
|
674
714
|
|
715
|
+
opts.on '--nvenc-recommended' do
|
716
|
+
@encoder = @hevc ? 'hevc_nvenc' : 'h264_nvenc'
|
717
|
+
@nvenc_spatial_aq = true
|
718
|
+
@nvenc_lookahead = 32
|
719
|
+
@nvenc_bframe_refs = 'middle'
|
720
|
+
end
|
721
|
+
|
675
722
|
opts.on '--nvenc-spatial-aq' do
|
676
723
|
@encoder = @hevc ? 'hevc_nvenc' : 'h264_nvenc'
|
677
724
|
@nvenc_spatial_aq = true
|
@@ -713,17 +760,29 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
713
760
|
@nvenc_bframes = [[arg, 0].max, 4].min
|
714
761
|
end
|
715
762
|
|
716
|
-
opts.on '--nvenc-
|
763
|
+
opts.on '--nvenc-bframe-refs ARG' do |arg|
|
717
764
|
@encoder = @hevc ? 'hevc_nvenc' : 'h264_nvenc'
|
718
765
|
|
719
|
-
@
|
720
|
-
when '
|
766
|
+
@nvenc_bframe_refs = case arg
|
767
|
+
when 'each', 'middle'
|
721
768
|
arg
|
722
769
|
else
|
723
|
-
fail UsageError, "invalid
|
770
|
+
fail UsageError, "invalid B-frames as references argument: #{arg}"
|
724
771
|
end
|
725
772
|
end
|
726
773
|
|
774
|
+
opts.on '--nvenc-cq ARG', Float do |arg|
|
775
|
+
@encoder = @hevc ? 'hevc_nvenc' : 'h264_nvenc'
|
776
|
+
@nvenc_cq = [[arg, 1].max, 51].min.to_s.sub(/\.0$/, '')
|
777
|
+
end
|
778
|
+
|
779
|
+
opts.on '--nvenc-gpu-only' do
|
780
|
+
@encoder = @hevc ? 'hevc_nvenc' : 'h264_nvenc'
|
781
|
+
@decode_scope = :all
|
782
|
+
@decode_method = 'cuda'
|
783
|
+
@nvenc_gpu_only = true
|
784
|
+
end
|
785
|
+
|
727
786
|
opts.on '--qsv-refs ARG', Integer do |arg|
|
728
787
|
@encoder = @hevc ? 'hevc_qsv' : 'h264_qsv'
|
729
788
|
@qsv_refs = [arg, 0].max
|
@@ -770,6 +829,16 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
770
829
|
@vaapi_compression = [arg, 0].max
|
771
830
|
end
|
772
831
|
|
832
|
+
opts.on '--x264-cbr' do
|
833
|
+
@encoder = 'libx264'
|
834
|
+
@hevc = false
|
835
|
+
@x264_mbtree = true
|
836
|
+
@x264_avbr = false
|
837
|
+
@x264_params = nil
|
838
|
+
@maxrate = 1.0
|
839
|
+
@bufsize = nil
|
840
|
+
end
|
841
|
+
|
773
842
|
opts.on '--x264-avbr' do
|
774
843
|
@encoder = 'libx264'
|
775
844
|
@hevc = false
|
@@ -796,7 +865,7 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
796
865
|
|
797
866
|
opts.on '--x264-params ARG' do |arg|
|
798
867
|
arg.split ':' do |param|
|
799
|
-
fail UsageError, "invalid argument: #{arg}" unless param =~ /^[\w\-]+=[\w
|
868
|
+
fail UsageError, "invalid argument: #{arg}" unless param =~ /^[\w\-]+=[\w\-\.,\(\)]+$/
|
800
869
|
end
|
801
870
|
|
802
871
|
@encoder = 'libx264'
|
@@ -809,7 +878,7 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
809
878
|
|
810
879
|
opts.on '--x265-params ARG' do |arg|
|
811
880
|
arg.split ':' do |param|
|
812
|
-
fail UsageError, "invalid argument: #{arg}" unless param =~ /^[\w\-]+=[\w
|
881
|
+
fail UsageError, "invalid argument: #{arg}" unless param =~ /^[\w\-]+=[\w\-\.,\(\)]+$/
|
813
882
|
end
|
814
883
|
|
815
884
|
@encoder = 'libx265'
|
@@ -860,6 +929,7 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
860
929
|
|
861
930
|
opts.on '--stereo-bitrate ARG', Integer do |arg|
|
862
931
|
@stereo_bitrate = arg
|
932
|
+
@mono_bitrate ||= @stereo_bitrate / 2
|
863
933
|
end
|
864
934
|
|
865
935
|
opts.on '--mono-bitrate ARG', Integer do |arg|
|
@@ -871,20 +941,32 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
871
941
|
@stereo_encoder = 'eac3'
|
872
942
|
end
|
873
943
|
|
874
|
-
opts.on '--aac
|
944
|
+
opts.on '--eac3-aac' do
|
945
|
+
@surround_encoder = 'eac3'
|
875
946
|
@stereo_encoder = nil
|
876
947
|
end
|
877
948
|
|
949
|
+
opts.on '--aac-only' do
|
950
|
+
@surround_encoder = nil
|
951
|
+
@stereo_encoder = nil
|
952
|
+
end
|
953
|
+
|
878
954
|
opts.on '--limit-ac3-surround' do
|
879
955
|
@keep_ac3_surround = false
|
880
956
|
end
|
881
957
|
|
882
958
|
opts.on '--keep-ac3-stereo' do
|
883
959
|
@keep_ac3_stereo = true
|
960
|
+
@surround_encoder ||= 'ac3'
|
884
961
|
end
|
885
962
|
|
886
963
|
opts.on '--pass-dts' do
|
887
964
|
@pass_dts = true
|
965
|
+
@surround_encoder ||= 'ac3'
|
966
|
+
end
|
967
|
+
|
968
|
+
opts.on '--fdk-vbr ARG', Integer do |arg|
|
969
|
+
@fdk_vbr_mode = [[arg, 1].max, 5].min.to_s
|
888
970
|
end
|
889
971
|
|
890
972
|
opts.on '--add-subtitle ARG' do |arg|
|
@@ -938,32 +1020,6 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
938
1020
|
@audio_selections.uniq!
|
939
1021
|
@subtitle_selections.uniq!
|
940
1022
|
|
941
|
-
if @surround_encoder == 'eac3'
|
942
|
-
@surround_bitrate ||= 384
|
943
|
-
@surround_bitrate = [[@surround_bitrate, 192].max, 768].min
|
944
|
-
else
|
945
|
-
@surround_bitrate ||= 640
|
946
|
-
@surround_bitrate = [[@surround_bitrate, 256].max, 640].min
|
947
|
-
end
|
948
|
-
|
949
|
-
if @stereo_encoder == 'eac3'
|
950
|
-
@stereo_bitrate ||= 192
|
951
|
-
@stereo_bitrate = [[@stereo_bitrate, 96].max, 768].min
|
952
|
-
else
|
953
|
-
@stereo_bitrate ||= 256
|
954
|
-
@stereo_bitrate = [[@stereo_bitrate, 128].max, 320].min
|
955
|
-
end
|
956
|
-
|
957
|
-
if @mono_bitrate.nil?
|
958
|
-
@mono_bitrate = @stereo_bitrate / 2
|
959
|
-
else
|
960
|
-
if @stereo_encoder == 'eac3'
|
961
|
-
@mono_bitrate = [[@mono_bitrate, 48].max, 768].min
|
962
|
-
else
|
963
|
-
@mono_bitrate = [[@mono_bitrate, 64].max, 256].min
|
964
|
-
end
|
965
|
-
end
|
966
|
-
|
967
1023
|
[
|
968
1024
|
['ffprobe', '-loglevel', 'quiet', '-version'],
|
969
1025
|
['ffmpeg', '-loglevel', 'quiet', '-version'],
|
@@ -1002,24 +1058,32 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1002
1058
|
end
|
1003
1059
|
end
|
1004
1060
|
|
1061
|
+
@nvenc_cq = nil unless @encoder =~ /nvenc$/
|
1005
1062
|
@ten_bit = (@hevc and @encoder =~ /(nvenc|qsv|x265)$/ ? true : false) if @ten_bit.nil?
|
1006
|
-
|
1007
|
-
@
|
1008
|
-
|
1009
|
-
|
1063
|
+
|
1064
|
+
if @encoder == 'libx264' and @x264_mbtree and @maxrate == 1.0
|
1065
|
+
@target_2160p ||= 15000
|
1066
|
+
@target_1080p ||= 7500
|
1067
|
+
@target_720p ||= 4500
|
1068
|
+
@target_480p ||= 2250
|
1069
|
+
else
|
1070
|
+
@target_2160p ||= @hevc ? 8000 : 12000
|
1071
|
+
@target_1080p ||= @hevc ? 4000 : 6000
|
1072
|
+
@target_720p ||= @hevc ? 2000 : 3000
|
1073
|
+
@target_480p ||= @hevc ? 1000 : 1500
|
1074
|
+
end
|
1075
|
+
|
1010
1076
|
@decode_method ||= @encoder =~ /nvenc$/ ? 'cuda' : 'auto'
|
1011
1077
|
|
1012
1078
|
if @stereo_encoder.nil?
|
1013
1079
|
if encoders =~ /aac_at/ or encoders =~ /libfdk_aac/
|
1014
1080
|
@stereo_encoder = $MATCH
|
1081
|
+
@aac_fallback_encoder = 'libfdk_aac' if encoders =~ /libfdk_aac/
|
1015
1082
|
else
|
1016
1083
|
@stereo_encoder = 'aac'
|
1017
1084
|
end
|
1018
|
-
end
|
1019
1085
|
|
1020
|
-
|
1021
|
-
capabilities = get_muxer_capabilities
|
1022
|
-
@mkv_options = ['-default_mode', 'passthrough'] if capabilities =~ /passthrough/
|
1086
|
+
@surround_encoder ||= @stereo_encoder
|
1023
1087
|
end
|
1024
1088
|
end
|
1025
1089
|
|
@@ -1069,17 +1133,17 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1069
1133
|
IO.popen([
|
1070
1134
|
'ffmpeg',
|
1071
1135
|
'-loglevel', 'quiet',
|
1072
|
-
'-nostdin'
|
1073
|
-
|
1136
|
+
'-nostdin',
|
1137
|
+
*(encoder =~ /vaapi$/ ? ['-vaapi_device', '/dev/dri/renderD128'] : []),
|
1074
1138
|
'-i', path,
|
1075
|
-
'-frames:v', '1'
|
1076
|
-
|
1139
|
+
'-frames:v', '1',
|
1140
|
+
*(encoder =~ /vaapi$/ ? ['-filter:v', 'format=nv12,hwupload'] : []),
|
1077
1141
|
'-c:v', encoder,
|
1078
|
-
'-b:v', '1000k'
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1142
|
+
'-b:v', '1000k',
|
1143
|
+
*(encoder =~ /nvenc$/ ? ['-rc:v', 'vbr'] : []),
|
1144
|
+
*(encoder == 'h264_qsv' ? ['-look_ahead:v', '1'] : []),
|
1145
|
+
*(encoder == 'hevc_qsv' ? ['-load_plugin:v', 'hevc_hw'] : []),
|
1146
|
+
*(encoder =~ /amf$/ ? ['-rc:v', 'vbr_latency'] : []),
|
1083
1147
|
'-an',
|
1084
1148
|
'-sn',
|
1085
1149
|
'-ignore_unknown',
|
@@ -1097,30 +1161,6 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1097
1161
|
$CHILD_STATUS.exitstatus == 0
|
1098
1162
|
end
|
1099
1163
|
|
1100
|
-
def get_muxer_capabilities
|
1101
|
-
Kernel.warn 'Getting muxer capabilities...'
|
1102
|
-
output = ''
|
1103
|
-
|
1104
|
-
begin
|
1105
|
-
IO.popen([
|
1106
|
-
'ffmpeg',
|
1107
|
-
'-loglevel', 'quiet',
|
1108
|
-
'-h', 'muxer=matroska'
|
1109
|
-
], :err=>[:child, :out]) do |io|
|
1110
|
-
io.each do |line|
|
1111
|
-
Kernel.warn line if @debug
|
1112
|
-
output += line
|
1113
|
-
end
|
1114
|
-
end
|
1115
|
-
rescue SystemCallError => e
|
1116
|
-
raise "getting muxer capabilities failed: #{e}"
|
1117
|
-
end
|
1118
|
-
|
1119
|
-
fail 'getting muxer capabilities failed' unless $CHILD_STATUS.exitstatus == 0
|
1120
|
-
|
1121
|
-
output
|
1122
|
-
end
|
1123
|
-
|
1124
1164
|
def process_input(path)
|
1125
1165
|
seconds = Time.now.tv_sec
|
1126
1166
|
|
@@ -1182,16 +1222,16 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1182
1222
|
ffmpeg_command = [
|
1183
1223
|
'ffmpeg',
|
1184
1224
|
'-loglevel', (@debug ? 'verbose' : 'error'),
|
1185
|
-
'-stats'
|
1186
|
-
|
1187
|
-
|
1188
|
-
'-i', path
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
'-metadata:g', 'title='
|
1194
|
-
|
1225
|
+
'-stats',
|
1226
|
+
*time_options,
|
1227
|
+
*decode_options,
|
1228
|
+
'-i', path,
|
1229
|
+
*(@max_muxing_queue_size.nil? ? [] : ['-max_muxing_queue_size', @max_muxing_queue_size.to_s]),
|
1230
|
+
*encode_options,
|
1231
|
+
*get_audio_options(media_info),
|
1232
|
+
*get_subtitle_options(media_info, burn_subtitle),
|
1233
|
+
'-metadata:g', 'title=',
|
1234
|
+
*(@format == :mkv ? ['-default_mode', 'passthrough'] : ['-movflags', 'disable_chpl']),
|
1195
1235
|
output_path
|
1196
1236
|
]
|
1197
1237
|
|
@@ -1242,6 +1282,11 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1242
1282
|
Kernel.warn 'Done.'
|
1243
1283
|
else
|
1244
1284
|
add_track_statistics_tags output_path
|
1285
|
+
ten_bit = (@ten_bit ? (@eight_bit_vc1 ? (video['codec_name'] != 'vc1') : true) : false)
|
1286
|
+
|
1287
|
+
if (video.fetch('pix_fmt', 'yuv420p') == 'yuv420p10le') and ten_bit
|
1288
|
+
add_hdr_info path, output_path
|
1289
|
+
end
|
1245
1290
|
end
|
1246
1291
|
|
1247
1292
|
Kernel.warn "\nElapsed time: #{seconds_to_time(Time.now.tv_sec - seconds)}\n\n"
|
@@ -1351,10 +1396,11 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1351
1396
|
index += 1
|
1352
1397
|
puts "\##{index} subtitle:"
|
1353
1398
|
print " format = #{stream['codec_name']}"
|
1354
|
-
|
1399
|
+
tags = stream.fetch('tags', {})
|
1400
|
+
frames = tags.fetch('NUMBER_OF_FRAMES', tags.fetch('NUMBER_OF_FRAMES-eng', ''))
|
1355
1401
|
puts frames.empty? ? '' : " / #{frames} " + (frames == 1 ? 'frame' : 'frames')
|
1356
|
-
puts " language = #{
|
1357
|
-
title =
|
1402
|
+
puts " language = #{tags.fetch('language', '')}"
|
1403
|
+
title = tags.fetch('title', '')
|
1358
1404
|
puts " title = #{title}" unless title.empty?
|
1359
1405
|
default = (stream['disposition']['default'] == 1)
|
1360
1406
|
forced = (stream['disposition']['forced'] == 1)
|
@@ -1369,8 +1415,8 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1369
1415
|
end
|
1370
1416
|
|
1371
1417
|
def get_bitrate(stream)
|
1372
|
-
|
1373
|
-
bitrate = stream.fetch('tags',
|
1418
|
+
tags = stream.fetch('tags', {})
|
1419
|
+
bitrate = stream.fetch('bit_rate', tags.fetch('BPS', tags.fetch('BPS-eng', '')))
|
1374
1420
|
return nil if bitrate.empty?
|
1375
1421
|
|
1376
1422
|
bitrate.to_i / 1000
|
@@ -1435,7 +1481,7 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1435
1481
|
'-ss', position.to_s,
|
1436
1482
|
'-i', path,
|
1437
1483
|
'-frames:v', '15',
|
1438
|
-
'-filter:v', 'cropdetect=24:2',
|
1484
|
+
'-filter:v', 'cropdetect=24.0/255:2',
|
1439
1485
|
'-an',
|
1440
1486
|
'-sn',
|
1441
1487
|
'-ignore_unknown',
|
@@ -1604,6 +1650,7 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1604
1650
|
overlay_filter = nil
|
1605
1651
|
else
|
1606
1652
|
overlay_filter = "[0:#{burn_subtitle['index']}]overlay"
|
1653
|
+
overlay_filter += "=#{@overlay_params}" unless @overlay_params.nil?
|
1607
1654
|
end
|
1608
1655
|
|
1609
1656
|
deinterlace = @deinterlace
|
@@ -1632,12 +1679,6 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1632
1679
|
width = video['width'].to_i
|
1633
1680
|
height = video['height'].to_i
|
1634
1681
|
|
1635
|
-
if width == 720 and height == 576 and video['codec_name'] == 'mpeg2video'
|
1636
|
-
pal = true
|
1637
|
-
else
|
1638
|
-
pal = false
|
1639
|
-
end
|
1640
|
-
|
1641
1682
|
if crop.nil? or (crop == {:width => width, :height => height, :x => 0, :y => 0})
|
1642
1683
|
crop_filter = nil
|
1643
1684
|
else
|
@@ -1670,6 +1711,8 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1670
1711
|
decode_options = []
|
1671
1712
|
end
|
1672
1713
|
|
1714
|
+
nvenc_gpu_only = false
|
1715
|
+
|
1673
1716
|
if (@decode_scope == :vc1 and video['codec_name'] == 'vc1') or @decode_scope == :all
|
1674
1717
|
if @encoder =~ /vaapi$/
|
1675
1718
|
decode_options = [
|
@@ -1686,6 +1729,18 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1686
1729
|
|
1687
1730
|
decode_options += ['-hwaccel', decode_method]
|
1688
1731
|
|
1732
|
+
if @nvenc_gpu_only and
|
1733
|
+
decode_method == 'cuda' and
|
1734
|
+
@encoder =~ /nvenc$/ and
|
1735
|
+
overlay_filter.nil? and
|
1736
|
+
(frame_rate_filter.nil? or frame_rate_filter !~ /fps=/) and
|
1737
|
+
crop_filter.nil? and
|
1738
|
+
scale_filter.nil?
|
1739
|
+
decode_options += ['-hwaccel_output_format', 'cuda']
|
1740
|
+
nvenc_gpu_only = true
|
1741
|
+
frame_rate_filter.sub!(/^yadif/, 'yadif_cuda') unless frame_rate_filter.nil?
|
1742
|
+
end
|
1743
|
+
|
1689
1744
|
if decode_method == 'qsv' and
|
1690
1745
|
overlay_filter.nil? and
|
1691
1746
|
frame_rate_filter.nil? and
|
@@ -1718,8 +1773,14 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1718
1773
|
end
|
1719
1774
|
end
|
1720
1775
|
|
1776
|
+
ten_bit = (@ten_bit ? (@eight_bit_vc1 ? (video['codec_name'] != 'vc1') : true) : false)
|
1777
|
+
pix_fmt = true
|
1778
|
+
|
1721
1779
|
if @encoder =~ /vaapi$/ and not decode_options.include?('-hwaccel')
|
1722
1780
|
conversion_filter = 'format=nv12,hwupload'
|
1781
|
+
elsif nvenc_gpu_only
|
1782
|
+
conversion_filter = "scale_cuda=format=#{ten_bit ? 'p010le' : 'yuv420p'}"
|
1783
|
+
pix_fmt = false
|
1723
1784
|
else
|
1724
1785
|
conversion_filter = nil
|
1725
1786
|
end
|
@@ -1758,61 +1819,59 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1758
1819
|
]
|
1759
1820
|
end
|
1760
1821
|
|
1761
|
-
|
1762
|
-
|
1822
|
+
color_primaries = video['color_primaries']
|
1823
|
+
color_trc = video['color_transfer']
|
1824
|
+
color_trc = 'gamma22' if color_trc == 'bt470m'
|
1825
|
+
color_trc = 'gamma28' if color_trc == 'bt470bg'
|
1826
|
+
colorspace = video['color_space']
|
1763
1827
|
|
1764
|
-
if
|
1765
|
-
color_primaries
|
1766
|
-
color_trc
|
1767
|
-
colorspace
|
1768
|
-
else
|
1769
|
-
color_primaries = 'bt709'
|
1770
|
-
color_trc = 'bt709'
|
1771
|
-
colorspace = 'bt709'
|
1828
|
+
if (video.fetch('pix_fmt', 'yuv420p') == 'yuv420p10le') and ten_bit
|
1829
|
+
color_primaries ||= 'bt2020'
|
1830
|
+
color_trc ||= 'smpte2084'
|
1831
|
+
colorspace ||= 'bt2020nc'
|
1772
1832
|
end
|
1773
1833
|
|
1774
1834
|
if width > 1920 or height > 1080
|
1835
|
+
level = '5.1'
|
1775
1836
|
bitrate = @target_2160p
|
1776
|
-
max_bitrate =
|
1777
|
-
max_dpb_mbs = 184320
|
1837
|
+
max_bitrate = @hevc ? 25000 : 135000 # Level 5 HEVC Main 10 or H.264 Main
|
1778
1838
|
elsif width > 1280 or height > 720
|
1839
|
+
level = '4'
|
1779
1840
|
bitrate = @target_1080p
|
1780
|
-
max_bitrate = 20000
|
1781
|
-
max_dpb_mbs = 32768
|
1841
|
+
max_bitrate = @hevc ? 12000 : 20000 # Level 4
|
1782
1842
|
elsif width > 720 or height > 576
|
1843
|
+
level = '3.1'
|
1783
1844
|
bitrate = @target_720p
|
1784
|
-
max_bitrate = 10000
|
1785
|
-
max_dpb_mbs = 18000
|
1845
|
+
max_bitrate = @hevc ? 10000 : 14000 # Level 3.1
|
1786
1846
|
else
|
1847
|
+
color_primaries ||= (width == 720 and height == 576 and video['codec_name'] == 'mpeg2video') ? 'bt470bg' : 'smpte170m'
|
1848
|
+
colorspace ||= 'smpte170m'
|
1849
|
+
level = '3'
|
1787
1850
|
bitrate = @target_480p
|
1788
|
-
max_bitrate =
|
1789
|
-
max_dpb_mbs = 8100
|
1790
|
-
|
1791
|
-
unless hdr
|
1792
|
-
color_primaries = pal ? 'bt470bg' : 'smpte170m'
|
1793
|
-
colorspace = 'smpte170m'
|
1794
|
-
end
|
1851
|
+
max_bitrate = @hevc ? 6000 : 10000 # Level 3
|
1795
1852
|
end
|
1796
1853
|
|
1854
|
+
color_primaries ||= 'bt709'
|
1855
|
+
color_trc ||= 'bt709'
|
1856
|
+
colorspace ||= 'bt709'
|
1797
1857
|
bitrate = @target unless @target.nil?
|
1798
1858
|
bitrate = [bitrate, max_bitrate].min
|
1799
|
-
maxrate = 0
|
1800
|
-
bufsize = 0
|
1801
1859
|
|
1802
1860
|
if @encoder =~ /(nvenc|hevc_qsv|libx26[45])$/
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
1806
|
-
maxrate = [[(bitrate * @maxrate).to_i,
|
1861
|
+
maxrate = [max_bitrate, bitrate * 2].max
|
1862
|
+
|
1863
|
+
unless @maxrate.nil?
|
1864
|
+
maxrate = [[(@maxrate < bitrate ? bitrate * @maxrate : @maxrate).to_i, bitrate].max, maxrate].min
|
1807
1865
|
end
|
1808
1866
|
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
1812
|
-
|
1813
|
-
bufsize = [[(bitrate * @bufsize).to_i, bitrate].max, bitrate * 4].min
|
1814
|
-
end
|
1867
|
+
bufsize = @encoder == 'hevc_qsv' ? 0 : maxrate
|
1868
|
+
|
1869
|
+
unless @bufsize.nil?
|
1870
|
+
bufsize = [[(@bufsize < bitrate ? bitrate * @bufsize : @bufsize).to_i, bitrate].max, maxrate].min
|
1815
1871
|
end
|
1872
|
+
else
|
1873
|
+
maxrate = 0
|
1874
|
+
bufsize = 0
|
1816
1875
|
end
|
1817
1876
|
|
1818
1877
|
unless @preset.nil?
|
@@ -1844,7 +1903,7 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1844
1903
|
text = "#{sprintf("%2d", video['index'])} = #{@encoder}"
|
1845
1904
|
|
1846
1905
|
unless @encoder == 'copy'
|
1847
|
-
text += " / #{bitrate} Kbps"
|
1906
|
+
text += @nvenc_cq.nil? ? " / #{bitrate} Kbps" : " / #{@nvenc_cq} CQ"
|
1848
1907
|
text += " / #{@preset}" unless @preset.nil?
|
1849
1908
|
end
|
1850
1909
|
|
@@ -1854,21 +1913,25 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1854
1913
|
|
1855
1914
|
Kernel.warn text
|
1856
1915
|
encode_options += ['-c:v', @encoder]
|
1857
|
-
encode_options += ['-pix_fmt:v', (@encoder =~ /(nvenc|qsv)$/ ? 'p010le' : 'yuv420p10le')] if ten_bit
|
1858
|
-
encode_options += ['-b:v', "#{bitrate}k"] unless @encoder == 'copy'
|
1916
|
+
encode_options += ['-pix_fmt:v', (@encoder =~ /(videotoolbox|nvenc|qsv)$/ ? 'p010le' : 'yuv420p10le')] if ten_bit and pix_fmt
|
1917
|
+
encode_options += (@nvenc_cq.nil? ? ['-b:v', "#{bitrate}k"] : ['-cq:v', @nvenc_cq]) unless @encoder == 'copy'
|
1859
1918
|
encode_options += ['-maxrate:v', "#{maxrate}k"] if maxrate > 0
|
1860
1919
|
encode_options += ['-bufsize:v', "#{bufsize}k"] if bufsize > 0
|
1861
1920
|
encode_options += ['-preset:v', @preset] unless @preset.nil?
|
1862
|
-
|
1921
|
+
|
1922
|
+
if @encoder =~ /videotoolbox$/
|
1923
|
+
encode_options += ['-allow_sw:v', '1'] if @vt_allow_sw
|
1924
|
+
encode_options += ['-profile:v', 'main10'] if ten_bit
|
1925
|
+
end
|
1863
1926
|
|
1864
1927
|
if @encoder =~ /nvenc$/
|
1865
|
-
encode_options += ['-rc:v', @nvenc_rc_mode]
|
1866
1928
|
encode_options += ['-spatial-aq:v', '1'] if @nvenc_spatial_aq
|
1867
1929
|
encode_options += ['-temporal-aq:v', '1'] if @nvenc_temporal_aq
|
1868
1930
|
encode_options += ['-rc-lookahead:v', @nvenc_lookahead.to_s] unless @nvenc_lookahead.nil?
|
1869
1931
|
encode_options += ['-multipass:v', @nvenc_multipass] unless @nvenc_multipass.nil?
|
1870
1932
|
encode_options += ['-refs:v', @nvenc_refs.to_s] unless @nvenc_refs.nil?
|
1871
1933
|
encode_options += ['-bf:v', @nvenc_bframes.to_s] unless @nvenc_bframes.nil?
|
1934
|
+
encode_options += ['-b_ref_mode:v', @nvenc_bframe_refs] unless @nvenc_bframe_refs.nil?
|
1872
1935
|
end
|
1873
1936
|
|
1874
1937
|
if @encoder =~ /qsv$/
|
@@ -1904,20 +1967,10 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1904
1967
|
]
|
1905
1968
|
end
|
1906
1969
|
else
|
1907
|
-
max_refs = [(max_dpb_mbs / (((width + 15) / 16) * ((height + 15) / 16))), 16].min
|
1908
|
-
|
1909
1970
|
case @preset
|
1910
|
-
when 'slow'
|
1911
|
-
|
1912
|
-
when 'slower'
|
1913
|
-
refs = 8
|
1914
|
-
when 'veryslow', 'placebo'
|
1915
|
-
refs = 16
|
1916
|
-
else
|
1917
|
-
refs = 0
|
1971
|
+
when 'slow', 'slower', 'veryslow', 'placebo'
|
1972
|
+
encode_options += ['-level:v', level]
|
1918
1973
|
end
|
1919
|
-
|
1920
|
-
encode_options += ['-refs:v', max_refs.to_s] if refs > max_refs
|
1921
1974
|
end
|
1922
1975
|
|
1923
1976
|
encode_options += ['-x264-params:v', @x264_params] unless @x264_params.nil?
|
@@ -1970,15 +2023,7 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1970
2023
|
|
1971
2024
|
audio_tracks = [{
|
1972
2025
|
:stream => main_audio,
|
1973
|
-
:width => width
|
1974
|
-
:bitrate => case width
|
1975
|
-
when :stereo
|
1976
|
-
@stereo_bitrate
|
1977
|
-
when :surround
|
1978
|
-
@surround_bitrate
|
1979
|
-
when :original
|
1980
|
-
nil
|
1981
|
-
end
|
2026
|
+
:width => width
|
1982
2027
|
}]
|
1983
2028
|
|
1984
2029
|
titles = {}
|
@@ -1992,15 +2037,6 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
1992
2037
|
|
1993
2038
|
width = selection[:width]
|
1994
2039
|
|
1995
|
-
bitrate = case width
|
1996
|
-
when :stereo
|
1997
|
-
@stereo_bitrate
|
1998
|
-
when :surround
|
1999
|
-
@surround_bitrate
|
2000
|
-
when :original
|
2001
|
-
nil
|
2002
|
-
end
|
2003
|
-
|
2004
2040
|
unless selection[:track].nil?
|
2005
2041
|
audio_track = 0
|
2006
2042
|
|
@@ -2012,8 +2048,7 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
2012
2048
|
if audio_track == selection[:track]
|
2013
2049
|
audio_tracks += [{
|
2014
2050
|
:stream => stream,
|
2015
|
-
:width => width
|
2016
|
-
:bitrate => bitrate
|
2051
|
+
:width => width
|
2017
2052
|
}]
|
2018
2053
|
|
2019
2054
|
break
|
@@ -2030,8 +2065,7 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
2030
2065
|
stream['index'] != main_audio['index']
|
2031
2066
|
audio_tracks += [{
|
2032
2067
|
:stream => stream,
|
2033
|
-
:width => width
|
2034
|
-
:bitrate => bitrate
|
2068
|
+
:width => width
|
2035
2069
|
}]
|
2036
2070
|
end
|
2037
2071
|
end
|
@@ -2046,8 +2080,7 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
2046
2080
|
if title =~ /#{selection[:title]}/i and stream['index'] != main_audio['index']
|
2047
2081
|
audio_tracks += [{
|
2048
2082
|
:stream => stream,
|
2049
|
-
:width => width
|
2050
|
-
:bitrate => bitrate
|
2083
|
+
:width => width
|
2051
2084
|
}]
|
2052
2085
|
|
2053
2086
|
titles[stream['index']] = title
|
@@ -2073,23 +2106,32 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
2073
2106
|
if track[:width] == :original
|
2074
2107
|
encoder = 'copy'
|
2075
2108
|
else
|
2109
|
+
input_bitrate = track[:stream].fetch('bit_rate', '256').to_i / 1000
|
2076
2110
|
dts = (codec_name == 'dts' and track[:stream].fetch('profile', 'DTS') =~ /^DTS(?:-ES)?$/)
|
2077
2111
|
|
2078
2112
|
if track[:width] == :surround
|
2079
|
-
if (
|
2080
|
-
(@
|
2113
|
+
if (@surround_encoder =~ /aac/ and codec_name == 'aac') or
|
2114
|
+
(@surround_encoder =~ /ac3$/ and
|
2115
|
+
(codec_name == @surround_encoder or codec_name == 'ac3') and
|
2116
|
+
(@keep_ac3_surround or input_bitrate <= (@surround_bitrate.nil? ? 640 : @surround_bitrate))) or
|
2081
2117
|
(@pass_dts and dts)
|
2082
2118
|
encoder = 'copy'
|
2083
2119
|
elsif input_channels > 2
|
2084
2120
|
encoder = @surround_encoder
|
2085
2121
|
bitrate = @surround_bitrate
|
2122
|
+
|
2123
|
+
if encoder =~ /aac/
|
2124
|
+
encoder = @aac_fallback_encoder if encoder == 'aac_at'
|
2125
|
+
channels = 6
|
2126
|
+
end
|
2086
2127
|
end
|
2087
2128
|
end
|
2088
2129
|
|
2089
2130
|
if encoder.nil?
|
2090
2131
|
if input_channels <= 2 and (codec_name == 'aac' or
|
2091
|
-
(
|
2092
|
-
(@
|
2132
|
+
(@surround_encoder =~ /ac3$/ and
|
2133
|
+
(codec_name == @surround_encoder or codec_name == 'ac3') and
|
2134
|
+
(@keep_ac3_stereo or input_bitrate <= (@stereo_bitrate.nil? ? 256 : @stereo_bitrate))) or
|
2093
2135
|
(@pass_dts and dts))
|
2094
2136
|
encoder = 'copy'
|
2095
2137
|
else
|
@@ -2116,21 +2158,31 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
2116
2158
|
next if configurations[input_index] == configuration
|
2117
2159
|
|
2118
2160
|
configurations[input_index] = configuration
|
2161
|
+
|
2162
|
+
if encoder == 'libfdk_aac' and not @fdk_vbr_mode.nil?
|
2163
|
+
bitrate = nil
|
2164
|
+
fdk_vbr_mode = @fdk_vbr_mode
|
2165
|
+
else
|
2166
|
+
fdk_vbr_mode = nil
|
2167
|
+
end
|
2168
|
+
|
2119
2169
|
text = "#{sprintf("%2d", input_index)} = #{encoder}"
|
2120
2170
|
text += " / #{bitrate} Kbps" unless bitrate.nil?
|
2121
|
-
text +=
|
2171
|
+
text += " / VBR mode #{fdk_vbr_mode}" unless fdk_vbr_mode.nil?
|
2172
|
+
text += ' / stereo' unless channels.nil? or channels > 2
|
2122
2173
|
text += " / #{titles[input_index]}" if titles.has_key?(input_index)
|
2123
2174
|
Kernel.warn text
|
2124
2175
|
copy_track_name = (@copy_track_names or titles.has_key?(input_index))
|
2125
2176
|
|
2126
2177
|
options += [
|
2127
2178
|
'-map', "0:#{input_index}",
|
2128
|
-
"-c:a:#{index}", encoder
|
2129
|
-
|
2130
|
-
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2179
|
+
"-c:a:#{index}", encoder,
|
2180
|
+
*(encoder == 'aac_at' ? ["-aac_at_mode:a:#{index}", 'cvbr'] : []),
|
2181
|
+
*(bitrate.nil? ? [] : ["-b:a:#{index}", "#{bitrate}k"]),
|
2182
|
+
*(fdk_vbr_mode.nil? ? [] : ["-vbr:a:#{index}", fdk_vbr_mode]),
|
2183
|
+
*(channels.nil? ? [] : ["-ac:a:#{index}", "#{channels}"]),
|
2184
|
+
*((encoder != 'copy' and track[:stream]['sample_rate'] != '48000') ? ["-ar:a:#{index}", '48000'] : []),
|
2185
|
+
*(copy_track_name ? [] : ["-metadata:s:a:#{index}", 'title=']),
|
2134
2186
|
"-disposition:a:#{index}", (index == 0 ? 'default' : '0')
|
2135
2187
|
]
|
2136
2188
|
|
@@ -2272,6 +2324,80 @@ Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
|
2272
2324
|
|
2273
2325
|
fail "adding track statistics tags failed: #{output_path}" unless $CHILD_STATUS.exitstatus == 0
|
2274
2326
|
end
|
2327
|
+
|
2328
|
+
def add_hdr_info(path, output_path)
|
2329
|
+
hdr_info = ''
|
2330
|
+
|
2331
|
+
IO.popen([
|
2332
|
+
'ffprobe',
|
2333
|
+
'-loglevel', 'quiet',
|
2334
|
+
'-select_streams', 'v:0',
|
2335
|
+
'-show_frames',
|
2336
|
+
'-read_intervals', '%+#1',
|
2337
|
+
'-show_entries', 'frame=side_data_list',
|
2338
|
+
'-print_format', 'json',
|
2339
|
+
path
|
2340
|
+
]) do |io|
|
2341
|
+
hdr_info = io.read
|
2342
|
+
end
|
2343
|
+
|
2344
|
+
fail "scanning media failed: #{path}" unless $CHILD_STATUS.exitstatus == 0
|
2345
|
+
|
2346
|
+
begin
|
2347
|
+
hdr_info = JSON.parse(hdr_info)
|
2348
|
+
rescue JSON::JSONError
|
2349
|
+
fail "media information not found: #{path}"
|
2350
|
+
end
|
2351
|
+
|
2352
|
+
md = nil
|
2353
|
+
cll = nil
|
2354
|
+
|
2355
|
+
hdr_info['frames'].each do |frame|
|
2356
|
+
frame.fetch('side_data_list', []).each do |side_data|
|
2357
|
+
if side_data['side_data_type'] == 'Mastering display metadata'
|
2358
|
+
md = side_data if md.nil?
|
2359
|
+
elsif side_data['side_data_type'] == 'Content light level metadata'
|
2360
|
+
cll = side_data if cll.nil?
|
2361
|
+
end
|
2362
|
+
end
|
2363
|
+
end
|
2364
|
+
|
2365
|
+
return if md.nil? or cll.nil?
|
2366
|
+
|
2367
|
+
Kernel.warn 'Adding HDR information...'
|
2368
|
+
|
2369
|
+
begin
|
2370
|
+
IO.popen([
|
2371
|
+
'mkvpropedit',
|
2372
|
+
output_path,
|
2373
|
+
'--edit', 'track:v1',
|
2374
|
+
'--set', "max-content-light=#{cll['max_content']}",
|
2375
|
+
'--set', "max-frame-light=#{cll['max_average']}",
|
2376
|
+
'--set', "chromaticity-coordinates-red-x=#{eval md['red_x'] + '.0'}",
|
2377
|
+
'--set', "chromaticity-coordinates-red-y=#{eval md['red_y'] + '.0'}",
|
2378
|
+
'--set', "chromaticity-coordinates-green-x=#{eval md['green_x'] + '.0'}",
|
2379
|
+
'--set', "chromaticity-coordinates-green-y=#{eval md['green_y'] + '.0'}",
|
2380
|
+
'--set', "chromaticity-coordinates-blue-x=#{eval md['blue_x'] + '.0'}",
|
2381
|
+
'--set', "chromaticity-coordinates-blue-y=#{eval md['blue_y'] + '.0'}",
|
2382
|
+
'--set', "white-coordinates-x=#{eval md['white_point_x'] + '.0'}",
|
2383
|
+
'--set', "white-coordinates-y=#{eval md['white_point_y'] + '.0'}",
|
2384
|
+
'--set', "max-luminance=#{eval md['max_luminance'] + '.0'}",
|
2385
|
+
'--set', "min-luminance=#{eval md['min_luminance'] + '.0'}"
|
2386
|
+
], 'rb') do |io|
|
2387
|
+
Signal.trap 'INT' do
|
2388
|
+
Process.kill 'INT', io.pid
|
2389
|
+
end
|
2390
|
+
|
2391
|
+
io.each_char do |char|
|
2392
|
+
STDERR.print char
|
2393
|
+
end
|
2394
|
+
end
|
2395
|
+
rescue SystemCallError => e
|
2396
|
+
raise "adding HDR information failed: #{e}"
|
2397
|
+
end
|
2398
|
+
|
2399
|
+
fail "adding HDR information failed: #{output_path}" unless $CHILD_STATUS.exitstatus == 0
|
2400
|
+
end
|
2275
2401
|
end
|
2276
2402
|
end
|
2277
2403
|
|
Binary file
|
Binary file
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: other_video_transcoding
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Don Melton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: " Other Video Transcoding is a package of tools to transcode videos.\n"
|
14
14
|
email: don@blivet.com
|
@@ -27,6 +27,7 @@ files:
|
|
27
27
|
- bin/other-transcode
|
28
28
|
- other_video_transcoding-0.1.0.gem
|
29
29
|
- other_video_transcoding-0.1.1.gem
|
30
|
+
- other_video_transcoding-0.10.0.gem
|
30
31
|
- other_video_transcoding-0.2.0.gem
|
31
32
|
- other_video_transcoding-0.3.0.gem
|
32
33
|
- other_video_transcoding-0.3.1.gem
|
@@ -35,6 +36,8 @@ files:
|
|
35
36
|
- other_video_transcoding-0.5.0.gem
|
36
37
|
- other_video_transcoding-0.6.0.gem
|
37
38
|
- other_video_transcoding-0.7.0.gem
|
39
|
+
- other_video_transcoding-0.8.0.gem
|
40
|
+
- other_video_transcoding-0.9.0.gem
|
38
41
|
- other_video_transcoding.gemspec
|
39
42
|
homepage: https://github.com/donmelton/other_video_transcoding
|
40
43
|
licenses:
|
@@ -55,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
58
|
- !ruby/object:Gem::Version
|
56
59
|
version: '0'
|
57
60
|
requirements: []
|
58
|
-
rubygems_version: 3.
|
61
|
+
rubygems_version: 3.3.7
|
59
62
|
signing_key:
|
60
63
|
specification_version: 4
|
61
64
|
summary: Other tools to transcode videos.
|