From 8730281d739d9ed1d6f2d366772582eea8ba0294 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Fri, 21 Aug 2026 13:52:11 +0200 Subject: feat: LAN Wi-Fi casting to Chromecast via local HTTP relay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-serve decrypted fMP4 video over HTTP on the LAN so a Chromecast can play the stream. The relay runs in the Electron main process — same trust boundary as downloads and MSE playback. - cast-relay.js: HTTP server with BoxAccumulator (reassembles WebRTC chunks into moof+mdat pairs), ring buffer, backpressure, finish() for clean end-of-stream, fixed port range 19550-19553 - cast-chromecast.js: mDNS discovery (bonjour-service) + CASTV2 protocol (castv2-client), connect/reload/disconnect lifecycle - Seek-aware: relay restarts on every seek, Chromecast reloads new URL; generation counter prevents stale async errors from killing active restarts; landingPlayheadRef suppresses programmatic seeking events - Device picker in video top bar with scan, device selection, copy-URL fallback, and cast status indicator - IPC bridge (main/preload/platform) for start/push/stop/finish/status/ discover/chromecastConnect/chromecastReload/chromecastDisconnect - Phase 3 design doc for DLNA/Smart TV in docs/cast-smart-tv.md Co-Authored-By: Claude Opus 4.6 --- packages/meshbay-hub/src/meshbay_hub/static/transport.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'packages/meshbay-hub/src/meshbay_hub/static/transport.js') diff --git a/packages/meshbay-hub/src/meshbay_hub/static/transport.js b/packages/meshbay-hub/src/meshbay_hub/static/transport.js index 17886f4..2cdf15d 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/transport.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/transport.js @@ -742,12 +742,14 @@ class MeshBayTransport { // `start` is a seek: the node retires whatever this session was streaming // and spawns ffmpeg again from there. Omitted or zero is the film's // beginning, which is what an 0.1 node understands. + console.log('[stream] sending stream_req start:', start, 'credits:', credits); this._send({ type: 'stream_req', v: '0.1', file_id: fileId, credits, start }); } /** Room for `n` more segments. */ grantStreamCredit(n = 1) { if (!this._connected) return; + console.log('[stream] grant credit:', n); this._send({ type: 'stream_more', v: '0.1', n }); } @@ -1200,6 +1202,7 @@ class MeshBayTransport { return; } if (msg.type === 'stream_init') { + console.log('[stream] recv stream_init, start:', msg.start, 'codec:', msg.codec, 'handler:', !!this._onStreamInit); if (this._onStreamInit) this._onStreamInit(msg); return; } @@ -1208,6 +1211,7 @@ class MeshBayTransport { return; } if (msg.type === 'stream_end') { + console.log('[stream] recv stream_end'); if (this._onStreamEnd) this._onStreamEnd(msg); return; } -- cgit v1.2.3