feat: mediabunny progress and cancel

This commit is contained in:
Maya 2026-02-28 00:06:16 +03:00
parent 9e58c693a0
commit ffb6ef856b
3 changed files with 48 additions and 10 deletions

View File

@ -26,7 +26,7 @@
"audio": "Audio", "audio": "Audio",
"documents": "Documents", "documents": "Documents",
"video": "Video", "video": "Video",
"video_server_processing": "Server supported", "video_server_processing": "Local & server supported",
"local_supported": "Local supported", "local_supported": "Local supported",
"status": { "status": {
"text": "<b>Status:</b> {status}", "text": "<b>Status:</b> {status}",

View File

@ -18,10 +18,14 @@ import {
} from "mediabunny"; } from "mediabunny";
import { Converter, FormatInfo, type WorkerStatus } from "./converter.svelte"; import { Converter, FormatInfo, type WorkerStatus } from "./converter.svelte";
import { ToastManager } from "$lib/util/toast.svelte"; import { ToastManager } from "$lib/util/toast.svelte";
import { error, log } from "$lib/util/logger";
export class MediabunnyConverter extends Converter { export class MediabunnyConverter extends Converter {
public name = "mediabunny"; public name = "mediabunny";
public status: WorkerStatus = $state("ready"); public status: WorkerStatus = $state("ready");
public reportsProgress: boolean = true;
private activeConversions = new Map<string, Conversion>();
public supportedFormats: FormatInfo[] = [ public supportedFormats: FormatInfo[] = [
new FormatInfo("mp4", true, true), new FormatInfo("mp4", true, true),
@ -45,12 +49,9 @@ export class MediabunnyConverter extends Converter {
const input = new Input({ const input = new Input({
// TODO: add settings & special handling for certain formats & codecs // TODO: add settings & special handling for certain formats & codecs
formats: [MP4, QTFF, MATROSKA, WEBM, MPEG_TS], formats: [MP4, QTFF, MATROSKA, WEBM, MPEG_TS],
source: new BlobSource(file.file) source: new BlobSource(file.file),
}); });
const toFormat = to.startsWith(".") ? to.slice(1) : to;
const originalName = file.file.name.split(".").slice(0, -1).join(".");
const output = new Output({ const output = new Output({
format: this.format(to), format: this.format(to),
target: new BufferTarget(), target: new BufferTarget(),
@ -72,12 +73,20 @@ export class MediabunnyConverter extends Converter {
throw new Error(`Mediabunny conversion not valid`); throw new Error(`Mediabunny conversion not valid`);
} }
conversion.onProgress = (progress) => {
file.progress = progress * 100;
};
this.activeConversions.set(file.id, conversion);
await conversion.execute(); await conversion.execute();
this.activeConversions.delete(file.id);
if (!output.target.buffer) { if (!output.target.buffer) {
throw new Error("Mediabunny conversion failed: no output buffer"); throw new Error("Mediabunny conversion failed: no output buffer");
} }
const toFormat = to.startsWith(".") ? to.slice(1) : to;
const originalName = file.file.name.split(".").slice(0, -1).join(".");
const f = new File( const f = new File(
[output.target.buffer], [output.target.buffer],
`${originalName}.${toFormat}`, `${originalName}.${toFormat}`,
@ -111,5 +120,22 @@ export class MediabunnyConverter extends Converter {
} }
} }
public async cancel(input: VertFile): Promise<void> {} public async cancel(input: VertFile): Promise<void> {
const conversion = this.activeConversions.get(input.id);
if (!conversion) {
error(
["converters", this.name],
`no active conversion found for file ${input.name}`,
);
return;
}
log(
["converters", this.name],
`cancelling conversion for file ${input.name}`,
);
conversion.cancel();
this.activeConversions.delete(input.id);
}
} }

View File

@ -66,10 +66,20 @@
}; };
if (!DISABLE_ALL_EXTERNAL_REQUESTS) { if (!DISABLE_ALL_EXTERNAL_REQUESTS) {
const formats = Array.from(
new Set([
...getSupportedFormats("vertd").split(", "),
...getSupportedFormats("mediabunny").split(", "),
]),
)
.filter((f) => f !== "none")
.join(", ");
output.Video = { output.Video = {
formats: getSupportedFormats("vertd"), formats,
icon: Film, icon: Film,
title: m["upload.cards.video"](), title: m["upload.cards.video"](),
// TODO: add "partial" state? somehow figure out diff between vertd and mediabunny
status: $vertdLoaded === true ? "ready" : "not-ready", // not using converter.status for this status: $vertdLoaded === true ? "ready" : "not-ready", // not using converter.status for this
}; };
} }
@ -231,9 +241,11 @@
</p> </p>
{/if} {/if}
<p> <p>
{@html sanitize(m["upload.cards.status.text"]({ {@html sanitize(
m["upload.cards.status.text"]({
status: getStatusText(s.status), status: getStatusText(s.status),
}))} }),
)}
</p> </p>
<div <div
class="flex flex-col items-center relative" class="flex flex-col items-center relative"