mirror of https://github.com/VERT-sh/VERT.git
feat: image sequences
This commit is contained in:
parent
95ab5092cf
commit
f210bb886e
|
|
@ -41,8 +41,20 @@
|
|||
let searchQuery = $state("");
|
||||
let rootCategory: string | null = null;
|
||||
|
||||
let imageSequence = $state(false);
|
||||
let imageSequenceFPS = $state(15);
|
||||
// svelte-ignore state_referenced_locally
|
||||
let imageSequence = $state(
|
||||
file?.conversionSettings?.imageSequence ?? false,
|
||||
);
|
||||
// svelte-ignore state_referenced_locally
|
||||
let imageSequenceFPS = $state(
|
||||
file?.conversionSettings?.imageSequenceFPS ?? 15,
|
||||
);
|
||||
|
||||
$effect(() => {
|
||||
if (!file) return;
|
||||
file.conversionSettings.imageSequence = imageSequence;
|
||||
file.conversionSettings.imageSequenceFPS = imageSequenceFPS;
|
||||
});
|
||||
|
||||
const normalize = (str: string) => str.replace(/^\./, "").toLowerCase();
|
||||
|
||||
|
|
@ -59,7 +71,7 @@
|
|||
|
||||
// if imageSequence is checked, filter image category to animated formats only
|
||||
if (imageSequence && cat === "image") {
|
||||
const animatedFormats = [".webp", ".gif"]; // .apng not supported by magick-wasm rn
|
||||
const animatedFormats = [".webp", ".gif", ".apng"]; // .apng not supported by magick-wasm rn
|
||||
formats = formats.filter((f) => animatedFormats.includes(f));
|
||||
}
|
||||
|
||||
|
|
@ -252,7 +264,6 @@
|
|||
onselect?.(allUnfilteredFormats[0]);
|
||||
} else {
|
||||
// no formats available, keeping previous selection
|
||||
|
||||
// i feel like this is all very scuffed and we need a better search and filtering system
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
import { toArgs, animatedImageFormats } from "$lib/converters/ffmpeg.codecs";
|
||||
import type { ConversionSettings } from "$lib/types/conversion-settings";
|
||||
|
||||
export function buildImageSequenceCommand(
|
||||
outputFormat: string,
|
||||
settings: ConversionSettings,
|
||||
isAlac: boolean,
|
||||
): string[] {
|
||||
const to = `.${outputFormat}`;
|
||||
const codecArgs = toArgs(to, isAlac);
|
||||
const baseArgs = [
|
||||
"-f",
|
||||
"concat",
|
||||
"-safe",
|
||||
"0",
|
||||
"-i",
|
||||
"frames.txt",
|
||||
...codecArgs,
|
||||
];
|
||||
const scaleFilter = "scale=trunc(iw/2)*2:trunc(ih/2)*2";
|
||||
const isAnimatedImage = animatedImageFormats.includes(outputFormat);
|
||||
|
||||
if (
|
||||
outputFormat === "mp4" ||
|
||||
outputFormat === "mkv" ||
|
||||
outputFormat === "mov"
|
||||
) {
|
||||
baseArgs.push("-vf", scaleFilter, "-pix_fmt", "yuv420p");
|
||||
} else if (outputFormat === "webm") {
|
||||
baseArgs.push(
|
||||
"-vf",
|
||||
scaleFilter,
|
||||
"-pix_fmt",
|
||||
"yuva420p",
|
||||
"-auto-alt-ref",
|
||||
"0",
|
||||
);
|
||||
} else if (outputFormat === "gif") {
|
||||
baseArgs.push(
|
||||
"-filter_complex",
|
||||
`fps=${settings.imageSequenceFPS || 15},${scaleFilter},split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse`,
|
||||
);
|
||||
} else if (isAnimatedImage) {
|
||||
baseArgs.push("-vf", scaleFilter);
|
||||
if (outputFormat === "apng") baseArgs.push("-plays", "0");
|
||||
} else {
|
||||
baseArgs.push("-vf", scaleFilter, "-pix_fmt", "yuv420p");
|
||||
}
|
||||
|
||||
baseArgs.push("output" + to);
|
||||
return baseArgs;
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
// prettier-ignore
|
||||
export const CONVERSION_BITRATES = ["auto", "custom", 16, 32, 64, 96, 128, 160, 192, 256, 320] as const;
|
||||
|
||||
// prettier-ignore
|
||||
export const SAMPLE_RATES = ["auto", "custom", 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,] as const;
|
||||
|
||||
// prettier-ignore
|
||||
export const videoFormats = ["mkv", "mp4", "avi", "mov", "webm", "ts", "mts", "m2ts", "wmv", "mpg", "mpeg", "flv", "f4v", "vob", "m4v", "3gp", "3g2", "mxf", "ogv", "rm", "rmvb", "divx"];
|
||||
|
||||
// prettier-ignore
|
||||
export const animatedImageFormats = ["gif", "webp", "apng"];
|
||||
|
||||
// prettier-ignore
|
||||
export const lossless = ["flac", "m4a", "caf", "alac", "wav", "dsd", "dsf", "dff"];
|
||||
|
||||
export const getCodecs = (
|
||||
ext: string,
|
||||
isAlac: boolean = false,
|
||||
): { video: string; audio: string } => {
|
||||
switch (ext) {
|
||||
// video <-> audio
|
||||
case ".mp4":
|
||||
case ".mkv":
|
||||
case ".mov":
|
||||
case ".mts":
|
||||
case ".ts":
|
||||
case ".m2ts":
|
||||
case ".flv":
|
||||
case ".f4v":
|
||||
case ".m4v":
|
||||
case ".3gp":
|
||||
case ".3g2":
|
||||
return { video: "libx264", audio: "aac" };
|
||||
case ".wmv":
|
||||
return { video: "wmv2", audio: "wmav2" };
|
||||
case ".webm":
|
||||
case ".ogv":
|
||||
return {
|
||||
video: ext === ".webm" ? "libvpx" : "libtheora",
|
||||
audio: "libvorbis",
|
||||
};
|
||||
case ".avi":
|
||||
case ".divx":
|
||||
return { video: "mpeg4", audio: "libmp3lame" };
|
||||
case ".mpg":
|
||||
case ".mpeg":
|
||||
case ".vob":
|
||||
return { video: "mpeg2video", audio: "mp2" };
|
||||
case ".mxf":
|
||||
return { video: "mpeg2video", audio: "pcm_s16le" };
|
||||
|
||||
// audio
|
||||
case ".mp3":
|
||||
return { video: "libx264", audio: "libmp3lame" };
|
||||
case ".flac":
|
||||
return { video: "libx264", audio: "flac" };
|
||||
case ".wav":
|
||||
return { video: "libx264", audio: "pcm_s16le" };
|
||||
case ".ogg":
|
||||
case ".oga":
|
||||
return { video: "libx264", audio: "libvorbis" };
|
||||
case ".opus":
|
||||
return { video: "libx264", audio: "libopus" };
|
||||
case ".aac":
|
||||
return { video: "libx264", audio: "aac" };
|
||||
case ".m4a":
|
||||
return {
|
||||
video: "libx264",
|
||||
audio: isAlac ? "alac" : "aac",
|
||||
};
|
||||
case ".alac":
|
||||
return { video: "libx264", audio: "alac" };
|
||||
case ".wma":
|
||||
return { video: "libx264", audio: "wmav2" };
|
||||
|
||||
// animated images
|
||||
case ".gif":
|
||||
case ".webp":
|
||||
//case ".apng":
|
||||
return { video: ext.slice(1), audio: "none" };
|
||||
|
||||
default:
|
||||
return { video: "copy", audio: "copy" };
|
||||
}
|
||||
};
|
||||
|
||||
// and here i was, thinking i'd be done with ffmpeg after finishing vertd
|
||||
// but OH NO we just HAD to have someone suggest to allow album art video generation.
|
||||
//
|
||||
// i hate you SO much.
|
||||
// - love, maddie
|
||||
export const toArgs = (ext: string, isAlac: boolean = false): string[] => {
|
||||
const codecs = getCodecs(ext, isAlac);
|
||||
const args = ["-c:v", codecs.video];
|
||||
|
||||
switch (codecs.video) {
|
||||
case "libx264": {
|
||||
args.push(
|
||||
"-preset",
|
||||
"ultrafast",
|
||||
"-crf",
|
||||
"18",
|
||||
"-tune",
|
||||
"stillimage",
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case "libvpx": {
|
||||
args.push("-c:v", "libvpx-vp9");
|
||||
break;
|
||||
}
|
||||
|
||||
case "mpeg2video": {
|
||||
// for mpeg, mpg, vob, mxf
|
||||
if (ext === ".mxf") args.push("-ar", "48000"); // force 48kHz sample rate
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// only add audio codec if not a no-audio format
|
||||
if (codecs.audio !== "none") {
|
||||
args.push("-c:a", codecs.audio);
|
||||
}
|
||||
|
||||
if (codecs.audio === "aac") args.push("-strict", "experimental");
|
||||
|
||||
if (ext === ".divx") args.unshift("-f", "avi");
|
||||
if (ext === ".mxf") args.push("-strict", "unofficial");
|
||||
|
||||
return args;
|
||||
};
|
||||
|
||||
export type ConversionBitrate = (typeof CONVERSION_BITRATES)[number];
|
||||
export type SampleRate = (typeof SAMPLE_RATES)[number];
|
||||
|
|
@ -6,37 +6,21 @@ import { error, log } from "$lib/util/logger";
|
|||
import { m } from "$lib/paraglide/messages";
|
||||
import { Settings } from "$lib/sections/settings/index.svelte";
|
||||
import { ToastManager } from "$lib/util/toast.svelte";
|
||||
import {
|
||||
videoFormats,
|
||||
getCodecs,
|
||||
toArgs,
|
||||
lossless,
|
||||
CONVERSION_BITRATES,
|
||||
SAMPLE_RATES,
|
||||
} from "./ffmpeg.codecs";
|
||||
import { buildImageSequenceCommand } from "./ffmpeg.animated";
|
||||
import type {
|
||||
SettingDefinition,
|
||||
ConversionSettings,
|
||||
} from "$lib/types/conversion-settings";
|
||||
|
||||
// TODO: differentiate in UI? (not native formats)
|
||||
const videoFormats = [
|
||||
"mkv",
|
||||
"mp4",
|
||||
"avi",
|
||||
"mov",
|
||||
"webm",
|
||||
"ts",
|
||||
"mts",
|
||||
"m2ts",
|
||||
"wmv",
|
||||
"mpg",
|
||||
"mpeg",
|
||||
"flv",
|
||||
"f4v",
|
||||
"vob",
|
||||
"m4v",
|
||||
"3gp",
|
||||
"3g2",
|
||||
"mxf",
|
||||
"ogv",
|
||||
"rm",
|
||||
"rmvb",
|
||||
"divx",
|
||||
];
|
||||
|
||||
export class FFmpegConverter extends Converter {
|
||||
private ffmpeg: FFmpeg = null!;
|
||||
public name = "ffmpeg";
|
||||
|
|
@ -415,23 +399,62 @@ export class FFmpegConverter extends Converter {
|
|||
const inputFormat = input.from.slice(1);
|
||||
const outputFormat = to.slice(1);
|
||||
const m4a = isAlac || to === ".m4a";
|
||||
const isImageSequence = input.isZip() && settings.imageSequence;
|
||||
|
||||
const lossless = [
|
||||
"flac",
|
||||
"m4a",
|
||||
"caf",
|
||||
"alac",
|
||||
"wav",
|
||||
"dsd",
|
||||
"dsf",
|
||||
"dff",
|
||||
];
|
||||
const userBitrate = settings.bitrate;
|
||||
const customBitrate = settings.customBitrate;
|
||||
const userSampleRate = settings.sampleRate;
|
||||
const customSampleRate = settings.customSampleRate;
|
||||
const keepMetadata = settings.metadata;
|
||||
|
||||
// image sequences -> animated image // video
|
||||
if (isImageSequence) {
|
||||
this.log(`converting image sequence ${input.name} to ${to}`);
|
||||
|
||||
const { extractZip } = await import("$lib/util/file");
|
||||
const entries = (await extractZip(input.file)).sort((a, b) =>
|
||||
a.filename.localeCompare(b.filename, undefined, {
|
||||
numeric: true,
|
||||
sensitivity: "base",
|
||||
}),
|
||||
);
|
||||
|
||||
if (!entries.length)
|
||||
throw new Error("No images found in zip archive");
|
||||
|
||||
const imageFiles: Array<{ name: string }> = [];
|
||||
|
||||
for (const [index, entry] of entries.entries()) {
|
||||
const fileName =
|
||||
entry.filename.split("/").pop() ?? entry.filename;
|
||||
const ext = fileName.split(".").pop()?.toLowerCase();
|
||||
if (!ext) continue;
|
||||
|
||||
const paddedName = `img${String(index + 1).padStart(5, "0")}.${ext}`;
|
||||
await ffmpeg.writeFile(paddedName, entry.data);
|
||||
imageFiles.push({ name: paddedName });
|
||||
}
|
||||
|
||||
if (!imageFiles.length)
|
||||
throw new Error("No images found in zip archive");
|
||||
|
||||
const listContent = imageFiles
|
||||
.map(
|
||||
(image) =>
|
||||
`file '${image.name}'\nduration ${1 / (settings.imageSequenceFPS || 15)}`,
|
||||
)
|
||||
.join("\n");
|
||||
await ffmpeg.writeFile(
|
||||
"frames.txt",
|
||||
`${listContent}\nfile '${imageFiles[imageFiles.length - 1].name}'\n`,
|
||||
);
|
||||
this.log(`wrote ${imageFiles.length} images to ffmpeg virtual fs`);
|
||||
|
||||
return buildImageSequenceCommand(outputFormat, settings, isAlac);
|
||||
}
|
||||
|
||||
// else normal single file conversion
|
||||
|
||||
let audioBitrateArgs: string[] = [];
|
||||
let sampleRateArgs: string[] = [];
|
||||
let channelsArgs: string[] = [];
|
||||
|
|
@ -683,138 +706,3 @@ export class FFmpegConverter extends Converter {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// and here i was, thinking i'd be done with ffmpeg after finishing vertd
|
||||
// but OH NO we just HAD to have someone suggest to allow album art video generation.
|
||||
//
|
||||
// i hate you SO much.
|
||||
// - love, maddie
|
||||
const toArgs = (ext: string, isAlac: boolean = false): string[] => {
|
||||
const codecs = getCodecs(ext, isAlac);
|
||||
const args = ["-c:v", codecs.video];
|
||||
|
||||
switch (codecs.video) {
|
||||
case "libx264": {
|
||||
args.push(
|
||||
"-preset",
|
||||
"ultrafast",
|
||||
"-crf",
|
||||
"18",
|
||||
"-tune",
|
||||
"stillimage",
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case "libvpx": {
|
||||
args.push("-c:v", "libvpx-vp9");
|
||||
break;
|
||||
}
|
||||
|
||||
case "mpeg2video": {
|
||||
// for mpeg, mpg, vob, mxf
|
||||
if (ext === ".mxf") args.push("-ar", "48000"); // force 48kHz sample rate
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
args.push("-c:a", codecs.audio);
|
||||
|
||||
if (codecs.audio === "aac") args.push("-strict", "experimental");
|
||||
|
||||
if (ext === ".divx") args.unshift("-f", "avi");
|
||||
if (ext === ".mxf") args.push("-strict", "unofficial");
|
||||
|
||||
return args;
|
||||
};
|
||||
|
||||
const getCodecs = (
|
||||
ext: string,
|
||||
isAlac: boolean = false,
|
||||
): { video: string; audio: string } => {
|
||||
switch (ext) {
|
||||
// video <-> audio
|
||||
case ".mp4":
|
||||
case ".mkv":
|
||||
case ".mov":
|
||||
case ".mts":
|
||||
case ".ts":
|
||||
case ".m2ts":
|
||||
case ".flv":
|
||||
case ".f4v":
|
||||
case ".m4v":
|
||||
case ".3gp":
|
||||
case ".3g2":
|
||||
return { video: "libx264", audio: "aac" };
|
||||
case ".wmv":
|
||||
return { video: "wmv2", audio: "wmav2" };
|
||||
case ".webm":
|
||||
case ".ogv":
|
||||
return {
|
||||
video: ext === ".webm" ? "libvpx" : "libtheora",
|
||||
audio: "libvorbis",
|
||||
};
|
||||
case ".avi":
|
||||
case ".divx":
|
||||
return { video: "mpeg4", audio: "libmp3lame" };
|
||||
case ".mpg":
|
||||
case ".mpeg":
|
||||
case ".vob":
|
||||
return { video: "mpeg2video", audio: "mp2" };
|
||||
case ".mxf":
|
||||
return { video: "mpeg2video", audio: "pcm_s16le" };
|
||||
|
||||
// audio
|
||||
case ".mp3":
|
||||
return { video: "libx264", audio: "libmp3lame" };
|
||||
case ".flac":
|
||||
return { video: "libx264", audio: "flac" };
|
||||
case ".wav":
|
||||
return { video: "libx264", audio: "pcm_s16le" };
|
||||
case ".ogg":
|
||||
case ".oga":
|
||||
return { video: "libx264", audio: "libvorbis" };
|
||||
case ".opus":
|
||||
return { video: "libx264", audio: "libopus" };
|
||||
case ".aac":
|
||||
return { video: "libx264", audio: "aac" };
|
||||
case ".m4a":
|
||||
return {
|
||||
video: "libx264",
|
||||
audio: isAlac ? "alac" : "aac",
|
||||
};
|
||||
case ".alac":
|
||||
return { video: "libx264", audio: "alac" };
|
||||
case ".wma":
|
||||
return { video: "libx264", audio: "wmav2" };
|
||||
|
||||
default:
|
||||
return { video: "libx264", audio: "aac" };
|
||||
}
|
||||
};
|
||||
|
||||
export const CONVERSION_BITRATES = [
|
||||
"auto",
|
||||
"custom",
|
||||
320,
|
||||
256,
|
||||
192,
|
||||
128,
|
||||
96,
|
||||
64,
|
||||
32,
|
||||
] as const;
|
||||
export type ConversionBitrate = (typeof CONVERSION_BITRATES)[number];
|
||||
|
||||
export const SAMPLE_RATES = [
|
||||
"auto",
|
||||
"custom",
|
||||
48000,
|
||||
44100,
|
||||
32000,
|
||||
22050,
|
||||
16000,
|
||||
11025,
|
||||
8000,
|
||||
] as const;
|
||||
export type SampleRate = (typeof SAMPLE_RATES)[number];
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import type {
|
|||
SettingDefinition,
|
||||
ConversionSettings,
|
||||
} from "$lib/types/conversion-settings";
|
||||
import { CONVERSION_BITRATES, SAMPLE_RATES } from "./ffmpeg.svelte";
|
||||
import { CONVERSION_BITRATES, SAMPLE_RATES } from "./ffmpeg.codecs";
|
||||
import { ToastManager } from "$lib/util/toast.svelte";
|
||||
import { browser } from "$app/environment";
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import type {
|
|||
SettingDefinition,
|
||||
ConversionSettings,
|
||||
} from "$lib/types/conversion-settings";
|
||||
import { CONVERSION_BITRATES, SAMPLE_RATES } from "./ffmpeg.svelte";
|
||||
import { CONVERSION_BITRATES, SAMPLE_RATES } from "./ffmpeg.codecs";
|
||||
import { formatBytes } from "$lib/util/file";
|
||||
|
||||
interface UploadResponse {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
type ConversionBitrate,
|
||||
SAMPLE_RATES,
|
||||
type SampleRate,
|
||||
} from "$lib/converters/ffmpeg.svelte";
|
||||
} from "$lib/converters/ffmpeg.codecs";
|
||||
import { m } from "$lib/paraglide/messages";
|
||||
import Dropdown from "$lib/components/functional/Dropdown.svelte";
|
||||
import FancyInput from "$lib/components/functional/FancyInput.svelte";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { PUB_VERTD_URL } from "$env/static/public";
|
||||
import type { ConversionBitrate } from "$lib/converters/ffmpeg.svelte";
|
||||
import type { ConversionBitrate } from "$lib/converters/ffmpeg.codecs";
|
||||
import type { ConversionSpeed } from "$lib/converters/vertd.svelte";
|
||||
import { readSettings } from "$lib/util/settings";
|
||||
import { VertdInstance } from "./vertdSettings.svelte";
|
||||
|
|
|
|||
|
|
@ -263,6 +263,13 @@ class Files {
|
|||
this.files.push(vf);
|
||||
this._addThumbnail(vf);
|
||||
|
||||
// set converter
|
||||
// TODO: this is weird, we rely on conversionSettings for the right converter but zip archives obv dont have settings to change
|
||||
vf.conversionSettings = {
|
||||
...vf.conversionSettings,
|
||||
converter: vf.converters[0].name,
|
||||
};
|
||||
|
||||
ToastManager.add({
|
||||
type: "success",
|
||||
message: m["convert.archive_file.detected"]({
|
||||
|
|
|
|||
|
|
@ -175,33 +175,48 @@ export class VertFile {
|
|||
|
||||
if (!this.converters.length) throw new Error("No converters found");
|
||||
|
||||
const customConverter = this.converters.find(
|
||||
(c) => c.name === this.conversionSettings.converter,
|
||||
);
|
||||
let converter = customConverter;
|
||||
let converter: Converter | undefined;
|
||||
const isImageSequence =
|
||||
this.conversionSettings.imageSequence && this.isZip();
|
||||
|
||||
if (!converter) {
|
||||
const compatibleConverters = this.findConverters([
|
||||
this.from,
|
||||
this.to,
|
||||
]);
|
||||
if (compatibleConverters.length) {
|
||||
converter = compatibleConverters[0];
|
||||
log(
|
||||
["file", "convert"],
|
||||
`found compatible converter: ${converter.name}`,
|
||||
);
|
||||
} else {
|
||||
log(
|
||||
["file", "convert"],
|
||||
`no compatible converter found for ${this.from} to ${this.to}`,
|
||||
// force ffmpeg for image sequences
|
||||
// TODO: should allow vertd as well probably(?) but maybe in the future
|
||||
if (isImageSequence) {
|
||||
converter = converters.find((c) => c.name === "ffmpeg");
|
||||
if (!converter) {
|
||||
throw new Error(
|
||||
"FFmpeg converter not found for image sequence conversion",
|
||||
);
|
||||
}
|
||||
} else {
|
||||
log(
|
||||
["file", "convert"],
|
||||
`using custom converter from settings: ${converter.name}`,
|
||||
const customConverter = this.converters.find(
|
||||
(c) => c.name === this.conversionSettings.converter,
|
||||
);
|
||||
converter = customConverter;
|
||||
|
||||
if (!converter) {
|
||||
const compatibleConverters = this.findConverters([
|
||||
this.from,
|
||||
this.to,
|
||||
]);
|
||||
if (compatibleConverters.length) {
|
||||
converter = compatibleConverters[0];
|
||||
log(
|
||||
["file", "convert"],
|
||||
`found compatible converter: ${converter.name}`,
|
||||
);
|
||||
} else {
|
||||
log(
|
||||
["file", "convert"],
|
||||
`no compatible converter found for ${this.from} to ${this.to}`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
log(
|
||||
["file", "convert"],
|
||||
`using custom converter from settings: ${converter.name}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!converter) throw new Error("No converter found");
|
||||
|
|
@ -224,14 +239,15 @@ export class VertFile {
|
|||
try {
|
||||
// for zips: extract > convert each > re-zip
|
||||
// else convert normally
|
||||
res = this.isZip()
|
||||
? await this.convertZip(converter)
|
||||
: await converter.convert(
|
||||
this,
|
||||
this.to,
|
||||
this.conversionSettings,
|
||||
...args,
|
||||
);
|
||||
res =
|
||||
this.isZip() && !this.conversionSettings.imageSequence
|
||||
? await this.convertZip(converter)
|
||||
: await converter.convert(
|
||||
this,
|
||||
this.to,
|
||||
this.conversionSettings,
|
||||
...args,
|
||||
);
|
||||
this.result = res;
|
||||
if (this.fallbackToastId !== null) {
|
||||
ToastManager.remove(this.fallbackToastId);
|
||||
|
|
|
|||
Loading…
Reference in New Issue