volume panel; copilot instructions

This commit is contained in:
2026-04-15 16:10:35 -06:00
parent 0df967507f
commit 4f90750497
11 changed files with 688 additions and 106 deletions

View File

@ -6,6 +6,7 @@ import type {
DeletedRange,
CutRange,
MuteRange,
GainRange,
TranscriptionResult,
ProjectFile,
SilenceDetectionRange,
@ -22,6 +23,8 @@ interface EditorState {
deletedRanges: DeletedRange[];
cutRanges: CutRange[];
muteRanges: MuteRange[];
gainRanges: GainRange[];
globalGainDb: number;
silenceTrimGroups: SilenceTrimGroup[];
transcriptionModel: string | null;
language: string;
@ -59,10 +62,14 @@ interface EditorActions {
restoreRange: (rangeId: string) => void;
addCutRange: (start: number, end: number, trimGroupId?: string) => void;
addMuteRange: (start: number, end: number) => void;
addGainRange: (start: number, end: number, gainDb: number) => void;
updateCutRange: (id: string, start: number, end: number) => void;
updateMuteRange: (id: string, start: number, end: number) => void;
updateGainRange: (id: string, gainDb: number) => void;
removeCutRange: (id: string) => void;
removeMuteRange: (id: string) => void;
removeGainRange: (id: string) => void;
setGlobalGainDb: (gainDb: number) => void;
applySilenceTrimGroup: (args: {
groupId?: string;
sourceRanges: SilenceDetectionRange[];
@ -86,6 +93,8 @@ const initialState: EditorState = {
deletedRanges: [],
cutRanges: [],
muteRanges: [],
gainRanges: [],
globalGainDb: 0,
silenceTrimGroups: [],
transcriptionModel: null,
language: '',
@ -142,7 +151,7 @@ export const useEditorStore = create<EditorState & EditorActions>()(
setTranscriptionModel: (model) => set({ transcriptionModel: model }),
saveProject: (): ProjectFile => {
const { videoPath, words, segments, deletedRanges, cutRanges, muteRanges, silenceTrimGroups, transcriptionModel, language, exportedAudioPath } = get();
const { videoPath, words, segments, deletedRanges, cutRanges, muteRanges, gainRanges, globalGainDb, silenceTrimGroups, transcriptionModel, language, exportedAudioPath } = get();
if (!videoPath) throw new Error('No video loaded');
const now = new Date().toISOString();
// Strip globalStartIndex (runtime-only field) before persisting
@ -157,6 +166,8 @@ export const useEditorStore = create<EditorState & EditorActions>()(
deletedRanges,
cutRanges,
muteRanges,
gainRanges,
globalGainDb,
silenceTrimGroups,
language,
createdAt: now, // will be overwritten if we track original creation time later
@ -259,6 +270,17 @@ export const useEditorStore = create<EditorState & EditorActions>()(
set({ muteRanges: [...muteRanges, newRange] });
},
addGainRange: (start, end, gainDb) => {
const { gainRanges } = get();
const newRange: GainRange = {
id: `gain_${nextRangeId++}`,
start,
end,
gainDb,
};
set({ gainRanges: [...gainRanges, newRange] });
},
updateCutRange: (id, start, end) => {
const { cutRanges } = get();
set({
@ -277,6 +299,15 @@ export const useEditorStore = create<EditorState & EditorActions>()(
});
},
updateGainRange: (id, gainDb) => {
const { gainRanges } = get();
set({
gainRanges: gainRanges.map((r) =>
r.id === id ? { ...r, gainDb } : r
),
});
},
removeCutRange: (id) => {
const { cutRanges } = get();
set({ cutRanges: cutRanges.filter((r) => r.id !== id) });
@ -287,6 +318,15 @@ export const useEditorStore = create<EditorState & EditorActions>()(
set({ muteRanges: muteRanges.filter((r) => r.id !== id) });
},
removeGainRange: (id) => {
const { gainRanges } = get();
set({ gainRanges: gainRanges.filter((r) => r.id !== id) });
},
setGlobalGainDb: (gainDb) => {
set({ globalGainDb: Math.max(-24, Math.min(24, gainDb)) });
},
applySilenceTrimGroup: ({ groupId, sourceRanges, settings }) => {
const { duration, cutRanges, silenceTrimGroups } = get();
const now = new Date().toISOString();
@ -415,6 +455,8 @@ export const useEditorStore = create<EditorState & EditorActions>()(
deletedRanges: data.deletedRanges || [],
cutRanges: data.cutRanges || [],
muteRanges: data.muteRanges || [],
gainRanges: data.gainRanges || [],
globalGainDb: typeof data.globalGainDb === 'number' ? data.globalGainDb : 0,
silenceTrimGroups: data.silenceTrimGroups || [],
transcriptionModel: data.transcriptionModel ?? null,
language: data.language || '',