import * as ffmpeg from 'fluent-ffmpeg'
+import { join } from 'path'
import { VideoResolution } from '../../shared/models/videos'
-import { CONFIG, MAX_VIDEO_TRANSCODING_FPS } from '../initializers'
+import { CONFIG, VIDEO_TRANSCODING_FPS } from '../initializers'
+import { unlinkPromise } from './core-utils'
import { processImage } from './image-utils'
-import { join } from 'path'
+import { logger } from './logger'
-async function getVideoFileHeight (path: string) {
+async function getVideoFileResolution (path: string) {
const videoStream = await getVideoFileStream(path)
- return videoStream.height
+
+ return {
+ videoFileResolution: Math.min(videoStream.height, videoStream.width),
+ isPortraitMode: videoStream.height > videoStream.width
+ }
}
async function getVideoFileFPS (path: string) {
folder
}
- await new Promise<string>((res, rej) => {
- ffmpeg(fromPath)
- .on('error', rej)
- .on('end', () => res(imageName))
- .thumbnail(options)
- })
-
const pendingImagePath = join(folder, pendingImageName)
- const destination = join(folder, imageName)
- await processImage({ path: pendingImagePath }, destination, size)
+
+ try {
+ await new Promise<string>((res, rej) => {
+ ffmpeg(fromPath)
+ .on('error', rej)
+ .on('end', () => res(imageName))
+ .thumbnail(options)
+ })
+
+ const destination = join(folder, imageName)
+ await processImage({ path: pendingImagePath }, destination, size)
+ } catch (err) {
+ logger.error('Cannot generate image from video %s.', fromPath, { err })
+
+ try {
+ await unlinkPromise(pendingImagePath)
+ } catch (err) {
+ logger.debug('Cannot remove pending image path after generation error.', { err })
+ }
+ }
}
type TranscodeOptions = {
inputPath: string
outputPath: string
resolution?: VideoResolution
+ isPortraitMode?: boolean
}
function transcode (options: TranscodeOptions) {
.outputOption('-movflags faststart')
// .outputOption('-crf 18')
- if (fps > MAX_VIDEO_TRANSCODING_FPS) command = command.withFPS(MAX_VIDEO_TRANSCODING_FPS)
+ // Our player has some FPS limits
+ if (fps > VIDEO_TRANSCODING_FPS.MAX) command = command.withFPS(VIDEO_TRANSCODING_FPS.MAX)
+ else if (fps < VIDEO_TRANSCODING_FPS.MIN) command = command.withFPS(VIDEO_TRANSCODING_FPS.MIN)
if (options.resolution !== undefined) {
- const size = `?x${options.resolution}` // '?x720' for example
+ // '?x720' or '720x?' for example
+ const size = options.isPortraitMode === true ? `${options.resolution}x?` : `?x${options.resolution}`
command = command.size(size)
}
- command.on('error', rej)
- .on('end', res)
- .run()
+ command
+ .on('error', (err, stdout, stderr) => {
+ logger.error('Error in transcoding job.', { stdout, stderr })
+ return rej(err)
+ })
+ .on('end', res)
+ .run()
})
}
// ---------------------------------------------------------------------------
export {
- getVideoFileHeight,
+ getVideoFileResolution,
getDurationFromVideoFile,
generateImageFromVideoFile,
transcode,