mirror of https://github.com/VERT-sh/VERT.git
feat: more conversion settings
This commit is contained in:
parent
1ef2639ca5
commit
3e4ff6bdbe
|
|
@ -88,19 +88,32 @@
|
|||
"quality": "Quality",
|
||||
"depth": "Color depth",
|
||||
"color_space": "Color space",
|
||||
"transparency": "Transparency",
|
||||
"metadata": "Metadata"
|
||||
"transparency": "Transparency"
|
||||
},
|
||||
"audio": {
|
||||
"quality": "Quality",
|
||||
"rate": "Sample rate",
|
||||
"metadata": "Metadata"
|
||||
"bitrate": "Bitrate",
|
||||
"sample_rate": "Sample rate",
|
||||
"channels": "Audio channels"
|
||||
},
|
||||
"video": {
|
||||
"quality": "Quality",
|
||||
"metadata": "Metadata"
|
||||
"metadata": "Metadata",
|
||||
"speed": "Conversion speed",
|
||||
"speed_very_slow": "Very Slow",
|
||||
"speed_slower": "Slower",
|
||||
"speed_slow": "Slow",
|
||||
"speed_medium": "Medium",
|
||||
"speed_fast": "Fast",
|
||||
"speed_ultra_fast": "Ultra Fast",
|
||||
"fps": "Frame rate (FPS)",
|
||||
"fps_placeholder": "Auto",
|
||||
"resolution": "Resolution",
|
||||
"resolution_placeholder": "Auto (e.g., 1920x1080)"
|
||||
},
|
||||
"document": {
|
||||
"something": "Something"
|
||||
},
|
||||
"common": {
|
||||
"metadata": "Metadata"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@
|
|||
checked={file.conversionSettings[
|
||||
setting.key
|
||||
] ?? setting.default}
|
||||
placeholder={setting.placeholder}
|
||||
onchange={(e) =>
|
||||
handleSettingChange(
|
||||
setting.key,
|
||||
|
|
@ -120,6 +121,7 @@
|
|||
value={file.conversionSettings[
|
||||
setting.key
|
||||
] ?? setting.default}
|
||||
placeholder={setting.placeholder}
|
||||
oninput={(e) =>
|
||||
handleSettingChange(
|
||||
setting.key,
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export class Converter {
|
|||
* Can be overridden per converter for format-specific settings.
|
||||
* @param input The input file.
|
||||
*/
|
||||
public getAvailableSettings(input: VertFile): SettingDefinition[] {
|
||||
public async getAvailableSettings(): Promise<SettingDefinition[]> {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
|
@ -63,9 +63,10 @@ export class Converter {
|
|||
* Get default settings for a conversion.
|
||||
* @param input The input file.
|
||||
*/
|
||||
public getDefaultSettings(input: VertFile): ConversionSettings {
|
||||
public async getDefaultSettings(): Promise<ConversionSettings> {
|
||||
const defaults: ConversionSettings = {};
|
||||
this.getAvailableSettings(input).forEach((setting) => {
|
||||
const settings = await this.getAvailableSettings();
|
||||
settings.forEach((setting) => {
|
||||
defaults[setting.key] = setting.default;
|
||||
});
|
||||
return defaults;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ 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 type { SettingDefinition, ConversionSettings } from "$lib/types/conversion-settings";
|
||||
|
||||
// TODO: differentiate in UI? (not native formats)
|
||||
const videoFormats = [
|
||||
|
|
@ -105,6 +106,63 @@ export class FFmpegConverter extends Converter {
|
|||
}
|
||||
}
|
||||
|
||||
public async getAvailableSettings(): Promise<SettingDefinition[]> {
|
||||
// audio - bitrate, sample rate, channels, normalize, trim silence
|
||||
|
||||
// TODO: detect bitrate, sample rate, audio channels and set default/max accordingly
|
||||
|
||||
const bitrate: SettingDefinition = {
|
||||
key: "bitrate",
|
||||
label: m["convert.settings.audio.bitrate"](),
|
||||
type: "select",
|
||||
default: "auto",
|
||||
options: CONVERSION_BITRATES.map((b) => ({
|
||||
value: b.toString(),
|
||||
label: b.toString(),
|
||||
})),
|
||||
};
|
||||
|
||||
const sampleRate: SettingDefinition = {
|
||||
key: "sampleRate",
|
||||
label: m["convert.settings.audio.sample_rate"](),
|
||||
type: "select",
|
||||
default: "auto",
|
||||
options: SAMPLE_RATES.map((r) => ({
|
||||
value: r.toString(),
|
||||
label: r.toString(),
|
||||
})),
|
||||
};
|
||||
|
||||
const channels: SettingDefinition = {
|
||||
key: "channels",
|
||||
label: m["convert.settings.audio.channels"](),
|
||||
type: "number",
|
||||
default: 2,
|
||||
min: 1,
|
||||
max: 8,
|
||||
};
|
||||
|
||||
const metadata: SettingDefinition = {
|
||||
key: "metadata",
|
||||
label: m["convert.settings.common.metadata"](),
|
||||
type: "boolean",
|
||||
default: true,
|
||||
};
|
||||
|
||||
// resize, crop, rotate - prob want a ui
|
||||
|
||||
return [bitrate, sampleRate, channels, metadata];
|
||||
}
|
||||
|
||||
public async getDefaultSettings(): Promise<ConversionSettings> {
|
||||
const defaults: ConversionSettings = {};
|
||||
const settings = await this.getAvailableSettings();
|
||||
settings.forEach((setting) => {
|
||||
defaults[setting.key] = setting.default;
|
||||
});
|
||||
return defaults;
|
||||
}
|
||||
|
||||
public async convert(input: VertFile, to: string): Promise<VertFile> {
|
||||
if (!to.startsWith(".")) to = `.${to}`;
|
||||
|
||||
|
|
|
|||
|
|
@ -116,8 +116,7 @@ export class MagickConverter extends Converter {
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public getAvailableSettings(input: VertFile): SettingDefinition[] {
|
||||
public async getAvailableSettings(): Promise<SettingDefinition[]> {
|
||||
// images - quality/compression/quantize/interlace/depth-DPI, resize, crop, rotate, flip/flop, autoOrient?, color space/bit depth, transparency settings
|
||||
|
||||
const quality: SettingDefinition = {
|
||||
|
|
@ -173,7 +172,7 @@ export class MagickConverter extends Converter {
|
|||
|
||||
const metadata: SettingDefinition = {
|
||||
key: "metadata",
|
||||
label: m["convert.settings.image.metadata"](),
|
||||
label: m["convert.settings.common.metadata"](),
|
||||
type: "boolean",
|
||||
default: true,
|
||||
};
|
||||
|
|
@ -183,9 +182,10 @@ export class MagickConverter extends Converter {
|
|||
return [quality, depth, colorSpace, transparency, metadata];
|
||||
}
|
||||
|
||||
public getDefaultSettings(input: VertFile): ConversionSettings {
|
||||
public async getDefaultSettings(): Promise<ConversionSettings> {
|
||||
const defaults: ConversionSettings = {};
|
||||
this.getAvailableSettings(input).forEach((setting) => {
|
||||
const settings = await this.getAvailableSettings();
|
||||
settings.forEach((setting) => {
|
||||
defaults[setting.key] = setting.default;
|
||||
});
|
||||
return defaults;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ import { Converter, FormatInfo } from "./converter.svelte";
|
|||
import { PUB_DISABLE_FAILURE_BLOCKS } from "$env/static/public";
|
||||
import { ToastManager } from "$lib/util/toast.svelte";
|
||||
import { converters } from "./index";
|
||||
import type {
|
||||
SettingDefinition,
|
||||
ConversionSettings,
|
||||
} from "$lib/types/conversion-settings";
|
||||
|
||||
interface UploadResponse {
|
||||
id: string;
|
||||
|
|
@ -266,7 +270,7 @@ export class VertdConverter extends Converter {
|
|||
new FormatInfo("mov", true, true),
|
||||
new FormatInfo("gif", true, true),
|
||||
new FormatInfo("apng", true, true),
|
||||
new FormatInfo("webp", true, true),
|
||||
new FormatInfo("webp", true, true),
|
||||
new FormatInfo("mts", true, true),
|
||||
new FormatInfo("ts", true, true),
|
||||
new FormatInfo("m2ts", true, true),
|
||||
|
|
@ -347,6 +351,77 @@ export class VertdConverter extends Converter {
|
|||
Settings.instance.save();
|
||||
}
|
||||
|
||||
public async getAvailableSettings(): Promise<SettingDefinition[]> {
|
||||
// video - bitrate, fps, resolution, trim, crop, rotate, flip/flop, audio settings?
|
||||
|
||||
const qualityOptions = [
|
||||
{
|
||||
value: "verySlow",
|
||||
label: m["convert.settings.video.speed_very_slow"](),
|
||||
},
|
||||
{
|
||||
value: "slower",
|
||||
label: m["convert.settings.video.speed_slower"](),
|
||||
},
|
||||
{ value: "slow", label: m["convert.settings.video.speed_slow"]() },
|
||||
{
|
||||
value: "medium",
|
||||
label: m["convert.settings.video.speed_medium"](),
|
||||
},
|
||||
{ value: "fast", label: m["convert.settings.video.speed_fast"]() },
|
||||
{
|
||||
value: "ultraFast",
|
||||
label: m["convert.settings.video.speed_ultra_fast"](),
|
||||
},
|
||||
];
|
||||
|
||||
const quality: SettingDefinition = {
|
||||
key: "vertdSpeed",
|
||||
label: m["convert.settings.video.speed"](),
|
||||
type: "select",
|
||||
default: "medium",
|
||||
options: qualityOptions,
|
||||
};
|
||||
|
||||
// TODO: for fps and resolution, set placeholder to detected values
|
||||
const fps: SettingDefinition = {
|
||||
key: "fps",
|
||||
label: m["convert.settings.video.fps"](),
|
||||
placeholder: m["convert.settings.video.fps_placeholder"](),
|
||||
type: "number",
|
||||
min: 1,
|
||||
};
|
||||
|
||||
const resolution: SettingDefinition = {
|
||||
key: "resolution",
|
||||
label: m["convert.settings.video.resolution"](),
|
||||
placeholder: m["convert.settings.video.resolution_placeholder"](),
|
||||
type: "string",
|
||||
};
|
||||
|
||||
const metadata: SettingDefinition = {
|
||||
key: "metadata",
|
||||
label: m["convert.settings.common.metadata"](),
|
||||
type: "boolean",
|
||||
default: true,
|
||||
};
|
||||
|
||||
// trim/crop/rotate - also have another ui for this prob
|
||||
|
||||
// import all audio settings?
|
||||
|
||||
return [quality, fps, resolution, metadata];
|
||||
}
|
||||
|
||||
public async getDefaultSettings(): Promise<ConversionSettings> {
|
||||
const defaults: ConversionSettings = {};
|
||||
const settings = await this.getAvailableSettings();
|
||||
settings.forEach((setting) => {
|
||||
defaults[setting.key] = setting.default;
|
||||
});
|
||||
return defaults;
|
||||
}
|
||||
|
||||
public async convert(input: VertFile, to: string): Promise<VertFile> {
|
||||
if (to.startsWith(".")) to = to.slice(1);
|
||||
|
||||
|
|
@ -357,10 +432,17 @@ export class VertdConverter extends Converter {
|
|||
// https://trac.ffmpeg.org/ticket/4907
|
||||
if (input.from === ".webp") {
|
||||
this.log(`animated webp detected, converting to gif first`);
|
||||
const magickConverter = converters.find((c) => c.name === "imagemagick");
|
||||
const magickConverter = converters.find(
|
||||
(c) => c.name === "imagemagick",
|
||||
);
|
||||
if (magickConverter) {
|
||||
try {
|
||||
fileUpload = await magickConverter.convert(input, ".gif", 100);
|
||||
fileUpload = await magickConverter.convert(
|
||||
input,
|
||||
".gif",
|
||||
input.conversionSettings,
|
||||
100,
|
||||
);
|
||||
this.log(`successfully converted webp to gif`);
|
||||
} catch (e) {
|
||||
this.log(`failed to convert webp to gif: ${e}`);
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ export type SettingType = "number" | "select" | "boolean" | "string" | "range";
|
|||
|
||||
export interface SettingDefinition {
|
||||
key: string;
|
||||
label: () => string;
|
||||
label: string;
|
||||
type: SettingType;
|
||||
default: any;
|
||||
default?: any;
|
||||
placeholder?: string;
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
|
|
|
|||
|
|
@ -69,4 +69,4 @@ export default defineConfig(({ command }) => {
|
|||
__COMMIT_HASH__: JSON.stringify(commitHash),
|
||||
},
|
||||
};
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue