mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-09-26 15:55:35 +00:00
feat: allow manual webcam footage import
This commit is contained in:
@@ -141,6 +141,8 @@ interface SettingsPanelProps {
|
||||
onBorderRadiusChange?: (radius: number) => void;
|
||||
webcam?: WebcamOverlaySettings;
|
||||
onWebcamChange?: (webcam: WebcamOverlaySettings) => void;
|
||||
onUploadWebcam?: () => void;
|
||||
onClearWebcam?: () => void;
|
||||
padding?: number;
|
||||
onPaddingChange?: (padding: number) => void;
|
||||
cropRegion?: CropRegion;
|
||||
@@ -222,6 +224,8 @@ export function SettingsPanel({
|
||||
onBorderRadiusChange,
|
||||
webcam,
|
||||
onWebcamChange,
|
||||
onUploadWebcam,
|
||||
onClearWebcam,
|
||||
padding = 50,
|
||||
onPaddingChange,
|
||||
cropRegion,
|
||||
@@ -356,6 +360,8 @@ export function SettingsPanel({
|
||||
}
|
||||
};
|
||||
|
||||
const webcamFileName = webcam?.sourcePath?.split(/[\\/]/).pop() ?? null;
|
||||
|
||||
const zoomEnabled = Boolean(selectedZoomDepth);
|
||||
const trimEnabled = Boolean(selectedTrimId);
|
||||
|
||||
@@ -816,6 +822,42 @@ export function SettingsPanel({
|
||||
className="data-[state=checked]:bg-[#2563EB] scale-90"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-2 rounded-lg border border-white/5 bg-white/5 p-2">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div>
|
||||
<div className="text-[10px] font-medium text-slate-300">
|
||||
{tSettings("effects.webcamFootage")}
|
||||
</div>
|
||||
<div className="mt-0.5 text-[10px] text-slate-500">
|
||||
{webcamFileName ?? tSettings("effects.webcamFootageDescription")}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={onUploadWebcam}
|
||||
className="h-7 gap-1.5 border-white/10 bg-white/5 px-2 text-[10px] text-slate-200 hover:bg-white/10 hover:text-white"
|
||||
>
|
||||
<Upload className="h-3 w-3" />
|
||||
{webcam?.sourcePath
|
||||
? tSettings("effects.replaceWebcamFootage")
|
||||
: tSettings("effects.uploadWebcamFootage")}
|
||||
</Button>
|
||||
{webcam?.sourcePath ? (
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={onClearWebcam}
|
||||
className="h-7 gap-1.5 border-white/10 bg-white/5 px-2 text-[10px] text-slate-200 hover:bg-white/10 hover:text-white"
|
||||
>
|
||||
<Trash2 className="h-3 w-3" />
|
||||
{tSettings("effects.removeWebcamFootage")}
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-2 rounded-lg bg-white/5 border border-white/5">
|
||||
<SliderControl
|
||||
label={tSettings("effects.roundness")}
|
||||
|
||||
@@ -455,6 +455,48 @@ export default function VideoEditor() {
|
||||
gifSizePreset,
|
||||
]);
|
||||
|
||||
const syncRecordingSessionWebcam = useCallback(
|
||||
async (webcamPath: string | null) => {
|
||||
const sourcePath = videoSourcePath ?? (videoPath ? fromFileUrl(videoPath) : null);
|
||||
if (!sourcePath || !window.electronAPI.setCurrentRecordingSession) {
|
||||
return;
|
||||
}
|
||||
|
||||
await window.electronAPI.setCurrentRecordingSession({
|
||||
videoPath: sourcePath,
|
||||
webcamPath,
|
||||
});
|
||||
},
|
||||
[videoPath, videoSourcePath],
|
||||
);
|
||||
|
||||
const handleUploadWebcam = useCallback(async () => {
|
||||
const result = await window.electronAPI.openVideoFilePicker();
|
||||
if (!result.success || !result.path) {
|
||||
return;
|
||||
}
|
||||
|
||||
setWebcam((prev) => ({
|
||||
...prev,
|
||||
enabled: true,
|
||||
sourcePath: result.path ?? null,
|
||||
}));
|
||||
|
||||
await syncRecordingSessionWebcam(result.path);
|
||||
toast.success(t("settings.effects.webcamFootageAdded"));
|
||||
}, [syncRecordingSessionWebcam, t]);
|
||||
|
||||
const handleClearWebcam = useCallback(async () => {
|
||||
setWebcam((prev) => ({
|
||||
...prev,
|
||||
enabled: false,
|
||||
sourcePath: null,
|
||||
}));
|
||||
|
||||
await syncRecordingSessionWebcam(null);
|
||||
toast.success(t("settings.effects.webcamFootageRemoved"));
|
||||
}, [syncRecordingSessionWebcam, t]);
|
||||
|
||||
useEffect(() => {
|
||||
const snapshot = cloneSnapshot(buildHistorySnapshot());
|
||||
|
||||
@@ -2208,6 +2250,8 @@ export default function VideoEditor() {
|
||||
onBorderRadiusChange={setBorderRadius}
|
||||
webcam={webcam}
|
||||
onWebcamChange={setWebcam}
|
||||
onUploadWebcam={handleUploadWebcam}
|
||||
onClearWebcam={handleClearWebcam}
|
||||
padding={padding}
|
||||
onPaddingChange={setPadding}
|
||||
cropRegion={cropRegion}
|
||||
|
||||
@@ -26,6 +26,13 @@
|
||||
"cursorClickBounce": "Cursor Click Bounce",
|
||||
"cursorSway": "Cursor Sway",
|
||||
"webcam": "Webcam Overlay",
|
||||
"webcamFootage": "Webcam Footage",
|
||||
"webcamFootageDescription": "No webcam footage linked to this video",
|
||||
"uploadWebcamFootage": "Upload footage",
|
||||
"replaceWebcamFootage": "Replace footage",
|
||||
"removeWebcamFootage": "Remove footage",
|
||||
"webcamFootageAdded": "Webcam footage linked",
|
||||
"webcamFootageRemoved": "Webcam footage removed",
|
||||
"webcamSize": "Webcam Size",
|
||||
"webcamReactToZoom": "Webcam Reacts To Zoom",
|
||||
"webcamRoundness": "Webcam Roundness",
|
||||
|
||||
@@ -26,6 +26,13 @@
|
||||
"cursorClickBounce": "Rebote de clic del cursor",
|
||||
"cursorSway": "Balanceo del cursor",
|
||||
"webcam": "Superposición de cámara",
|
||||
"webcamFootage": "Metraje de cámara",
|
||||
"webcamFootageDescription": "No hay metraje de cámara vinculado a este video",
|
||||
"uploadWebcamFootage": "Subir metraje",
|
||||
"replaceWebcamFootage": "Reemplazar metraje",
|
||||
"removeWebcamFootage": "Quitar metraje",
|
||||
"webcamFootageAdded": "Metraje de cámara vinculado",
|
||||
"webcamFootageRemoved": "Metraje de cámara eliminado",
|
||||
"webcamSize": "Tamaño de cámara",
|
||||
"webcamReactToZoom": "La cámara reacciona al zoom",
|
||||
"webcamRoundness": "Redondez de cámara",
|
||||
|
||||
@@ -26,6 +26,13 @@
|
||||
"cursorClickBounce": "光标点击弹跳",
|
||||
"cursorSway": "光标摆动",
|
||||
"webcam": "摄像头叠加",
|
||||
"webcamFootage": "摄像头素材",
|
||||
"webcamFootageDescription": "此视频尚未关联摄像头素材",
|
||||
"uploadWebcamFootage": "上传素材",
|
||||
"replaceWebcamFootage": "替换素材",
|
||||
"removeWebcamFootage": "移除素材",
|
||||
"webcamFootageAdded": "已关联摄像头素材",
|
||||
"webcamFootageRemoved": "已移除摄像头素材",
|
||||
"webcamSize": "摄像头大小",
|
||||
"webcamReactToZoom": "摄像头随缩放变化",
|
||||
"webcamRoundness": "摄像头圆角",
|
||||
|
||||
Reference in New Issue
Block a user