From ef993a09d00aa9b544deeeec5804569720edae69 Mon Sep 17 00:00:00 2001 From: Alan Trebugeais Date: Sat, 9 May 2026 19:24:07 +0200 Subject: [PATCH] fix: audioRegions are now allowed (reloading a project with a user audio would not work. --- electron/ipc/project/manager.ts | 8 ++++++ src/components/video-editor/VideoEditor.tsx | 2 +- .../video-editor/audio/audioTypes.ts | 25 +++++++++++++++++++ .../video-editor/audio/sourceAudioTracks.ts | 5 ---- .../audio/useClipAudioSettingsController.ts | 6 ++--- .../audio/useSourceAudioFallback.ts | 2 +- .../audio/useSourceAudioTrackSettings.ts | 7 +++--- .../video-editor/audio/useVideoEditorAudio.ts | 2 +- .../video-editor/projectPersistence.ts | 2 +- .../video-editor/timeline/TimelineEditor.tsx | 16 +++++++----- .../components/viewport/TimelineCanvas.tsx | 14 +++++++---- src/components/video-editor/types.ts | 8 +----- src/lib/exporter/sourceTrackRoutingPolicy.ts | 3 --- 13 files changed, 64 insertions(+), 36 deletions(-) create mode 100644 src/components/video-editor/audio/audioTypes.ts delete mode 100644 src/components/video-editor/audio/sourceAudioTracks.ts diff --git a/electron/ipc/project/manager.ts b/electron/ipc/project/manager.ts index 404654b1..2f6e4fc2 100644 --- a/electron/ipc/project/manager.ts +++ b/electron/ipc/project/manager.ts @@ -428,6 +428,7 @@ export async function loadProjectFromPath(projectPath: string) { const projectObj = project as Record; const editorObj = projectObj?.editor as Record | undefined; const audioTracks = editorObj?.audioTracks as { sourcePath?: unknown }[] | undefined; + const audioRegions = editorObj?.audioRegions as { audioPath?: unknown }[] | undefined; const approvedProjectPaths: Array = [ mediaSources.videoPath, mediaSources.webcamPath, @@ -439,6 +440,13 @@ export async function loadProjectFromPath(projectPath: string) { } } } + if (Array.isArray(audioRegions)) { + for (const region of audioRegions) { + if (typeof region?.audioPath === "string") { + approvedProjectPaths.push(region.audioPath); + } + } + } await replaceApprovedSessionLocalReadPaths(approvedProjectPaths); await rememberRecentProject(normalizedPath); diff --git a/src/components/video-editor/VideoEditor.tsx b/src/components/video-editor/VideoEditor.tsx index 83992392..08988c6d 100644 --- a/src/components/video-editor/VideoEditor.tsx +++ b/src/components/video-editor/VideoEditor.tsx @@ -149,6 +149,7 @@ import { } from "./TutorialHelp"; import TimelineEditor, { type TimelineEditorHandle } from "./timeline/TimelineEditor"; import { normalizeCursorTelemetry } from "./timeline/zoomSuggestionUtils"; +import type { SourceAudioTrackSettings } from "@/components/video-editor/audio/audioTypes"; import { type AnnotationRegion, type AudioRegion, @@ -197,7 +198,6 @@ import { type ZoomMotionBlurTuning, type ZoomRegion, type ZoomTransitionEasing, - type SourceAudioTrackSettings, } from "./types"; import VideoPlayback, { VideoPlaybackRef } from "./VideoPlayback"; import { diff --git a/src/components/video-editor/audio/audioTypes.ts b/src/components/video-editor/audio/audioTypes.ts new file mode 100644 index 00000000..d20c224f --- /dev/null +++ b/src/components/video-editor/audio/audioTypes.ts @@ -0,0 +1,25 @@ +import type { AudioPeaksData } from "../timeline/core/timelineTypes"; + +export type SourceAudioTrackId = "mixed" | "system" | "mic" | (string & {}); + +export interface SourceAudioTrackSetting { + volume: number; + normalize: boolean; +} + +export type SourceAudioTrackSettings = Record; + +export interface SourceAudioTrackMetaItem { + id: SourceAudioTrackId; + label: string; +} + +export type SourceAudioTrackMeta = SourceAudioTrackMetaItem[]; + +export interface SourceAudioTrackWithPeaks extends SourceAudioTrackMetaItem { + peaks: AudioPeaksData; +} + +export const SOURCE_AUDIO_FALLBACK_TOAST_ID = "source-audio-fallback-error"; +export const SOURCE_AUDIO_NORMALIZE_GAIN = 1.35; + diff --git a/src/components/video-editor/audio/sourceAudioTracks.ts b/src/components/video-editor/audio/sourceAudioTracks.ts deleted file mode 100644 index b3ea2cee..00000000 --- a/src/components/video-editor/audio/sourceAudioTracks.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { getSourceTrackIdFromPath } from "@/lib/exporter/sourceTrackRoutingPolicy"; - -export const SOURCE_AUDIO_FALLBACK_TOAST_ID = "source-audio-fallback-error"; -export const SOURCE_AUDIO_NORMALIZE_GAIN = 1.35; -export { getSourceTrackIdFromPath }; diff --git a/src/components/video-editor/audio/useClipAudioSettingsController.ts b/src/components/video-editor/audio/useClipAudioSettingsController.ts index 8c79ac09..08ad0d5e 100644 --- a/src/components/video-editor/audio/useClipAudioSettingsController.ts +++ b/src/components/video-editor/audio/useClipAudioSettingsController.ts @@ -1,10 +1,10 @@ import React, { useCallback, useMemo } from "react"; import { SOURCE_AUDIO_NORMALIZE_GAIN, - getSourceTrackIdFromPath, -} from "./sourceAudioTracks"; + type SourceAudioTrackSettings, +} from "@/components/video-editor/audio/audioTypes"; import { useSourceAudioTrackSettings } from "./useSourceAudioTrackSettings"; -import { SourceAudioTrackSettings } from "../types"; +import { getSourceTrackIdFromPath } from "@/lib/exporter/audioRoutingEngine"; interface UseClipAudioSettingsControllerParams { selectedClipId: string | null; diff --git a/src/components/video-editor/audio/useSourceAudioFallback.ts b/src/components/video-editor/audio/useSourceAudioFallback.ts index 64b4caa8..69be8c24 100644 --- a/src/components/video-editor/audio/useSourceAudioFallback.ts +++ b/src/components/video-editor/audio/useSourceAudioFallback.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; import { toast } from "sonner"; -import { SOURCE_AUDIO_FALLBACK_TOAST_ID } from "./sourceAudioTracks"; +import { SOURCE_AUDIO_FALLBACK_TOAST_ID } from "@/components/video-editor/audio/audioTypes"; interface UseSourceAudioFallbackParams { currentSourcePath: string | null; diff --git a/src/components/video-editor/audio/useSourceAudioTrackSettings.ts b/src/components/video-editor/audio/useSourceAudioTrackSettings.ts index 54b2d751..2e776eb2 100644 --- a/src/components/video-editor/audio/useSourceAudioTrackSettings.ts +++ b/src/components/video-editor/audio/useSourceAudioTrackSettings.ts @@ -1,7 +1,8 @@ import React, { useCallback, useMemo, useState } from "react"; -import type { SourceAudioTrackSettings } from "../types"; - -export type SourceAudioTrackMeta = Array<{ id: string; label: string }>; +import type { + SourceAudioTrackMeta, + SourceAudioTrackSettings, +} from "@/components/video-editor/audio/audioTypes"; interface UseSourceAudioTrackSettingsParams { selectedClipId: string | null; diff --git a/src/components/video-editor/audio/useVideoEditorAudio.ts b/src/components/video-editor/audio/useVideoEditorAudio.ts index d992e871..a82ea941 100644 --- a/src/components/video-editor/audio/useVideoEditorAudio.ts +++ b/src/components/video-editor/audio/useVideoEditorAudio.ts @@ -3,9 +3,9 @@ import { resolveSourceTrackRoutingPolicy } from "@/lib/exporter/sourceTrackRouti import type { AudioRegion, ClipRegion, - SourceAudioTrackSettings, SpeedRegion, } from "../types"; +import type { SourceAudioTrackSettings } from "@/components/video-editor/audio/audioTypes"; import { getActiveClipIdAtSourceTime, isClipMutedById } from "./clipAudio"; import { useAudioPreviewSync } from "./useAudioPreviewSync"; import { useClipAudioSettingsController } from "./useClipAudioSettingsController"; diff --git a/src/components/video-editor/projectPersistence.ts b/src/components/video-editor/projectPersistence.ts index 4ba24920..9adb3608 100644 --- a/src/components/video-editor/projectPersistence.ts +++ b/src/components/video-editor/projectPersistence.ts @@ -20,6 +20,7 @@ import { import { DEFAULT_WALLPAPER_PATH } from "@/lib/wallpapers"; import { ASPECT_RATIOS, type AspectRatio, isCustomAspectRatio } from "@/utils/aspectRatioUtils"; import { CURSOR_MOTION_PRESETS, resolveCursorMotionPresetId } from "./cursorMotionPresets"; +import type { SourceAudioTrackSettings } from "@/components/video-editor/audio/audioTypes"; import { type AnnotationRegion, type AudioRegion, @@ -62,7 +63,6 @@ import { DEFAULT_ZOOM_SMOOTHNESS, getDefaultCaptionFontFamily, type Padding, - SourceAudioTrackSettings, type SpeedRegion, type TrimRegion, type WebcamOverlaySettings, diff --git a/src/components/video-editor/timeline/TimelineEditor.tsx b/src/components/video-editor/timeline/TimelineEditor.tsx index 28e83a5f..df2ed47b 100644 --- a/src/components/video-editor/timeline/TimelineEditor.tsx +++ b/src/components/video-editor/timeline/TimelineEditor.tsx @@ -18,6 +18,11 @@ import { import { formatShortcut } from "@/utils/platformUtils"; import { loadEditorPreferences, saveEditorPreferences } from "../editorPreferences"; import { fromFileUrl } from "../projectPersistence"; +import type { + SourceAudioTrackMeta, + SourceAudioTrackSettings, + SourceAudioTrackWithPeaks, +} from "@/components/video-editor/audio/audioTypes"; import type { AnnotationRegion, AudioRegion, @@ -36,7 +41,6 @@ import { useTimelineEditorRuntime } from "./hooks/useTimelineEditorRuntime"; import { useTimelineRange } from "./hooks/useTimelineRange"; import TimelineCanvas from "./components/viewport/TimelineCanvas"; import TimelineToolbar from "./components/toolbar/TimelineToolbar"; -import type { AudioPeaksData } from "./core/timelineTypes"; export interface TimelineEditorProps { videoDuration: number; @@ -84,11 +88,11 @@ export interface TimelineEditorProps { hideToolbar?: boolean; showSourceAudioTrack?: boolean; onSourceAudioAvailabilityChange?: (available: boolean) => void; - sourceAudioTrackSettings?: Record; + sourceAudioTrackSettings?: SourceAudioTrackSettings; getSourceAudioTrackSettingsForClip?: ( clipId: string | null, - ) => Record; - onSourceAudioTracksMetaChange?: (tracks: Array<{ id: string; label: string }>) => void; + ) => SourceAudioTrackSettings; + onSourceAudioTracksMetaChange?: (tracks: SourceAudioTrackMeta) => void; } function extractLocalPathFromMediaServerUrl(input: string | null | undefined): string | null { @@ -288,9 +292,9 @@ const TimelineEditor = forwardRef( ); const micSidecarPeaks = useTimelineAudioPeaks(micSidecarPath); const systemSidecarPeaks = useTimelineAudioPeaks(systemSidecarPath); - const sourceAudioTracks = useMemo>(() => { + const sourceAudioTracks = useMemo(() => { if (systemSidecarPeaks || micSidecarPeaks) { - const tracks: Array<{ id: string; label: string; peaks: AudioPeaksData }> = []; + const tracks: SourceAudioTrackWithPeaks[] = []; if (systemSidecarPeaks) tracks.push({ id: "system", diff --git a/src/components/video-editor/timeline/components/viewport/TimelineCanvas.tsx b/src/components/video-editor/timeline/components/viewport/TimelineCanvas.tsx index 806593c5..4d81b323 100644 --- a/src/components/video-editor/timeline/components/viewport/TimelineCanvas.tsx +++ b/src/components/video-editor/timeline/components/viewport/TimelineCanvas.tsx @@ -11,6 +11,10 @@ import { type MouseEventHandler, } from "react"; import { cn } from "@/lib/utils"; +import type { + SourceAudioTrackSettings, + SourceAudioTrackWithPeaks, +} from "@/components/video-editor/audio/audioTypes"; import { getTimelineContentMinHeightPx, getTimelineRowsMinHeightPx, @@ -21,7 +25,7 @@ import glassStyles from "../../ItemGlass.module.css"; import Item from "../../Item"; import Row from "../../Row"; import { CLIP_ROW_ID, SOURCE_AUDIO_ROW_ID, ZOOM_ROW_ID } from "../../core/constants"; -import type { AudioPeaksData, TimelineRenderItem } from "../../core/timelineTypes"; +import type { TimelineRenderItem } from "../../core/timelineTypes"; import { getAnnotationTrackIndex, getAnnotationTrackRowId, @@ -57,10 +61,10 @@ interface TimelineCanvasProps { selectAllBlocksActive?: boolean; onClearBlockSelection?: () => void; keyframes?: { id: string; time: number }[]; - sourceAudioTracks?: Array<{ id: string; label: string; peaks: AudioPeaksData }>; + sourceAudioTracks?: SourceAudioTrackWithPeaks[]; getSourceAudioTrackSettingsForClip?: ( clipId: string | null, - ) => Record; + ) => SourceAudioTrackSettings; showSourceAudioTrack?: boolean; liveSpanPreviewById?: Record; liveHiddenItemIds?: string[]; @@ -224,10 +228,10 @@ interface TimelineCanvasRowsProps { onSelectClip?: (id: string | null) => void; onSelectAnnotation?: (id: string | null) => void; onSelectAudio?: (id: string | null) => void; - sourceAudioTracks?: Array<{ id: string; label: string; peaks: AudioPeaksData }>; + sourceAudioTracks?: SourceAudioTrackWithPeaks[]; getSourceAudioTrackSettingsForClip?: ( clipId: string | null, - ) => Record; + ) => SourceAudioTrackSettings; showSourceAudioTrack?: boolean; liveSpanPreviewById?: Record; liveHiddenItemIds?: string[]; diff --git a/src/components/video-editor/types.ts b/src/components/video-editor/types.ts index 3e18f720..e6a7c6f0 100644 --- a/src/components/video-editor/types.ts +++ b/src/components/video-editor/types.ts @@ -466,13 +466,7 @@ export const DEFAULT_PADDING: Padding = { right: 20, linked: true, }; - -export interface SourceAudioTrackSetting { - volume: number; - normalize: boolean; -} - -export type SourceAudioTrackSettings = Record; +export type { SourceAudioTrackSetting, SourceAudioTrackSettings } from "@/components/video-editor/audio/audioTypes"; export interface AudioRegion { id: string; diff --git a/src/lib/exporter/sourceTrackRoutingPolicy.ts b/src/lib/exporter/sourceTrackRoutingPolicy.ts index f09e00ea..05c9fa84 100644 --- a/src/lib/exporter/sourceTrackRoutingPolicy.ts +++ b/src/lib/exporter/sourceTrackRoutingPolicy.ts @@ -1,11 +1,8 @@ import { buildResolvedAudioPlan, - getSourceTrackIdFromPath, type SourceTrackId, } from "./audioRoutingEngine"; -export { getSourceTrackIdFromPath, type SourceTrackId }; - export interface SourceTrackRoutingPolicy { hasEmbeddedSourceAudio: boolean; pathsByTrack: Partial>;