import { FFmpegCommandWrapper, FFmpegCommandWrapperOptions } from './ffmpeg-command-wrapper' export class FFmpegImage { private readonly commandWrapper: FFmpegCommandWrapper constructor (options: FFmpegCommandWrapperOptions) { this.commandWrapper = new FFmpegCommandWrapper(options) } convertWebPToJPG (options: { path: string destination: string }): Promise { const { path, destination } = options this.commandWrapper.buildCommand(path) .output(destination) return this.commandWrapper.runCommand({ silent: true }) } processGIF (options: { path: string destination: string newSize: { width: number, height: number } }): Promise { const { path, destination, newSize } = options this.commandWrapper.buildCommand(path) .fps(20) .size(`${newSize.width}x${newSize.height}`) .output(destination) return this.commandWrapper.runCommand() } async generateThumbnailFromVideo (options: { fromPath: string folder: string imageName: string }) { const { fromPath, folder, imageName } = options const pendingImageName = 'pending-' + imageName const thumbnailOptions = { filename: pendingImageName, count: 1, folder } return new Promise((res, rej) => { this.commandWrapper.buildCommand(fromPath) .on('error', rej) .on('end', () => res(imageName)) .thumbnail(thumbnailOptions) }) } async generateStoryboardFromVideo (options: { path: string destination: string sprites: { size: { width: number height: number } count: { width: number height: number } duration: number } }) { const { path, destination, sprites } = options const command = this.commandWrapper.buildCommand(path) const filter = [ `setpts=N/round(FRAME_RATE)/TB`, `select='not(mod(t,${options.sprites.duration}))'`, `scale=${sprites.size.width}:${sprites.size.height}`, `tile=layout=${sprites.count.width}x${sprites.count.height}` ].join(',') command.outputOption('-filter_complex', filter) command.outputOption('-frames:v', '1') command.outputOption('-q:v', '2') command.output(destination) return this.commandWrapper.runCommand() } }