@@ -36,8 +36,14 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
3636import { useScopedT } from "@/contexts/I18nContext" ;
3737import { getAssetPath } from "@/lib/assetPath" ;
3838import { WEBCAM_LAYOUT_PRESETS } from "@/lib/compositeLayout" ;
39- import type { ExportFormat , ExportQuality , GifFrameRate , GifSizePreset } from "@/lib/exporter" ;
40- import { GIF_FRAME_RATES , GIF_SIZE_PRESETS } from "@/lib/exporter" ;
39+ import type {
40+ ExportFormat ,
41+ ExportQuality ,
42+ GifFrameRate ,
43+ GifSizePreset ,
44+ Mp4FrameRate ,
45+ } from "@/lib/exporter" ;
46+ import { GIF_FRAME_RATES , GIF_SIZE_PRESETS , MP4_FRAME_RATES } from "@/lib/exporter" ;
4147import { cn } from "@/lib/utils" ;
4248import { type AspectRatio , isPortraitAspectRatio } from "@/utils/aspectRatioUtils" ;
4349import { getTestId } from "@/utils/getTestId" ;
@@ -188,6 +194,8 @@ interface SettingsPanelProps {
188194 // Export format settings
189195 exportFormat ?: ExportFormat ;
190196 onExportFormatChange ?: ( format : ExportFormat ) => void ;
197+ mp4FrameRate ?: Mp4FrameRate ;
198+ onMp4FrameRateChange ?: ( rate : Mp4FrameRate ) => void ;
191199 gifFrameRate ?: GifFrameRate ;
192200 onGifFrameRateChange ?: ( rate : GifFrameRate ) => void ;
193201 gifLoop ?: boolean ;
@@ -268,6 +276,8 @@ export function SettingsPanel({
268276 onExportQualityChange,
269277 exportFormat = "mp4" ,
270278 onExportFormatChange,
279+ mp4FrameRate = 60 ,
280+ onMp4FrameRateChange,
271281 gifFrameRate = 15 ,
272282 onGifFrameRateChange,
273283 gifLoop = true ,
@@ -1306,40 +1316,58 @@ export function SettingsPanel({
13061316 </ div >
13071317
13081318 { exportFormat === "mp4" && (
1309- < div className = "mb-3 bg-white/5 border border-white/5 p-0.5 w-full grid grid-cols-3 h-7 rounded-lg" >
1310- < button
1311- onClick = { ( ) => onExportQualityChange ?.( "medium" ) }
1312- className = { cn (
1313- "rounded-md transition-all text-[10px] font-medium" ,
1314- exportQuality === "medium"
1315- ? "bg-white text-black"
1316- : "text-slate-400 hover:text-slate-200" ,
1317- ) }
1318- >
1319- { t ( "exportQuality.low" ) }
1320- </ button >
1321- < button
1322- onClick = { ( ) => onExportQualityChange ?.( "good" ) }
1323- className = { cn (
1324- "rounded-md transition-all text-[10px] font-medium" ,
1325- exportQuality === "good"
1326- ? "bg-white text-black"
1327- : "text-slate-400 hover:text-slate-200" ,
1328- ) }
1329- >
1330- { t ( "exportQuality.medium" ) }
1331- </ button >
1332- < button
1333- onClick = { ( ) => onExportQualityChange ?.( "source" ) }
1334- className = { cn (
1335- "rounded-md transition-all text-[10px] font-medium" ,
1336- exportQuality === "source"
1337- ? "bg-white text-black"
1338- : "text-slate-400 hover:text-slate-200" ,
1339- ) }
1340- >
1341- { t ( "exportQuality.high" ) }
1342- </ button >
1319+ < div className = "mb-3 space-y-1.5" >
1320+ < div className = "bg-white/5 border border-white/5 p-0.5 w-full grid grid-cols-3 h-7 rounded-lg" >
1321+ < button
1322+ onClick = { ( ) => onExportQualityChange ?.( "medium" ) }
1323+ className = { cn (
1324+ "rounded-md transition-all text-[10px] font-medium" ,
1325+ exportQuality === "medium"
1326+ ? "bg-white text-black"
1327+ : "text-slate-400 hover:text-slate-200" ,
1328+ ) }
1329+ >
1330+ { t ( "exportQuality.low" ) }
1331+ </ button >
1332+ < button
1333+ onClick = { ( ) => onExportQualityChange ?.( "good" ) }
1334+ className = { cn (
1335+ "rounded-md transition-all text-[10px] font-medium" ,
1336+ exportQuality === "good"
1337+ ? "bg-white text-black"
1338+ : "text-slate-400 hover:text-slate-200" ,
1339+ ) }
1340+ >
1341+ { t ( "exportQuality.medium" ) }
1342+ </ button >
1343+ < button
1344+ onClick = { ( ) => onExportQualityChange ?.( "source" ) }
1345+ className = { cn (
1346+ "rounded-md transition-all text-[10px] font-medium" ,
1347+ exportQuality === "source"
1348+ ? "bg-white text-black"
1349+ : "text-slate-400 hover:text-slate-200" ,
1350+ ) }
1351+ >
1352+ { t ( "exportQuality.high" ) }
1353+ </ button >
1354+ </ div >
1355+ < div className = "bg-white/5 border border-white/5 p-0.5 w-full grid grid-cols-3 h-7 rounded-lg" >
1356+ { MP4_FRAME_RATES . map ( ( rate ) => (
1357+ < button
1358+ key = { rate . value }
1359+ onClick = { ( ) => onMp4FrameRateChange ?.( rate . value ) }
1360+ className = { cn (
1361+ "rounded-md transition-all text-[10px] font-medium" ,
1362+ mp4FrameRate === rate . value
1363+ ? "bg-white text-black"
1364+ : "text-slate-400 hover:text-slate-200" ,
1365+ ) }
1366+ >
1367+ { rate . value }
1368+ </ button >
1369+ ) ) }
1370+ </ div >
13431371 </ div >
13441372 ) }
13451373
0 commit comments