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 }}",
"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!",
"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">
import mime from "mime";
import LibAVWrapper from "$lib/libav";
import { beforeNavigate } from '$app/navigation';
import { openURL } from "$lib/download";
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 FileReceiver from "$components/misc/FileReceiver.svelte";
import { createDialog } from "$lib/dialogs";
import mime from "mime";
let draggedOver = false;
let file: File | Blob | undefined;
let totalDuration: number | undefined;
let processedDuration: number | undefined;
let speed: number | undefined;
let progress = '';
let progress: string | undefined;
$: {
if (totalDuration && processedDuration) {
const percentage = Math.max(0, Math.min(100, (processedDuration / totalDuration) * 100)).toFixed(2);
progress = `${percentage}%, ${speed}x`;
progress = percentage;
} else if (processing) {
progress = 'getting video metadata';
progress = undefined;
speed = undefined;
} else {
progress = '';
progress = undefined;
speed = undefined;
}
}
@ -44,25 +50,51 @@
const render = async () => {
if (!file || processing) return;
await ff.init();
let dialogOpened;
try {
progress = '';
progress = undefined;
speed = undefined;
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) {
return createDialog({
id: "remux-error",
type: "small",
meowbalt: "error",
bodyText: $t("error.remux.corrupted"),
buttons: [
{
text: $t("button.gotit"),
main: true,
action: () => {},
},
],
});
if (!dialogOpened)
return createDialog({
id: "remux-error",
type: "small",
meowbalt: "error",
bodyText: $t("error.remux.corrupted"),
buttons: [
{
text: $t("button.gotit"),
main: true,
action: () => {},
},
],
});
return;
}
totalDuration = Number(file_info.format.duration);
@ -76,6 +108,22 @@
const render = await ff.render({
blob: file,
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) {
@ -87,9 +135,28 @@
} finally {
processing = false;
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) {
render();
}
@ -122,7 +189,16 @@
<div id="remux-processing" class: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}
done!
{/if}
@ -151,12 +227,20 @@
#remux-processing {
position: absolute;
display: flex;
flex-direction: column;
opacity: 0;
transform: scale(0.9);
transition: transform 0.2s, opacity 0.2s;
pointer-events: none;
}
.progress-bar {
height: 20px;
width: 400px;
border-radius: 6px;
background: var(--button);
}
#remux-processing.processing {
opacity: 1;
transform: none;