mirror of
https://github.com/wukko/cobalt.git
synced 2024-11-15 12:50:01 +00:00
web/remux: handle more errors, add a basic progress bar
This commit is contained in:
parent
7a5e60f39a
commit
21832005e2
2 changed files with 108 additions and 22 deletions
|
@ -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!",
|
||||
|
|
|
@ -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,12 +50,37 @@
|
|||
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) {
|
||||
if (!dialogOpened)
|
||||
return createDialog({
|
||||
id: "remux-error",
|
||||
type: "small",
|
||||
|
@ -63,6 +94,7 @@
|
|||
},
|
||||
],
|
||||
});
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue