- Rename namespace BlaxSoftware\LaravelWebRtc -> Blax\WebRtc (house standard) + update kernel imports to Blax\ReactPhpKernel - README rewritten to the Blax OSS package principles: OSS banner, title+badges, emoji feature list, quick start, wire shape, config, architecture, star history - Add PHPUnit suite (8 tests / 18 assertions, green): SignalingHandler routing (offer/ice/record/connect/bridge/close/error paths via a fake engine) + NullMediaEngine behaviour - Add pint.json (laravel preset, applied), composer scripts, .gitattributes, test.sh (nix), CHANGELOG - Verified end-to-end: composer install resolves blax-software/reactphp-kernel from Forgejo VCS and the suite runs green on it rel learn-atc #1055 #1051 #1019 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| config | ||
| rust | ||
| src | ||
| tests | ||
| .gitattributes | ||
| .gitignore | ||
| CHANGELOG.md | ||
| LICENSE | ||
| README.md | ||
| composer.json | ||
| phpunit.xml.dist | ||
| pint.json | ||
| test.sh | ||
README.md
Laravel WebRTC
WebRTC for Laravel on the shared reactphp-kernel backbone. PHP owns signaling + orchestration; a pluggable media engine owns the real-time media (ICE/DTLS/SRTP/RTP/Opus) — with the production engine backed by a Rust core (str0m) via ext-php-rs, so PHP never runs per-20ms DSP.
Features
- 🎙️ Record / intercept / log — the engine terminates media server-side, so every participant's audio (human or AI) can be captured
- 🤖 AI realtime, provider hidden — bridge a caller to an external realtime model (e.g. OpenAI Realtime) over a server-side socket; the browser only ever talks to you, and the model is a config swap
- 👥 Party-to-party & group calls — instructor↔student, controller↔pilot, guest↔admin are just peers the engine routes between
- 🧩 On the shared kernel — signaling runs on
reactphp-kernelalongside your WebSockets, one process, one loop - 🔌 Pluggable
MediaEngine—NullMediaEnginefor signaling-only dev;Str0mMediaEnginefor the real Rust-backed media - 🦀 Rust media core —
str0m(sans-IO WebRTC) viaext-php-rs, shipped inrust/ - 🎛️ Transport-agnostic signaling — route browser frames from this package's raw server or from
laravel-websocketsinto the same handler
Installation
composer require blax-software/laravel-webrtc
php artisan vendor:publish --tag="webrtc-config"
It depends on blax-software/reactphp-kernel, resolved from git.blax.at via the repositories entry in composer.json.
Quick Start
Run the signaling server (on the shared kernel):
php artisan webrtc:serve
With the default NullMediaEngine, signaling runs and the engine refuses offer() loudly. Build the Rust core (see rust/README.md) and switch the engine for real calls:
WEBRTC_MEDIA_ENGINE="Blax\WebRtc\Media\Str0mMediaEngine"
Signaling wire shape (newline-delimited JSON)
{ "type": "offer", "peer": "p1", "sdp": "..." } // -> { "type": "answer", "peer": "p1", "sdp": "..." }
{ "type": "ice", "peer": "p1", "candidate": {...} } // (no reply)
{ "type": "record", "peer": "p1", "path": "..." } // -> { "type": "ack", ... }
{ "type": "connect", "peer": "p1", "other": "p2" } // party-to-party
{ "type": "bridge", "peer": "p1", "options": {...} } // dial an external realtime model
{ "type": "close", "peer": "p1" }
SignalingHandler is transport-agnostic — feed it frames from the built-in raw SignalingServer today, or from the laravel-websockets WS transport (for browsers) later, without changing the media wiring.
Configuration
config/webrtc.php covers the signaling bind (host/port/tls), the media_engine binding, recording disk/path, advertised ice_servers, and the external bridge (e.g. OpenAI model + key). Swapping the realtime model — or the whole provider — is a server-side config change the browser never sees.
Status
MVP scaffold. Signaling + the engine abstraction are real, tested, and runnable with NullMediaEngine; the Str0mMediaEngine + rust/ core are the seam to build next. This is the WebRTC half of the blax realtime stack.
Architecture
reactphp-kernel shared backbone (loop, IPC, signals)
└─ laravel-webrtc (this) signaling on the kernel
├─ NullMediaEngine signaling-only (dev/tests)
└─ Str0mMediaEngine Rust/str0m core via ext-php-rs (rust/)
Testing
composer install
composer test
The signaling router and engines are unit-tested against a fake media engine — no browser, sockets, or external services required.
License
MIT. See LICENSE.