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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b33c51af021fb92ec9d41e7b4b95e92740b9c15832f276a471d6ecd8a92abe4
4
- data.tar.gz: c3e030f58c77f2cce69cd02a3563428f4a0f6dbed0b6216928f4c40c6b2f3d73
3
+ metadata.gz: 2a38e8e2bf7937b708b2b024767f266beee682bc92f7377f4e8062dee7babd09
4
+ data.tar.gz: e3fd2a8a57f2fad558b9a30fcb2fae633b8b7120d9e802f3d08a65de1053b1ab
5
5
  SHA512:
6
- metadata.gz: 5f5e7f4135a53ed651720e0803f605a52768cb12758fcb9c13c15c4d8cc59ec94340f02aab11d9c3db9b390bf296c51b9fb7f49c8314bbf4906352252dbc4942
7
- data.tar.gz: 8df50e3a3be13cb47483fd5b0ce9b2c9e97b3b4fe6755e5843e450bf177709df070e82e2ba18ab79c76d5f30172d588b9407b6aec25757ffcb0fd6e45e180881
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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2019-2021 Don Melton
1
+ Copyright (c) 2019-2022 Don Melton
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/bin/ask-ffmpeg-log CHANGED
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # ask-ffmpeg-log
4
4
  #
5
- # Copyright (c) 2019-2021 Don Melton
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.8.0
20
- Copyright (c) 2019-2021 Don Melton
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-2021 Don Melton
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.8.0
22
- Copyright (c) 2019-2021 Don Melton
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-rc-mode vbr|vbr_hq
164
- set ratecontrol mode (default: vbr)
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: 640)
259
+ set surround audio bitrate (default: 448)
245
260
  --stereo-bitrate BITRATE
246
- set stereo audio bitrate (default: 256)
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: 384 for surround, 192 for stereo)
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-stereo use AAC format for stereo audio
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 transcoding bitrate
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 transcoding bitrate
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
- @nvenc_rc_mode = 'vbr'
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 + usage19
427
+ usage17 + usage18 + usage20
397
428
  else
398
429
  puts usage1 + usage3 + usage6 + usage8 + usage11 + usage13 +
399
- usage15 + usage17 + usage19
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-rc-mode ARG' do |arg|
763
+ opts.on '--nvenc-bframe-refs ARG' do |arg|
717
764
  @encoder = @hevc ? 'hevc_nvenc' : 'h264_nvenc'
718
765
 
719
- @nvenc_rc_mode = case arg
720
- when 'vbr', 'vbr_hq'
766
+ @nvenc_bframe_refs = case arg
767
+ when 'each', 'middle'
721
768
  arg
722
769
  else
723
- fail UsageError, "invalid rate control argument: #{arg}"
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-stereo' do
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
- @target_2160p ||= @hevc ? 8000 : 12000
1007
- @target_1080p ||= @hevc ? 4000 : 6000
1008
- @target_720p ||= @hevc ? 2000 : 3000
1009
- @target_480p ||= @hevc ? 1000 : 1500
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
- if @format == :mkv
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
- ] + (encoder =~ /vaapi$/ ? ['-vaapi_device', '/dev/dri/renderD128'] : []) + [
1136
+ '-nostdin',
1137
+ *(encoder =~ /vaapi$/ ? ['-vaapi_device', '/dev/dri/renderD128'] : []),
1074
1138
  '-i', path,
1075
- '-frames:v', '1'
1076
- ] + (encoder =~ /vaapi$/ ? ['-filter:v', 'format=nv12,hwupload'] : []) + [
1139
+ '-frames:v', '1',
1140
+ *(encoder =~ /vaapi$/ ? ['-filter:v', 'format=nv12,hwupload'] : []),
1077
1141
  '-c:v', encoder,
1078
- '-b:v', '1000k'
1079
- ] + (encoder =~ /nvenc$/ ? ['-rc:v', @nvenc_rc_mode] : []) +
1080
- (encoder == 'h264_qsv' ? ['-look_ahead:v', '1'] : []) +
1081
- (encoder == 'hevc_qsv' ? ['-load_plugin:v', 'hevc_hw'] : []) +
1082
- (encoder =~ /amf$/ ? ['-rc:v', 'vbr_latency'] : []) + [
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
- ] + time_options +
1187
- decode_options + [
1188
- '-i', path
1189
- ] + (@max_muxing_queue_size.nil? ? [] : ['-max_muxing_queue_size', @max_muxing_queue_size.to_s]) +
1190
- encode_options +
1191
- get_audio_options(media_info) +
1192
- get_subtitle_options(media_info, burn_subtitle) + [
1193
- '-metadata:g', 'title='
1194
- ] + (@format == :mkv ? @mkv_options : ['-movflags', 'disable_chpl']) + [
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
- frames = stream.fetch('tags', {}).fetch('NUMBER_OF_FRAMES-eng', '')
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 = #{stream.fetch('tags', {}).fetch('language', '')}"
1357
- title = stream.fetch('tags', {}).fetch('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
- bitrate = stream.fetch('bit_rate', '')
1373
- bitrate = stream.fetch('tags', {}).fetch('BPS-eng', '') if bitrate.empty?
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
- ten_bit = (@ten_bit ? (@eight_bit_vc1 ? (video['codec_name'] != 'vc1') : true) : false)
1762
- hdr = ((video.fetch('pix_fmt', 'yuv420p') == 'yuv420p10le') and ten_bit)
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 hdr
1765
- color_primaries = 'bt2020'
1766
- color_trc = 'smpte2084'
1767
- colorspace = 'bt2020nc'
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 = 40000
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 = 5000
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
- if @maxrate.nil?
1804
- maxrate = bitrate * 3
1805
- else
1806
- maxrate = [[(bitrate * @maxrate).to_i, (bitrate * 1.5).to_i].max, bitrate * 3].min
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
- if @bufsize.nil?
1810
- bufsize = maxrate if @encoder =~ /(nvenc|libx26[45])$/
1811
- else
1812
- unless @bufsize == 0 and @encoder =~ /nvenc$/
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
- encode_options += ['-allow_sw:v', '1'] if @encoder =~ /videotoolbox$/ and @vt_allow_sw
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
- refs = 5
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 ((codec_name == @surround_encoder or codec_name == 'ac3') and
2080
- (@keep_ac3_surround or (track[:stream]['bit_rate'].to_i / 1000) <= @surround_bitrate)) or
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
- ((codec_name == @surround_encoder or codec_name == 'ac3') and
2092
- (@keep_ac3_stereo or (track[:stream]['bit_rate'].to_i / 1000) <= @stereo_bitrate)) or
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 += ' / stereo' unless channels.nil?
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
- ] + (encoder == 'aac_at' ? ["-aac_at_mode:a:#{index}", 'cvbr'] : []) +
2130
- (bitrate.nil? ? [] : ["-b:a:#{index}", "#{bitrate}k"]) +
2131
- (channels.nil? ? [] : ["-ac:a:#{index}", "#{channels}"]) +
2132
- (track[:stream]['sample_rate'] != '48000' ? ["-ar:a:#{index}", '48000'] : []) +
2133
- (copy_track_name ? [] : ["-metadata:s:a:#{index}", 'title=']) + [
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
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'other_video_transcoding'
3
- s.version = '0.8.0'
3
+ s.version = '0.11.0'
4
4
  s.required_ruby_version = '>= 2.0'
5
5
  s.summary = 'Other tools to transcode videos.'
6
6
  s.description = <<-HERE
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.8.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: 2021-02-13 00:00:00.000000000 Z
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.1.4
61
+ rubygems_version: 3.3.7
59
62
  signing_key:
60
63
  specification_version: 4
61
64
  summary: Other tools to transcode videos.