Skip to content

Latest commit

 

History

History
executable file
·
158 lines (119 loc) · 8.16 KB

File metadata and controls

executable file
·
158 lines (119 loc) · 8.16 KB

CLAUDE.md

AI assistant context for StreamGRID. Read this before touching any code.

What this project is

StreamGRID is a cross-platform Electron desktop application for monitoring multiple live video streams simultaneously in configurable grid layouts. It plays HLS and HTTP streams (native RTMP cannot play in-browser and requires HLS transcoding). The app targets professional streaming workflows: broadcast monitoring, content production, security surveillance.

Version: 1.0.0 AppId: com.streamgrid.app Repo: https://github.com/sanchez314c/stream-grid


Tech stack

Layer Technology
Shell Electron 39
UI React 18 + TypeScript 5
Bundler Vite 7 (dev server port: 52774)
Styling Tailwind CSS 3 + custom CSS tokens
State Zustand 5 + Immer 10
Server state TanStack React Query 5
Video HLS.js 1.6
Database sqlite3 5 (userData/streams.db)
Settings JSON file (userData/settings.json) — NOT electron-store
Logging Winston 3
Tests Vitest 3 + React Testing Library
Packager electron-builder 26

Process architecture

src/main/       — Node.js main process (full fs/system access)
src/preload/    — Context bridge (index.ts exposes window.api)
src/renderer/   — React renderer (sandboxed, no Node access)
src/shared/     — Types shared across processes

CRITICAL: Never set experimentalFeatures: true in webPreferences — it breaks contextBridge IPC on Linux.


Key files

File Role
src/main/index.ts App entry. Sets GPU flags before app.ready, calls initializeApp()
src/main/window.ts Creates BrowserWindow (960x960, frameless, transparent). Sets app menu, IPC handlers for window controls. Validates external URLs to http/https/mailto only.
src/main/database/database.ts SQLite CRUD for streams and layouts tables
src/main/settings.ts Reads/writes settings.json. updateSettings() validates path against ALLOWED_SETTING_PATHS whitelist
src/main/ipc/handlers.ts Registers all IPC channels: stream:*, layout:*, settings:*, system:*, monitoring:*, hardware:*, discovery:*
src/main/ipc/advanced-controls-handlers.ts Advanced controls IPC: recording, VFX, randomizer, stream control
src/main/ipc/stream-validator.ts validateStreamUrl(), parseStreamUrl(), normalizeStreamUrl()
src/main/discovery/discovery-service.ts DiscoveryService singleton. Orchestrates NetworkScanner sessions. Emits discovery:progress, discovery:completed, discovery:error
src/main/discovery/network-scanner.ts Port scanning for RTSP/HTTP/ONVIF/MJPEG
src/main/monitoring/hardware-verifier.ts HardwareVerifier singleton. Platform-specific: nvidia-smi (Linux NVIDIA), VAAPI, VideoToolbox (macOS), DXVA (Windows)
src/main/monitoring/bandwidth-monitor.ts EventEmitter, emits metrics events forwarded to renderer
src/main/monitoring/gpu-monitor.ts GPU metrics, forwarded to renderer
src/preload/index.ts Exposes window.api (stream, layout, settings, discovery, monitoring, hardware, advancedControls, storage) and window.electronAPI (window controls)
src/renderer/App.tsx Root component. Loads streams/layouts via React Query. Registers menu IPC listeners.
src/renderer/store/index.ts useStreamGridStore — Zustand+Immer+persist. Serializes Map/Set to/from JSON for localStorage.
src/renderer/components/StreamGrid.tsx Grid layout using PRESET_LAYOUTS. Handles pagination with streamPageOffset. Auto-cycles pages every 60s when streams > slots.
src/renderer/components/StreamTile.tsx Per-stream tile with overlay controls
src/renderer/components/VideoPlayer.tsx HLS.js or native video. GPU/CPU decode path controlled by accelerationMode in store. Configurable buffer (1-30s via bufferSize).
src/shared/types/layout.ts PRESET_LAYOUTS: 1x1, 2x1, 3x1, 2x2, 3x3, 4x4
src/shared/types/settings.ts AppSettings, DEFAULT_SETTINGS, advanced controls profiles

Run commands

# Development (starts Vite + Electron together)
npm run dev

# Run from source (Linux) — use this for iteration
./run-source-linux.sh

# Type check
npm run type-check

# Lint
npm run lint

# Tests
npm test

# Production build
npm run build         # tsc + vite build
npm run dist:linux    # AppImage + deb + rpm + snap
npm run dist:mac      # DMG (x64 + arm64)
npm run dist:win      # NSIS + MSI + ZIP

IPC channel reference

All channels use ipcMain.handle / ipcRenderer.invoke pattern.

Stream: stream:add, stream:update, stream:delete, stream:getAll, stream:get, stream:save, stream:validate Layout: layout:create, layout:update, layout:delete, layout:getAll, layout:setActive Settings: settings:get, settings:update System: system:getInfo Monitoring: monitoring:startBandwidth, monitoring:stopBandwidth, monitoring:getBandwidthMetrics, monitoring:startGPU, monitoring:stopGPU, monitoring:getGPUInfo, monitoring:getHardwareVerification, monitoring:performHardwareVerification Hardware: hardware:verify, hardware:getVerification, hardware:getVideoToolboxInfo, hardware:startContinuousVerification, hardware:stopContinuousVerification Discovery: discovery:start, discovery:stop, discovery:getProgress, discovery:getResults Advanced Controls: advanced-controls:start-recording, advanced-controls:stop-recording, advanced-controls:pause-recording, advanced-controls:get-recording-state, advanced-controls:randomize-now, advanced-controls:randomize-single-tile, advanced-controls:apply-vfx-filter, advanced-controls:update-vfx-intensity, advanced-controls:reload-streams, advanced-controls:pause-streams, advanced-controls:stop-streams Window: minimize-window, maximize-window, close-window, open-external Storage: storage:getInfo, storage:openRecordingFolder, storage:cleanup


Settings paths (validated whitelist in settings.ts)

Settings are updated via settings:update IPC with a dot-path string. Only paths in ALLOWED_SETTING_PATHS are accepted. Key paths:

  • general.theme, general.minimizeToTray, general.defaultLayout
  • display.alwaysOnTop, display.showLabels, display.showStatistics
  • performance.maxConcurrentStreams, performance.gpuDecoding, performance.accelerationMode
  • audio.defaultVolume, audio.defaultMuted
  • advanced.logLevel, advanced.rtmpTimeout

Database schema

streams table: id TEXT PK, url, label, status, metadata JSON, settings JSON, statistics JSON, createdAt, updatedAt layouts table: id TEXT PK, name, type, grid JSON, streams JSON, isActive INTEGER, createdAt, updatedAt

Database location: app.getPath('userData')/streams.db


Known constraints and gotchas

  • RTMP URLs cannot play directly. VideoPlayer.tsx surfaces an error and tells the user to use HLS (.m3u8). RTMP validation still works for storage.
  • sqlite3 is a native module. After any Electron version upgrade, run npm run rebuild.
  • Dev server port is 52774 (hardcoded in vite.config.ts and src/main/window.ts).
  • experimentalFeatures: true in BrowserWindow webPreferences breaks contextBridge IPC on Linux. Never set it.
  • Zustand store uses custom serialization in the persist middleware to handle Map/Set (which JSON doesn't support natively). See storage.getItem / storage.setItem in src/renderer/store/index.ts.
  • Linux requires --no-sandbox or sudo sysctl -w kernel.unprivileged_userns_clone=1 for Electron.
  • Hardware verification on Linux checks nvidia-smi first, then vainfo, then radeontop. The status bar shows "GPU MODE" / "CPU MODE" based on store accelerationMode.
  • settings.json is written directly with fs.writeFileSync — not electron-store (removed due to ESM incompatibility).

Advanced Controls profiles (defined in settings.ts)

Profile Keyboard Recording VFX Randomizer
clean off off off off
broadcast on on off off
creative on on on on
monitoring on off off on