diff --git a/src/components/video-editor/ExportSettingsMenu.tsx b/src/components/video-editor/ExportSettingsMenu.tsx index 42ee4fbb..d0cf053c 100644 --- a/src/components/video-editor/ExportSettingsMenu.tsx +++ b/src/components/video-editor/ExportSettingsMenu.tsx @@ -4,12 +4,15 @@ import { Button } from "@/components/ui/button"; import { Switch } from "@/components/ui/switch"; import { useScopedT } from "@/contexts/I18nContext"; import type { + ExportEncodingMode, ExportFormat, + ExportMp4FrameRate, + ExportPipelineModel, ExportQuality, GifFrameRate, GifSizePreset, } from "@/lib/exporter"; -import { GIF_FRAME_RATES, GIF_SIZE_PRESETS } from "@/lib/exporter"; +import { GIF_FRAME_RATES, GIF_SIZE_PRESETS, MP4_FRAME_RATES } from "@/lib/exporter"; import { cn } from "@/lib/utils"; interface ExportSettingsMenuProps { @@ -17,6 +20,12 @@ interface ExportSettingsMenuProps { onExportFormatChange?: (format: ExportFormat) => void; exportQuality: ExportQuality; onExportQualityChange?: (quality: ExportQuality) => void; + exportEncodingMode: ExportEncodingMode; + onExportEncodingModeChange?: (encodingMode: ExportEncodingMode) => void; + mp4FrameRate: ExportMp4FrameRate; + onMp4FrameRateChange?: (frameRate: ExportMp4FrameRate) => void; + exportPipelineModel?: ExportPipelineModel; + onExportPipelineModelChange?: (pipelineModel: ExportPipelineModel) => void; mp4OutputDimensions?: Record; gifFrameRate: GifFrameRate; onGifFrameRateChange?: (rate: GifFrameRate) => void; @@ -34,6 +43,12 @@ export function ExportSettingsMenu({ onExportFormatChange, exportQuality, onExportQualityChange, + exportEncodingMode, + onExportEncodingModeChange, + mp4FrameRate, + onMp4FrameRateChange, + exportPipelineModel = "legacy", + onExportPipelineModelChange, mp4OutputDimensions, gifFrameRate, onGifFrameRateChange, @@ -46,6 +61,7 @@ export function ExportSettingsMenu({ className, }: ExportSettingsMenuProps) { const tSettings = useScopedT("settings"); + const isLegacyModel = exportPipelineModel === "legacy"; return (
@@ -130,6 +146,108 @@ export function ExportSettingsMenu({ ); })}
+
+ + {tSettings("export.encodingTitle", "Encoding")} + +
+
+ {([ + { value: "fast", label: tSettings("export.encoding.fast", "Fast") }, + { value: "balanced", label: tSettings("export.encoding.balanced", "Balanced") }, + { value: "quality", label: tSettings("export.encoding.quality", "Quality") }, + ] as const).map((option) => { + const isActive = exportEncodingMode === option.value; + return ( + + ); + })} +
+
+ + {tSettings("export.fpsTitle", "FPS")} + +
+
+ {MP4_FRAME_RATES.map((rate) => { + const isActive = mp4FrameRate === rate; + return ( + + ); + })} +
+
+ + {tSettings("export.pipelineTitle", "Pipeline")} + +
+
+ {([ + { value: "legacy", label: tSettings("export.pipeline.legacy", "Legacy") }, + { value: "modern", label: tSettings("export.pipeline.modern", "Lightning (Beta)") }, + ] as const).map((option) => { + const isActive = exportPipelineModel === option.value; + return ( + + ); + })} +
+

+ {isLegacyModel + ? tSettings("export.pipeline.legacyHint", "Legacy uses the current stable WebCodecs export path.") + : tSettings( + "export.pipeline.lightningHint", + "Lightning (Beta) automatically uses the fastest compatible backend and falls back when needed.", + )} +

) : (