web/remux: handle more errors, add a basic progress bar

This commit is contained in:
wukko 2024-09-05 08:51:41 +06:00
parent 7a5e60f39a
commit 21832005e2
No known key found for this signature in database
GPG key ID: 3E30B3F26C7B4AA2
2 changed files with 108 additions and 22 deletions

View file

@ -4,6 +4,8 @@
"import.unknown": "couldn't load data from the file. it may be corrupted or of wrong format. here's the error i got:\n\n{{ value }}", "import.unknown": "couldn't load data from the file. it may be corrupted or of wrong format. here's the error i got:\n\n{{ value }}",
"remux.corrupted": "couldn't read the metadata from this file, it may be corrupted.", "remux.corrupted": "couldn't read the metadata from this file, it may be corrupted.",
"remux.out_of_resources": "cobalt ran out of resources and can't continue with on-device processing. this is related to limitations on your browser's side. try refreshing or reopening the app and trying again. some devices can only process tiny files.",
"tunnel.probe": "couldn't verify whether you can download this file. try again in a few seconds!", "tunnel.probe": "couldn't verify whether you can download this file. try again in a few seconds!",
"api.auth.jwt.missing": "couldn't confirm whether you're not a robot because the processing server didn't receive the human access token. try again in a few seconds or reload the page!", "api.auth.jwt.missing": "couldn't confirm whether you're not a robot because the processing server didn't receive the human access token. try again in a few seconds or reload the page!",

View file

@ -1,29 +1,35 @@
<script lang="ts"> <script lang="ts">
import mime from "mime";
import LibAVWrapper from "$lib/libav"; import LibAVWrapper from "$lib/libav";
import { beforeNavigate } from '$app/navigation';
import { openURL } from "$lib/download"; import { openURL } from "$lib/download";
import { t } from "$lib/i18n/translations"; import { t } from "$lib/i18n/translations";
import { createDialog } from "$lib/dialogs";
import Skeleton from "$components/misc/Skeleton.svelte";
import DropReceiver from "$components/misc/DropReceiver.svelte"; import DropReceiver from "$components/misc/DropReceiver.svelte";
import FileReceiver from "$components/misc/FileReceiver.svelte"; import FileReceiver from "$components/misc/FileReceiver.svelte";
import { createDialog } from "$lib/dialogs";
import mime from "mime";
let draggedOver = false; let draggedOver = false;
let file: File | Blob | undefined; let file: File | Blob | undefined;
let totalDuration: number | undefined; let totalDuration: number | undefined;
let processedDuration: number | undefined; let processedDuration: number | undefined;
let speed: number | undefined; let speed: number | undefined;
let progress = ''; let progress: string | undefined;
$: { $: {
if (totalDuration && processedDuration) { if (totalDuration && processedDuration) {
const percentage = Math.max(0, Math.min(100, (processedDuration / totalDuration) * 100)).toFixed(2); const percentage = Math.max(0, Math.min(100, (processedDuration / totalDuration) * 100)).toFixed(2);
progress = `${percentage}%, ${speed}x`; progress = percentage;
} else if (processing) { } else if (processing) {
progress = 'getting video metadata'; progress = undefined;
speed = undefined;
} else { } else {
progress = ''; progress = undefined;
speed = undefined;
} }
} }
@ -44,25 +50,51 @@
const render = async () => { const render = async () => {
if (!file || processing) return; if (!file || processing) return;
await ff.init(); await ff.init();
let dialogOpened;
try { try {
progress = ''; progress = undefined;
speed = undefined;
processing = true; processing = true;
const file_info = await ff.probe(file); const file_info = await ff.probe(file).catch(e => {
if (e?.message?.toLowerCase().includes("out of memory")) {
console.error("uh oh! out of memory");
console.error(e);
dialogOpened = true;
return createDialog({
id: "remux-error",
type: "small",
meowbalt: "error",
bodyText: $t("error.remux.out_of_resources"),
buttons: [
{
text: $t("button.gotit"),
main: true,
action: () => {},
},
],
});
}
});
if (!file_info?.format) { if (!file_info?.format) {
return createDialog({ if (!dialogOpened)
id: "remux-error", return createDialog({
type: "small", id: "remux-error",
meowbalt: "error", type: "small",
bodyText: $t("error.remux.corrupted"), meowbalt: "error",
buttons: [ bodyText: $t("error.remux.corrupted"),
{ buttons: [
text: $t("button.gotit"), {
main: true, text: $t("button.gotit"),
action: () => {}, main: true,
}, action: () => {},
], },
}); ],
});
return;
} }
totalDuration = Number(file_info.format.duration); totalDuration = Number(file_info.format.duration);
@ -76,6 +108,22 @@
const render = await ff.render({ const render = await ff.render({
blob: file, blob: file,
args: ['-c', 'copy', '-map', '0'] args: ['-c', 'copy', '-map', '0']
}).catch(e => {
console.error("uh-oh! render error")
console.error(e)
return createDialog({
id: "remux-error",
type: "small",
meowbalt: "error",
bodyText: $t("error.remux.out_of_resources"),
buttons: [
{
text: $t("button.gotit"),
main: true,
action: () => {},
},
],
});
}); });
if (render) { if (render) {
@ -87,9 +135,28 @@
} finally { } finally {
processing = false; processing = false;
file = undefined; file = undefined;
progress = undefined;
speed = undefined;
} }
}; };
const beforeUnloadHandler = (event: BeforeUnloadEvent) => {
event.preventDefault();
};
beforeNavigate((event) => {
if (processing) {
event.cancel();
//TODO: show a popup with an option to kill ongoing processing
}
})
$: if (processing) {
window.addEventListener("beforeunload", beforeUnloadHandler);
} else {
window.removeEventListener("beforeunload", beforeUnloadHandler);
}
$: if (file) { $: if (file) {
render(); render();
} }
@ -122,7 +189,16 @@
<div id="remux-processing" class:processing> <div id="remux-processing" class:processing>
{#if processing} {#if processing}
processing{progress ? ` (${(progress)})` : ''}... {#if progress && speed}
<div class="progress-bar">
<Skeleton width="{progress}%" height="20px" class="elevated" />
</div>
<div class="progress-text">
processing ({progress}%, {speed}x)...
</div>
{:else}
processing...
{/if}
{:else} {:else}
done! done!
{/if} {/if}
@ -151,12 +227,20 @@
#remux-processing { #remux-processing {
position: absolute; position: absolute;
display: flex; display: flex;
flex-direction: column;
opacity: 0; opacity: 0;
transform: scale(0.9); transform: scale(0.9);
transition: transform 0.2s, opacity 0.2s; transition: transform 0.2s, opacity 0.2s;
pointer-events: none; pointer-events: none;
} }
.progress-bar {
height: 20px;
width: 400px;
border-radius: 6px;
background: var(--button);
}
#remux-processing.processing { #remux-processing.processing {
opacity: 1; opacity: 1;
transform: none; transform: none;