feat: mediabunny new formats, fix bugs

This commit is contained in:
Maya 2026-02-27 21:49:56 +03:00
parent 7f888e3f43
commit 9e58c693a0
No known key found for this signature in database
4 changed files with 44 additions and 15 deletions

View File

@ -1,5 +1,6 @@
{ {
"lockfileVersion": 1, "lockfileVersion": 1,
"configVersion": 0,
"workspaces": { "workspaces": {
"": { "": {
"name": "vert", "name": "vert",
@ -17,7 +18,8 @@
"clsx": "^2.1.1", "clsx": "^2.1.1",
"fflate": "^0.8.2", "fflate": "^0.8.2",
"lucide-svelte": "^0.554.0", "lucide-svelte": "^0.554.0",
"music-metadata": "^11.10.1", "mediabunny": "^1.35.1",
"music-metadata": "^11.10.3",
"overlayscrollbars": "^2.12.0", "overlayscrollbars": "^2.12.0",
"overlayscrollbars-svelte": "^0.5.5", "overlayscrollbars-svelte": "^0.5.5",
"p-queue": "^9.0.1", "p-queue": "^9.0.1",
@ -31,7 +33,7 @@
"@inlang/paraglide-js": "^2.5.0", "@inlang/paraglide-js": "^2.5.0",
"@poppanator/sveltekit-svg": "^5.0.1", "@poppanator/sveltekit-svg": "^5.0.1",
"@sveltejs/adapter-static": "^3.0.10", "@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.48.5", "@sveltejs/kit": "^2.49.0",
"@sveltejs/vite-plugin-svelte": "^4.0.4", "@sveltejs/vite-plugin-svelte": "^4.0.4",
"@types/eslint": "^9.6.1", "@types/eslint": "^9.6.1",
"@types/sanitize-html": "^2.16.0", "@types/sanitize-html": "^2.16.0",
@ -44,8 +46,8 @@
"prettier": "^3.6.2", "prettier": "^3.6.2",
"prettier-plugin-svelte": "^3.4.0", "prettier-plugin-svelte": "^3.4.0",
"prettier-plugin-tailwindcss": "^0.6.14", "prettier-plugin-tailwindcss": "^0.6.14",
"sass": "^1.94.1", "sass": "^1.94.2",
"svelte": "^5.43.12", "svelte": "^5.43.14",
"svelte-check": "^4.3.4", "svelte-check": "^4.3.4",
"tailwindcss": "^3.4.18", "tailwindcss": "^3.4.18",
"typescript": "^5.9.3", "typescript": "^5.9.3",
@ -314,6 +316,10 @@
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
"@types/dom-mediacapture-transform": ["@types/dom-mediacapture-transform@0.1.11", "", { "dependencies": { "@types/dom-webcodecs": "*" } }, "sha512-Y2p+nGf1bF2XMttBnsVPHUWzRRZzqUoJAKmiP10b5umnO6DDrWI0BrGDJy1pOHoOULVmGSfFNkQrAlC5dcj6nQ=="],
"@types/dom-webcodecs": ["@types/dom-webcodecs@0.1.13", "", {}, "sha512-O5hkiFIcjjszPIYyUSyvScyvrBoV3NOEEZx/pMlsu44TKzWNkLVBBxnxJz42in5n3QIolYOcBYFCPZZ0h8SkwQ=="],
"@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="],
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
@ -628,6 +634,8 @@
"media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="], "media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
"mediabunny": ["mediabunny@1.35.1", "", { "dependencies": { "@types/dom-mediacapture-transform": "^0.1.11", "@types/dom-webcodecs": "0.1.13" } }, "sha512-VrprpjkLTZyIyhzBAc9D3HqgXarAE+le7+6x0Sdu9WN2SD86L8bUy0hz06Xwf14dVPqS7OwpY2KOhlUyqmI2eQ=="],
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],

View File

@ -51,6 +51,7 @@
"clsx": "^2.1.1", "clsx": "^2.1.1",
"fflate": "^0.8.2", "fflate": "^0.8.2",
"lucide-svelte": "^0.554.0", "lucide-svelte": "^0.554.0",
"mediabunny": "^1.35.1",
"music-metadata": "^11.10.3", "music-metadata": "^11.10.3",
"overlayscrollbars": "^2.12.0", "overlayscrollbars": "^2.12.0",
"overlayscrollbars-svelte": "^0.5.5", "overlayscrollbars-svelte": "^0.5.5",

View File

@ -5,6 +5,7 @@ import { PandocConverter } from "./pandoc.svelte";
import { VertdConverter } from "./vertd.svelte"; import { VertdConverter } from "./vertd.svelte";
import { MagickConverter } from "./magick.svelte"; import { MagickConverter } from "./magick.svelte";
import { DISABLE_ALL_EXTERNAL_REQUESTS } from "$lib/util/consts"; import { DISABLE_ALL_EXTERNAL_REQUESTS } from "$lib/util/consts";
import { MediabunnyConverter } from "./mediabunny.svelte";
const getConverters = (): Converter[] => { const getConverters = (): Converter[] => {
const converters: Converter[] = [ const converters: Converter[] = [
@ -12,10 +13,12 @@ const getConverters = (): Converter[] => {
new FFmpegConverter(), new FFmpegConverter(),
]; ];
if (!DISABLE_ALL_EXTERNAL_REQUESTS) { if (DISABLE_ALL_EXTERNAL_REQUESTS) {
converters.push(new VertdConverter()); converters.push(new VertdConverter());
} }
converters.push(new MediabunnyConverter());
converters.push(new PandocConverter()); converters.push(new PandocConverter());
return converters; return converters;
}; };
@ -45,7 +48,7 @@ categories.audio.formats =
.map((f) => f.name) || []; .map((f) => f.name) || [];
categories.video.formats = categories.video.formats =
converters converters
.find((c) => c.name === "vertd") .find((c) => c.name === "mediabunny")
?.supportedFormats.filter((f) => f.toSupported && f.isNative) ?.supportedFormats.filter((f) => f.toSupported && f.isNative)
.map((f) => f.name) || []; .map((f) => f.name) || [];
categories.image.formats = categories.image.formats =

View File

@ -1,16 +1,19 @@
import { VertFile } from "$lib/types"; import { VertFile } from "$lib/types";
import { import {
ALL_FORMATS, BlobSource,
BufferTarget, BufferTarget,
Conversion, Conversion,
Input, Input,
MATROSKA,
MkvOutputFormat, MkvOutputFormat,
MovOutputFormat, MovOutputFormat,
Mp4InputFormat, MP4,
Mp4OutputFormat, Mp4OutputFormat,
MPEG_TS,
MpegTsOutputFormat,
Output, Output,
ReadableStreamSource, QTFF,
WebMInputFormat, WEBM,
WebMOutputFormat, WebMOutputFormat,
} from "mediabunny"; } from "mediabunny";
import { Converter, FormatInfo, type WorkerStatus } from "./converter.svelte"; import { Converter, FormatInfo, type WorkerStatus } from "./converter.svelte";
@ -22,9 +25,16 @@ export class MediabunnyConverter extends Converter {
public supportedFormats: FormatInfo[] = [ public supportedFormats: FormatInfo[] = [
new FormatInfo("mp4", true, true), new FormatInfo("mp4", true, true),
new FormatInfo("mkv", false, true), new FormatInfo("m4v", true, true),
new FormatInfo("mkv", true, true),
new FormatInfo("webm", true, true), new FormatInfo("webm", true, true),
new FormatInfo("mov", false, true), new FormatInfo("mov", true, true),
// mp4-based formats (should work)
new FormatInfo("f4v", true, true),
new FormatInfo("3gp", true, true),
new FormatInfo("3g2", true, true),
new FormatInfo("ts", true, true),
]; ];
constructor() { constructor() {
@ -32,10 +42,10 @@ export class MediabunnyConverter extends Converter {
} }
public async convert(file: VertFile, to: string): Promise<VertFile> { public async convert(file: VertFile, to: string): Promise<VertFile> {
const stream = file.file.stream(); // ReadableStream<Uint8Array<ArrayBuffer>>
const input = new Input({ const input = new Input({
formats: [new Mp4InputFormat(), new WebMInputFormat()], // TODO: add settings & special handling for certain formats & codecs
source: new ReadableStreamSource(stream), formats: [MP4, QTFF, MATROSKA, WEBM, MPEG_TS],
source: new BlobSource(file.file)
}); });
const toFormat = to.startsWith(".") ? to.slice(1) : to; const toFormat = to.startsWith(".") ? to.slice(1) : to;
@ -81,7 +91,12 @@ export class MediabunnyConverter extends Converter {
private format(ext: string) { private format(ext: string) {
switch (ext) { switch (ext) {
// i'm seeing this "ISMV" format from microsoft, so maybe?
case ".mp4": case ".mp4":
case ".m4v":
case ".f4v":
case ".3gp":
case ".3g2":
return new Mp4OutputFormat(); return new Mp4OutputFormat();
case ".mkv": case ".mkv":
return new MkvOutputFormat(); return new MkvOutputFormat();
@ -89,6 +104,8 @@ export class MediabunnyConverter extends Converter {
return new WebMOutputFormat(); return new WebMOutputFormat();
case ".mov": case ".mov":
return new MovOutputFormat(); return new MovOutputFormat();
case ".ts":
return new MpegTsOutputFormat();
default: default:
throw new Error(`Unsupported format: ${ext}`); throw new Error(`Unsupported format: ${ext}`);
} }