Connection
The WebSocket server runs on ws://localhost:5000/ and accepts connections from the frontend.
const socket = new WebSocket ( 'ws://localhost:5000/' );
The backend only allows one active WebSocket connection. New connections automatically close previous ones.
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
Starts a manual recording session. Parameters: NoneExample: sendMessageToBackend ( 'StartRecording' );
Stops the current recording. Parameters: NoneExample: sendMessageToBackend ( 'StopRecording' );
Authentication
Authenticates the user with Supabase tokens. Parameters: Supabase access token from the session
Supabase refresh token for token renewal
Example: sendMessageToBackend ( 'Login' , {
accessToken: session . access_token ,
refreshToken: session . refresh_token ,
});
Signs out the current user. Parameters: NoneExample: sendMessageToBackend ( 'Logout' );
Clip Creation
Creates clips from selected video segments. Parameters: Array of selection objects defining clip segments Unique identifier for this selection
Start timestamp in seconds
Full path to source video
Content type (e.g., “recording”, “replay”)
Game name for organizing clips
Optional title for the clip
Example: sendMessageToBackend ( 'CreateClip' , {
Selections: [{
id: 1 ,
startTime: 30.5 ,
endTime: 45.2 ,
fileName: "gameplay_2024.mp4" ,
filePath: "C:/Videos/gameplay_2024.mp4" ,
type: "recording" ,
game: "Valorant" ,
title: "Epic Ace" ,
igdbId: 12345
}]
});
Cancels an in-progress clip operation. Parameters: The clip operation ID to cancel
Example: sendMessageToBackend ( 'CancelClip' , { id: 123 });
Creates AI-generated highlights from a video. Parameters: Video file name to process
Example: sendMessageToBackend ( 'CreateAiClip' , {
FileName: "gameplay_2024.mp4"
});
Content Management
Deletes a single piece of content. Parameters: File name of the content to delete
Type of content (“Recording”, “Clip”, “Replay”)
Example: sendMessageToBackend ( 'DeleteContent' , {
FileName: "clip_001.mp4" ,
ContentType: "Clip"
});
Deletes multiple content items in a batch operation. Parameters: 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" }
]
});
Renames a content file. Parameters: Handled by ContentService.HandleRenameContentExample: sendMessageToBackend ( 'RenameContent' , {
// Parameters defined in ContentService
});
Imports an external video file into Segra. Parameters: Handled by ImportService.HandleImportFileExample: sendMessageToBackend ( 'ImportFile' , {
// Parameters defined in ImportService
});
Upload & Compression
Uploads content to a platform (e.g., Segra.tv). Parameters: Handled by UploadService.HandleUploadContentExample: sendMessageToBackend ( 'UploadContent' , {
// Parameters defined in UploadService
});
Cancels an in-progress upload. Parameters: File name of the upload to cancel
Example: sendMessageToBackend ( 'CancelUpload' , {
fileName: "clip_001.mp4"
});
Compresses a video to reduce file size. Parameters: Full path to the video file
Example: sendMessageToBackend ( 'CompressVideo' , {
FilePath: "C:/Videos/large_file.mp4"
});
Bookmarks
Adds a bookmark during recording or playback. Parameters: Handled by ContentService.HandleAddBookmarkExample: sendMessageToBackend ( 'AddBookmark' , {
// Parameters defined in ContentService
});
Removes a bookmark. Parameters: Handled by ContentService.HandleDeleteBookmarkExample: sendMessageToBackend ( 'DeleteBookmark' , {
// Parameters defined in ContentService
});
Settings
Updates application settings. Parameters: Handled by SettingsService.HandleUpdateSettingsExample: sendMessageToBackend ( 'UpdateSettings' , {
// Settings object with changed values
});
Opens a folder picker to change the video storage location. Parameters: NoneExample: sendMessageToBackend ( 'SetVideoLocation' );
Opens a folder picker to change the cache storage location. Parameters: NoneExample: sendMessageToBackend ( 'SetCacheLocation' );
Applies a video quality preset. Parameters: Name of the preset (e.g., “1080p60”, “4k60”)
Example: sendMessageToBackend ( 'ApplyVideoPreset' , {
preset: "1080p60"
});
Applies a clip quality preset. Parameters: Example: sendMessageToBackend ( 'ApplyClipPreset' , {
preset: "high_quality"
});
Game Management
Adds a game to the recording whitelist. Parameters: Game object with name and paths Array of executable paths
Example: sendMessageToBackend ( 'AddToWhitelist' , {
game: {
Name: "Valorant" ,
Paths: [ "C:/Games/Valorant/VALORANT.exe" ]
}
});
Removes a game from the whitelist. Parameters: Game object matching the one to remove
Adds a game to the recording blacklist. Parameters: Game object with name and paths
Removes a game from the blacklist. Parameters: Game object matching the one to remove
Moves a game between whitelist and blacklist. Parameters: Target list: “whitelist” or “blacklist”
Example: sendMessageToBackend ( 'MoveGame' , {
game: { Name: "GameName" , Paths: [ ... ] },
targetList: "blacklist"
});
Opens a file picker to select a game executable. Parameters: NoneResponse: Backend sends SelectedGameExecutable message with the selected fileExample: sendMessageToBackend ( 'SelectGameExecutable' );
System Actions
Opens Windows Explorer to the file location. Parameters: Example: sendMessageToBackend ( 'OpenFileLocation' , {
FilePath: "C:/Videos/clip.mp4"
});
Opens a URL in the default browser. Parameters: Example: sendMessageToBackend ( 'OpenInBrowser' , {
Url: "https://segra.tv"
});
Opens Windows Explorer to the logs folder. Parameters: NoneExample: sendMessageToBackend ( 'OpenLogsLocation' );
Toggles fullscreen mode. Parameters: True to enable fullscreen, false to disable
Example: sendMessageToBackend ( 'ToggleFullscreen' , {
enabled: true
});
Updates
Checks for available application updates. Parameters: NoneExample: sendMessageToBackend ( 'CheckForUpdates' );
Applies a downloaded update and restarts the application. Parameters: NoneExample: sendMessageToBackend ( 'ApplyUpdate' );
Connection
Signals that a new WebSocket connection has been established. The backend responds with initial state. Parameters: NoneResponse: Backend sends:
Settings with current application state
GameList with available games
AppVersion with backend version
Example: sendMessageToBackend ( 'NewConnection' );
Storage & Recovery
Confirms or cancels a storage warning action. Parameters: Handled by StorageWarningService.HandleStorageWarningConfirm
Confirms recovery of temporary files after a crash. Parameters: Handled by RecoveryService.HandleRecoveryConfirm
Backend to Frontend Events
These messages are sent from the backend to update the frontend state.
State Updates
Sends the complete application state to the frontend. Content: Complete Settings.Instance object containing all application state
Example: {
"method" : "Settings" ,
"content" : {
"contentFolder" : "C:/Videos" ,
"cacheFolder" : "C:/AppData/Segra" ,
"state" : {
"recording" : null ,
"content" : [ ... ],
// ... full state object
}
}
}
Sends the list of detected games. Content: Array of game objects with names and executable paths
Example: {
"method" : "GameList" ,
"content" : [
{
"name" : "Valorant" ,
"paths" : [ "C:/Games/Valorant/VALORANT.exe" ],
"igdbId" : 12345
}
]
}
Sends the backend application version for version mismatch detection. Content: 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
Reports progress of clip creation operations. Content: Progress percentage (0-100), or -1 for error
Array of selections being processed
Error message if progress is -1
Example: {
"method" : "ClipProgress" ,
"content" : {
"id" : 123456 ,
"progress" : 45 ,
"selections" : [ ... ]
}
}
Reports progress of upload operations. Content: Progress percentage (0-100), or -1 for error
Upload status: “uploading”, “processing”, “done”, or “error”
Status message or error description
Example: {
"method" : "UploadProgress" ,
"content" : {
"fileName" : "clip_001.mp4" ,
"progress" : 75 ,
"status" : "uploading" ,
"message" : "Uploading to server..."
}
}
Reports progress of file import operations. Content: Current file being imported
Progress percentage for current file
Import status: “importing”, “done”, or “error”
Total number of files to import
Index of current file (0-based)
Reports progress of video compression. Content: Progress percentage (0-100), or -1 for error
Status: “compressing”, “done”, “skipped”, or “error”
Example: {
"method" : "CompressionProgress" ,
"content" : {
"filePath" : "C:/Videos/large.mp4" ,
"progress" : 50 ,
"status" : "compressing"
}
}
Reports progress of application updates. Content: Download progress (0-100)
Status: “downloading”, “downloaded”, “ready”, or “error”
Human-readable status message
Reports progress of AI highlight generation. Content: Handled by AiService
Reports status of data migration operations. Content: Whether migration is currently running
Description of current migration
User Notifications
Displays a modal dialog to the user. Content: Modal type: “info”, “warning”, or “error”
Example: {
"method" : "ShowModal" ,
"content" : {
"title" : "Error" ,
"description" : "Failed to start recording" ,
"type" : "error"
}
}
Warns user about storage space issues and requests confirmation. Content: Unique ID for this warning
Action to perform if confirmed
Data needed to perform the action
Prompts user to recover files after a crash. Content: Array of recoverable file objects
Total number of files that can be recovered
Notifies that a bookmark was created (typically from a keybind). Content: Empty objectExample: {
"method" : "BookmarkCreated" ,
"content" : {}
}
UI Events
Returns the game executable selected by the user. Content: Game name (derived from executable name)
Array containing the selected executable path
Example: {
"method" : "SelectedGameExecutable" ,
"content" : {
"name" : "MyGame" ,
"paths" : [ "C:/Games/MyGame/game.exe" ]
}
}
Sends release notes for available versions. Content: Array of release note objects Release notes in base64-encoded markdown
Triggers the frontend to display release notes. Content: Version string to show notes for
Reports OBS download progress during first-time setup. Content: Download progress (0-100)
Download status: “downloading”
Heartbeat
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:
Logs the error with Serilog
Sends a progress event with progress: -1 and an error field
Optionally shows a ShowModal message to the user
Example error response:
{
"method" : "ClipProgress" ,
"content" : {
"id" : 123456 ,
"progress" : -1 ,
"selections" : [ ... ],
"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' , {
Selections: [{
id: id ,
startTime: 10 ,
endTime: 20 ,
fileName: 'gameplay.mp4' ,
type: 'recording' ,
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