Skip to main content

Connection

The WebSocket server runs on ws://localhost:44030/ and accepts connections from the frontend.
const socket = new WebSocket('ws://localhost:44030/');
The backend only allows one active WebSocket connection. New connections automatically close previous ones.
The backend also listens on the legacy port ws://localhost:5000/. Connections to that port immediately receive an AppVersion message and are then closed, which causes older frontends to detect a version mismatch and reload against the current port.

Message Structure

Frontend to Backend

Messages sent via window.external.sendMessage() use this JSON structure:
{
  "Method": "string",
  "Parameters": {
    // Method-specific parameters
  }
}

Backend to Frontend

Messages received via WebSocket use this JSON structure:
{
  "method": "string",
  "content": {
    // Event-specific data
  }
}
Note the casing difference: Method (capitalized) for frontend-to-backend, method (lowercase) for backend-to-frontend due to JSON serialization settings.

Frontend to Backend Methods

These commands can be sent from the frontend to control the backend.

Recording Control

StartRecording
method
Starts a manual recording session.Parameters: NoneExample:
sendMessageToBackend('StartRecording');
StopRecording
method
Stops the current recording.Parameters: NoneExample:
sendMessageToBackend('StopRecording');

Authentication

Login
method
Authenticates the user with Supabase tokens.Parameters:
accessToken
string
required
Supabase access token from the session
refreshToken
string
required
Supabase refresh token for token renewal
Example:
sendMessageToBackend('Login', {
  accessToken: session.access_token,
  refreshToken: session.refresh_token,
});
Logout
method
Signs out the current user.Parameters: NoneExample:
sendMessageToBackend('Logout');

Clip Creation

CreateClip
method
Creates clips from selected video segments.Parameters:
Segments
array
required
Array of segment objects defining clip ranges
id
number
required
Unique identifier for this segment
startTime
number
required
Start timestamp in seconds
endTime
number
required
End timestamp in seconds
fileName
string
required
Source video file name
filePath
string
Full path to source video
type
string
required
Content type: Session, Buffer, Clip, or Highlight
game
string
required
Game name for organizing clips
title
string
Optional title for the clip
igdbId
number
IGDB game database ID
mutedAudioTracks
number[]
Optional array of audio track indexes to mute in the output
audioTrackVolumes
object
Optional map of { "<trackIndex>": <volume> } to apply per-track volume adjustments
Example:
sendMessageToBackend('CreateClip', {
  Segments: [{
    id: 1,
    startTime: 30.5,
    endTime: 45.2,
    fileName: "gameplay_2024",
    filePath: "C:/Videos/gameplay_2024.mp4",
    type: "Session",
    game: "Valorant",
    title: "Epic Ace",
    igdbId: 12345
  }]
});
CancelClip
method
Cancels an in-progress clip operation.Parameters:
id
number
required
The clip operation ID to cancel
Example:
sendMessageToBackend('CancelClip', { id: 123 });
CreateAiClip
method
Creates AI-generated highlights from a video.Parameters:
FileName
string
required
Video file name to process
Example:
sendMessageToBackend('CreateAiClip', {
  FileName: "gameplay_2024.mp4"
});

Content Management

DeleteContent
method
Deletes a single piece of content.Parameters:
FileName
string
required
File name of the content to delete
ContentType
string
required
Type of content: Session, Buffer, Clip, or Highlight
Example:
sendMessageToBackend('DeleteContent', {
  FileName: "clip_001",
  ContentType: "Clip"
});
DeleteMultipleContent
method
Deletes multiple content items in a batch operation.Parameters:
Items
array
required
Array of items to delete, each with FileName and ContentType
Example:
sendMessageToBackend('DeleteMultipleContent', {
  Items: [
    { FileName: "clip_001.mp4", ContentType: "Clip" },
    { FileName: "clip_002.mp4", ContentType: "Clip" }
  ]
});
RenameContent
method
Renames a content file.Parameters: Handled by ContentService.HandleRenameContentExample:
sendMessageToBackend('RenameContent', {
  // Parameters defined in ContentService
});
ImportFile
method
Imports an external video file into Segra.Parameters: Handled by ImportService.HandleImportFileExample:
sendMessageToBackend('ImportFile', {
  // Parameters defined in ImportService
});

Upload & Compression

UploadContent
method
Uploads content to a platform (e.g., Segra.tv).Parameters: Handled by UploadService.HandleUploadContentExample:
sendMessageToBackend('UploadContent', {
  // Parameters defined in UploadService
});
CancelUpload
method
Cancels an in-progress upload.Parameters:
fileName
string
required
File name of the upload to cancel
Example:
sendMessageToBackend('CancelUpload', {
  fileName: "clip_001.mp4"
});
CompressVideo
method
Compresses a video to reduce file size.Parameters:
FilePath
string
required
Full path to the video file
Example:
sendMessageToBackend('CompressVideo', {
  FilePath: "C:/Videos/large_file.mp4"
});

Bookmarks

AddBookmark
method
Adds a bookmark during recording or playback.Parameters: Handled by ContentService.HandleAddBookmarkExample:
sendMessageToBackend('AddBookmark', {
  // Parameters defined in ContentService
});
DeleteBookmark
method
Removes a bookmark.Parameters: Handled by ContentService.HandleDeleteBookmarkExample:
sendMessageToBackend('DeleteBookmark', {
  // Parameters defined in ContentService
});

Settings

UpdateSettings
method
Updates application settings.Parameters: Handled by SettingsService.HandleUpdateSettingsExample:
sendMessageToBackend('UpdateSettings', {
  // Settings object with changed values
});
SetVideoLocation
method
Opens a folder picker to change the video storage location.Parameters: NoneExample:
sendMessageToBackend('SetVideoLocation');
SetCacheLocation
method
Opens a folder picker to change the cache storage location.Parameters: NoneExample:
sendMessageToBackend('SetCacheLocation');
ApplyVideoPreset
method
Applies a video quality preset (see PresetsService.ApplyVideoPreset).Parameters:
preset
string
required
Preset name: low, standard, high, or custom
Example:
sendMessageToBackend('ApplyVideoPreset', {
  preset: "high"
});
ApplyClipPreset
method
Applies a clip quality preset (see PresetsService.ApplyClipPreset).Parameters:
preset
string
required
Preset name: low, standard, high, or custom
Example:
sendMessageToBackend('ApplyClipPreset', {
  preset: "standard"
});

Game Management

Per-game record/skip preferences live on the unified games array in Settings.Instance (each entry has a record boolean plus optional quality / recording-mode overrides). Update them by sending an UpdateSettings message with the modified games array — there are no dedicated AddToWhitelist / AddToBlacklist / MoveGame methods. The legacy whitelist / blacklist fields are migration-only and may be removed in a future release.
SelectGameExecutable
method
Opens a file picker to select a game executable.Parameters: NoneResponse: Backend sends SelectedGameExecutable message with the selected fileExample:
sendMessageToBackend('SelectGameExecutable');

System Actions

OpenFileLocation
method
Opens Windows Explorer to the file location.Parameters:
FilePath
string
required
Full path to the file
Example:
sendMessageToBackend('OpenFileLocation', {
  FilePath: "C:/Videos/clip.mp4"
});
CopyFileToClipboard
method
Copies a file to the Windows clipboard so it can be pasted into Explorer, chat clients, or other apps that accept file drops.Parameters:
FilePath
string
required
Full path to the file to copy
Example:
sendMessageToBackend('CopyFileToClipboard', {
  FilePath: "C:/Videos/clip.mp4"
});
OpenInBrowser
method
Opens a URL in the default browser.Parameters:
Url
string
required
URL to open
Example:
sendMessageToBackend('OpenInBrowser', {
  Url: "https://segra.tv"
});
OpenLogsLocation
method
Opens Windows Explorer to the logs folder.Parameters: NoneExample:
sendMessageToBackend('OpenLogsLocation');
ToggleFullscreen
method
Toggles fullscreen mode.Parameters:
enabled
boolean
required
True to enable fullscreen, false to disable
Example:
sendMessageToBackend('ToggleFullscreen', {
  enabled: true
});

Updates

CheckForUpdates
method
Checks for available application updates.Parameters: NoneExample:
sendMessageToBackend('CheckForUpdates');
ApplyUpdate
method
Applies a downloaded update and restarts the application.Parameters: NoneExample:
sendMessageToBackend('ApplyUpdate');

Connection

NewConnection
method
Signals that a new WebSocket connection has been established. The backend responds with initial state.Parameters: NoneResponse: Backend sends:
  • Settings with persisted settings
  • State with runtime application state
  • GameList with available games
  • AppVersion with backend version (only when an update manager build is available)
  • UpdateProgress if an update download/install was in flight when the client (re)connected, replaying the most recent progress payload
  • ReleaseNotes asynchronously, after fetching from the update channel
Example:
sendMessageToBackend('NewConnection');

Storage & Recovery

StorageWarningConfirm
method
Confirms or cancels a storage warning action.Parameters: Handled by StorageWarningService.HandleStorageWarningConfirm
RecoveryConfirm
method
Confirms recovery of temporary files after a crash.Parameters: Handled by RecoveryService.HandleRecoveryConfirm
MigrateContent
method
Triggers migration of existing content into Segra’s canonical folder layout.Parameters: Handled by ContentMigrationService.HandleMigrateContentProgress: The backend streams ContentMigrationProgress events while the migration runs.

Backend to Frontend Events

These messages are sent from the backend to update the frontend state.

State Updates

Settings
event
Sends the persisted user settings to the frontend. content is the bare Settings.Instance object (no wrapping settings key).Example:
{
  "method": "Settings",
  "content": {
    "contentFolder": "C:/Videos",
    "cacheFolder": "C:/AppData/Segra",
    "resolution": "1440p",
    "frameRate": 60,
    "recordingMode": "Hybrid",
    "keybindings": [...]
    // ... all persisted settings
  }
}
Runtime state (active recording, content library, detected devices, current folder size, etc.) is no longer nested under settings.state. It is delivered separately via the State message described below.
State
event
Sends the runtime AppState.Instance object to the frontend. This is non-persisted, in-memory state that mirrors the live application status.Content (selected fields):
recording
object
The active Recording (or null when idle)
preRecording
object
A PreRecording placeholder while Segra is preparing to record (or null)
content
array
All known content items (sessions, buffers, clips, highlights)
inputDevices
array
Detected audio input devices
outputDevices
array
Detected audio output devices
displays
array
Detected monitors
codecs
array
Available video codecs/encoders
availableOBSVersions
array
OBS versions known to the updater
gpuVendor
string
Detected GPU vendor (Nvidia, Amd, Intel, or Unknown)
cudaComputeCapability
number
Detected CUDA compute capability for NVIDIA GPUs
maxDisplayHeight
number
Maximum height of any connected display (used for resolution clamping)
hasLoadedObs
boolean
True once OBS has been initialized
isCheckingForUpdates
boolean
True while an update check is in-flight
currentFolderSizeGb
number
Total size of the content folder in GB
Example:
{
  "method": "State",
  "content": {
    "recording": null,
    "preRecording": null,
    "content": [],
    "gpuVendor": "Nvidia",
    "currentFolderSizeGb": 12.4,
    "hasLoadedObs": true
  }
}
GameList
event
Sends the list of detected games.Content: The content field is itself an array of GameEntry objects — there is no wrapping games key.Example:
{
  "method": "GameList",
  "content": [
    {
      "name": "Valorant",
      "executables": ["C:\\Games\\Valorant\\VALORANT.exe"]
    }
  ]
}
Each entry uses the GameEntry shape from Backend/Games/GameUtils.csname and executables (back-slashed). It is distinct from the Game shape used for whitelist/blacklist commands, which uses paths.
AppVersion
event
Sends the backend application version for version mismatch detection.Content:
version
string
Semantic version string (e.g., “1.2.3”)
Example:
{
  "method": "AppVersion",
  "content": {
    "version": "1.2.3"
  }
}
Frontend automatically reloads if this doesn’t match __APP_VERSION__

Progress Events

ClipProgress
event
Reports progress of clip creation operations.Content:
id
number
required
Clip operation ID
progress
number
required
Progress percentage (0-100), or -1 for error
segments
array
required
Array of segments being processed (mirrors what was sent in CreateClip)
error
string
Error message if progress is -1
Example:
{
  "method": "ClipProgress",
  "content": {
    "id": 123456,
    "progress": 45,
    "segments": [...]
  }
}
UploadProgress
event
Reports progress of upload operations.Content:
fileName
string
required
File being uploaded
title
string
required
Title submitted with the upload (mirrored in every progress event)
progress
number
required
Progress percentage (0-100), or -1 for error
status
string
required
Upload status: “uploading”, “processing”, “done”, or “error”
message
string
Status message or error description
Example:
{
  "method": "UploadProgress",
  "content": {
    "fileName": "clip_001.mp4",
    "progress": 75,
    "status": "uploading",
    "message": "Uploading to server..."
  }
}
ImportProgress
event
Reports progress of file import operations.Content:
id
number
required
Import operation ID
fileName
string
required
Current file being imported
progress
number
required
Progress percentage for current file
status
string
required
Import status: “importing”, “done”, or “error”
totalFiles
number
required
Total number of files to import
currentFileIndex
number
required
Index of current file (0-based)
message
string
Status message
CompressionProgress
event
Reports progress of video compression.Content:
filePath
string
required
File being compressed
progress
number
required
Progress percentage (0-100), or -1 for error
status
string
required
Status: “compressing”, “done”, “skipped”, or “error”
message
string
Status message
Example:
{
  "method": "CompressionProgress",
  "content": {
    "filePath": "C:/Videos/large.mp4",
    "progress": 50,
    "status": "compressing"
  }
}
UpdateProgress
event
Reports progress of application updates.Content:
version
string
required
Version being downloaded
progress
number
required
Download progress (0-100)
status
string
required
Status: “downloading”, “downloaded”, or “ready”
message
string
required
Human-readable status message
AiProgress
event
Reports progress of AI highlight generation.Content: Handled by AiService
RecordingPreviewState
event
Indicates whether the recording-preview window is currently active (the in-app live preview controlled by the TogglePreview keybind).Content:
enabled
boolean
required
Whether preview rendering is active
RecordingPreviewFrame
event
Streams a frame of the live recording preview to the frontend (sent only while the preview is enabled).Content: A frame payload emitted by RecordingPreviewService.
MigrationStatus
event
Reports status of data migration operations.Content:
isRunning
boolean
required
Whether migration is currently running
currentMigration
string
Description of current migration
ContentMigrationProgress
event
Reports progress of a content-folder migration triggered by MigrateContent.Content:
id
string
required
Migration operation ID
fileName
string
required
File currently being moved
progress
number
required
Progress percentage (0-100), or -1 for error
status
string
required
Migration status (e.g. "migrating", "done", "error")
totalFiles
number
Total number of files in the migration
currentFileIndex
number
Index of the file currently being moved
message
string
Status or error message
ReplayBufferSaved
event
Fired when the user saves the replay buffer (typically via the SaveReplayBuffer keybind). Emitted with an empty content payload — frontends usually surface a toast or sound effect in response.

User Notifications

ShowModal
event
Displays a modal dialog to the user.Content:
title
string
required
Modal title
subtitle
string
Optional subtitle
description
string
required
Modal body text
type
string
required
Modal type: “info”, “warning”, or “error”
Example:
{
  "method": "ShowModal",
  "content": {
    "title": "Error",
    "description": "Failed to start recording",
    "type": "error"
  }
}
StorageWarning
event
Warns user about storage space issues and requests confirmation.Content:
warningId
string
required
Unique ID for this warning
title
string
required
Warning title
description
string
required
Warning description
confirmText
string
required
Text for confirm button
cancelText
string
required
Text for cancel button
action
string
required
Action to perform if confirmed
actionData
any
required
Data needed to perform the action
RecoveryPrompt
event
Prompts user to recover files after a crash.Content:
files
array
required
Array of recoverable file objects
totalCount
number
required
Total number of files that can be recovered
BookmarkCreated
event
Notifies that a bookmark was created (typically from a keybind).Content: Empty objectExample:
{
  "method": "BookmarkCreated",
  "content": {}
}

UI Events

SelectedGameExecutable
event
Returns the game executable selected by the user.Content:
name
string
required
Game name (derived from executable name)
paths
array
required
Array containing the selected executable path
Example:
{
  "method": "SelectedGameExecutable",
  "content": {
    "name": "MyGame",
    "paths": ["C:/Games/MyGame/game.exe"]
  }
}
ReleaseNotes
event
Sends release notes for available versions.Content:
releaseNotesList
array
required
Array of release note objects
version
string
required
Version number
base64Markdown
string
required
Release notes in base64-encoded markdown
releaseDate
string
required
ISO 8601 date string
ShowReleaseNotes
event
Triggers the frontend to display release notes.Content: Version string to show notes for
ObsDownloadProgress
event
Reports OBS download progress during first-time setup.Content:
progress
number
required
Download progress (0-100)
status
string
required
Download status: “downloading”

Heartbeat

pong
event
Response to ping heartbeat message.Content: Empty objectExample:
{
  "method": "pong",
  "content": {}
}

Error Handling

Frontend Validation

Always check if the backend connection is available before sending messages:
if ((window as any).external && typeof (window as any).external.sendMessage === 'function') {
  sendMessageToBackend('StartRecording');
} else {
  console.error('Backend connection not available');
}

Backend Error Responses

When operations fail, the backend typically:
  1. Logs the error with Serilog
  2. Sends a progress event with progress: -1 and an error field
  3. Optionally shows a ShowModal message to the user
Example error response:
{
  "method": "ClipProgress",
  "content": {
    "id": 123456,
    "progress": -1,
    "segments": [...],
    "error": "FFmpeg not found. Please reinstall Segra."
  }
}

Connection Failures

The WebSocket automatically reconnects if the connection drops:
  • Reconnect attempts: Infinite
  • Reconnect interval: 3 seconds
  • Heartbeat timeout: 30 seconds
When reconnected, the backend re-sends the full state:
onOpen: () => {
  console.log('WebSocket reconnected - resyncing state');
  sendMessageToBackend('NewConnection');
}

Best Practices

Use TypeScript Types

Import message type definitions from Models/WebSocketMessages.ts for type safety.

Handle All States

Progress events can be: in-progress (0-100), complete (100), or error (-1). Handle all cases.

Listen to Events

Use window.addEventListener('websocket-message') to react to backend events globally.

Graceful Degradation

Always check if window.external.sendMessage exists before calling it.
Never assume the WebSocket is connected. Use the isConnected state from useWebSocketContext() to check connection status.

Example: Complete Clip Workflow

Here’s a complete example showing the clip creation workflow:
import { sendMessageToBackend } from '../Utils/MessageUtils';
import { useEffect, useState } from 'react';

function ClipCreator() {
  const [progress, setProgress] = useState(0);
  const [clipId, setClipId] = useState<number | null>(null);

  // Listen for progress updates
  useEffect(() => {
    const handleMessage = (event: CustomEvent) => {
      const { method, content } = event.detail;
      
      if (method === 'ClipProgress') {
        if (content.id === clipId) {
          if (content.progress === -1) {
            console.error('Clip failed:', content.error);
          } else if (content.progress === 100) {
            console.log('Clip complete!');
          } else {
            setProgress(content.progress);
          }
        }
      }
    };

    window.addEventListener('websocket-message', handleMessage as EventListener);
    return () => window.removeEventListener('websocket-message', handleMessage as EventListener);
  }, [clipId]);

  const createClip = () => {
    const id = Math.floor(Math.random() * 1000000);
    setClipId(id);
    
    sendMessageToBackend('CreateClip', {
      Segments: [{
        id: id,
        startTime: 10,
        endTime: 20,
        fileName: 'gameplay',
        type: 'Session',
        game: 'Valorant',
        title: 'Epic Play'
      }]
    });
  };

  const cancelClip = () => {
    if (clipId) {
      sendMessageToBackend('CancelClip', { id: clipId });
    }
  };

  return (
    <div>
      <button onClick={createClip}>Create Clip</button>
      <button onClick={cancelClip}>Cancel</button>
      <progress value={progress} max={100} />
    </div>
  );
}

Next Steps

API Overview

Learn about the internal architecture

Core Services

Browse backend service documentation