Skip to content

Feature: stream recording support#142

Merged
zortos293 merged 17 commits intoOpenCloudGaming:devfrom
Jayian1890:feature/stream-recording
Mar 9, 2026
Merged

Feature: stream recording support#142
zortos293 merged 17 commits intoOpenCloudGaming:devfrom
Jayian1890:feature/stream-recording

Conversation

@Jayian1890
Copy link

@Jayian1890 Jayian1890 commented Mar 7, 2026

Summary

Adds stream recording support to OpenNOW, allowing users to record their GeForce NOW sessions directly from the client. Recordings are captured via the browser's MediaRecorder API, streamed in chunks to the main process, and saved to disk as MP4 or WebM files.

Changes

Main Process (src/main/index.ts)

  • Enabled the MediaRecorderEnableMp4Muxer Chromium feature flag to support MP4 output via MediaRecorder (Chromium 127+).
  • Added a full recording pipeline with IPC handlers:
    • RECORDING_BEGIN — allocates a temp write stream and returns a recordingId
    • RECORDING_CHUNK — streams binary chunks from the renderer to the temp file
    • RECORDING_FINISH — finalises the recording, encodes an optional thumbnail, renames the temp file to its final timestamped name (with duration encoded), and enforces a 20-recording limit (oldest auto-deleted)
    • RECORDING_ABORT — cancels an in-progress recording and removes the temp file
    • RECORDING_LIST — reads the recordings directory and returns metadata for all saved recordings (including base64-encoded thumbnails)
    • RECORDING_DELETE — deletes a recording and its thumbnail
    • RECORDING_SHOW_IN_FOLDER — reveals a recording in the system file manager via shell.showItemInFolder
  • Recordings are saved to ~/Pictures/OpenNOW/Recordings/ with filenames encoding the game title, timestamp, and duration.
  • Input is sanitised to prevent path traversal (assertSafeRecordingId).

Preload (src/preload/index.ts)

  • Exposed all seven recording API methods on window.openNow: beginRecording, sendRecordingChunk, finishRecording, abortRecording, listRecordings, deleteRecording, showRecordingInFolder.

Renderer — StreamView (src/renderer/src/components/StreamView.tsx)

  • Added recording state: isRecording, recordingDurationMs, recordings, recordingError.
  • Implemented startRecording / stopRecording using MediaRecorder on the stream's video track, with chunk streaming to the main process.
  • Live recording timer ticks every second while recording is active.
  • Recording controls displayed in the sidebar (start/stop button, duration display, error feedback).
  • Recordings gallery in the sidebar — lists saved recordings with thumbnail, duration, file size, game title, date, and actions (open in folder, delete).
  • Configurable keyboard shortcut to toggle recording, with conflict detection against existing shortcuts.
  • recordingApiAvailable guard ensures controls are only shown when the preload API is present.

App (src/renderer/src/App.tsx)

  • Wired onRecordingShortcutChange prop to persist the recording shortcut via settings.

Settings (src/main/settings.ts)

  • Added recording shortcut key to the persisted settings schema.

Shared Types (src/shared/gfn.ts, src/shared/ipc.ts)

  • Added RecordingEntry, RecordingBeginRequest, RecordingBeginResult, RecordingChunkRequest, RecordingFinishRequest, RecordingAbortRequest, RecordingDeleteRequest interfaces.
  • Added shortcutToggleRecording to the OpenNowAPI interface.
  • Added RECORDING_* IPC channel constants.

Styles (src/renderer/src/styles.css)

  • Added styles for the recording indicator (pulsing red dot), recording controls, and recording card gallery items in the sidebar.

Notes

  • The MP4 muxer flag is required for MP4 output; the implementation falls back to WebM if MP4 is not supported by the browser.
  • The recording limit is capped at 20 entries; exceeding this auto-deletes the oldest recording.
  • Thumbnails are captured as JPEG and stored alongside the video file (<stem>-thumb.jpg).

- Introduced `requestKeyframe` method in GfnSignalingClient to send keyframe requests with reason, backlog frames, and attempt count.
- Added IPC handler for keyframe requests in the main process.
- Updated preload API to include `requestKeyframe` method.
- Enhanced StreamView component to manage sidebar tabs for preferences and shortcuts.
- Implemented decoder pressure detection and recovery mechanisms in GfnWebRtcClient, including bitrate reduction and keyframe requests.
- Updated diagnostics to track decoder pressure state and recovery attempts.
- Styled sidebar tabs for better user experience.
- Introduced new settings for recording shortcuts in settings.ts and App.tsx.
- Implemented recording API methods in preload/index.ts for starting, stopping, and managing recordings.
- Enhanced StreamView component to handle recording state, display recording controls, and show recordings in a sidebar.
- Added CSS styles for recording indicators and recording cards in styles.css.
- Updated IPC channels in ipc.ts to support recording operations.
- Defined new types for recording requests and entries in gfn.ts.
@zortos293 zortos293 changed the base branch from main to dev March 7, 2026 15:07
@Jayian1890 Jayian1890 closed this Mar 7, 2026
@Jayian1890 Jayian1890 reopened this Mar 7, 2026
@zortos293 zortos293 merged commit ab32f7e into OpenCloudGaming:dev Mar 9, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants