WebSocket server for edrys-Lite to create a connection between peers and share video streams.
This project is a modified version of y-websocket-server by Kevin Jahns.
The WebSocket server provides two main functions:
- A backend for y-websocket to handle Yjs document collaboration
- A video streaming server to enable real-time video sharing between peers
npm install
This repository implements a server that handles both Yjs document collaboration and video streaming in a single process. (source code)
Start the server:
node dist/server.cjs --port 3210
For secure connections (required when your app is hosted on HTTPS), enable SSL/TLS:
# Enable SSL with auto-generated self-signed certificates
node dist/server.cjs --ssl --port 3210
# Or use custom certificates
node dist/server.cjs --ssl-key /path/to/private.key --ssl-cert /path/to/certificate.crt --port 3210Important for HTTPS-hosted applications: Browsers enforce mixed content security policies that prevent HTTPS websites from connecting to non-secure WebSocket servers (ws://). You must use secure WebSocket connections (wss://) when your application is served over HTTPS.
The server exposes two WebSocket endpoints:
ws://hostname:port/orwss://hostname:port/- For Yjs document collaborationws://hostname:port/streamorwss://hostname:port/stream- For video streaming
import * as Y from 'yjs'
import { WebsocketProvider } from 'y-websocket'
const doc = new Y.Doc()
// Use wss:// for secure connections when your app is served over HTTPS
const wsProvider = new WebsocketProvider('wss://localhost:1234', 'my-roomname', doc)
wsProvider.on('status', event => {
console.log(event.status) // logs "connected" or "disconnected"
})// Connect to the streaming endpoint
const ws = new WebSocket('ws://localhost:1234/stream')
// For stream source (sender)
ws.onopen = () => {
// Register as a video source for a specific room
ws.send(JSON.stringify({
type: 'register-source',
roomId: 'my-room-id'
}))
// Send video frames (example)
function sendFrame(frameData) {
ws.send(JSON.stringify({
type: 'frame',
data: frameData
}))
}
}
// For stream viewer (receiver)
ws.onopen = () => {
// Join a specific room to receive video
ws.send(JSON.stringify({
type: 'join-room',
roomId: 'my-room-id'
}))
}
// Handle incoming messages
ws.onmessage = (event) => {
const data = JSON.parse(event.data)
if (data.type === 'source-available') {
console.log('A video source is available in this room')
} else if (data.type === 'frame') {
// Handle incoming video frame
displayFrame(data.data)
}
}The streaming WebSocket endpoint relays MediaRecorder output (WebM/VP8[/Opus] chunks) from one source per room to all viewers in that room. Media chunks are sent as binary WebSocket messages; control messages are JSON text frames:
-
Register as a stream source (station → server). Registration is last-writer-wins: a re-registration for the same room replaces the previous source and terminates its socket.
{ "type": "register-source", "roomId": "unique-room-identifier", "streamName": "Camera 1", "mimeType": "video/webm;codecs=\"vp8,opus\"" } -
Join a room to receive video (viewer → server)
{ "type": "join-room", "roomId": "unique-room-identifier" } -
Source available (server → viewer, on join or registration). The viewer must create its MediaSource SourceBuffer with exactly this mimeType.
{ "type": "source-available", "roomId": "unique-room-identifier", "mimeType": "video/webm;codecs=\"vp8,opus\"" } -
Viewer joined (server → source). The source restarts its MediaRecorder so the new viewer receives a fresh init segment at t=0.
{ "type": "viewer-joined", "roomId": "unique-room-identifier" } -
Source disconnected (server → viewers)
{ "type": "source-disconnected", "roomId": "unique-room-identifier" }
# Basic server options
node dist/server.cjs [options]
Options:
--port=NUMBER Port to listen on (default: 1234)
--host=STRING Host to bind to (default: 0.0.0.0)
--help, -h Show help message
# SSL/TLS options
--ssl, --https Enable HTTPS/WSS with self-signed certificates
--ssl-key=PATH Path to SSL private key file
--ssl-cert=PATH Path to SSL certificate fileYou can also configure the server using environment variables:
# Basic configuration
export PORT=3210
export HOST=0.0.0.0
export NODE_ENV=production
# SSL certificate paths
export SSL_KEY=/path/to/private.key
export SSL_CERT=/path/to/certificate.crt
# Start server
node dist/server.cjsFor development and testing, the server can automatically generate self-signed certificates:
# Auto-generate self-signed certificates
node dist/server.cjs --sslSelf-signed certificates will be saved in the ./certs/ directory and reused on subsequent starts.
Browser Security Warnings: Self-signed certificates will trigger security warnings in browsers. Users need to:
- Click "Advanced" when the security warning appears
- Click "Proceed to localhost" (or your domain)
- Accept the certificate risk
Pre-built standalone executables for Linux, macOS, and Windows are available on the GitHub Releases page. They include all dependencies and do not require Node.js on the target machine.
To build the executables yourself:
# Build for the current platform only
./build-sea.sh
# Build for all platforms (Linux x64, macOS x64, Windows x64)
./build-sea.sh --allThis produces three distribution folders:
| Folder | Platform | Executable |
|---|---|---|
edrys-executable-linux-x64/ |
Linux x64 | edrys-server-linux-x64 |
edrys-executable-darwin-x64/ |
macOS x64 | edrys-server-macos-x64 |
edrys-executable-win-x64/ |
Windows x64 | edrys-server-win-x64.exe |
Each folder also contains a ready-to-use startup script (start-server.sh / start-server.bat).
# Run directly (Linux/macOS)
cd edrys-executable-linux-x64
./edrys-server-linux-x64 --port 3210
# Or use the startup script
./start-server.shThe standalone executable supports all the same command-line options as the Node.js version.
Note: The
--ssl/--httpsflag requires OpenSSL to be installed on the target machine (used to generate self-signed certificates). On Linux install it withsudo apt-get install openssl, on macOS withbrew install openssl. If you already have certificate files, you can skip this requirement by passing--ssl-keyand--ssl-certdirectly.
The MIT License © Kevin Jahns
Fork maintained by: edrys-labs