mirror of https://github.com/VERT-sh/VERT.git
feat: further optimisation for massive conversions
This commit is contained in:
parent
fb42680b40
commit
e5df89ac57
|
@ -4,43 +4,41 @@
|
||||||
import Panel from "../visual/Panel.svelte";
|
import Panel from "../visual/Panel.svelte";
|
||||||
import Dropdown from "./Dropdown.svelte";
|
import Dropdown from "./Dropdown.svelte";
|
||||||
import Tooltip from "../visual/Tooltip.svelte";
|
import Tooltip from "../visual/Tooltip.svelte";
|
||||||
|
import ProgressBar from "../visual/ProgressBar.svelte";
|
||||||
|
import { fade } from "$lib/animation";
|
||||||
|
|
||||||
|
const length = $derived(files.files.length);
|
||||||
|
const progress = $derived(files.files.filter((f) => f.result).length);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Panel
|
<Panel class="flex flex-col gap-4">
|
||||||
class="w-full h-auto flex items-center justify-between flex-col md:flex-row gap-4"
|
<div
|
||||||
>
|
class="w-full h-auto flex items-center justify-between flex-col md:flex-row gap-4"
|
||||||
<div class="flex items-center flex-col md:flex-row gap-2.5 max-md:w-full">
|
>
|
||||||
<button
|
<div
|
||||||
onclick={() => files.convertAll()}
|
class="flex items-center flex-col md:flex-row gap-2.5 max-md:w-full"
|
||||||
class="btn {$effects
|
|
||||||
? ''
|
|
||||||
: '!scale-100'} highlight flex gap-3 max-md:w-full"
|
|
||||||
disabled={!files.ready}
|
|
||||||
>
|
>
|
||||||
<RefreshCw size="24" />
|
|
||||||
<p>Convert all</p>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="btn {$effects ? '' : '!scale-100'} flex gap-3 max-md:w-full"
|
|
||||||
disabled={!files.ready || !files.results}
|
|
||||||
onclick={() => files.downloadAll()}
|
|
||||||
>
|
|
||||||
<FolderArchiveIcon size="24" />
|
|
||||||
<p>Download all as .zip</p>
|
|
||||||
</button>
|
|
||||||
{#if $isMobile}
|
|
||||||
<button
|
<button
|
||||||
class="btn p-4 {$effects
|
onclick={() => files.convertAll()}
|
||||||
|
class="btn {$effects
|
||||||
|
? ''
|
||||||
|
: '!scale-100'} highlight flex gap-3 max-md:w-full"
|
||||||
|
disabled={!files.ready}
|
||||||
|
>
|
||||||
|
<RefreshCw size="24" />
|
||||||
|
<p>Convert all</p>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn {$effects
|
||||||
? ''
|
? ''
|
||||||
: '!scale-100'} flex gap-3 max-md:w-full"
|
: '!scale-100'} flex gap-3 max-md:w-full"
|
||||||
disabled={files.files.length === 0}
|
disabled={!files.ready || !files.results}
|
||||||
onclick={() => (files.files = [])}
|
onclick={() => files.downloadAll()}
|
||||||
>
|
>
|
||||||
<Trash2Icon size="24" />
|
<FolderArchiveIcon size="24" />
|
||||||
<p>Remove all files</p>
|
<p>Download all as .zip</p>
|
||||||
</button>
|
</button>
|
||||||
{:else}
|
{#if $isMobile}
|
||||||
<Tooltip text="Remove all files" position="right">
|
|
||||||
<button
|
<button
|
||||||
class="btn p-4 {$effects
|
class="btn p-4 {$effects
|
||||||
? ''
|
? ''
|
||||||
|
@ -49,28 +47,53 @@
|
||||||
onclick={() => (files.files = [])}
|
onclick={() => (files.files = [])}
|
||||||
>
|
>
|
||||||
<Trash2Icon size="24" />
|
<Trash2Icon size="24" />
|
||||||
|
<p>Remove all files</p>
|
||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
{:else}
|
||||||
{/if}
|
<Tooltip text="Remove all files" position="right">
|
||||||
</div>
|
<button
|
||||||
<div class="w-full bg-separator h-0.5 flex md:hidden"></div>
|
class="btn p-4 {$effects
|
||||||
<div class="flex items-center gap-2">
|
? ''
|
||||||
<p class="whitespace-nowrap text-xl">Set all to</p>
|
: '!scale-100'} flex gap-3 max-md:w-full"
|
||||||
{#if files.requiredConverters.length === 1}
|
disabled={files.files.length === 0}
|
||||||
<!-- cannot convert to svg or heif -->
|
onclick={() => (files.files = [])}
|
||||||
{@const supported = files.files[0]?.converters
|
>
|
||||||
.flatMap((c) => c.supportedFormats)
|
<Trash2Icon size="24" />
|
||||||
?.filter((format) => format !== ".svg" && format !== ".heif")}
|
</button>
|
||||||
<Dropdown
|
</Tooltip>
|
||||||
onselect={(r) =>
|
{/if}
|
||||||
files.files.forEach((f) => {
|
</div>
|
||||||
f.to = r;
|
<div class="w-full bg-separator h-0.5 flex md:hidden"></div>
|
||||||
f.result = null;
|
<div class="flex items-center gap-2">
|
||||||
})}
|
<p class="whitespace-nowrap text-xl">Set all to</p>
|
||||||
options={supported || []}
|
{#if files.requiredConverters.length === 1}
|
||||||
/>
|
<!-- cannot convert to svg or heif -->
|
||||||
{:else}
|
{@const supported = files.files[0]?.converters
|
||||||
<Dropdown options={["N/A"]} disabled />
|
.flatMap((c) => c.supportedFormats)
|
||||||
{/if}
|
?.filter(
|
||||||
|
(format) => format !== ".svg" && format !== ".heif",
|
||||||
|
)}
|
||||||
|
<Dropdown
|
||||||
|
onselect={(r) =>
|
||||||
|
files.files.forEach((f) => {
|
||||||
|
f.to = r;
|
||||||
|
f.result = null;
|
||||||
|
})}
|
||||||
|
options={supported || []}
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<Dropdown options={["N/A"]} disabled />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{#if files.files.length > 50}
|
||||||
|
<div class="w-full px-2 flex gap-4 items-center">
|
||||||
|
<div class="flex-shrink-0 -mt-0.5 font-normal text-sm text-muted">
|
||||||
|
{progress}/{length}
|
||||||
|
</div>
|
||||||
|
<div class="flex-grow">
|
||||||
|
<ProgressBar min={0} max={length} {progress} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|
|
@ -23,43 +23,49 @@ class Files {
|
||||||
this.files.length === 0 ? false : this.files.every((f) => f.result),
|
this.files.length === 0 ? false : this.files.every((f) => f.result),
|
||||||
);
|
);
|
||||||
|
|
||||||
private _addThumbnail = async (file: VertFile) => {
|
private thumbnailQueue = new PQueue({
|
||||||
const isAudio = converters
|
concurrency: navigator.hardwareConcurrency || 4,
|
||||||
.find((c) => c.name === "ffmpeg")
|
});
|
||||||
?.supportedFormats?.includes(file.from.toLowerCase());
|
|
||||||
const isVideo = converters
|
|
||||||
.find((c) => c.name === "vertd")
|
|
||||||
?.supportedFormats?.includes(file.from.toLowerCase());
|
|
||||||
|
|
||||||
try {
|
private _addThumbnail = async (file: VertFile) => {
|
||||||
if (isAudio) {
|
this.thumbnailQueue.add(async () => {
|
||||||
// try to get the thumbnail from the audio via music-metadata
|
const isAudio = converters
|
||||||
const { common } = await parseBlob(file.file, {
|
.find((c) => c.name === "ffmpeg")
|
||||||
skipPostHeaders: true,
|
?.supportedFormats?.includes(file.from.toLowerCase());
|
||||||
});
|
const isVideo = converters
|
||||||
const cover = selectCover(common.picture);
|
.find((c) => c.name === "vertd")
|
||||||
if (cover) {
|
?.supportedFormats?.includes(file.from.toLowerCase());
|
||||||
const blob = new Blob([cover.data], {
|
|
||||||
type: cover.format,
|
try {
|
||||||
|
if (isAudio) {
|
||||||
|
// try to get the thumbnail from the audio via music-metadata
|
||||||
|
const { common } = await parseBlob(file.file, {
|
||||||
|
skipPostHeaders: true,
|
||||||
});
|
});
|
||||||
file.blobUrl = URL.createObjectURL(blob);
|
const cover = selectCover(common.picture);
|
||||||
|
if (cover) {
|
||||||
|
const blob = new Blob([cover.data], {
|
||||||
|
type: cover.format,
|
||||||
|
});
|
||||||
|
file.blobUrl = URL.createObjectURL(blob);
|
||||||
|
}
|
||||||
|
} else if (isVideo) {
|
||||||
|
// video
|
||||||
|
file.blobUrl = await this._generateThumbnailFromMedia(
|
||||||
|
file.file,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// image
|
||||||
|
file.blobUrl = await this._generateThumbnailFromMedia(
|
||||||
|
file.file,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if (isVideo) {
|
} catch (e) {
|
||||||
// video
|
error(["files"], e);
|
||||||
file.blobUrl = await this._generateThumbnailFromMedia(
|
|
||||||
file.file,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// image
|
|
||||||
file.blobUrl = await this._generateThumbnailFromMedia(
|
|
||||||
file.file,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
});
|
||||||
error(["files"], e);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private async _generateThumbnailFromMedia(
|
private async _generateThumbnailFromMedia(
|
||||||
|
|
|
@ -29,7 +29,6 @@ export class VertFile {
|
||||||
const converter = this.converters.filter((converter) =>
|
const converter = this.converters.filter((converter) =>
|
||||||
converter.supportedFormats.map((f) => supportedFormats.includes(f)),
|
converter.supportedFormats.map((f) => supportedFormats.includes(f)),
|
||||||
);
|
);
|
||||||
console.log(this.converters, supportedFormats);
|
|
||||||
return converter;
|
return converter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue