fix: making the correct image adjustments on the cloud functions (#299)

* fix: making the correct image adjustments on the cloud functions

* fixing lint and timeout issue
This commit is contained in:
Erick
2023-01-05 12:29:16 -03:00
committed by GitHub
parent a5bd535760
commit aa492084bc
4 changed files with 1405 additions and 12 deletions

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@
"firebase-functions": "^4.1.0",
"fluent-ffmpeg": "^2.1.2",
"fs": "^0.0.1-security",
"jimp": "^0.16.2",
"mustache": "^4.2.0",
"uuid": "^9.0.0"
},

View File

@ -120,7 +120,6 @@ function setUpReadable(currentEvent: string) {
return readable;
}
jest.mock('busboy', () => () => {
return {
end: jest.fn(),
@ -135,6 +134,20 @@ jest.mock('busboy', () => () => {
};
});
jest.mock('jimp', () => {
return {
read: jest.fn().mockImplementation((name) => {
const _name = name || '';
return {
bitmap: {
width: _name.indexOf('odd') != -1 ? 501 : 600,
height: _name.indexOf('odd') != -1 ? 301 : 400,
},
};
}),
};
});
jest.mock('fluent-ffmpeg', () => () => {
return {
addInput: jest.fn().mockReturnThis(),
@ -340,6 +353,33 @@ describe('convertToVideo', () => {
).resolves.toBe(`${tempDir}/video.mp4`);
});
describe('when the dimensions of the image are even', () => {
it('keeps the dimension on the scale flag', async () => {
setUpFfmpeg('end');
await convert.convertToVideo(ffmpeg, [ `${tempDir}/frame_1.png` ], tempDir);
expect(ffmpeg.addOptions).toHaveBeenCalledWith([
'-codec:v libx264',
'-s 600x400',
'-pix_fmt yuv420p',
]);
});
});
describe('when the dimensions of the image are odd', () => {
it('uses the nearest (down) even number', async () => {
setUpFfmpeg('end');
await convert.convertToVideo(ffmpeg, [ `${tempDir}/frame_odd.png` ], tempDir);
expect(ffmpeg.addOptions).toHaveBeenCalledWith([
'-codec:v libx264',
'-s 500x300',
'-pix_fmt yuv420p',
]);
});
});
it('throws error when unable to convert frames.', async () => {
setUpFfmpeg('error');

View File

@ -4,6 +4,8 @@ import * as path from 'path';
import { UPLOAD_PATH, ALLOWED_HOSTS } from '../config';
import ffmpeg from 'fluent-ffmpeg';
import Jimp from 'jimp';
import fs from 'fs';
import os from 'os';
import _busboy from 'busboy';
@ -33,7 +35,7 @@ export const convert = functions.https.onRequest(async (req, res) => {
export async function convertImages(
req: functions.https.Request,
): Promise<{
status: number;
status: number,
videoUrl: string,
gifUrl: string,
}> {
@ -59,8 +61,10 @@ export async function convertImages(
const videoPath = await convertToVideo(ffmpeg(), frames, tempDir);
const gifPath = await convertVideoToGif(ffmpeg(), videoPath, tempDir);
const videoUrl = await uploadFile(userId + '.mp4', videoPath);
const gifUrl = await uploadFile(userId + '.gif', gifPath);
const [ videoUrl, gifUrl ] = await Promise.all([
uploadFile(userId + '.mp4', videoPath),
uploadFile(userId + '.gif', gifPath),
]);
return { status: 200, videoUrl, gifUrl };
} catch (error) {
@ -132,16 +136,35 @@ export async function proceedFile(
});
}
function adjustDimensions(width: number, height: number): {
width: number,
height: number,
} {
const w = width % 2 == 0 ? width : width - 1;
const h = height % 2 == 0 ? height : height - 1;
return { width: w, height: h };
}
export async function convertToVideo(
ffmpeg: ffmpeg,
frames: string[],
folder: string
): Promise<string> {
const videoPath = `${folder}/video.mp4`;
const image = await Jimp.read(frames[0]);
const adjustedDimensions = adjustDimensions(
image.bitmap.width,
image.bitmap.height,
);
const scaleArg = `${adjustedDimensions.width}x${adjustedDimensions.height}`;
return new Promise((resolve, reject) => {
ffmpeg
.addInput(folder + '/frame_%d.png')
.addOptions([ '-codec:v libx264', '-s 980x620', '-pix_fmt yuv420p' ])
.addOptions([ '-codec:v libx264', `-s ${scaleArg}`, '-pix_fmt yuv420p' ])
.inputFPS(frames.length / 5)
.mergeToFile(videoPath)
.on('end', () => {