diff --git a/- b/- deleted file mode 100644 index 8b13789..0000000 --- a/- +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/hooks/useScreenRecorder.ts b/src/hooks/useScreenRecorder.ts index ee848fa..ccaeb90 100644 --- a/src/hooks/useScreenRecorder.ts +++ b/src/hooks/useScreenRecorder.ts @@ -20,8 +20,6 @@ const DEFAULT_HEIGHT = 1080; const CODEC_ALIGNMENT = 2; const RECORDER_TIMESLICE_MS = 1000; const BITS_PER_MEGABIT = 1_000_000; -const MIN_FRAME_RATE = 30; -const CHROME_MEDIA_SOURCE = "desktop"; const RECORDING_FILE_PREFIX = "recording-"; const VIDEO_FILE_EXTENSION = ".webm"; const AUDIO_BITRATE_VOICE = 128_000; @@ -57,6 +55,11 @@ type UseScreenRecorderReturn = { setCountdownDelay: (delay: number) => void; }; +type ExtendedDisplayMediaStreamOptions = DisplayMediaStreamOptions & { + selfBrowserSurface?: "exclude" | "include"; + surfaceSwitching?: "exclude" | "include"; +}; + export function useScreenRecorder(): UseScreenRecorderReturn { const [recording, setRecording] = useState(false); const [paused, setPaused] = useState(false); @@ -571,45 +574,47 @@ export function useScreenRecorder(): UseScreenRecorderReturn { let videoTrack: MediaStreamTrack | undefined; let systemAudioIncluded = false; - const browserScreenVideoConstraints = { - mandatory: { - chromeMediaSource: CHROME_MEDIA_SOURCE, - chromeMediaSourceId: selectedSource.id, - maxWidth: TARGET_WIDTH, - maxHeight: TARGET_HEIGHT, - maxFrameRate: TARGET_FRAME_RATE, - minFrameRate: MIN_FRAME_RATE, - googCaptureCursor: false, - }, + const displayMediaVideoConstraints = { + displaySurface: selectedSource.id?.startsWith("window:") ? "window" : "monitor", + width: { ideal: TARGET_WIDTH, max: TARGET_WIDTH }, + height: { ideal: TARGET_HEIGHT, max: TARGET_HEIGHT }, + frameRate: { ideal: TARGET_FRAME_RATE, max: TARGET_FRAME_RATE }, cursor: "never" as const, }; + const displayMediaOptions: ExtendedDisplayMediaStreamOptions = { + selfBrowserSurface: "exclude", + surfaceSwitching: "exclude", + }; if (wantsAudioCapture) { let screenMediaStream: MediaStream; if (systemAudioEnabled) { try { - screenMediaStream = await (navigator.mediaDevices as any).getUserMedia({ - audio: { - mandatory: { - chromeMediaSource: CHROME_MEDIA_SOURCE, - chromeMediaSourceId: selectedSource.id, - }, - }, - video: browserScreenVideoConstraints, + screenMediaStream = await navigator.mediaDevices.getDisplayMedia({ + audio: true, + video: displayMediaVideoConstraints, + ...displayMediaOptions, }); + if (screenMediaStream.getAudioTracks().length === 0) { + alert( + "System audio is not available for this source. Recording will continue without system audio.", + ); + } } catch (audioError) { console.warn("System audio capture failed, falling back to video-only:", audioError); alert("System audio is not available for this source. Recording will continue without system audio."); - screenMediaStream = await (navigator.mediaDevices as any).getUserMedia({ + screenMediaStream = await navigator.mediaDevices.getDisplayMedia({ audio: false, - video: browserScreenVideoConstraints, + video: displayMediaVideoConstraints, + ...displayMediaOptions, }); } } else { - screenMediaStream = await (navigator.mediaDevices as any).getUserMedia({ + screenMediaStream = await navigator.mediaDevices.getDisplayMedia({ audio: false, - video: browserScreenVideoConstraints, + video: displayMediaVideoConstraints, + ...displayMediaOptions, }); } @@ -676,16 +681,9 @@ export function useScreenRecorder(): UseScreenRecorderReturn { } else { const mediaStream = await navigator.mediaDevices.getDisplayMedia({ audio: false, - video: { - displaySurface: selectedSource.id?.startsWith("window:") ? "window" : "monitor", - width: { ideal: TARGET_WIDTH, max: TARGET_WIDTH }, - height: { ideal: TARGET_HEIGHT, max: TARGET_HEIGHT }, - frameRate: { ideal: TARGET_FRAME_RATE, max: TARGET_FRAME_RATE }, - cursor: "never", - }, - selfBrowserSurface: "exclude", - surfaceSwitching: "exclude", - } as any); + video: displayMediaVideoConstraints, + ...displayMediaOptions, + }); stream.current = mediaStream; videoTrack = mediaStream.getVideoTracks()[0];