import { FileData } from './types/definitions' ;
import { Config } from 'ass-json' ;
import fs from 'fs-extra' ;
import ffmpeg from 'ffmpeg-static' ;
import sharp from 'sharp' ;
// @ts-ignore
import shell from 'any-shell-escape' ;
import { exec } from 'child_process' ;
import { isProd , path } from './utils' ;
const { diskFilePath } : Config = fs . readJsonSync ( path ( 'config.json' ) ) ;
// Thumbnail parameters
const THUMBNAIL = {
QUALITY : 75 ,
WIDTH : 200 * 2 ,
HEIGHT : 140 * 2 ,
}
/ * *
* Builds a safe escaped ffmpeg command
* /
function getCommand ( src : String , dest : String ) {
return shell ( [
ffmpeg , '-y' ,
'-v' , ( isProd ? 'error' : 'debug' ) , // Log level
'-i' , src , // Input file
'-ss' , '00:00:01.000' , // Timestamp of frame to grab
'-vf' , ` scale= ${ THUMBNAIL . WIDTH } : ${ THUMBNAIL . HEIGHT } :force_original_aspect_ratio=increase,crop= ${ THUMBNAIL . WIDTH } : ${ THUMBNAIL . HEIGHT } ` , // Dimensions of output file
'-frames:v' , '1' , // Number of frames to grab
dest // Output file
] ) ;
}
/ * *
* Builds a thumbnail filename
* /
function getNewName ( oldName : String ) {
return oldName . concat ( '.thumbnail.jpg' ) ;
}
/ * *
* Builds a path to the thumbnails
* /
function getNewNamePath ( oldName : String ) {
return path ( diskFilePath , 'thumbnails/' , getNewName ( oldName ) ) ;
}
/ * *
* Extracts an image from a video file to use as a thumbnail , using ffmpeg
* /
function getVideoThumbnail ( file : FileData ) {
return new Promise ( ( resolve : Function , reject : Function ) = > exec (
getCommand ( file . path , getNewNamePath ( file . randomId ) ) ,
// @ts-ignore
( err : Error ) = > ( err ? reject ( err ) : resolve ( ) )
) ) ;
}
/ * *
* Generates a thumbnail for the provided image
* /
function getImageThumbnail ( file : FileData ) {
return new Promise ( ( resolve , reject ) = >
sharp ( file . path )
. resize ( THUMBNAIL . WIDTH , THUMBNAIL . HEIGHT , { kernel : 'cubic' } )
. jpeg ( { quality : THUMBNAIL.QUALITY } )
. toFile ( getNewNamePath ( file . randomId ) )
. then ( resolve )
. catch ( reject ) ) ;
}
/ * *
* Generates a thumbnail
* /
export default ( file : FileData ) : Promise < string > = >
new Promise ( ( resolve , reject ) = >
( file . is . video ? getVideoThumbnail : ( file . is . image && ! file . mimetype . includes ( 'webp' ) ) ? getImageThumbnail : ( ) = > Promise . resolve ( ) ) ( file )
. then ( ( ) = > resolve ( ( file . is . video || file . is . image ) ? getNewName ( file . randomId ) : file . is . audio ? 'views/ass-audio-icon.png' : 'views/ass-file-icon.png' ) )
. catch ( reject ) ) ;