diff options
-rw-r--r-- | server/helpers/ffmpeg-utils.ts | 47 |
1 files changed, 29 insertions, 18 deletions
diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts index eb1c86ab9..13bce7d30 100644 --- a/server/helpers/ffmpeg-utils.ts +++ b/server/helpers/ffmpeg-utils.ts | |||
@@ -87,7 +87,8 @@ function transcode (options: TranscodeOptions) { | |||
87 | let command = ffmpeg(options.inputPath) | 87 | let command = ffmpeg(options.inputPath) |
88 | .output(options.outputPath) | 88 | .output(options.outputPath) |
89 | .outputOption('-threads ' + CONFIG.TRANSCODING.THREADS) | 89 | .outputOption('-threads ' + CONFIG.TRANSCODING.THREADS) |
90 | .preset(standard) | 90 | .renice(5) // we don't want to make the system unrepsonsive |
91 | .preset(standard) | ||
91 | 92 | ||
92 | let fps = await getVideoFileFPS(options.inputPath) | 93 | let fps = await getVideoFileFPS(options.inputPath) |
93 | if (options.resolution !== undefined) { | 94 | if (options.resolution !== undefined) { |
@@ -154,8 +155,8 @@ function getVideoFileStream (path: string) { | |||
154 | * and quality. Superfast and ultrafast will give you better | 155 | * and quality. Superfast and ultrafast will give you better |
155 | * performance, but then quality is noticeably worse. | 156 | * performance, but then quality is noticeably worse. |
156 | */ | 157 | */ |
157 | function veryfast (ffmpeg) { | 158 | function veryfast (_ffmpeg) { |
158 | ffmpeg | 159 | _ffmpeg |
159 | .preset(standard) | 160 | .preset(standard) |
160 | .outputOption('-preset:v veryfast') | 161 | .outputOption('-preset:v veryfast') |
161 | .outputOption(['--aq-mode=2', '--aq-strength=1.3']) | 162 | .outputOption(['--aq-mode=2', '--aq-strength=1.3']) |
@@ -175,8 +176,8 @@ function veryfast (ffmpeg) { | |||
175 | /** | 176 | /** |
176 | * A preset optimised for a stillimage audio video | 177 | * A preset optimised for a stillimage audio video |
177 | */ | 178 | */ |
178 | function audio (ffmpeg) { | 179 | function audio (_ffmpeg) { |
179 | ffmpeg | 180 | _ffmpeg |
180 | .preset(veryfast) | 181 | .preset(veryfast) |
181 | .outputOption('-tune stillimage') | 182 | .outputOption('-tune stillimage') |
182 | } | 183 | } |
@@ -185,15 +186,22 @@ function audio (ffmpeg) { | |||
185 | * A toolbox to play with audio | 186 | * A toolbox to play with audio |
186 | */ | 187 | */ |
187 | namespace audio { | 188 | namespace audio { |
188 | export const get = (ffmpeg, pos = 0) => { | 189 | export const get = (_ffmpeg, pos: number | string = 0) => { |
189 | // without position, ffprobe considers the last input only | 190 | // without position, ffprobe considers the last input only |
190 | // we make it consider the first input only | 191 | // we make it consider the first input only |
191 | ffmpeg | 192 | // if you pass a file path to pos, then ffprobe acts on that file directly |
192 | .ffprobe(pos, (_,data) => { | 193 | return new Promise<any>((res, rej) => { |
193 | return data['streams'].find(stream => { | 194 | _ffmpeg |
194 | return stream['codec_type'] === 'audio' | 195 | .ffprobe(pos, (err,data) => { |
196 | if (err) return rej(err) | ||
197 | |||
198 | if ('streams' in data) { | ||
199 | return res(data['streams'].find(stream => stream['codec_type'] === 'audio')) | ||
200 | } else { | ||
201 | rej() | ||
202 | } | ||
195 | }) | 203 | }) |
196 | }) | 204 | }) |
197 | } | 205 | } |
198 | 206 | ||
199 | export namespace bitrate { | 207 | export namespace bitrate { |
@@ -229,34 +237,37 @@ namespace audio { | |||
229 | * As for the audio, quality '5' is the highest and ensures 96-112kbps/channel | 237 | * As for the audio, quality '5' is the highest and ensures 96-112kbps/channel |
230 | * See https://trac.ffmpeg.org/wiki/Encode/AAC#fdk_vbr | 238 | * See https://trac.ffmpeg.org/wiki/Encode/AAC#fdk_vbr |
231 | */ | 239 | */ |
232 | async function standard (ffmpeg) { | 240 | async function standard (_ffmpeg) { |
233 | let _bitrate = audio.bitrate.baseKbitrate | 241 | let _bitrate = audio.bitrate.baseKbitrate |
234 | let _ffmpeg = ffmpeg | 242 | let localFfmpeg = _ffmpeg |
235 | .format('mp4') | 243 | .format('mp4') |
236 | .videoCodec('libx264') | 244 | .videoCodec('libx264') |
237 | .outputOption('-level 3.1') // 3.1 is the minimal ressource allocation for our highest supported resolution | 245 | .outputOption('-level 3.1') // 3.1 is the minimal ressource allocation for our highest supported resolution |
238 | .outputOption('-b_strategy 1') // NOTE: b-strategy 1 - heuristic algorythm, 16 is optimal B-frames for it | 246 | .outputOption('-b_strategy 1') // NOTE: b-strategy 1 - heuristic algorythm, 16 is optimal B-frames for it |
239 | .outputOption('-bf 16') // NOTE: Why 16: https://github.com/Chocobozzz/PeerTube/pull/774. b-strategy 2 -> B-frames<16 | 247 | .outputOption('-bf 16') // NOTE: Why 16: https://github.com/Chocobozzz/PeerTube/pull/774. b-strategy 2 -> B-frames<16 |
248 | .outputOption('-map_metadata -1') // strip all metadata | ||
240 | .outputOption('-movflags faststart') | 249 | .outputOption('-movflags faststart') |
241 | let _audio = audio.get(_ffmpeg) | 250 | let _audio = audio.get(localFfmpeg) |
251 | .then(res => res) | ||
252 | .catch(_ => undefined) | ||
242 | 253 | ||
243 | if (!_audio) return _ffmpeg.noAudio() | 254 | if (!_audio) return localFfmpeg.noAudio() |
244 | 255 | ||
245 | // we try to reduce the ceiling bitrate by making rough correspondances of bitrates | 256 | // we try to reduce the ceiling bitrate by making rough correspondances of bitrates |
246 | // of course this is far from perfect, but it might save some space in the end | 257 | // of course this is far from perfect, but it might save some space in the end |
247 | if (audio.bitrate[_audio['codec_name']]) { | 258 | if (audio.bitrate[_audio['codec_name']]) { |
248 | _bitrate = audio.bitrate[_audio['codec_name']](_audio['bit_rate']) | 259 | _bitrate = audio.bitrate[_audio['codec_name']](_audio['bit_rate']) |
249 | if (_bitrate === -1) { | 260 | if (_bitrate === -1) { |
250 | return _ffmpeg.audioCodec('copy') | 261 | return localFfmpeg.audioCodec('copy') |
251 | } | 262 | } |
252 | } | 263 | } |
253 | 264 | ||
254 | // we favor VBR, if a good AAC encoder is available | 265 | // we favor VBR, if a good AAC encoder is available |
255 | if ((await checkFFmpegEncoders()).get('libfdk_aac')) { | 266 | if ((await checkFFmpegEncoders()).get('libfdk_aac')) { |
256 | return _ffmpeg | 267 | return localFfmpeg |
257 | .audioCodec('libfdk_aac') | 268 | .audioCodec('libfdk_aac') |
258 | .audioQuality(5) | 269 | .audioQuality(5) |
259 | } | 270 | } |
260 | 271 | ||
261 | return _ffmpeg.audioBitrate(_bitrate) | 272 | return localFfmpeg.audioBitrate(_bitrate) |
262 | } | 273 | } |