Skip to content

Commit

Permalink
fix: thumbnail generation (better now)
Browse files Browse the repository at this point in the history
  • Loading branch information
diced committed Jun 2, 2024
1 parent 6de3260 commit 75a1d17
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 103 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"fast-glob": "^3.3.2",
"fastify": "^4.26.2",
"fastify-plugin": "^4.5.1",
"ffmpeg-static": "^5.2.0",
"fluent-ffmpeg": "^2.1.3",
"highlight.js": "^11.9.0",
"isomorphic-dompurify": "^1.11.0",
"katex": "^0.16.9",
Expand All @@ -75,6 +75,7 @@
"devDependencies": {
"@types/bytes": "^3.1.4",
"@types/express": "^4.17.21",
"@types/fluent-ffmpeg": "^2.1.24",
"@types/katex": "^0.16.7",
"@types/ms": "^0.7.34",
"@types/multer": "^1.4.11",
Expand Down
95 changes: 35 additions & 60 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions src/components/pages/upload/uploadPartialFiles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ export async function uploadPartialFiles(
() => {
const res: Response['/api/upload'] = JSON.parse(req.responseText);

console.log(res);

if ((res as ErrorBody).message) {
notifications.update({
id: 'upload-partial',
Expand Down
68 changes: 28 additions & 40 deletions src/offload/thumbnails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import { config } from '@/lib/config';
import { datasource } from '@/lib/datasource';
import { prisma } from '@/lib/db';
import { log } from '@/lib/logger';
import { spawn } from 'child_process';
import ffmpegPath from 'ffmpeg-static';
import { createWriteStream } from 'fs';
import ffmpeg from 'fluent-ffmpeg';
import { createWriteStream, readFileSync, unlinkSync } from 'fs';
import { join } from 'path';
import { isMainThread, parentPort, workerData } from 'worker_threads';

Expand All @@ -30,43 +29,31 @@ if (!enabled) {

logger.debug('started thumbnail worker');

async function ffmpeg(file: string): Promise<Buffer | undefined> {
const args = ['-i', file, '-frames:v', '1', '-f', 'mjpeg', 'pipe:1'];

const proc = spawn(ffmpegPath!, args, {
stdio: ['ignore', 'pipe', 'ignore'],
function genThumbnail(file: string, thumbnailTmp: string): Promise<Buffer | undefined> {
return new Promise((resolve, reject) => {
ffmpeg(file)
.videoFilters('thumbnail')
.frames(1)
.format('mjpeg')
.output(thumbnailTmp)
.on('start', (cmd) => {
logger.debug('generating thumbnail', { cmd });
})
.on('error', (err) => {
logger.error('failed to generate thumbnail', { err: err.message });
reject(err);
})
.on('end', () => {
const buffer = readFileSync(thumbnailTmp);

unlinkSync(thumbnailTmp);
unlinkSync(file);
logger.debug('removed temporary files', { file, thumbnail: thumbnailTmp });

resolve(buffer);
})
.run();
});

try {
const buffer = await new Promise<Buffer>((resolve, reject) => {
const data: Buffer[] = [];

proc.stdout!.on('data', (d) => {
data.push(d);
});

proc.once('error', reject);

proc.once('close', (code) => {
if (code !== 0) {
const stringed = Buffer.concat([...data]).toString();

logger.error('ffmpeg exited with non-zero code');

reject(stringed);
} else {
resolve(Buffer.concat([...data]));
}
});
});

return buffer;
} catch (e) {
logger.error('failed to generate thumbnail', {
file,
error: e,
});
}
}

async function generate(ids: string[]) {
Expand Down Expand Up @@ -103,7 +90,8 @@ async function generate(ids: string[]) {
writeStream.on('finish', resolve);
});

const thumbnail = await ffmpeg(tmpFile);
const thumbnailTmpFile = join(config.core.tempDirectory, `zthumbnail_${file.id}.jpg`);
const thumbnail = await genThumbnail(tmpFile, thumbnailTmpFile);
if (!thumbnail) return;

await datasource.put(`.thumbnail.${file.id}.jpg`, thumbnail);
Expand Down

0 comments on commit 75a1d17

Please sign in to comment.