speed zones work now
This commit is contained in:
@ -3,7 +3,6 @@ import { temporal } from 'zundo';
|
||||
import type {
|
||||
Word,
|
||||
Segment,
|
||||
DeletedRange,
|
||||
CutRange,
|
||||
MuteRange,
|
||||
GainRange,
|
||||
@ -21,7 +20,6 @@ interface EditorState {
|
||||
exportedAudioPath: string | null; // path to modified audio from a previous export
|
||||
words: Word[];
|
||||
segments: Segment[];
|
||||
deletedRanges: DeletedRange[];
|
||||
cutRanges: CutRange[];
|
||||
muteRanges: MuteRange[];
|
||||
gainRanges: GainRange[];
|
||||
@ -61,7 +59,6 @@ interface EditorActions {
|
||||
setHoveredWordIndex: (index: number | null) => void;
|
||||
deleteSelectedWords: () => void;
|
||||
deleteWordRange: (startIndex: number, endIndex: number) => void;
|
||||
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;
|
||||
@ -97,7 +94,6 @@ const initialState: EditorState = {
|
||||
exportedAudioPath: null,
|
||||
words: [],
|
||||
segments: [],
|
||||
deletedRanges: [],
|
||||
cutRanges: [],
|
||||
muteRanges: [],
|
||||
gainRanges: [],
|
||||
@ -159,7 +155,7 @@ export const useEditorStore = create<EditorState & EditorActions>()(
|
||||
setTranscriptionModel: (model) => set({ transcriptionModel: model }),
|
||||
|
||||
saveProject: (): ProjectFile => {
|
||||
const { videoPath, words, segments, deletedRanges, cutRanges, muteRanges, gainRanges, speedRanges, globalGainDb, silenceTrimGroups, transcriptionModel, language, exportedAudioPath } = get();
|
||||
const { videoPath, words, segments, cutRanges, muteRanges, gainRanges, speedRanges, 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.
|
||||
@ -175,7 +171,6 @@ export const useEditorStore = create<EditorState & EditorActions>()(
|
||||
transcriptionModel: transcriptionModel ?? undefined,
|
||||
words,
|
||||
segments: persistSegments as unknown as Segment[],
|
||||
deletedRanges,
|
||||
cutRanges,
|
||||
muteRanges,
|
||||
gainRanges,
|
||||
@ -210,7 +205,6 @@ export const useEditorStore = create<EditorState & EditorActions>()(
|
||||
words: result.words,
|
||||
segments: annotatedSegments,
|
||||
language: result.language,
|
||||
deletedRanges: [],
|
||||
selectedWordIndices: [],
|
||||
});
|
||||
},
|
||||
@ -222,44 +216,20 @@ export const useEditorStore = create<EditorState & EditorActions>()(
|
||||
setHoveredWordIndex: (index) => set({ hoveredWordIndex: index }),
|
||||
|
||||
deleteSelectedWords: () => {
|
||||
const { selectedWordIndices, words, deletedRanges } = get();
|
||||
const { selectedWordIndices, words } = get();
|
||||
if (selectedWordIndices.length === 0) return;
|
||||
|
||||
const sorted = [...selectedWordIndices].sort((a, b) => a - b);
|
||||
const startWord = words[sorted[0]];
|
||||
const endWord = words[sorted[sorted.length - 1]];
|
||||
|
||||
const newRange: DeletedRange = {
|
||||
id: `dr_${nextRangeId++}`,
|
||||
start: startWord.start,
|
||||
end: endWord.end,
|
||||
wordIndices: sorted,
|
||||
};
|
||||
|
||||
set({
|
||||
deletedRanges: [...deletedRanges, newRange],
|
||||
selectedWordIndices: [],
|
||||
});
|
||||
get().addCutRange(startWord.start, endWord.end);
|
||||
set({ selectedWordIndices: [] });
|
||||
},
|
||||
|
||||
deleteWordRange: (startIndex, endIndex) => {
|
||||
const { words, deletedRanges } = get();
|
||||
const indices = [];
|
||||
for (let i = startIndex; i <= endIndex; i++) indices.push(i);
|
||||
|
||||
const newRange: DeletedRange = {
|
||||
id: `dr_${nextRangeId++}`,
|
||||
start: words[startIndex].start,
|
||||
end: words[endIndex].end,
|
||||
wordIndices: indices,
|
||||
};
|
||||
|
||||
set({ deletedRanges: [...deletedRanges, newRange] });
|
||||
},
|
||||
|
||||
restoreRange: (rangeId) => {
|
||||
const { deletedRanges } = get();
|
||||
set({ deletedRanges: deletedRanges.filter((r) => r.id !== rangeId) });
|
||||
const { words } = get();
|
||||
get().addCutRange(words[startIndex].start, words[endIndex].end);
|
||||
},
|
||||
|
||||
addCutRange: (start, end, trimGroupId) => {
|
||||
@ -438,15 +408,10 @@ export const useEditorStore = create<EditorState & EditorActions>()(
|
||||
}),
|
||||
|
||||
getKeepSegments: () => {
|
||||
const { words, deletedRanges, cutRanges, duration } = get();
|
||||
const { words, cutRanges, duration } = get();
|
||||
if (words.length === 0) return [{ start: 0, end: duration }];
|
||||
|
||||
const deletedSet = new Set<number>();
|
||||
for (const range of deletedRanges) {
|
||||
for (const idx of range.wordIndices) deletedSet.add(idx);
|
||||
}
|
||||
|
||||
// Also exclude words that fall within cut ranges
|
||||
for (const cutRange of cutRanges) {
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
const word = words[i];
|
||||
@ -508,8 +473,11 @@ export const useEditorStore = create<EditorState & EditorActions>()(
|
||||
videoUrl: url,
|
||||
words: data.words || [],
|
||||
segments: annotatedSegments,
|
||||
deletedRanges: data.deletedRanges || [],
|
||||
cutRanges: data.cutRanges || [],
|
||||
// Backward compat: merge legacy deletedRanges into cutRanges as time-range cuts
|
||||
cutRanges: [
|
||||
...(data.cutRanges || []),
|
||||
...(data.deletedRanges || []).map((r: any) => ({ id: r.id, start: r.start, end: r.end })),
|
||||
],
|
||||
muteRanges: data.muteRanges || [],
|
||||
gainRanges: data.gainRanges || [],
|
||||
speedRanges: data.speedRanges || [],
|
||||
|
||||
Reference in New Issue
Block a user