Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion -

This file was deleted.

66 changes: 32 additions & 34 deletions src/hooks/useScreenRecorder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
});
}

Expand Down Expand Up @@ -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];
Expand Down