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",
"documents": "Documents",
"video": "Video",
"video_server_processing": "Server supported",
"video_server_processing": "Local & server supported",
"local_supported": "Local supported",
"status": {
"text": "<b>Status:</b> {status}",

View File

@ -18,10 +18,14 @@ import {
} from "mediabunny";
import { Converter, FormatInfo, type WorkerStatus } from "./converter.svelte";
import { ToastManager } from "$lib/util/toast.svelte";
import { error, log } from "$lib/util/logger";
export class MediabunnyConverter extends Converter {
public name = "mediabunny";
public status: WorkerStatus = $state("ready");
public reportsProgress: boolean = true;
private activeConversions = new Map<string, Conversion>();
public supportedFormats: FormatInfo[] = [
new FormatInfo("mp4", true, true),
@ -45,12 +49,9 @@ export class MediabunnyConverter extends Converter {
const input = new Input({
// TODO: add settings & special handling for certain formats & codecs
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({
format: this.format(to),
target: new BufferTarget(),
@ -72,12 +73,20 @@ export class MediabunnyConverter extends Converter {
throw new Error(`Mediabunny conversion not valid`);
}
conversion.onProgress = (progress) => {
file.progress = progress * 100;
};
this.activeConversions.set(file.id, conversion);
await conversion.execute();
this.activeConversions.delete(file.id);
if (!output.target.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(
[output.target.buffer],
`${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) {
const formats = Array.from(
new Set([
...getSupportedFormats("vertd").split(", "),
...getSupportedFormats("mediabunny").split(", "),
]),
)
.filter((f) => f !== "none")
.join(", ");
output.Video = {
formats: getSupportedFormats("vertd"),
formats,
icon: Film,
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
};
}
@ -231,9 +241,11 @@
</p>
{/if}
<p>
{@html sanitize(m["upload.cards.status.text"]({
status: getStatusText(s.status),
}))}
{@html sanitize(
m["upload.cards.status.text"]({
status: getStatusText(s.status),
}),
)}
</p>
<div
class="flex flex-col items-center relative"