fix: webcam recording, now it works, alongside the microphone etc

This commit is contained in:
Alan Trebugeais
2026-05-10 23:37:07 +02:00
parent 34dcddc455
commit ccbeb5fa1d
4 changed files with 73 additions and 16 deletions
+3 -4
View File
@@ -20,6 +20,7 @@ import {
persistRecordingsDirectorySetting,
rememberRecentProject,
replaceApprovedSessionLocalReadPaths,
rememberApprovedLocalReadPath,
resolveApprovedLocalMediaPath,
saveProjectThumbnail,
saveRecentProjectPaths,
@@ -581,10 +582,8 @@ export function registerProjectHandlers() {
timeOffsetMs: normalizeRecordingTimeOffsetMs(session.timeOffsetMs),
hideOverlayCursorByDefault: normalizeBoolean(session.hideOverlayCursorByDefault),
});
await replaceApprovedSessionLocalReadPaths([
currentRecordingSession!.videoPath,
currentRecordingSession!.webcamPath,
])
await rememberApprovedLocalReadPath(currentRecordingSession!.videoPath)
await rememberApprovedLocalReadPath(currentRecordingSession!.webcamPath)
if (!options?.preserveProjectPath) {
setCurrentProjectPath(null)
}
+32 -5
View File
@@ -283,9 +283,14 @@ function focusOrCreateMainWindow() {
return;
}
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
return;
if (!mainWindow || mainWindow.isDestroyed()) {
const existingHud = getHudOverlayWindow();
if (existingHud && !existingHud.isDestroyed()) {
mainWindow = existingHud;
} else {
createWindow();
return;
}
}
if (mainWindow && !mainWindow.isDestroyed()) {
@@ -793,7 +798,15 @@ function createEditorWindowWrapper() {
const previousWindow = mainWindow;
if (previousWindow && !previousWindow.isDestroyed()) {
const closingEditorWindow = isEditorWindow(previousWindow);
closeEditorWindowBypassingUnsavedPrompt(previousWindow);
if (closingEditorWindow) {
closeEditorWindowBypassingUnsavedPrompt(previousWindow);
} else {
// It's the HUD or another window. Hide it instead of closing so background
// tasks (like webcam finalizing) can finish in its renderer process.
previousWindow.hide();
}
if (!closingEditorWindow) {
isForceClosing = false;
}
@@ -923,7 +936,21 @@ app.whenReady().then(async () => {
}
ipcMain.on("hud-overlay-close", () => {
app.quit();
const hud = getHudOverlayWindow();
if (hud) {
console.log("[main] Closing HUD window via hud-overlay-close");
hud.close();
}
// If this was the last window (or we are in a state where we should quit), do it.
// We use a small delay to allow window.close() to propagate.
setTimeout(() => {
const windows = BrowserWindow.getAllWindows().filter((w) => !w.isDestroyed());
if (windows.length === 0) {
console.log("[main] No windows left, quitting app");
app.quit();
}
}, 100);
});
syncDockIcon();
createTray();
@@ -2505,6 +2505,13 @@ export default function VideoEditor() {
}
return window.electronAPI.onRecordingSessionChanged((session) => {
console.log("[VideoEditor] onRecordingSessionChanged received!", {
sessionVideoPath: session?.videoPath,
videoSourcePath: videoSourcePath,
match: session?.videoPath === videoSourcePath,
webcamPath: session?.webcamPath
});
if (!session || session.videoPath !== videoSourcePath) {
return;
}
+31 -7
View File
@@ -867,6 +867,11 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
const webcamPath = await stopWebcamRecorder();
await storeMicrophoneSidecar(resolvedMicFallbackBlobPromise, result.path, startDelayMs);
await finalizeRecordingSession(result.path, webcamPath);
if (typeof window.electronAPI?.hudOverlayClose === "function") {
window.electronAPI.hudOverlayClose();
}
return result.path;
},
[
@@ -1073,6 +1078,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
try {
// Await the webcam path in the background
const webcamPath = await webcamPathPromise;
console.log("[useScreenRecorder] Background native processing: webcamPath is", webcamPath);
// Store sidecars
await storeMicrophoneSidecar(
@@ -1087,6 +1093,8 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
await window.electronAPI.muxNativeWindowsRecording(expectedDurationMs);
}
console.log("[useScreenRecorder] Emitting setCurrentRecordingSession with:", { finalPath, webcamPath });
// Update the session state to notify the editor that all background assets (webcam, mic, etc.) are now ready.
// This broadcasts a 'recording-session-changed' event that the open editor listens to for re-scanning assets.
await window.electronAPI.setCurrentRecordingSession({
@@ -1101,6 +1109,13 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
);
} catch (bgError) {
console.error("Error in background finalization:", bgError);
} finally {
// After all background tasks are done (webcam, mic sidecars, muxing),
// we can safely close the HUD window to release hardware and resources.
if (typeof window.electronAPI?.hudOverlayClose === "function") {
console.log("[useScreenRecorder] All background tasks finished, closing HUD");
window.electronAPI.hudOverlayClose();
}
}
})();
})();
@@ -1749,13 +1764,22 @@ export function useScreenRecorder(): UseScreenRecorderReturn {
? await pendingWebcamPathPromise.current
: resolvedWebcamPath.current;
if (webcamPath) {
await window.electronAPI.setCurrentRecordingSession({
videoPath: finalVideoPath,
webcamPath,
timeOffsetMs: webcamTimeOffsetMs.current,
hideOverlayCursorByDefault: hideEditorOverlayCursorByDefault.current,
});
try {
if (webcamPath) {
await window.electronAPI.setCurrentRecordingSession({
videoPath: finalVideoPath,
webcamPath,
timeOffsetMs: webcamTimeOffsetMs.current,
hideOverlayCursorByDefault: hideEditorOverlayCursorByDefault.current,
});
}
} finally {
// After all background tasks are done (webcam),
// we can safely close the HUD window to release hardware and resources.
if (typeof window.electronAPI?.hudOverlayClose === "function") {
console.log("[useScreenRecorder:browser] All background tasks finished, closing HUD");
window.electronAPI.hudOverlayClose();
}
}
})();
} else {