Write uploads to disk so ffmpeg can seek properly

This commit is contained in:
Alex Gleason 2025-03-01 20:59:14 -06:00
parent c2e6e10a3a
commit 5168ccd748
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
5 changed files with 28 additions and 18 deletions

View file

@ -64,9 +64,12 @@ export async function uploadFile(
}
if (needsTranscode) {
const stream = transcodeVideo(file.stream(), { ffmpegPath });
const tmp = new URL('file://' + await Deno.makeTempFile());
await Deno.writeFile(tmp, file.stream());
const stream = transcodeVideo(tmp, { ffmpegPath });
const transcoded = await new Response(stream).bytes();
file = new File([transcoded], file.name, { type: 'video/mp4' });
await Deno.remove(tmp);
}
}
perf.mark('transcode-end');
@ -108,7 +111,10 @@ export async function uploadFile(
const { width, height } = video;
try {
const bytes = await extractVideoFrame(file.stream(), '00:00:01', { ffmpegPath });
const tmp = new URL('file://' + await Deno.makeTempFile());
await Deno.writeFile(tmp, file.stream());
const bytes = await extractVideoFrame(tmp, '00:00:01', { ffmpegPath });
await Deno.remove(tmp);
const [[, url]] = await uploader.upload(new File([bytes], 'thumb.jpg', { type: 'image/jpeg' }), { signal });
if (!image) {

View file

@ -92,7 +92,7 @@ export function analyzeFile(
opts?: { ffprobePath?: string | URL },
): Promise<AnalyzeResult> {
const stream = ffprobe(input, {
'v': 'error',
'loglevel': 'fatal',
'show_streams': '',
'show_format': '',
'of': 'json',

View file

@ -1,7 +1,9 @@
import { ffmpeg } from './ffmpeg.ts';
const uri = new URL('./buckbunny.mp4', import.meta.url);
Deno.test('ffmpeg', async () => {
await using file = await Deno.open(new URL('./buckbunny.mp4', import.meta.url));
await using file = await Deno.open(uri);
const output = ffmpeg(file.readable, {
'c:v': 'libx264',
@ -12,11 +14,11 @@ Deno.test('ffmpeg', async () => {
});
await Deno.mkdir(new URL('./tmp', import.meta.url), { recursive: true });
await Deno.writeFile(new URL('./tmp/buckbunny-transcoded.mp4', import.meta.url), output);
await Deno.writeFile(new URL('./tmp/transcoded-1.mp4', import.meta.url), output);
});
Deno.test('ffmpeg from file', async () => {
const output = ffmpeg(new URL('./buckbunny.mp4', import.meta.url), {
Deno.test('ffmpeg from file URI', async () => {
const output = ffmpeg(uri, {
'c:v': 'libx264',
'preset': 'veryfast',
'loglevel': 'fatal',
@ -25,5 +27,5 @@ Deno.test('ffmpeg from file', async () => {
});
await Deno.mkdir(new URL('./tmp', import.meta.url), { recursive: true });
await Deno.writeFile(new URL('./tmp/buckbunny-transcoded-fromfile.mp4', import.meta.url), output);
await Deno.writeFile(new URL('./tmp/transcoded-2.mp4', import.meta.url), output);
});

View file

@ -1,9 +1,11 @@
import { assertEquals } from '@std/assert';
import { assertObjectMatch } from '@std/assert';
import { ffprobe } from './ffprobe.ts';
Deno.test('ffprobe', async () => {
await using file = await Deno.open(new URL('./buckbunny.mp4', import.meta.url));
const uri = new URL('./buckbunny.mp4', import.meta.url);
Deno.test('ffprobe from ReadableStream', async () => {
await using file = await Deno.open(uri);
const stream = ffprobe(file.readable, {
'v': 'error',
@ -14,12 +16,10 @@ Deno.test('ffprobe', async () => {
const { streams: [dimensions] } = await new Response(stream).json();
assertEquals(dimensions, { width: 1920, height: 1080 });
assertObjectMatch(dimensions, { width: 1920, height: 1080 });
});
Deno.test('ffprobe from file', async () => {
const uri = new URL('./buckbunny.mp4', import.meta.url);
Deno.test('ffprobe from file URI', async () => {
const stream = ffprobe(uri, {
'v': 'error',
'select_streams': 'v:0',
@ -29,5 +29,5 @@ Deno.test('ffprobe from file', async () => {
const { streams: [dimensions] } = await new Response(stream).json();
assertEquals(dimensions, { width: 1920, height: 1080 });
assertObjectMatch(dimensions, { width: 1920, height: 1080 });
});

View file

@ -1,10 +1,12 @@
import { extractVideoFrame } from './frame.ts';
const uri = new URL('./buckbunny.mp4', import.meta.url);
Deno.test('extractVideoFrame', async () => {
await using file = await Deno.open(new URL('./buckbunny.mp4', import.meta.url));
await using file = await Deno.open(uri);
const result = await extractVideoFrame(file.readable);
await Deno.mkdir(new URL('./tmp', import.meta.url), { recursive: true });
await Deno.writeFile(new URL('./tmp/buckbunny-poster.jpg', import.meta.url), result);
await Deno.writeFile(new URL('./tmp/poster.jpg', import.meta.url), result);
});