From 123f61933611f326ea5a5e8c2ea253ee8720e4f0 Mon Sep 17 00:00:00 2001 From: Kimsible <1877318+kimsible@users.noreply.github.com> Date: Wed, 25 Nov 2020 09:26:31 +0100 Subject: [PATCH] Add pixel size to tooltip and gif support with FFmpeg for avatar upload (#3329) * Add avatar pixel size upload in tooltip * Add gif support for avatar * Add ffmpeg GIF process Co-authored-by: kimsible --- .../account/actor-avatar-info.component.html | 3 +- .../account/actor-avatar-info.component.ts | 10 +++--- server/helpers/ffmpeg-utils.ts | 35 +++++++++++++++++++ server/helpers/image-utils.ts | 10 +++++- server/initializers/constants.ts | 2 +- 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/client/src/app/shared/shared-main/account/actor-avatar-info.component.html b/client/src/app/shared/shared-main/account/actor-avatar-info.component.html index d01b9ac7f..e63d8de2d 100644 --- a/client/src/app/shared/shared-main/account/actor-avatar-info.component.html +++ b/client/src/app/shared/shared-main/account/actor-avatar-info.component.html @@ -4,7 +4,8 @@ Avatar
-
+
diff --git a/client/src/app/shared/shared-main/account/actor-avatar-info.component.ts b/client/src/app/shared/shared-main/account/actor-avatar-info.component.ts index 5daa54cb5..de78a390e 100644 --- a/client/src/app/shared/shared-main/account/actor-avatar-info.component.ts +++ b/client/src/app/shared/shared-main/account/actor-avatar-info.component.ts @@ -17,16 +17,12 @@ export class ActorAvatarInfoComponent implements OnInit { @Output() avatarChange = new EventEmitter() - maxSizeText: string - private serverConfig: ServerConfig constructor ( private serverService: ServerService, private notifier: Notifier - ) { - this.maxSizeText = $localize`max size` - } + ) { } ngOnInit (): void { this.serverConfig = this.serverService.getTmpConfig() @@ -58,4 +54,8 @@ export class ActorAvatarInfoComponent implements OnInit { get avatarExtensions () { return this.serverConfig.avatar.file.extensions.join(', ') } + + get avatarFormat () { + return `${$localize`max size`}: 192*192px, ${this.maxAvatarSizeInBytes} ${$localize`extensions`}: ${this.avatarExtensions}` + } } diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts index c8d6969ff..66b9d2e44 100644 --- a/server/helpers/ffmpeg-utils.ts +++ b/server/helpers/ffmpeg-utils.ts @@ -355,6 +355,40 @@ function convertWebPToJPG (path: string, destination: string): Promise { }) } +function processGIF ( + path: string, + destination: string, + newSize: { width: number, height: number }, + keepOriginal = false +): Promise { + return new Promise(async (res, rej) => { + if (path === destination) { + throw new Error('FFmpeg needs an input path different that the output path.') + } + + logger.debug('Processing gif %s to %s.', path, destination) + + try { + const command = ffmpeg(path) + .fps(20) + .size(`${newSize.width}x${newSize.height}`) + .output(destination) + + command.on('error', (err, stdout, stderr) => { + logger.error('Error in ffmpeg gif resizing process.', { stdout, stderr }) + return rej(err) + }) + .on('end', async () => { + if (keepOriginal !== true) await remove(path) + res() + }) + .run() + } catch (err) { + return rej(err) + } + }) +} + function runLiveTranscoding (rtmpUrl: string, outPath: string, resolutions: number[], fps, deleteSegments: boolean) { const command = getFFmpeg(rtmpUrl) command.inputOption('-fflags nobuffer') @@ -474,6 +508,7 @@ export { getAudioStreamCodec, runLiveMuxing, convertWebPToJPG, + processGIF, getVideoStreamSize, getVideoFileResolution, getMetadataFromFile, diff --git a/server/helpers/image-utils.ts b/server/helpers/image-utils.ts index 5f254a7aa..fdf06e848 100644 --- a/server/helpers/image-utils.ts +++ b/server/helpers/image-utils.ts @@ -1,5 +1,6 @@ +import { extname } from 'path' import { remove, rename } from 'fs-extra' -import { convertWebPToJPG } from './ffmpeg-utils' +import { convertWebPToJPG, processGIF } from './ffmpeg-utils' import { logger } from './logger' const Jimp = require('jimp') @@ -10,6 +11,13 @@ async function processImage ( newSize: { width: number, height: number }, keepOriginal = false ) { + const extension = extname(path) + + // Use FFmpeg to process GIF + if (extension === '.gif') { + return processGIF(path, destination, newSize, keepOriginal) + } + if (path === destination) { throw new Error('Jimp needs an input path different that the output path.') } diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 79e6a744c..5c6d06077 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts @@ -291,7 +291,7 @@ const CONSTRAINTS_FIELDS = { PRIVATE_KEY: { min: 10, max: 5000 }, // Length URL: { min: 3, max: 2000 }, // Length AVATAR: { - EXTNAME: [ '.png', '.jpeg', '.jpg' ], + EXTNAME: [ '.png', '.jpeg', '.jpg', '.gif' ], FILE_SIZE: { max: 2 * 1024 * 1024 // 2MB }