mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29:46 +00:00
Call ffprobe, improve transcoding
This commit is contained in:
parent
2533d2f469
commit
bd4c94852f
2 changed files with 46 additions and 36 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { extractVideoFrame, transcodeVideo } from '@ditto/transcode';
|
import { analyzeFile, extractVideoFrame, transcodeVideo } from '@ditto/transcode';
|
||||||
import { HTTPException } from '@hono/hono/http-exception';
|
import { HTTPException } from '@hono/hono/http-exception';
|
||||||
import { logi } from '@soapbox/logi';
|
import { logi } from '@soapbox/logi';
|
||||||
import { crypto } from '@std/crypto';
|
import { crypto } from '@std/crypto';
|
||||||
|
|
@ -38,17 +38,27 @@ export async function uploadFile(
|
||||||
|
|
||||||
const [baseType] = file.type.split('/');
|
const [baseType] = file.type.split('/');
|
||||||
|
|
||||||
|
const probe = await analyzeFile(file.stream()).catch(() => null);
|
||||||
|
|
||||||
if (baseType === 'video') {
|
if (baseType === 'video') {
|
||||||
file = new Proxy(file, {
|
let needsTranscode = false;
|
||||||
get(target, prop) {
|
|
||||||
if (prop === 'stream') {
|
for (const stream of probe?.streams ?? []) {
|
||||||
return () => transcodeVideo(target.stream());
|
if (stream.codec_type === 'video' && stream.codec_name !== 'h264') {
|
||||||
} else {
|
needsTranscode = true;
|
||||||
// @ts-ignore This is fine.
|
break;
|
||||||
return target[prop];
|
}
|
||||||
|
if (stream.codec_type === 'audio' && stream.codec_name !== 'aac') {
|
||||||
|
needsTranscode = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsTranscode) {
|
||||||
|
const stream = transcodeVideo(file.stream());
|
||||||
|
const transcoded = await new Response(stream).bytes();
|
||||||
|
file = new File([transcoded], file.name, file);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const tags = await uploader.upload(file, { signal });
|
const tags = await uploader.upload(file, { signal });
|
||||||
|
|
@ -80,24 +90,25 @@ export async function uploadFile(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (baseType === 'video' && (!image || !thumb)) {
|
if (baseType === 'video' && (!image || !thumb)) {
|
||||||
const tmp = new URL('file://' + await Deno.makeTempFile());
|
const bytes = await extractVideoFrame(file.stream());
|
||||||
await Deno.writeFile(tmp, file.stream());
|
|
||||||
const bytes = await extractVideoFrame(tmp);
|
|
||||||
const [[, url]] = await uploader.upload(new File([bytes], 'thumb.jpg', { type: 'image/jpeg' }), { signal });
|
const [[, url]] = await uploader.upload(new File([bytes], 'thumb.jpg', { type: 'image/jpeg' }), { signal });
|
||||||
|
|
||||||
if (!image) {
|
if (!image) {
|
||||||
tags.push(['image', url]);
|
tags.push(['image', url]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!blurhash || !dim) {
|
const video = probe?.streams.find((stream) => stream.codec_type === 'video');
|
||||||
|
|
||||||
|
if (video && video.width && video.height) {
|
||||||
|
if (!dim) {
|
||||||
|
tags.push(['dim', `${video.width}x${video.height}`]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blurhash) {
|
||||||
try {
|
try {
|
||||||
const img = sharp(bytes);
|
const img = sharp(bytes);
|
||||||
const { width, height } = await img.metadata();
|
const { width, height } = await img.metadata();
|
||||||
|
|
||||||
if (!dim && (width && height)) {
|
|
||||||
tags.push(['dim', `${width}x${height}`]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!blurhash && (width && height)) {
|
if (!blurhash && (width && height)) {
|
||||||
const pixels = await img
|
const pixels = await img
|
||||||
.raw()
|
.raw()
|
||||||
|
|
@ -112,8 +123,7 @@ export async function uploadFile(
|
||||||
logi({ level: 'error', ns: 'ditto.upload.analyze', error: errorJson(e) });
|
logi({ level: 'error', ns: 'ditto.upload.analyze', error: errorJson(e) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
await Deno.remove(tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the uploader didn't already, try to get a blurhash and media dimensions.
|
// If the uploader didn't already, try to get a blurhash and media dimensions.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { ffmpeg } from './ffmpeg.ts';
|
import { ffmpeg } from './ffmpeg.ts';
|
||||||
|
|
||||||
export function transcodeVideo(input: ReadableStream<Uint8Array>): ReadableStream<Uint8Array> {
|
export function transcodeVideo(input: URL | ReadableStream<Uint8Array>): ReadableStream<Uint8Array> {
|
||||||
return ffmpeg(input, {
|
return ffmpeg(input, {
|
||||||
'safe': '1', // Safe mode
|
'safe': '1', // Safe mode
|
||||||
'nostdin': '', // Disable stdin
|
'nostdin': '', // Disable stdin
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue