mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
feat(server, web): accepted codecs (#6460)
* chore: rebase * chore: open api --------- Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
parent
96b7885583
commit
8aef92affc
14 changed files with 181 additions and 10 deletions
|
|
@ -9,6 +9,7 @@
|
|||
import { handleError } from '$lib/utils/handle-error';
|
||||
import type { SettingsEventType } from './admin-settings';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
export let config: SystemConfigDto;
|
||||
|
||||
|
|
@ -25,16 +26,17 @@
|
|||
}
|
||||
};
|
||||
|
||||
const handleSave = async (config: Partial<SystemConfigDto>) => {
|
||||
const handleSave = async (update: Partial<SystemConfigDto>) => {
|
||||
try {
|
||||
const result = await api.systemConfigApi.updateConfig({
|
||||
const { data: newConfig } = await api.systemConfigApi.updateConfig({
|
||||
systemConfigDto: {
|
||||
...savedConfig,
|
||||
...config,
|
||||
...update,
|
||||
},
|
||||
});
|
||||
|
||||
savedConfig = { ...result.data };
|
||||
config = cloneDeep(newConfig);
|
||||
savedConfig = cloneDeep(newConfig);
|
||||
notificationController.show({ message: 'Settings saved', type: NotificationType.Info });
|
||||
|
||||
dispatch('save');
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@
|
|||
import SettingInputField, { SettingInputFieldType } from '../setting-input-field.svelte';
|
||||
import SettingSelect from '../setting-select.svelte';
|
||||
import SettingSwitch from '../setting-switch.svelte';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import SettingCheckboxes from '../setting-checkboxes.svelte';
|
||||
import { isEqual, sortBy } from 'lodash-es';
|
||||
import { fade } from 'svelte/transition';
|
||||
import SettingAccordion from '../setting-accordion.svelte';
|
||||
import { mdiHelpCircleOutline } from '@mdi/js';
|
||||
|
|
@ -89,6 +90,21 @@
|
|||
]}
|
||||
name="acodec"
|
||||
isEdited={config.ffmpeg.targetAudioCodec !== savedConfig.ffmpeg.targetAudioCodec}
|
||||
on:select={() => (config.ffmpeg.acceptedAudioCodecs = [config.ffmpeg.targetAudioCodec])}
|
||||
/>
|
||||
|
||||
<SettingCheckboxes
|
||||
label="ACCEPTED AUDIO CODECS"
|
||||
{disabled}
|
||||
desc="Select which audio codecs do not need to be transcoded. Only used for certain transcode policies."
|
||||
bind:value={config.ffmpeg.acceptedAudioCodecs}
|
||||
name="audioCodecs"
|
||||
options={[
|
||||
{ value: AudioCodec.Aac, text: 'AAC' },
|
||||
{ value: AudioCodec.Mp3, text: 'MP3' },
|
||||
{ value: AudioCodec.Libopus, text: 'Opus' },
|
||||
]}
|
||||
isEdited={!isEqual(sortBy(config.ffmpeg.acceptedAudioCodecs), sortBy(savedConfig.ffmpeg.acceptedAudioCodecs))}
|
||||
/>
|
||||
|
||||
<SettingSelect
|
||||
|
|
@ -103,6 +119,21 @@
|
|||
]}
|
||||
name="vcodec"
|
||||
isEdited={config.ffmpeg.targetVideoCodec !== savedConfig.ffmpeg.targetVideoCodec}
|
||||
on:select={() => (config.ffmpeg.acceptedVideoCodecs = [config.ffmpeg.targetVideoCodec])}
|
||||
/>
|
||||
|
||||
<SettingCheckboxes
|
||||
label="ACCEPTED VIDEO CODECS"
|
||||
{disabled}
|
||||
desc="Select which video codecs do not need to be transcoded. Only used for certain transcode policies."
|
||||
bind:value={config.ffmpeg.acceptedVideoCodecs}
|
||||
name="videoCodecs"
|
||||
options={[
|
||||
{ value: VideoCodec.H264, text: 'H.264' },
|
||||
{ value: VideoCodec.Hevc, text: 'HEVC' },
|
||||
{ value: VideoCodec.Vp9, text: 'VP9' },
|
||||
]}
|
||||
isEdited={!isEqual(sortBy(config.ffmpeg.acceptedVideoCodecs), sortBy(savedConfig.ffmpeg.acceptedVideoCodecs))}
|
||||
/>
|
||||
|
||||
<SettingSelect
|
||||
|
|
@ -150,11 +181,11 @@
|
|||
{ value: TranscodePolicy.All, text: 'All videos' },
|
||||
{
|
||||
value: TranscodePolicy.Optimal,
|
||||
text: 'Videos higher than target resolution or not in the desired format',
|
||||
text: 'Videos higher than target resolution or not in an accepted format',
|
||||
},
|
||||
{
|
||||
value: TranscodePolicy.Required,
|
||||
text: 'Only videos not in the desired format',
|
||||
text: 'Only videos not in an accepted format',
|
||||
},
|
||||
{
|
||||
value: TranscodePolicy.Disabled,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
<script lang="ts">
|
||||
import { quintOut } from 'svelte/easing';
|
||||
import { fly } from 'svelte/transition';
|
||||
|
||||
export let value: string[];
|
||||
export let options: { value: string; text: string }[];
|
||||
export let label = '';
|
||||
export let desc = '';
|
||||
export let name = '';
|
||||
export let isEdited = false;
|
||||
export let disabled = false;
|
||||
|
||||
function handleCheckboxChange(option: string) {
|
||||
if (value.includes(option)) {
|
||||
value = value.filter((item) => item !== option);
|
||||
} else {
|
||||
value = [...value, option];
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="mb-4 w-full">
|
||||
<div class={`flex h-[26px] place-items-center gap-1`}>
|
||||
<label class={`immich-form-label text-sm`} for="{name}-select">{label}</label>
|
||||
|
||||
{#if isEdited}
|
||||
<div
|
||||
transition:fly={{ x: 10, duration: 200, easing: quintOut }}
|
||||
class="rounded-full bg-orange-100 px-2 text-[10px] text-orange-900"
|
||||
>
|
||||
Unsaved change
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if desc}
|
||||
<p class="immich-form-label pb-2 text-sm" id="{name}-desc">
|
||||
{desc}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
{#each options as option}
|
||||
<label class="flex items-center mb-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="form-checkbox h-5 w-5 color"
|
||||
{disabled}
|
||||
checked={value.includes(option.value)}
|
||||
on:change={() => handleCheckboxChange(option.value)}
|
||||
/>
|
||||
<span class="ml-2 text-sm text-gray-500 dark:text-gray-300 pt-1">{option.text}</span>
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { quintOut } from 'svelte/easing';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
export let value: string | number;
|
||||
export let options: { value: string | number; text: string }[];
|
||||
|
|
@ -11,11 +12,14 @@
|
|||
export let number = false;
|
||||
export let disabled = false;
|
||||
|
||||
const dispatch = createEventDispatcher<{ select: string | number }>();
|
||||
|
||||
const handleChange = (e: Event) => {
|
||||
value = (e.target as HTMLInputElement).value;
|
||||
if (number) {
|
||||
value = parseInt(value);
|
||||
}
|
||||
dispatch('select', value);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue