Real-time MJPEG webcam streaming server with integrated CBS (Credit Based Shaper) control for Microchip LAN969x TSN switches.
┌─────────────┐ Socket.IO ┌─────────────┐ MJPEG HTTP ┌─────────────┐
│ Broadcaster │ ──── Binary ────→ │ Server │ ───── Stream ────→ │ Viewer │
│ (Browser) │ (no wait) │ (Node.js) │ (non-blocking) │ (Browser) │
└─────────────┘ └─────────────┘ └─────────────┘
│ │
│ getUserMedia │ CBS CLI
│ Canvas → JPEG │ (mvdct.cli)
▼ ▼
Webcam TSN Switch
(LAN969x)
# Clone repository
git clone https://github.com/hwkim3330/webrtc-mjpge-cbs.git
cd webrtc-mjpge-cbs
# Install dependencies
npm install
# Start server
npm start
# Or use the start script
./start.sh
| Page | URL | Description |
|---|---|---|
| Main | http://localhost:3000 | Landing page |
| Broadcast | http://localhost:3000/broadcast | Webcam streaming + CBS control |
| Watch | http://[IP]:3000/watch | Viewer page with stats |
| CBS Only | http://localhost:3000/cbs | CBS control only |
| Direct Stream | http://[IP]:3000/stream.mjpg | Raw MJPEG stream |
| Preset | Resolution | FPS | Quality | Use Case |
|---|---|---|---|---|
| Low Latency | 480p | 15 | Low | Default, recommended |
| Balanced | 720p | 30 | Mid | General use |
| Quality | 1080p | 30 | High | High quality needs |
| Old Mac | 240p | 10 | Very Low | Legacy hardware |
Prevents latency buildup by skipping frames when previous transmission is incomplete:
if (isSending) {
droppedFrames++;
return; // Skip this frame
}
Each viewer receives frames independently. Slow viewers don’t block others:
if (viewer.res.writableNeedDrain) {
viewer.droppedFrames++;
return; // Skip slow viewer
}
Uses Socket.IO for efficient binary frame transfer with volatile emit:
socket.volatile.emit('frame', { frame: buffer, timestamp });
wget http://mscc-ent-open-source.s3-website-eu-west-1.amazonaws.com/public_root/velocitydrivect/2025.06/Microchip_VelocityDRIVE_CT-CLI-linux-2025.07.12.tgz
tar -xzf Microchip_VelocityDRIVE_CT-CLI-linux-2025.07.12.tgz
server.js:
const CBS_CLI_PATH = '/path/to/mvdct.cli';
const CBS_DEVICE = '/dev/ttyACM0';
sudo usermod -aG dialout $USER
# Logout and login again
.
├── server.js # Express server + CBS API + MJPEG streaming
├── package.json # Dependencies
├── start.sh # Start script
├── public/
│ ├── index.html # Main landing page
│ ├── broadcaster.html # Broadcast + CBS control (3-column layout)
│ ├── viewer.html # Viewer page with real-time stats
│ └── cbs.html # CBS control only
└── README.md # This file
| Method | Endpoint | Description |
|---|---|---|
| GET | /stream.mjpg |
MJPEG stream (multipart/x-mixed-replace) |
| POST | /frame |
Receive frame from broadcaster (HTTP fallback) |
| GET | /api/status |
Get streaming status (broadcasting, viewers count) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/cbs/device |
Check device connection |
| GET | /api/cbs/config |
Get CBS config for all ports |
| POST | /api/cbs/set |
Set CBS on ports |
| POST | /api/cbs/delete |
Delete CBS config |
curl -X POST http://localhost:3000/api/cbs/set \
-H "Content-Type: application/json" \
-d '{"ports": [8,9,10,11], "tc": 0, "idleSlope": 100000}'
curl -X POST http://localhost:3000/api/cbs/delete \
-H "Content-Type: application/json" \
-d '{"port": 8, "tc": 0}'
curl http://localhost:3000/api/status
# {"broadcasting":true,"viewers":2}
multipart/x-mixed-replace HTTP streamingtoBlob()| Technique | Purpose |
|———–|———|
| Frame dropping | Prevent queue buildup |
| socket.volatile.emit() | Drop frames if buffer full |
| writableNeedDrain check | Skip slow viewers |
| Binary transfer | 33% less overhead vs base64 |
| toBlob() async | Non-blocking JPEG encoding |
ls -la /dev/ttyACM0groups $USER./mvdct.cli device /dev/ttyACM0 typeMIT
Pull requests welcome. For major changes, please open an issue first.