other_video_transcoding 0.1.1 → 0.4.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 +61 -0
- data/README.md +4 -0
- data/bin/ask-ffmpeg-log +8 -5
- data/bin/other-transcode +567 -170
- data/other_video_transcoding-0.1.0.gem +0 -0
- data/other_video_transcoding-0.1.1.gem +0 -0
- data/other_video_transcoding-0.2.0.gem +0 -0
- data/other_video_transcoding-0.3.0.gem +0 -0
- data/other_video_transcoding-0.3.1.gem +0 -0
- data/other_video_transcoding-0.3.2.gem +0 -0
- data/other_video_transcoding.gemspec +1 -1
- metadata +12 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa5db474ee387172ee779cd57befc925892dde23348ed6376cd35c416662576f
|
4
|
+
data.tar.gz: bd15276c43996afe54cf1bd7ad0f52eb55e5f5a6c1d90ebd36721d206eb17205
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 577dcc59ee2b7b2304ad59243abd5999851ed5a0407934eccfd25e59d320145428b40a86eb3f6938b30e6c45d2343cc20aa2b62f474e7b4d0c1dd9a99d8dc43e
|
7
|
+
data.tar.gz: 053d07452a33c7d04239e8dee324ec954e08682607871cf8c79e2cdbf0cb6bbca0dff202e8464e2fe49f80c6e7a4adb50c3a9f815636e0fe786e7ac86829ddd6
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,67 @@
|
|
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.4.0](https://github.com/donmelton/other_video_transcoding/releases/tag/0.4.0)
|
6
|
+
|
7
|
+
Sunday, November 1, 2020
|
8
|
+
|
9
|
+
* Modify the behavior and augment the capabilities of both encoding and decoding when using Nvidia hardware with `other-transcode`. This is necessary for compatibility with unleased versions of `ffmpeg` which are now built using the new Nvidia Software Development Kit (SDK) version 11.0. This SDK changes default encoder behavior and adds new presets which allow finer control of the performance/quality trade-off when transcoding video. To allow maximum performance, `other-transcode` no longer enables some quality settings by default:
|
10
|
+
* Multipass mode, now accessible via a new `--nvenc-multipass` option. Be advised that any improved quality from enabling multipass mode is probably not worth the performance impact.
|
11
|
+
* Spatial and temporal adaptive quantization (AQ), accessible via the `--nvenc-spatial-aq` and `--nvenc-temporal-aq` options. While enabling spatial AQ is still useful in reducing color banding for some inputs, be advised that enabling temporal AQ is probably not necessary and can cause some other side effects.
|
12
|
+
* Add support for seven new Nvidia encoder presets to `other-transcode`. Use `--preset p1` for best performance and `--preset p7` for best quality. It's not necessary to use `--preset p4` since that's the default. See the [Nvidia preset migration guide](https://docs.nvidia.com/video-technologies/video-codec-sdk/nvenc-preset-migration-guide/index.html) to understand how these presets work and how they map to older behavior.
|
13
|
+
* Add a `--nvenc-rc-mode` option to `other-transcode` for backward comaptibility with `ffmpeg` version 4.3.1 and older.
|
14
|
+
* Add `--cuda` and `--no-cuda` options to `other-transcode`. These options enable or disable the scoped use of the Nvidia CUDA hardware decoder instead of the generic hardware decoder. By default the CUDA _decoder_ is enabled when using the Nvidia video _encoder_, but disabled when using other encoders.
|
15
|
+
* Deprecate the `--cuvid` option in `other-transcode` because the CUDA decoder is faster and more flexible.
|
16
|
+
* Deprecate `--preset none` in `other-transcode` because it's no longer necessary.
|
17
|
+
* Always use hyphen-based spellings of Nvidia AQ options in `ffmpeg` commands generated by `other-transcode`.
|
18
|
+
* Add `--x264-params` and `--x265-params` options to `other-transcode` for _very_ advanced manipulation of the `x264` and `x265` software encoders.
|
19
|
+
* Modify `other-transcode` to assume a video input without a `field_order` tag is progressive instead of interlaced so a deinterlace fliter is not automatically and incorrectly applied to that video. This avoids problems with some 4K Ultra HD Blu-ray rips.
|
20
|
+
* Update the link to Docker containers for Linux in the "README" document. Thanks, @ttyS0!
|
21
|
+
|
22
|
+
## [0.3.2](https://github.com/donmelton/other_video_transcoding/releases/tag/0.3.2)
|
23
|
+
|
24
|
+
Friday, September 11, 2020
|
25
|
+
|
26
|
+
* Modify `other-transcode` to use a new `ffmpeg` Matroksa muxer option so the `-disposition` option is once again honored when using `ffmpeg` version 4.3 and later.
|
27
|
+
* Change the codec ID from the default of `hev1` to `hvc1` for HEVC video in MP4 output from `other-transcode` to enable playback in QuickTime on macOS. Via [ #50](https://github.com/donmelton/other_video_transcoding/issues/50).
|
28
|
+
* Convert added SRT format subtitles to MOV-compatible format in MP4 output from `other-transcode`. Via [ #55](https://github.com/donmelton/other_video_transcoding/issues/55).
|
29
|
+
|
30
|
+
## [0.3.1](https://github.com/donmelton/other_video_transcoding/releases/tag/0.3.1)
|
31
|
+
|
32
|
+
Tuesday, May 26, 2020
|
33
|
+
|
34
|
+
* Modify the `--preview-crop` option in `other-transcode` to show commands compatible with newer versions of `mpv`.
|
35
|
+
* No longer force a NTSC film frame rate for interlaced inputs in PAL MPEG-2 format.
|
36
|
+
* When using the `--dry-run` option in `other-transcode`, issue a warning instead of failing if the output or log files already exist.
|
37
|
+
* Add a link to another Docker container for Linux in the "README" document. Thanks, @ttyS0!
|
38
|
+
|
39
|
+
## [0.3.0](https://github.com/donmelton/other_video_transcoding/releases/tag/0.3.0)
|
40
|
+
|
41
|
+
Thursday, February 27, 2020
|
42
|
+
|
43
|
+
* Add a `--scan` option to `other-transcode`. This prints media information and then exits, allowing easy identification of track numbers and formats. Via [ #11](https://github.com/donmelton/other_video_transcoding/issues/11).
|
44
|
+
* Add a `--mono-bitrate` option to `other-transcode`. This sets the mono audio bitrate, which is otherwise 50% of the stereo bitrate.
|
45
|
+
* Raise the maximum bitrates for audio in AAC format to 320 Kbps for stereo and 256 Kbps for mono. The default birates remain the same.
|
46
|
+
* Add a `--all-eac3` option to `other-transcode`. This uses the Dolby Digital Plus (Enhanced AC-3) format for all transcoded audio. The behavior of the `--eac3` option, which uses Dolby Digital Plus for surround audio only, remains the same.
|
47
|
+
* Add a `--keep-ac3-stereo` option to `other-transcode`. This copies stereo and mono audio in AC-3 format even when the original source bitrate is above the output transcoding bitrate.
|
48
|
+
* Add a `--pass-dts` option to `other-transcode`. This enables passthrough of audio in DTS and DTS-ES formats. However, such audio also in surround format will still be transcoded if that audio is output to a stereo-width track.
|
49
|
+
* Add `--rc-maxrate` and `--rc-bufsize` options to `other-transcode`. These set the ratecontrol maximum rate and/or the buffer size as a multiple of the video bitrate target, but only for certain encoders and ratecontrol systems.
|
50
|
+
* Add a `--x264-mbtree` option to `other-transcode`. This uses macroblock-tree ratecontrol and disables AVBR if in use.
|
51
|
+
* In order to ensure compatible H.264 levels, limit the number of reference frames when using the `x264` encoder with slower presets.
|
52
|
+
* Remove the deprecated `--name` option of `other-transcode`.
|
53
|
+
* Add a link to a Docker container for Linux in the "README" document. Thanks, @ttyS0!
|
54
|
+
|
55
|
+
## [0.2.0](https://github.com/donmelton/other_video_transcoding/releases/tag/0.2.0)
|
56
|
+
|
57
|
+
Monday, January 13, 2020
|
58
|
+
|
59
|
+
* Allow `all` to be used as an argument to the `--add-audio` and `--add-subtitle` options of `other-transcode`, adding all audio tracks or all subtitle tracks. Via [ #3](https://github.com/donmelton/other_video_transcoding/issues/3).
|
60
|
+
* Add `original` as a width attribute to the `--main-audio` and `--add-audio` options of `other-transcode`. Unlike `stereo` and `surround`, this disables transcoding and always copies the selected track(s). Via [ #5](https://github.com/donmelton/other_video_transcoding/issues/5).
|
61
|
+
* Add a `--copy-video` option to `other-transcode`. This disables transcoding and copies the original video track to the output.
|
62
|
+
* No longer ignore any image-based subtitles added to MP4 output. Instead, let `ffmpeg` foolishly add DVD-style subtitles and (currently) fail when adding Blu-ray Disc-style subtitles.
|
63
|
+
* Deprecate the `--name` option of `other-transcode` because it doesn't make sense to name only the first output file from a tool which can take multiple inputs. The option still works for now, but using it issues a warning message. It will be removed in a future release.
|
64
|
+
* Remove warnings when other options disable the Nvidia video decoder, which could only happen if the `--burn-subtitle` or `--detelecine` options were used with the `--cuvid` option.
|
65
|
+
|
5
66
|
## [0.1.1](https://github.com/donmelton/other_video_transcoding/releases/tag/0.1.1)
|
6
67
|
|
7
68
|
Friday, January 3, 2020
|
data/README.md
CHANGED
@@ -62,6 +62,10 @@ See "[Download FFmpeg](https://ffmpeg.org/download.html)," "[MKVToolNix Download
|
|
62
62
|
|
63
63
|
Additional documentation for installing these programs on Windows is available in the [wiki](https://github.com/donmelton/other_video_transcoding/wiki/Windows).
|
64
64
|
|
65
|
+
[Docker](https://en.wikipedia.org/wiki/Docker_(software)) containers for Linux, including installation instructions, are available here:
|
66
|
+
|
67
|
+
https://github.com/ttyS0/docker-other-transcode
|
68
|
+
|
65
69
|
On macOS, all of these programs can be easily installed via [Homebrew](http://brew.sh/), an optional package manager:
|
66
70
|
|
67
71
|
brew install ffmpeg
|
data/bin/ask-ffmpeg-log
CHANGED
@@ -15,14 +15,14 @@ module Transcoding
|
|
15
15
|
|
16
16
|
class Command
|
17
17
|
def about
|
18
|
-
|
19
|
-
ask-ffmpeg-log 0.
|
18
|
+
<<-HERE
|
19
|
+
ask-ffmpeg-log 0.4.0
|
20
20
|
Copyright (c) 2019-2020 Don Melton
|
21
|
-
HERE
|
21
|
+
HERE
|
22
22
|
end
|
23
23
|
|
24
24
|
def usage
|
25
|
-
|
25
|
+
<<-HERE
|
26
26
|
Report temporal information from ffmpeg-generated `.log` files
|
27
27
|
containing encoding statistics.
|
28
28
|
|
@@ -34,7 +34,7 @@ Options:
|
|
34
34
|
--tabular use tab character as field delimiter and suppress labels
|
35
35
|
-h, --help display this help and exit
|
36
36
|
--version output version information and exit
|
37
|
-
HERE
|
37
|
+
HERE
|
38
38
|
end
|
39
39
|
|
40
40
|
def initialize
|
@@ -65,6 +65,7 @@ HERE
|
|
65
65
|
end
|
66
66
|
|
67
67
|
fail UsageError, 'missing argument' if ARGV.empty?
|
68
|
+
|
68
69
|
ARGV.each { |arg| process_input arg }
|
69
70
|
complete
|
70
71
|
exit
|
@@ -92,10 +93,12 @@ HERE
|
|
92
93
|
if File.directory? input
|
93
94
|
logs = Dir[input + File::SEPARATOR + '*.log']
|
94
95
|
fail "does not contain `.log` files: #{input}" if logs.empty?
|
96
|
+
|
95
97
|
@logs += logs
|
96
98
|
@paths << input
|
97
99
|
else
|
98
100
|
fail "not a `.log` file: #{input}" unless File.extname(input) == '.log'
|
101
|
+
|
99
102
|
@logs << File.absolute_path(input)
|
100
103
|
@paths << File.dirname(input)
|
101
104
|
end
|
data/bin/other-transcode
CHANGED
@@ -17,14 +17,14 @@ module Transcoding
|
|
17
17
|
|
18
18
|
class Command
|
19
19
|
def about
|
20
|
-
|
21
|
-
other-transcode 0.
|
20
|
+
<<-HERE
|
21
|
+
other-transcode 0.4.0
|
22
22
|
Copyright (c) 2019-2020 Don Melton
|
23
|
-
HERE
|
23
|
+
HERE
|
24
24
|
end
|
25
25
|
|
26
26
|
def usage1
|
27
|
-
|
27
|
+
<<-HERE
|
28
28
|
Transcode Blu-ray Disc or DVD rip into a smaller, more portable format
|
29
29
|
while remaining high enough quality to be mistaken for the original.
|
30
30
|
|
@@ -34,56 +34,55 @@ Creates Matroska `.mkv` format file in current working directory.
|
|
34
34
|
|
35
35
|
Automatically selects a platform-specific hardware video encoder.
|
36
36
|
|
37
|
-
HERE
|
37
|
+
HERE
|
38
38
|
end
|
39
39
|
|
40
40
|
def usage2
|
41
|
-
|
41
|
+
<<-HERE
|
42
42
|
Input options:
|
43
43
|
--position TIME, --duration TIME
|
44
44
|
start transcoding at position and/or limit to duration
|
45
45
|
in seconds[.milliseconds] or [HH:]MM:SS[.m...] format
|
46
46
|
|
47
|
-
HERE
|
47
|
+
HERE
|
48
48
|
end
|
49
49
|
|
50
50
|
def usage3
|
51
|
-
|
51
|
+
<<-HERE
|
52
52
|
Output options:
|
53
53
|
--debug increase diagnostic information
|
54
|
+
--scan print media information and exit
|
54
55
|
--preview-crop show commands to preview detected video crop and exit
|
55
|
-
HERE
|
56
|
+
HERE
|
56
57
|
end
|
57
58
|
|
58
59
|
def usage4
|
59
|
-
|
60
|
+
<<-HERE
|
60
61
|
--print-crop print only detected video crop geometry and exit
|
61
62
|
--mp4 output MP4 instead of Matroska `.mkv` format
|
62
|
-
--name STRING set output filename, excluding format extension
|
63
|
-
(default: based on input filename)
|
64
63
|
--copy-track-names
|
65
64
|
copy all input audio track names to output
|
66
|
-
HERE
|
65
|
+
HERE
|
67
66
|
end
|
68
67
|
|
69
68
|
def usage5
|
70
|
-
|
69
|
+
<<-HERE
|
71
70
|
--max-muxing-queue-size SIZE
|
72
71
|
set maximum number of packets to buffer when muxing
|
73
|
-
HERE
|
72
|
+
HERE
|
74
73
|
end
|
75
74
|
|
76
75
|
def usage6
|
77
|
-
|
76
|
+
<<-HERE
|
78
77
|
-n, --dry-run don't transcode, just show `ffmpeg` command and exit
|
79
78
|
|
80
79
|
Video options:
|
81
80
|
--hevc use HEVC version of platform-specific video encoder
|
82
|
-
HERE
|
81
|
+
HERE
|
83
82
|
end
|
84
83
|
|
85
84
|
def usage7
|
86
|
-
|
85
|
+
<<-HERE
|
87
86
|
--vt use Apple Video Toolbox encoder
|
88
87
|
--nvenc use Nvidia video encoder
|
89
88
|
--qsv use Intel Quick Sync video encoder
|
@@ -94,19 +93,20 @@ HERE
|
|
94
93
|
--10-bit, --no-10-bit
|
95
94
|
use 10-bit pixel format (default: not used for H.264,
|
96
95
|
used for HEVC with Nvidia, Intel and x265 encoders)
|
97
|
-
--preset NAME
|
98
|
-
apply video encoder preset or disable default settings
|
96
|
+
--preset NAME apply video encoder preset
|
99
97
|
--decode vc1|all|none
|
100
98
|
set scope of automatic hardware decoder acceleration
|
101
99
|
(default: vc1 for VC-1 format only)
|
102
|
-
--
|
103
|
-
|
104
|
-
|
105
|
-
|
100
|
+
--cuda, --no-cuda
|
101
|
+
enable or disable scoped use of Nvidia video decoder
|
102
|
+
instead of generic hardware decoder
|
103
|
+
(default: enabled when using Nvidia video encoder,
|
104
|
+
disabled when using other encoders)
|
105
|
+
HERE
|
106
106
|
end
|
107
107
|
|
108
108
|
def usage8
|
109
|
-
|
109
|
+
<<-HERE
|
110
110
|
--target [2160p=|1080p=|720p=|480p=]BITRATE
|
111
111
|
set video bitrate target (default: based on input)
|
112
112
|
or target for specific input resolution
|
@@ -114,11 +114,11 @@ HERE
|
|
114
114
|
set video crop geometry (default: none)
|
115
115
|
or automatically detect it
|
116
116
|
--720p fit video within 1280x720 pixel bounds
|
117
|
-
HERE
|
117
|
+
HERE
|
118
118
|
end
|
119
119
|
|
120
120
|
def usage9
|
121
|
-
|
121
|
+
<<-HERE
|
122
122
|
--1080p " " " 1920x1080 " "
|
123
123
|
--deinterlace reduce interlace artifacts without changing frame rate
|
124
124
|
(applied automatically for some inputs)
|
@@ -127,27 +127,34 @@ HERE
|
|
127
127
|
--detelecine drop duplicate frames to restore original frame rate
|
128
128
|
(disables any deinterlacing and forced frame rate)
|
129
129
|
--no-filters disable any automatic adjustments via filters
|
130
|
-
HERE
|
130
|
+
HERE
|
131
131
|
end
|
132
132
|
|
133
133
|
def usage10
|
134
|
-
|
134
|
+
<<-HERE
|
135
|
+
--rc-maxrate FACTOR, --rc-bufsize FACTOR
|
136
|
+
set ratecontrol maximum rate and/or buffer size
|
137
|
+
as multiple of video bitrate target
|
138
|
+
--copy-video disable transcoding and copy original video track
|
135
139
|
|
136
140
|
Apple Video Toolbox encoder options:
|
137
141
|
--vt-allow-sw allow software encoding
|
138
142
|
|
139
143
|
Nvidia video encoder options:
|
140
|
-
--nvenc-spatial-aq
|
141
|
-
enable
|
142
|
-
--nvenc-temporal-aq
|
143
|
-
enable
|
144
|
-
(default: enabled for H.264, disabled for HEVC)
|
144
|
+
--nvenc-spatial-aq
|
145
|
+
enable spatial adaptive quantization (AQ)
|
146
|
+
--nvenc-temporal-aq
|
147
|
+
enable temporal adaptive quantization (AQ)
|
145
148
|
--nvenc-lookahead FRAMES
|
146
149
|
set number of frames to look ahead for ratecontrol
|
150
|
+
--nvenc-multipass qres|fullres
|
151
|
+
set multipass encoding resolution
|
147
152
|
--nvenc-refs FRAMES
|
148
153
|
set number of reference frames
|
149
154
|
--nvenc-bframes FRAMES
|
150
155
|
set maximum number of B-frames
|
156
|
+
--nvenc-rc-mode vbr|vbr_hq
|
157
|
+
set ratecontrol mode (default: vbr)
|
151
158
|
|
152
159
|
Intel Quick Sync video encoder options:
|
153
160
|
--qsv-refs FRAMES
|
@@ -172,22 +179,42 @@ Video Acceleration API encoder options:
|
|
172
179
|
|
173
180
|
x264 software video encoder options:
|
174
181
|
--x264-avbr use average variable bitrate (AVBR) ratecontrol
|
182
|
+
--x264-mbtree use macroblock-tree ratecontrol (disables AVBR if in use)
|
175
183
|
--x264-quick increase encoding speed by 70-80%
|
176
184
|
with no easily perceptible loss in video quality
|
177
185
|
(avoids quality problems with some encoder presets)
|
178
|
-
|
186
|
+
--x264-params KEY=VALUE[:KEY=VALUE]...
|
187
|
+
override x264 configuration (disables other x264 options)
|
188
|
+
|
189
|
+
x265 software video encoder options:
|
190
|
+
--x265-params KEY=VALUE[:KEY=VALUE]...
|
191
|
+
override x265 configuration
|
192
|
+
HERE
|
179
193
|
end
|
180
194
|
|
181
195
|
def usage11
|
182
|
-
|
196
|
+
<<-HERE
|
183
197
|
|
184
198
|
Audio options:
|
185
199
|
--main-audio TRACK[=WIDTH]
|
186
200
|
select main audio track by number (default: 1)
|
187
201
|
with optional width (default: surround)
|
188
|
-
|
202
|
+
HERE
|
203
|
+
end
|
204
|
+
|
205
|
+
def usage12
|
206
|
+
<<-HERE
|
207
|
+
(use `original` to disable transcoding)
|
208
|
+
HERE
|
209
|
+
end
|
210
|
+
|
211
|
+
def usage13
|
212
|
+
<<-HERE
|
213
|
+
--add-audio TRACK|all|LANGUAGE|STRING[=WIDTH]
|
189
214
|
add single audio track by number
|
190
215
|
including main audio track
|
216
|
+
or all audio tracks
|
217
|
+
excluding main audio track
|
191
218
|
or audio tracks by language code
|
192
219
|
excluding main audio track
|
193
220
|
(in ISO 639-2 format, e.g.: `eng`)
|
@@ -195,22 +222,61 @@ Audio options:
|
|
195
222
|
excluding main audio track
|
196
223
|
(comparison is case-insensitve)
|
197
224
|
with optional width (default: stereo)
|
225
|
+
HERE
|
226
|
+
end
|
227
|
+
|
228
|
+
def usage14
|
229
|
+
<<-HERE
|
230
|
+
(use `original` to disable transcoding)
|
231
|
+
HERE
|
232
|
+
end
|
233
|
+
|
234
|
+
def usage15
|
235
|
+
<<-HERE
|
198
236
|
--surround-bitrate BITRATE
|
199
237
|
set surround audio bitrate (default: 640)
|
200
238
|
--stereo-bitrate BITRATE
|
201
239
|
set stereo audio bitrate (default: 256)
|
240
|
+
HERE
|
241
|
+
end
|
242
|
+
|
243
|
+
def usage16
|
244
|
+
<<-HERE
|
245
|
+
--mono-bitrate BITRATE
|
246
|
+
set mono audio bitrate (default: 50% of stereo bitrate)
|
247
|
+
HERE
|
248
|
+
end
|
249
|
+
|
250
|
+
def usage17
|
251
|
+
<<-HERE
|
202
252
|
--eac3 use Enhanced AC-3 format for surround audio
|
253
|
+
HERE
|
254
|
+
end
|
255
|
+
|
256
|
+
def usage18
|
257
|
+
<<-HERE
|
258
|
+
--all-eac3 " " " " " all audio
|
259
|
+
--keep-ac3-stereo
|
260
|
+
copy stereo and mono audio in AC-3 format
|
261
|
+
even when orginal bitrate is above transcoding bitrate
|
262
|
+
--pass-dts enable passthrough of audio in DTS and DTS-ES formats
|
263
|
+
HERE
|
264
|
+
end
|
265
|
+
|
266
|
+
def usage19
|
267
|
+
<<-HERE
|
203
268
|
|
204
269
|
Subtitle options:
|
205
|
-
--add-subtitle TRACK[=forced]|auto|LANGUAGE|STRING
|
270
|
+
--add-subtitle TRACK[=forced]|auto|all|LANGUAGE|STRING
|
206
271
|
add single subtitle track by number
|
207
272
|
optionally setting forced disposition
|
208
273
|
or enable automatic addition of forced subtitle
|
209
|
-
or add subtitle tracks
|
274
|
+
or add all subtitle tracks
|
275
|
+
or subtitle tracks by language code
|
210
276
|
(in ISO 639-2 format, e.g.: `eng`)
|
211
277
|
or subtitle tracks with titles containing string
|
212
278
|
(comparison is case-insensitve)
|
213
|
-
(
|
279
|
+
(variations exclude any burned track)
|
214
280
|
--burn-subtitle TRACK|auto
|
215
281
|
burn subtitle track by number into video
|
216
282
|
or enable automatic burning of forced subtitle
|
@@ -223,17 +289,18 @@ Other options:
|
|
223
289
|
--version output version information and exit
|
224
290
|
|
225
291
|
Requires `ffprobe`, `ffmpeg` and `mkvpropedit`.
|
226
|
-
HERE
|
292
|
+
HERE
|
227
293
|
end
|
228
294
|
|
229
295
|
def initialize
|
230
296
|
@position = nil
|
231
297
|
@duration = nil
|
232
298
|
@debug = false
|
299
|
+
@scan = false
|
233
300
|
@detect = false
|
234
301
|
@preview = false
|
235
302
|
@format = :mkv
|
236
|
-
@
|
303
|
+
@mkv_options = []
|
237
304
|
@copy_track_names = false
|
238
305
|
@max_muxing_queue_size = nil
|
239
306
|
@dry_run = false
|
@@ -242,6 +309,7 @@ HERE
|
|
242
309
|
@ten_bit = nil
|
243
310
|
@preset = nil
|
244
311
|
@decode_scope = :vc1
|
312
|
+
@decode_method = nil
|
245
313
|
@decoder_type = nil
|
246
314
|
@target_2160p = nil
|
247
315
|
@target_1080p = nil
|
@@ -255,12 +323,16 @@ HERE
|
|
255
323
|
@rate = nil
|
256
324
|
@detelecine = false
|
257
325
|
@enable_filters = true
|
326
|
+
@maxrate = nil
|
327
|
+
@bufsize = nil
|
258
328
|
@vt_allow_sw = false
|
259
|
-
@nvenc_spatial_aq =
|
260
|
-
@nvenc_temporal_aq =
|
329
|
+
@nvenc_spatial_aq = false
|
330
|
+
@nvenc_temporal_aq = false
|
261
331
|
@nvenc_lookahead = nil
|
332
|
+
@nvenc_multipass = nil
|
262
333
|
@nvenc_refs = nil
|
263
334
|
@nvenc_bframes = nil
|
335
|
+
@nvenc_rc_mode = 'vbr'
|
264
336
|
@qsv_refs = nil
|
265
337
|
@qsv_bframes = nil
|
266
338
|
@amf_quality = nil
|
@@ -270,7 +342,10 @@ HERE
|
|
270
342
|
@amf_bframes = nil
|
271
343
|
@vaapi_compression = nil
|
272
344
|
@x264_avbr = false
|
345
|
+
@x264_mbtree = false
|
273
346
|
@x264_quick = false
|
347
|
+
@x264_params = nil
|
348
|
+
@x265_params = nil
|
274
349
|
@audio_selections = [{
|
275
350
|
:track => 1,
|
276
351
|
:language => nil,
|
@@ -279,8 +354,11 @@ HERE
|
|
279
354
|
}]
|
280
355
|
@surround_bitrate = 640
|
281
356
|
@stereo_bitrate = 256
|
357
|
+
@mono_bitrate = nil
|
282
358
|
@surround_encoder = 'ac3'
|
283
359
|
@stereo_encoder = nil
|
360
|
+
@keep_ac3_stereo = false
|
361
|
+
@pass_dts = false
|
284
362
|
@subtitle_selections = []
|
285
363
|
@auto_add_subtitle = false
|
286
364
|
@burn_subtitle_track = 0
|
@@ -295,12 +373,16 @@ HERE
|
|
295
373
|
case arg
|
296
374
|
when 'full'
|
297
375
|
puts usage1 + usage2 + usage3 + usage4 + usage5 + usage6 +
|
298
|
-
usage7 + usage8 + usage9 + usage10 + usage11
|
376
|
+
usage7 + usage8 + usage9 + usage10 + usage11 + usage12 +
|
377
|
+
usage13 + usage14 + usage15 + usage16 + usage17 +
|
378
|
+
usage18 + usage19
|
299
379
|
when 'more'
|
300
380
|
puts usage1 + usage2 + usage3 + usage4 + usage6 + usage7 +
|
301
|
-
usage8 + usage9 + usage11
|
381
|
+
usage8 + usage9 + usage11 + usage13 + usage15 + usage16 +
|
382
|
+
usage17 + usage18 + usage19
|
302
383
|
else
|
303
|
-
puts usage1 + usage3 + usage6 + usage8 + usage11
|
384
|
+
puts usage1 + usage3 + usage6 + usage8 + usage11 + usage13 +
|
385
|
+
usage15 + usage17 + usage19
|
304
386
|
end
|
305
387
|
|
306
388
|
exit
|
@@ -316,6 +398,7 @@ HERE
|
|
316
398
|
end
|
317
399
|
|
318
400
|
fail UsageError, 'missing argument' if ARGV.empty?
|
401
|
+
|
319
402
|
configure ARGV.first
|
320
403
|
ARGV.each { |arg| process_input arg }
|
321
404
|
exit
|
@@ -344,6 +427,10 @@ HERE
|
|
344
427
|
@debug = true
|
345
428
|
end
|
346
429
|
|
430
|
+
opts.on '--scan' do
|
431
|
+
@scan = true
|
432
|
+
end
|
433
|
+
|
347
434
|
opts.on '--preview-crop' do
|
348
435
|
@detect = true
|
349
436
|
@preview = true
|
@@ -358,10 +445,6 @@ HERE
|
|
358
445
|
@format = :mp4
|
359
446
|
end
|
360
447
|
|
361
|
-
opts.on '--name ARG' do |arg|
|
362
|
-
@name = arg
|
363
|
-
end
|
364
|
-
|
365
448
|
opts.on '--copy-track-names' do
|
366
449
|
@copy_track_names = true
|
367
450
|
end
|
@@ -411,10 +494,20 @@ HERE
|
|
411
494
|
|
412
495
|
opts.on '--[no-]10-bit' do |arg|
|
413
496
|
@ten_bit = arg
|
497
|
+
@encoder = nil if @encoder == 'copy'
|
414
498
|
end
|
415
499
|
|
416
500
|
opts.on '--preset ARG' do |arg|
|
417
|
-
|
501
|
+
if arg == 'none'
|
502
|
+
Kernel.warn '**********'
|
503
|
+
Kernel.warn 'Using deprecated `--preset` argument: none'
|
504
|
+
Kernel.warn '**********'
|
505
|
+
@preset = nil
|
506
|
+
else
|
507
|
+
@preset = arg
|
508
|
+
end
|
509
|
+
|
510
|
+
@encoder = nil if @encoder == 'copy'
|
418
511
|
end
|
419
512
|
|
420
513
|
opts.on '--decode ARG' do |arg|
|
@@ -426,7 +519,14 @@ HERE
|
|
426
519
|
end
|
427
520
|
end
|
428
521
|
|
522
|
+
opts.on '--[no-]cuda' do |arg|
|
523
|
+
@decode_method = arg ? 'cuda' : 'auto'
|
524
|
+
end
|
525
|
+
|
429
526
|
opts.on '--cuvid' do
|
527
|
+
Kernel.warn '**********'
|
528
|
+
Kernel.warn 'Using deprecated option: --cuvid'
|
529
|
+
Kernel.warn '**********'
|
430
530
|
@decoder_type = :cuvid
|
431
531
|
end
|
432
532
|
|
@@ -451,6 +551,8 @@ HERE
|
|
451
551
|
else
|
452
552
|
@target = [arg.to_i, 1].max
|
453
553
|
end
|
554
|
+
|
555
|
+
@encoder = nil if @encoder == 'copy'
|
454
556
|
end
|
455
557
|
|
456
558
|
opts.on '--crop ARG' do |arg|
|
@@ -462,22 +564,27 @@ HERE
|
|
462
564
|
else
|
463
565
|
fail UsageError, "invalid crop geometry: #{arg}"
|
464
566
|
end
|
567
|
+
|
568
|
+
@encoder = nil if @encoder == 'copy'
|
465
569
|
end
|
466
570
|
|
467
571
|
opts.on '--720p' do
|
468
572
|
@max_width = 1280
|
469
573
|
@max_height = 720
|
574
|
+
@encoder = nil if @encoder == 'copy'
|
470
575
|
end
|
471
576
|
|
472
577
|
opts.on '--1080p' do
|
473
578
|
@max_width = 1920
|
474
579
|
@max_height = 1080
|
580
|
+
@encoder = nil if @encoder == 'copy'
|
475
581
|
end
|
476
582
|
|
477
583
|
opts.on '--deinterlace' do
|
478
584
|
@deinterlace = true
|
479
585
|
@detelecine = false
|
480
586
|
@enable_filters = false
|
587
|
+
@encoder = nil if @encoder == 'copy' and @decoder_type != :cuvid
|
481
588
|
end
|
482
589
|
|
483
590
|
opts.on '--rate ARG' do |arg|
|
@@ -500,6 +607,7 @@ HERE
|
|
500
607
|
|
501
608
|
@detelecine = false
|
502
609
|
@enable_filters = false
|
610
|
+
@encoder = nil if @encoder == 'copy'
|
503
611
|
end
|
504
612
|
|
505
613
|
opts.on '--detelecine' do
|
@@ -507,23 +615,59 @@ HERE
|
|
507
615
|
@deinterlace = false
|
508
616
|
@rate = nil
|
509
617
|
@enable_filters = false
|
618
|
+
@encoder = nil if @encoder == 'copy'
|
510
619
|
end
|
511
620
|
|
512
621
|
opts.on '--no-filters' do
|
513
622
|
@enable_filters = false
|
514
623
|
end
|
515
624
|
|
625
|
+
opts.on '--rc-maxrate ARG', Float do |arg|
|
626
|
+
@maxrate = arg
|
627
|
+
@encoder = nil if @encoder == 'copy'
|
628
|
+
end
|
629
|
+
|
630
|
+
opts.on '--rc-bufsize ARG', Float do |arg|
|
631
|
+
@bufsize = arg
|
632
|
+
@encoder = nil if @encoder == 'copy'
|
633
|
+
end
|
634
|
+
|
635
|
+
opts.on '--copy-video' do
|
636
|
+
@encoder = 'copy'
|
637
|
+
@hevc = false
|
638
|
+
@ten_bit = nil
|
639
|
+
@preset = nil
|
640
|
+
@target = nil
|
641
|
+
@crop = nil
|
642
|
+
@rate = nil
|
643
|
+
@detelecine = false
|
644
|
+
@enable_filters = false
|
645
|
+
@burn_subtitle_track = 0
|
646
|
+
end
|
647
|
+
|
516
648
|
opts.on '--vt-allow-sw' do
|
517
649
|
@encoder = @hevc ? 'hevc_videotoolbox' : 'h264_videotoolbox'
|
518
650
|
@vt_allow_sw = true
|
519
651
|
end
|
520
652
|
|
521
653
|
opts.on '--[no-]nvenc-spatial-aq' do |arg|
|
654
|
+
unless arg
|
655
|
+
Kernel.warn '**********'
|
656
|
+
Kernel.warn 'Using deprecated option: --no-nvenc-spatial-aq'
|
657
|
+
Kernel.warn '**********'
|
658
|
+
end
|
659
|
+
|
522
660
|
@encoder = @hevc ? 'hevc_nvenc' : 'h264_nvenc'
|
523
661
|
@nvenc_spatial_aq = arg
|
524
662
|
end
|
525
663
|
|
526
664
|
opts.on '--[no-]nvenc-temporal-aq' do |arg|
|
665
|
+
unless arg
|
666
|
+
Kernel.warn '**********'
|
667
|
+
Kernel.warn 'Using deprecated option: --no-nvenc-temporal-aq'
|
668
|
+
Kernel.warn '**********'
|
669
|
+
end
|
670
|
+
|
527
671
|
@encoder = @hevc ? 'hevc_nvenc' : 'h264_nvenc'
|
528
672
|
@nvenc_temporal_aq = arg
|
529
673
|
end
|
@@ -533,6 +677,17 @@ HERE
|
|
533
677
|
@nvenc_lookahead = [[arg, 0].max, 32].min
|
534
678
|
end
|
535
679
|
|
680
|
+
opts.on '--nvenc-multipass ARG' do |arg|
|
681
|
+
@encoder = @hevc ? 'hevc_nvenc' : 'h264_nvenc'
|
682
|
+
|
683
|
+
@nvenc_multipass = case arg
|
684
|
+
when 'qres', 'fullres'
|
685
|
+
arg
|
686
|
+
else
|
687
|
+
fail UsageError, "invalid multipass resolution argument: #{arg}"
|
688
|
+
end
|
689
|
+
end
|
690
|
+
|
536
691
|
opts.on '--nvenc-refs ARG', Integer do |arg|
|
537
692
|
@encoder = @hevc ? 'hevc_nvenc' : 'h264_nvenc'
|
538
693
|
@nvenc_refs = [arg, 0].max
|
@@ -543,6 +698,17 @@ HERE
|
|
543
698
|
@nvenc_bframes = [[arg, 0].max, 4].min
|
544
699
|
end
|
545
700
|
|
701
|
+
opts.on '--nvenc-rc-mode ARG' do |arg|
|
702
|
+
@encoder = @hevc ? 'hevc_nvenc' : 'h264_nvenc'
|
703
|
+
|
704
|
+
@nvenc_rc_mode = case arg
|
705
|
+
when 'vbr', 'vbr_hq'
|
706
|
+
arg
|
707
|
+
else
|
708
|
+
fail UsageError, "invalid rate control argument: #{arg}"
|
709
|
+
end
|
710
|
+
end
|
711
|
+
|
546
712
|
opts.on '--qsv-refs ARG', Integer do |arg|
|
547
713
|
@encoder = @hevc ? 'hevc_qsv' : 'h264_qsv'
|
548
714
|
@qsv_refs = [arg, 0].max
|
@@ -593,17 +759,51 @@ HERE
|
|
593
759
|
@encoder = 'libx264'
|
594
760
|
@hevc = false
|
595
761
|
@x264_avbr = true
|
762
|
+
@x264_mbtree = false
|
763
|
+
@x264_params = nil
|
764
|
+
end
|
765
|
+
|
766
|
+
opts.on '--x264-mbtree' do
|
767
|
+
@encoder = 'libx264'
|
768
|
+
@hevc = false
|
769
|
+
@x264_mbtree = true
|
770
|
+
@x264_avbr = false
|
771
|
+
@x264_params = nil
|
596
772
|
end
|
597
773
|
|
598
774
|
opts.on '--x264-quick' do
|
599
775
|
@encoder = 'libx264'
|
600
776
|
@hevc = false
|
601
777
|
@x264_quick = true
|
778
|
+
@x264_params = nil
|
602
779
|
@preset = nil
|
603
780
|
end
|
604
781
|
|
782
|
+
opts.on '--x264-params ARG' do |arg|
|
783
|
+
arg.split ':' do |param|
|
784
|
+
fail UsageError, "invalid argument: #{arg}" unless param =~ /^[\w\-]+=[\w\-\.,]+$/
|
785
|
+
end
|
786
|
+
|
787
|
+
@encoder = 'libx264'
|
788
|
+
@hevc = false
|
789
|
+
@x264_params = arg
|
790
|
+
@x264_avbr = false
|
791
|
+
@x264_mbtree = true
|
792
|
+
@x264_quick = false
|
793
|
+
end
|
794
|
+
|
795
|
+
opts.on '--x265-params ARG' do |arg|
|
796
|
+
arg.split ':' do |param|
|
797
|
+
fail UsageError, "invalid argument: #{arg}" unless param =~ /^[\w\-]+=[\w\-\.,]+$/
|
798
|
+
end
|
799
|
+
|
800
|
+
@encoder = 'libx265'
|
801
|
+
@hevc = true
|
802
|
+
@x265_params = arg
|
803
|
+
end
|
804
|
+
|
605
805
|
opts.on '--main-audio ARG' do |arg|
|
606
|
-
if arg =~ /^([0-9]+)(?:=(surround|
|
806
|
+
if arg =~ /^([0-9]+)(?:=(stereo|surround|original))?$/
|
607
807
|
@audio_selections[0][:track] = $1.to_i
|
608
808
|
@audio_selections[0][:width] = $2.to_sym unless $2.nil?
|
609
809
|
else
|
@@ -612,7 +812,7 @@ HERE
|
|
612
812
|
end
|
613
813
|
|
614
814
|
opts.on '--add-audio ARG' do |arg|
|
615
|
-
if arg =~ /^([^=]+)(?:=(surround|
|
815
|
+
if arg =~ /^([^=]+)(?:=(stereo|surround|original))?$/
|
616
816
|
scope = $1
|
617
817
|
width = $2
|
618
818
|
|
@@ -647,10 +847,27 @@ HERE
|
|
647
847
|
@stereo_bitrate = arg
|
648
848
|
end
|
649
849
|
|
850
|
+
opts.on '--mono-bitrate ARG', Integer do |arg|
|
851
|
+
@mono_bitrate = arg
|
852
|
+
end
|
853
|
+
|
650
854
|
opts.on '--eac3' do
|
651
855
|
@surround_encoder = 'eac3'
|
652
856
|
end
|
653
857
|
|
858
|
+
opts.on '--all-eac3' do
|
859
|
+
@surround_encoder = 'eac3'
|
860
|
+
@stereo_encoder = 'eac3'
|
861
|
+
end
|
862
|
+
|
863
|
+
opts.on '--keep-ac3-stereo' do
|
864
|
+
@keep_ac3_stereo = true
|
865
|
+
end
|
866
|
+
|
867
|
+
opts.on '--pass-dts' do
|
868
|
+
@pass_dts = true
|
869
|
+
end
|
870
|
+
|
654
871
|
opts.on '--add-subtitle ARG' do |arg|
|
655
872
|
if arg =~ /^([0-9]+)(?:=(forced))?$|^(auto)$|^([a-z]{3})$|^(.*)$/
|
656
873
|
@subtitle_selections += [{
|
@@ -676,6 +893,8 @@ HERE
|
|
676
893
|
else
|
677
894
|
fail UsageError, "invalid subtitle track: #{arg}"
|
678
895
|
end
|
896
|
+
|
897
|
+
@encoder = nil if @encoder == 'copy'
|
679
898
|
end
|
680
899
|
end
|
681
900
|
|
@@ -700,7 +919,13 @@ HERE
|
|
700
919
|
@audio_selections.uniq!
|
701
920
|
@subtitle_selections.uniq!
|
702
921
|
@surround_bitrate = [[@surround_bitrate, 256].max, (@surround_encoder == 'ac3' ? 640 : 768)].min
|
703
|
-
@stereo_bitrate = [[@stereo_bitrate, 128].max,
|
922
|
+
@stereo_bitrate = [[@stereo_bitrate, 128].max, (@stereo_encoder == 'eac3' ? 768 : 320)].min
|
923
|
+
|
924
|
+
if @mono_bitrate.nil?
|
925
|
+
@mono_bitrate = @stereo_bitrate / 2
|
926
|
+
else
|
927
|
+
@mono_bitrate = [[@mono_bitrate, 64].max, (@stereo_encoder == 'eac3' ? 768 : 256)].min
|
928
|
+
end
|
704
929
|
|
705
930
|
[
|
706
931
|
['ffprobe', '-loglevel', 'quiet', '-version'],
|
@@ -710,7 +935,7 @@ HERE
|
|
710
935
|
verify_tool_availability command
|
711
936
|
end
|
712
937
|
|
713
|
-
return if @detect
|
938
|
+
return if @scan or @detect
|
714
939
|
|
715
940
|
encoders = find_encoders
|
716
941
|
|
@@ -735,7 +960,7 @@ HERE
|
|
735
960
|
else
|
736
961
|
@encoder.sub!(/^h264/, 'hevc') if @hevc
|
737
962
|
|
738
|
-
unless @dry_run or encoders =~ /#{@encoder}/
|
963
|
+
unless @dry_run or @encoder == 'copy' or encoders =~ /#{@encoder}/
|
739
964
|
fail "video encoder not available: #{@encoder}"
|
740
965
|
end
|
741
966
|
end
|
@@ -745,6 +970,7 @@ HERE
|
|
745
970
|
@target_1080p ||= (@hevc and @ten_bit) ? 6000 : 8000
|
746
971
|
@target_720p ||= (@hevc and @ten_bit) ? 3000 : 4000
|
747
972
|
@target_480p ||= (@hevc and @ten_bit) ? 1500 : 2000
|
973
|
+
@decode_method ||= @encoder =~ /nvenc$/ ? 'cuda' : 'auto'
|
748
974
|
|
749
975
|
if @stereo_encoder.nil?
|
750
976
|
if encoders =~ /aac_at/ or encoders =~ /libfdk_aac/
|
@@ -753,6 +979,11 @@ HERE
|
|
753
979
|
@stereo_encoder = 'aac'
|
754
980
|
end
|
755
981
|
end
|
982
|
+
|
983
|
+
if @format == :mkv
|
984
|
+
capabilities = get_muxer_capabilities
|
985
|
+
@mkv_options = ['-default_mode', 'passthrough'] if capabilities =~ /passthrough/
|
986
|
+
end
|
756
987
|
end
|
757
988
|
|
758
989
|
def verify_tool_availability(command)
|
@@ -808,8 +1039,7 @@ HERE
|
|
808
1039
|
] + (encoder =~ /vaapi$/ ? ['-filter:v', 'format=nv12,hwupload'] : []) + [
|
809
1040
|
'-c:v', encoder,
|
810
1041
|
'-b:v', '1000k'
|
811
|
-
] + (encoder =~ /nvenc$/ ? ['-rc:v',
|
812
|
-
(encoder == 'h264_nvenc' ? ['-temporal-aq:v', '1'] : []) +
|
1042
|
+
] + (encoder =~ /nvenc$/ ? ['-rc:v', @nvenc_rc_mode] : []) +
|
813
1043
|
(encoder == 'h264_qsv' ? ['-look_ahead:v', '1'] : []) +
|
814
1044
|
(encoder == 'hevc_qsv' ? ['-load_plugin:v', 'hevc_hw'] : []) +
|
815
1045
|
(encoder =~ /amf$/ ? ['-rc:v', 'vbr_latency'] : []) + [
|
@@ -830,23 +1060,51 @@ HERE
|
|
830
1060
|
$CHILD_STATUS.exitstatus == 0
|
831
1061
|
end
|
832
1062
|
|
1063
|
+
def get_muxer_capabilities
|
1064
|
+
Kernel.warn 'Getting muxer capabilities...'
|
1065
|
+
output = ''
|
1066
|
+
|
1067
|
+
begin
|
1068
|
+
IO.popen([
|
1069
|
+
'ffmpeg',
|
1070
|
+
'-loglevel', 'quiet',
|
1071
|
+
'-h', 'muxer=matroska'
|
1072
|
+
], :err=>[:child, :out]) do |io|
|
1073
|
+
io.each do |line|
|
1074
|
+
Kernel.warn line if @debug
|
1075
|
+
output += line
|
1076
|
+
end
|
1077
|
+
end
|
1078
|
+
rescue SystemCallError => e
|
1079
|
+
raise "getting muxer capabilities failed: #{e}"
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
fail 'getting muxer capabilities failed' unless $CHILD_STATUS.exitstatus == 0
|
1083
|
+
|
1084
|
+
output
|
1085
|
+
end
|
1086
|
+
|
833
1087
|
def process_input(path)
|
834
1088
|
seconds = Time.now.tv_sec
|
835
1089
|
|
836
|
-
unless @detect
|
837
|
-
output_path =
|
838
|
-
|
839
|
-
fail "output file already exists: #{output_path}" if File.exist? output_path
|
1090
|
+
unless @scan or @detect
|
1091
|
+
output_path = File.basename(path, '.*') + '.' + @format.to_s
|
1092
|
+
fail_or_warn "output file already exists: #{output_path}" if File.exist? output_path
|
840
1093
|
|
841
1094
|
log_path = output_path + '.log'
|
842
|
-
|
1095
|
+
fail_or_warn "log file already exists: #{log_path}" if File.exist? log_path
|
843
1096
|
|
844
1097
|
tmp_log_path = "_ffmpeg_#{rand(10000..99999)}_#{$PROCESS_ID}.#{@format.to_s}.log"
|
845
|
-
|
1098
|
+
fail_or_warn "log file already exists: #{tmp_log_path}" if File.exist? tmp_log_path
|
846
1099
|
end
|
847
1100
|
|
848
1101
|
media_info = scan_media(path)
|
849
1102
|
|
1103
|
+
if @scan
|
1104
|
+
print_media_info media_info
|
1105
|
+
return
|
1106
|
+
end
|
1107
|
+
|
850
1108
|
video, burn_subtitle = get_video_streams(media_info)
|
851
1109
|
fail "video track not found: #{path}" if video.nil?
|
852
1110
|
|
@@ -857,7 +1115,7 @@ HERE
|
|
857
1115
|
crop = detect_crop(media_info, video)
|
858
1116
|
|
859
1117
|
if @detect
|
860
|
-
present_crop
|
1118
|
+
present_crop crop, path
|
861
1119
|
return
|
862
1120
|
else
|
863
1121
|
Kernel.warn "crop = #{crop[:width]}:#{crop[:height]}:#{crop[:x]}:#{crop[:y]}"
|
@@ -890,13 +1148,13 @@ HERE
|
|
890
1148
|
'-stats'
|
891
1149
|
] + time_options +
|
892
1150
|
decode_options + [
|
893
|
-
'-i',
|
1151
|
+
'-i', path
|
894
1152
|
] + (@max_muxing_queue_size.nil? ? [] : ['-max_muxing_queue_size', @max_muxing_queue_size.to_s]) +
|
895
1153
|
encode_options +
|
896
1154
|
get_audio_options(media_info) +
|
897
1155
|
get_subtitle_options(media_info, burn_subtitle) + [
|
898
1156
|
'-metadata:g', 'title='
|
899
|
-
] + (@format == :
|
1157
|
+
] + (@format == :mkv ? @mkv_options : ['-movflags', 'disable_chpl']) + [
|
900
1158
|
output_path
|
901
1159
|
]
|
902
1160
|
|
@@ -941,17 +1199,25 @@ HERE
|
|
941
1199
|
FileUtils.mv tmp_log_path, log_path
|
942
1200
|
end
|
943
1201
|
|
944
|
-
assemble_log
|
1202
|
+
assemble_log log_path, output
|
945
1203
|
|
946
1204
|
if @format == :mp4
|
947
1205
|
Kernel.warn 'Done.'
|
948
1206
|
else
|
949
|
-
add_track_statistics_tags
|
1207
|
+
add_track_statistics_tags output_path
|
950
1208
|
end
|
951
1209
|
|
952
1210
|
Kernel.warn "\nElapsed time: #{seconds_to_time(Time.now.tv_sec - seconds)}\n\n"
|
953
1211
|
end
|
954
1212
|
|
1213
|
+
def fail_or_warn(message)
|
1214
|
+
if @dry_run
|
1215
|
+
Kernel.warn "#{$PROGRAM_NAME}: #{message}"
|
1216
|
+
else
|
1217
|
+
fail message
|
1218
|
+
end
|
1219
|
+
end
|
1220
|
+
|
955
1221
|
def scan_media(path)
|
956
1222
|
Kernel.warn 'Scanning media...'
|
957
1223
|
output = ''
|
@@ -986,6 +1252,93 @@ HERE
|
|
986
1252
|
media_info
|
987
1253
|
end
|
988
1254
|
|
1255
|
+
def print_media_info(media_info)
|
1256
|
+
video = nil
|
1257
|
+
audio_streams = []
|
1258
|
+
subtitles = []
|
1259
|
+
|
1260
|
+
media_info['streams'].each do |stream|
|
1261
|
+
case stream['codec_type']
|
1262
|
+
when 'video'
|
1263
|
+
video = stream if video.nil?
|
1264
|
+
when 'audio'
|
1265
|
+
audio_streams += [stream]
|
1266
|
+
when 'subtitle'
|
1267
|
+
subtitles += [stream]
|
1268
|
+
end
|
1269
|
+
end
|
1270
|
+
|
1271
|
+
puts media_info['format']['filename']
|
1272
|
+
size = "#{video['width']} x #{video['height']}"
|
1273
|
+
print " format = #{video['codec_name']} / #{size} / #{video['avg_frame_rate']} fps"
|
1274
|
+
bitrate = get_bitrate(video)
|
1275
|
+
puts bitrate.nil? ? '' : " / #{bitrate} Kbps"
|
1276
|
+
duration = media_info['format']['duration'].to_f
|
1277
|
+
time = seconds_to_time(duration.to_i)
|
1278
|
+
milliseconds = duration.to_s.sub(/^[0-9]+(\.[0-9]+)$/, '\1')
|
1279
|
+
time += milliseconds unless milliseconds == '.0'
|
1280
|
+
puts " duration = #{time}"
|
1281
|
+
index = 0
|
1282
|
+
|
1283
|
+
audio_streams.each do |stream|
|
1284
|
+
index += 1
|
1285
|
+
puts "\##{index} audio:"
|
1286
|
+
codec_name = stream['codec_name']
|
1287
|
+
print " format = #{codec_name}"
|
1288
|
+
|
1289
|
+
if codec_name == 'dts'
|
1290
|
+
profile = stream.fetch('profile', 'DTS')
|
1291
|
+
print " (#{profile})" unless profile == 'DTS'
|
1292
|
+
end
|
1293
|
+
|
1294
|
+
print ' / '
|
1295
|
+
layout = stream.fetch('channel_layout', '')
|
1296
|
+
|
1297
|
+
if layout.empty?
|
1298
|
+
channels = stream['channels'].to_i
|
1299
|
+
print "#{channels} " + (channels > 1 ? 'channels' : 'channel')
|
1300
|
+
else
|
1301
|
+
print "#{layout}"
|
1302
|
+
end
|
1303
|
+
|
1304
|
+
bitrate = get_bitrate(stream)
|
1305
|
+
puts bitrate.nil? ? '' : " / #{bitrate} Kbps"
|
1306
|
+
puts " language = #{stream.fetch('tags', {}).fetch('language', '')}"
|
1307
|
+
title = stream.fetch('tags', {}).fetch('title', '')
|
1308
|
+
puts " title = #{title}" unless title.empty?
|
1309
|
+
end
|
1310
|
+
|
1311
|
+
index = 0
|
1312
|
+
|
1313
|
+
subtitles.each do |stream|
|
1314
|
+
index += 1
|
1315
|
+
puts "\##{index} subtitle:"
|
1316
|
+
print " format = #{stream['codec_name']}"
|
1317
|
+
frames = stream.fetch('tags', {}).fetch('NUMBER_OF_FRAMES-eng', '')
|
1318
|
+
puts frames.empty? ? '' : " / #{frames} " + (frames == 1 ? 'frame' : 'frames')
|
1319
|
+
puts " language = #{stream.fetch('tags', {}).fetch('language', '')}"
|
1320
|
+
title = stream.fetch('tags', {}).fetch('title', '')
|
1321
|
+
puts " title = #{title}" unless title.empty?
|
1322
|
+
default = (stream['disposition']['default'] == 1)
|
1323
|
+
forced = (stream['disposition']['forced'] == 1)
|
1324
|
+
|
1325
|
+
if default or forced
|
1326
|
+
puts ' flags = ' +
|
1327
|
+
(default ? 'default' : '') +
|
1328
|
+
((default and forced) ? ' / ' : '') +
|
1329
|
+
(forced ? 'forced' : '')
|
1330
|
+
end
|
1331
|
+
end
|
1332
|
+
end
|
1333
|
+
|
1334
|
+
def get_bitrate(stream)
|
1335
|
+
bitrate = stream.fetch('bit_rate', '')
|
1336
|
+
bitrate = stream.fetch('tags', {}).fetch('BPS-eng', '') if bitrate.empty?
|
1337
|
+
return nil if bitrate.empty?
|
1338
|
+
|
1339
|
+
bitrate.to_i / 1000
|
1340
|
+
end
|
1341
|
+
|
989
1342
|
def detect_crop(media_info, video)
|
990
1343
|
Kernel.warn 'Detecting crop...'
|
991
1344
|
duration = media_info['format']['duration'].to_f
|
@@ -1108,10 +1461,10 @@ HERE
|
|
1108
1461
|
drawbox_string = "#{crop[:x]}:#{crop[:y]}:#{crop[:width]}:#{crop[:height]}"
|
1109
1462
|
puts
|
1110
1463
|
puts escape_command([
|
1111
|
-
'mpv', '--no-audio',
|
1464
|
+
'mpv', '--no-audio', "--vf=lavfi=[drawbox=#{drawbox_string}:invert:1]", path
|
1112
1465
|
])
|
1113
1466
|
puts escape_command([
|
1114
|
-
'mpv', '--no-audio',
|
1467
|
+
'mpv', '--no-audio', "--vf=crop=#{crop_string}", path
|
1115
1468
|
])
|
1116
1469
|
puts
|
1117
1470
|
puts escape_command([
|
@@ -1241,23 +1594,17 @@ HERE
|
|
1241
1594
|
overlay_filter = nil
|
1242
1595
|
else
|
1243
1596
|
overlay_filter = "[0:#{burn_subtitle['index']}]overlay"
|
1244
|
-
|
1245
|
-
unless cuvid_decoder.nil?
|
1246
|
-
Kernel.warn '**********'
|
1247
|
-
Kernel.warn "burning subtitle disables video decoder: #{cuvid_decoder}"
|
1248
|
-
Kernel.warn '**********'
|
1249
|
-
cuvid_decoder = nil
|
1250
|
-
end
|
1597
|
+
cuvid_decoder = nil
|
1251
1598
|
end
|
1252
1599
|
|
1253
1600
|
deinterlace = @deinterlace
|
1254
1601
|
rate = @rate
|
1255
1602
|
|
1256
1603
|
if @enable_filters
|
1257
|
-
if video['avg_frame_rate'] == '30000/1001' or video
|
1604
|
+
if video['avg_frame_rate'] == '30000/1001' or video.fetch('field_order', 'progressive') != 'progressive'
|
1258
1605
|
deinterlace = true
|
1259
1606
|
|
1260
|
-
if video['codec_name'] == 'mpeg2video'
|
1607
|
+
if video['codec_name'] == 'mpeg2video' and video['avg_frame_rate'] != '25/1'
|
1261
1608
|
rate = '24000/1001'
|
1262
1609
|
end
|
1263
1610
|
end
|
@@ -1267,7 +1614,7 @@ HERE
|
|
1267
1614
|
|
1268
1615
|
if deinterlace
|
1269
1616
|
if cuvid_decoder.nil?
|
1270
|
-
frame_rate_filter = 'yadif=deint=interlaced'
|
1617
|
+
frame_rate_filter = 'yadif=deint=interlaced' unless @encoder == 'copy'
|
1271
1618
|
else
|
1272
1619
|
cuvid_options += ['-deint:v', 'adaptive']
|
1273
1620
|
end
|
@@ -1280,14 +1627,8 @@ HERE
|
|
1280
1627
|
end
|
1281
1628
|
|
1282
1629
|
if @detelecine
|
1283
|
-
unless cuvid_decoder.nil?
|
1284
|
-
Kernel.warn '**********'
|
1285
|
-
Kernel.warn "detelecine disables video decoder: #{cuvid_decoder}"
|
1286
|
-
Kernel.warn '**********'
|
1287
|
-
cuvid_decoder = nil
|
1288
|
-
end
|
1289
|
-
|
1290
1630
|
frame_rate_filter = 'fieldmatch=order=tff:combmatch=none,decimate'
|
1631
|
+
cuvid_decoder = nil
|
1291
1632
|
end
|
1292
1633
|
|
1293
1634
|
width = video['width'].to_i
|
@@ -1358,7 +1699,7 @@ HERE
|
|
1358
1699
|
'-hwaccel_output_format', 'vaapi'
|
1359
1700
|
]
|
1360
1701
|
else
|
1361
|
-
decode_options += ['-hwaccel',
|
1702
|
+
decode_options += ['-hwaccel', @decode_method]
|
1362
1703
|
end
|
1363
1704
|
end
|
1364
1705
|
else
|
@@ -1375,12 +1716,16 @@ HERE
|
|
1375
1716
|
conversion_filter = nil
|
1376
1717
|
end
|
1377
1718
|
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1719
|
+
if @encoder == 'copy'
|
1720
|
+
filter = ''
|
1721
|
+
else
|
1722
|
+
filter = overlay_filter.nil? ? '' : overlay_filter
|
1723
|
+
filter += frame_rate_filter.nil? ? '' : ",#{frame_rate_filter}"
|
1724
|
+
filter += crop_filter.nil? ? '' : ",#{crop_filter}"
|
1725
|
+
filter += scale_filter.nil? ? '' : ",#{scale_filter}"
|
1726
|
+
filter += conversion_filter.nil? ? '' : ",#{conversion_filter}"
|
1727
|
+
filter.sub!(/^,/, '')
|
1728
|
+
end
|
1384
1729
|
|
1385
1730
|
if overlay_filter.nil?
|
1386
1731
|
encode_options = [
|
@@ -1414,15 +1759,19 @@ HERE
|
|
1414
1759
|
if width > 1920 or height > 1080
|
1415
1760
|
bitrate = @target_2160p
|
1416
1761
|
max_bitrate = 40000
|
1762
|
+
max_dpb_mbs = 184320
|
1417
1763
|
elsif width > 1280 or height > 720
|
1418
1764
|
bitrate = @target_1080p
|
1419
1765
|
max_bitrate = 20000
|
1766
|
+
max_dpb_mbs = 32768
|
1420
1767
|
elsif width > 720 or height > 576
|
1421
1768
|
bitrate = @target_720p
|
1422
1769
|
max_bitrate = 10000
|
1770
|
+
max_dpb_mbs = 18000
|
1423
1771
|
else
|
1424
1772
|
bitrate = @target_480p
|
1425
1773
|
max_bitrate = 5000
|
1774
|
+
max_dpb_mbs = 8100
|
1426
1775
|
|
1427
1776
|
unless hdr
|
1428
1777
|
color_primaries = pal ? 'bt470bg' : 'smpte170m'
|
@@ -1432,17 +1781,30 @@ HERE
|
|
1432
1781
|
|
1433
1782
|
bitrate = @target unless @target.nil?
|
1434
1783
|
bitrate = [bitrate, max_bitrate].min
|
1435
|
-
maxrate =
|
1784
|
+
maxrate = 0
|
1785
|
+
bufsize = 0
|
1436
1786
|
|
1437
|
-
if @
|
1438
|
-
|
1439
|
-
|
1787
|
+
if @encoder =~ /(nvenc|hevc_qsv|libx26[45])$/
|
1788
|
+
if @maxrate.nil?
|
1789
|
+
maxrate = bitrate * 3
|
1790
|
+
else
|
1791
|
+
maxrate = [[(bitrate * @maxrate).to_i, (bitrate * 1.5).to_i].max, bitrate * 3].min
|
1792
|
+
end
|
1793
|
+
|
1794
|
+
if @bufsize.nil?
|
1795
|
+
bufsize = maxrate if @encoder =~ /^libx26[45]$/
|
1796
|
+
else
|
1797
|
+
bufsize = [[(bitrate * @bufsize).to_i, bitrate].max, bitrate * 4].min
|
1798
|
+
end
|
1799
|
+
end
|
1800
|
+
|
1801
|
+
unless @preset.nil?
|
1440
1802
|
valid = false
|
1441
1803
|
|
1442
1804
|
case @encoder
|
1443
1805
|
when /nvenc$/
|
1444
1806
|
case @preset
|
1445
|
-
when 'fast', 'medium', 'slow'
|
1807
|
+
when 'fast', 'medium', 'slow', /^p[1-7]$/
|
1446
1808
|
valid = true
|
1447
1809
|
end
|
1448
1810
|
when /qsv$/
|
@@ -1459,12 +1821,15 @@ HERE
|
|
1459
1821
|
end
|
1460
1822
|
|
1461
1823
|
fail "invalid preset for encoder: #{@preset}" unless valid
|
1462
|
-
preset = @preset
|
1463
1824
|
end
|
1464
1825
|
|
1465
1826
|
Kernel.warn 'Stream mapping:'
|
1466
|
-
text = "#{sprintf("%2d", video['index'])} = #{@encoder}
|
1467
|
-
|
1827
|
+
text = "#{sprintf("%2d", video['index'])} = #{@encoder}"
|
1828
|
+
|
1829
|
+
unless @encoder == 'copy'
|
1830
|
+
text += " / #{bitrate} Kbps"
|
1831
|
+
text += " / #{@preset}" unless @preset.nil?
|
1832
|
+
end
|
1468
1833
|
|
1469
1834
|
unless burn_subtitle.nil?
|
1470
1835
|
text += " / #{sprintf("%d", burn_subtitle['index'])} = #{burn_subtitle['codec_name']} / burn"
|
@@ -1473,36 +1838,18 @@ HERE
|
|
1473
1838
|
Kernel.warn text
|
1474
1839
|
encode_options += ['-c:v', @encoder]
|
1475
1840
|
encode_options += ['-pix_fmt:v', (@encoder =~ /(nvenc|qsv)$/ ? 'p010le' : 'yuv420p10le')] if @ten_bit
|
1476
|
-
encode_options += ['-b:v', "#{bitrate}k"]
|
1477
|
-
encode_options += ['-maxrate:v', "#{maxrate}k"] if
|
1478
|
-
encode_options += ['-bufsize:v', "#{
|
1479
|
-
encode_options += ['-preset:v', preset] unless preset.nil?
|
1841
|
+
encode_options += ['-b:v', "#{bitrate}k"] unless @encoder == 'copy'
|
1842
|
+
encode_options += ['-maxrate:v', "#{maxrate}k"] if maxrate > 0
|
1843
|
+
encode_options += ['-bufsize:v', "#{bufsize}k"] if bufsize > 0
|
1844
|
+
encode_options += ['-preset:v', @preset] unless @preset.nil?
|
1480
1845
|
encode_options += ['-allow_sw:v', '1'] if @encoder =~ /videotoolbox$/ and @vt_allow_sw
|
1481
1846
|
|
1482
1847
|
if @encoder =~ /nvenc$/
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
if @hevc
|
1487
|
-
spatial_aq_option = '-spatial_aq:v'
|
1488
|
-
temporal_aq_option = '-temporal_aq:v'
|
1489
|
-
else
|
1490
|
-
spatial_aq_option = '-spatial-aq:v'
|
1491
|
-
temporal_aq_option = '-temporal-aq:v'
|
1492
|
-
end
|
1493
|
-
|
1494
|
-
if @preset.nil?
|
1495
|
-
encode_options += ['-rc:v', 'vbr_hq']
|
1496
|
-
spatial_aq = true if @nvenc_spatial_aq.nil?
|
1497
|
-
|
1498
|
-
unless @hevc
|
1499
|
-
temporal_aq = true if @nvenc_temporal_aq.nil?
|
1500
|
-
end
|
1501
|
-
end
|
1502
|
-
|
1503
|
-
encode_options += [spatial_aq_option, '1'] if spatial_aq
|
1504
|
-
encode_options += [temporal_aq_option, '1'] if temporal_aq
|
1848
|
+
encode_options += ['-rc:v', @nvenc_rc_mode]
|
1849
|
+
encode_options += ['-spatial-aq:v', '1'] if @nvenc_spatial_aq
|
1850
|
+
encode_options += ['-temporal-aq:v', '1'] if @nvenc_temporal_aq
|
1505
1851
|
encode_options += ['-rc-lookahead:v', @nvenc_lookahead.to_s] unless @nvenc_lookahead.nil?
|
1852
|
+
encode_options += ['-multipass:v', @nvenc_multipass] unless @nvenc_multipass.nil?
|
1506
1853
|
encode_options += ['-refs:v', @nvenc_refs.to_s] unless @nvenc_refs.nil?
|
1507
1854
|
encode_options += ['-bf:v', @nvenc_bframes.to_s] unless @nvenc_bframes.nil?
|
1508
1855
|
end
|
@@ -1529,29 +1876,59 @@ HERE
|
|
1529
1876
|
|
1530
1877
|
if @encoder == 'libx264'
|
1531
1878
|
encode_options += ['-x264opts:v', 'ratetol=inf'] if @x264_avbr
|
1532
|
-
encode_options += ['-mbtree:v', '0']
|
1879
|
+
encode_options += ['-mbtree:v', '0'] unless @x264_mbtree
|
1533
1880
|
|
1534
|
-
if @preset.nil?
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1881
|
+
if @preset.nil?
|
1882
|
+
if @x264_quick
|
1883
|
+
encode_options += [
|
1884
|
+
'-refs:v', '1',
|
1885
|
+
'-rc-lookahead:v', '30',
|
1886
|
+
'-partitions:v', 'none'
|
1887
|
+
]
|
1888
|
+
end
|
1889
|
+
else
|
1890
|
+
max_refs = [(max_dpb_mbs / (((width + 15) / 16) * ((height + 15) / 16))), 16].min
|
1891
|
+
|
1892
|
+
case @preset
|
1893
|
+
when 'slow'
|
1894
|
+
refs = 5
|
1895
|
+
when 'slower'
|
1896
|
+
refs = 8
|
1897
|
+
when 'veryslow', 'placebo'
|
1898
|
+
refs = 16
|
1899
|
+
else
|
1900
|
+
refs = 0
|
1901
|
+
end
|
1902
|
+
|
1903
|
+
encode_options += ['-refs:v', max_refs.to_s] if refs > max_refs
|
1540
1904
|
end
|
1905
|
+
|
1906
|
+
encode_options += ['-x264-params:v', @x264_params] unless @x264_params.nil?
|
1907
|
+
end
|
1908
|
+
|
1909
|
+
if @encoder == 'libx265'
|
1910
|
+
encode_options += ['-x265-params:v', @x265_params] unless @x265_params.nil?
|
1541
1911
|
end
|
1542
1912
|
|
1543
1913
|
unless @ten_bit
|
1544
1914
|
encode_options += ['-profile:v', 'high'] if @encoder =~ /^(h264_nvenc|h264_amf|libx264)$/
|
1545
1915
|
end
|
1546
1916
|
|
1917
|
+
unless @encoder == 'copy'
|
1918
|
+
encode_options += [
|
1919
|
+
'-color_primaries:v', color_primaries,
|
1920
|
+
'-color_trc:v', color_trc,
|
1921
|
+
'-colorspace:v', colorspace
|
1922
|
+
]
|
1923
|
+
end
|
1924
|
+
|
1547
1925
|
encode_options += [
|
1548
|
-
'-color_primaries:v', color_primaries,
|
1549
|
-
'-color_trc:v', color_trc,
|
1550
|
-
'-colorspace:v', colorspace,
|
1551
1926
|
'-metadata:s:v', 'title=',
|
1552
1927
|
'-disposition:v', 'default'
|
1553
1928
|
]
|
1554
1929
|
|
1930
|
+
encode_options += ['-tag:v', 'hvc1'] if @format == :mp4 and @hevc
|
1931
|
+
|
1555
1932
|
[decode_options, encode_options]
|
1556
1933
|
end
|
1557
1934
|
|
@@ -1577,7 +1954,14 @@ HERE
|
|
1577
1954
|
audio_tracks = [{
|
1578
1955
|
:stream => main_audio,
|
1579
1956
|
:width => width,
|
1580
|
-
:bitrate => width
|
1957
|
+
:bitrate => case width
|
1958
|
+
when :stereo
|
1959
|
+
@stereo_bitrate
|
1960
|
+
when :surround
|
1961
|
+
@surround_bitrate
|
1962
|
+
when :original
|
1963
|
+
nil
|
1964
|
+
end
|
1581
1965
|
}]
|
1582
1966
|
|
1583
1967
|
titles = {}
|
@@ -1590,7 +1974,15 @@ HERE
|
|
1590
1974
|
end
|
1591
1975
|
|
1592
1976
|
width = selection[:width]
|
1593
|
-
|
1977
|
+
|
1978
|
+
bitrate = case width
|
1979
|
+
when :stereo
|
1980
|
+
@stereo_bitrate
|
1981
|
+
when :surround
|
1982
|
+
@surround_bitrate
|
1983
|
+
when :original
|
1984
|
+
nil
|
1985
|
+
end
|
1594
1986
|
|
1595
1987
|
unless selection[:track].nil?
|
1596
1988
|
audio_track = 0
|
@@ -1616,7 +2008,8 @@ HERE
|
|
1616
2008
|
media_info['streams'].each do |stream|
|
1617
2009
|
next if stream['codec_type'] != 'audio'
|
1618
2010
|
|
1619
|
-
if
|
2011
|
+
if (selection[:language] == 'all' or
|
2012
|
+
stream.fetch('tags', {}).fetch('language', '') == selection[:language]) and
|
1620
2013
|
stream['index'] != main_audio['index']
|
1621
2014
|
audio_tracks += [{
|
1622
2015
|
:stream => stream,
|
@@ -1660,28 +2053,37 @@ HERE
|
|
1660
2053
|
bitrate = nil
|
1661
2054
|
channels = nil
|
1662
2055
|
|
1663
|
-
if track[:width] == :
|
1664
|
-
if codec_name == @surround_encoder or codec_name == 'ac3'
|
2056
|
+
if track[:width] == :original
|
1665
2057
|
encoder = 'copy'
|
1666
|
-
|
1667
|
-
|
1668
|
-
|
2058
|
+
else
|
2059
|
+
dts = (codec_name == 'dts' and track[:stream].fetch('profile', 'DTS') =~ /^DTS(?:-ES)?$/)
|
2060
|
+
|
2061
|
+
if track[:width] == :surround
|
2062
|
+
if codec_name == @surround_encoder or
|
2063
|
+
codec_name == 'ac3' or
|
2064
|
+
(@pass_dts and dts)
|
2065
|
+
encoder = 'copy'
|
2066
|
+
elsif input_channels > 2
|
2067
|
+
encoder = @surround_encoder
|
2068
|
+
bitrate = @surround_bitrate
|
2069
|
+
end
|
1669
2070
|
end
|
1670
|
-
end
|
1671
2071
|
|
1672
|
-
|
1673
|
-
|
1674
|
-
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
1679
|
-
|
2072
|
+
if encoder.nil?
|
2073
|
+
if input_channels <= 2 and (codec_name == 'aac' or
|
2074
|
+
((codec_name == @surround_encoder or codec_name == 'ac3') and
|
2075
|
+
(@keep_ac3_stereo or (track[:stream]['bit_rate'].to_i / 1000) <= @stereo_bitrate)) or
|
2076
|
+
(@pass_dts and dts))
|
2077
|
+
encoder = 'copy'
|
2078
|
+
else
|
2079
|
+
encoder = @stereo_encoder
|
2080
|
+
bitrate = @stereo_bitrate
|
1680
2081
|
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
2082
|
+
if input_channels > 2
|
2083
|
+
channels = 2
|
2084
|
+
elsif input_channels == 1
|
2085
|
+
bitrate = @mono_bitrate
|
2086
|
+
end
|
1685
2087
|
end
|
1686
2088
|
end
|
1687
2089
|
end
|
@@ -1764,7 +2166,8 @@ HERE
|
|
1764
2166
|
media_info['streams'].each do |stream|
|
1765
2167
|
next if stream['codec_type'] != 'subtitle'
|
1766
2168
|
|
1767
|
-
if
|
2169
|
+
if (selection[:language] == 'all' or
|
2170
|
+
stream.fetch('tags', {}).fetch('language', '') == selection[:language])
|
1768
2171
|
subtitles += [stream]
|
1769
2172
|
end
|
1770
2173
|
end
|
@@ -1781,10 +2184,7 @@ HERE
|
|
1781
2184
|
end
|
1782
2185
|
end
|
1783
2186
|
|
1784
|
-
unless force_subtitle.nil?
|
1785
|
-
subtitles = [force_subtitle] + subtitles
|
1786
|
-
end
|
1787
|
-
|
2187
|
+
subtitles = [force_subtitle] + subtitles unless force_subtitle.nil?
|
1788
2188
|
subtitles.uniq!
|
1789
2189
|
options = []
|
1790
2190
|
index = 0
|
@@ -1792,9 +2192,6 @@ HERE
|
|
1792
2192
|
subtitles.each do |subtitle|
|
1793
2193
|
next if (not burn_subtitle.nil?) and burn_subtitle['index'] == subtitle['index']
|
1794
2194
|
|
1795
|
-
next if @format == :mp4 and
|
1796
|
-
(subtitle['codec_name'] == 'hdmv_pgs_subtitle' or subtitle['codec_name'] == 'dvd_subtitle')
|
1797
|
-
|
1798
2195
|
force = (index == 0 and not force_subtitle.nil?)
|
1799
2196
|
text = "#{sprintf("%2d", subtitle['index'])} = #{subtitle['codec_name']}"
|
1800
2197
|
text += ' / force' if force
|
@@ -1804,7 +2201,7 @@ HERE
|
|
1804
2201
|
|
1805
2202
|
options += [
|
1806
2203
|
'-map', "0:#{subtitle['index']}",
|
1807
|
-
"-c:s:#{index}", 'copy',
|
2204
|
+
"-c:s:#{index}", ((@format == :mp4 and subtitle['codec_name'] == 'subrip') ? 'mov_text' : 'copy'),
|
1808
2205
|
"-disposition:s:#{index}", (force ? 'default+forced' : '0')
|
1809
2206
|
]
|
1810
2207
|
|