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 }}",
|
"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!",
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue