aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/helpers/ffmpeg-utils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/helpers/ffmpeg-utils.ts')
-rw-r--r--server/helpers/ffmpeg-utils.ts54
1 files changed, 33 insertions, 21 deletions
diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts
index c170fc1a8..ced56b82d 100644
--- a/server/helpers/ffmpeg-utils.ts
+++ b/server/helpers/ffmpeg-utils.ts
@@ -56,7 +56,7 @@ async function generateImageFromVideoFile (fromPath: string, folder: string, ima
56 56
57 try { 57 try {
58 await new Promise<string>((res, rej) => { 58 await new Promise<string>((res, rej) => {
59 ffmpeg(fromPath, { 'niceness': FFMPEG_NICE.THUMBNAIL }) 59 ffmpeg(fromPath, { niceness: FFMPEG_NICE.THUMBNAIL })
60 .on('error', rej) 60 .on('error', rej)
61 .on('end', () => res(imageName)) 61 .on('end', () => res(imageName))
62 .thumbnail(options) 62 .thumbnail(options)
@@ -84,11 +84,13 @@ type TranscodeOptions = {
84 84
85function transcode (options: TranscodeOptions) { 85function transcode (options: TranscodeOptions) {
86 return new Promise<void>(async (res, rej) => { 86 return new Promise<void>(async (res, rej) => {
87 let command = ffmpeg(options.inputPath, { 'niceness': FFMPEG_NICE.TRANSCODING }) 87 let command = ffmpeg(options.inputPath, { niceness: FFMPEG_NICE.TRANSCODING })
88 .output(options.outputPath) 88 .output(options.outputPath)
89 .preset(standard) 89 .preset(standard)
90
90 if (CONFIG.TRANSCODING.THREADS > 0) { 91 if (CONFIG.TRANSCODING.THREADS > 0) {
91 command.outputOption('-threads ' + CONFIG.TRANSCODING.THREADS) // if we don't set any threads ffmpeg will chose automatically 92 // if we don't set any threads ffmpeg will chose automatically
93 command = command.outputOption('-threads ' + CONFIG.TRANSCODING.THREADS)
92 } 94 }
93 95
94 let fps = await getVideoFileFPS(options.inputPath) 96 let fps = await getVideoFileFPS(options.inputPath)
@@ -131,7 +133,8 @@ export {
131 getDurationFromVideoFile, 133 getDurationFromVideoFile,
132 generateImageFromVideoFile, 134 generateImageFromVideoFile,
133 transcode, 135 transcode,
134 getVideoFileFPS 136 getVideoFileFPS,
137 audio
135} 138}
136 139
137// --------------------------------------------------------------------------- 140// ---------------------------------------------------------------------------
@@ -191,17 +194,21 @@ namespace audio {
191 // without position, ffprobe considers the last input only 194 // without position, ffprobe considers the last input only
192 // we make it consider the first input only 195 // we make it consider the first input only
193 // if you pass a file path to pos, then ffprobe acts on that file directly 196 // if you pass a file path to pos, then ffprobe acts on that file directly
194 return new Promise<any>((res, rej) => { 197 return new Promise<{ absolutePath: string, audioStream?: any }>((res, rej) => {
195 _ffmpeg 198 _ffmpeg.ffprobe(pos, (err,data) => {
196 .ffprobe(pos, (err,data) => { 199 if (err) return rej(err)
197 if (err) return rej(err) 200
198 201 if ('streams' in data) {
199 if ('streams' in data) { 202 const audioStream = data['streams'].find(stream => stream['codec_type'] === 'audio')
200 return res(data['streams'].find(stream => stream['codec_type'] === 'audio')) 203 if (audioStream) {
201 } else { 204 return res({
202 rej() 205 absolutePath: data.format.filename,
206 audioStream
207 })
203 } 208 }
204 }) 209 }
210 return res({ absolutePath: data.format.filename })
211 })
205 }) 212 })
206 } 213 }
207 214
@@ -212,7 +219,7 @@ namespace audio {
212 219
213 export const aac = (bitrate: number): number => { 220 export const aac = (bitrate: number): number => {
214 switch (true) { 221 switch (true) {
215 case bitrate > toBits(384): 222 case bitrate > toBits(baseKbitrate):
216 return baseKbitrate 223 return baseKbitrate
217 default: 224 default:
218 return -1 // we interpret it as a signal to copy the audio stream as is 225 return -1 // we interpret it as a signal to copy the audio stream as is
@@ -220,6 +227,11 @@ namespace audio {
220 } 227 }
221 228
222 export const mp3 = (bitrate: number): number => { 229 export const mp3 = (bitrate: number): number => {
230 /*
231 a 192kbit/sec mp3 doesn't hold as much information as a 192kbit/sec aac.
232 That's why, when using aac, we can go to lower kbit/sec. The equivalences
233 made here are not made to be accurate, especially with good mp3 encoders.
234 */
223 switch (true) { 235 switch (true) {
224 case bitrate <= toBits(192): 236 case bitrate <= toBits(192):
225 return 128 237 return 128
@@ -248,16 +260,16 @@ async function standard (_ffmpeg) {
248 .outputOption('-bf 16') // NOTE: Why 16: https://github.com/Chocobozzz/PeerTube/pull/774. b-strategy 2 -> B-frames<16 260 .outputOption('-bf 16') // NOTE: Why 16: https://github.com/Chocobozzz/PeerTube/pull/774. b-strategy 2 -> B-frames<16
249 .outputOption('-map_metadata -1') // strip all metadata 261 .outputOption('-map_metadata -1') // strip all metadata
250 .outputOption('-movflags faststart') 262 .outputOption('-movflags faststart')
251 let _audio = audio.get(localFfmpeg) 263 const _audio = await audio.get(localFfmpeg)
252 .then(res => res)
253 .catch(_ => undefined)
254 264
255 if (!_audio) return localFfmpeg.noAudio() 265 if (!_audio.audioStream) {
266 return localFfmpeg.noAudio()
267 }
256 268
257 // we try to reduce the ceiling bitrate by making rough correspondances of bitrates 269 // we try to reduce the ceiling bitrate by making rough correspondances of bitrates
258 // of course this is far from perfect, but it might save some space in the end 270 // of course this is far from perfect, but it might save some space in the end
259 if (audio.bitrate[_audio['codec_name']]) { 271 if (audio.bitrate[_audio.audioStream['codec_name']]) {
260 _bitrate = audio.bitrate[_audio['codec_name']](_audio['bit_rate']) 272 _bitrate = audio.bitrate[_audio.audioStream['codec_name']](_audio.audioStream['bit_rate'])
261 if (_bitrate === -1) { 273 if (_bitrate === -1) {
262 return localFfmpeg.audioCodec('copy') 274 return localFfmpeg.audioCodec('copy')
263 } 275 }