feat: add @device-stream/stream-only package#2
Merged
Conversation
Standalone package for streaming device screens to browsers via WebSocket, without control APIs. Supports Android (scrcpy H.264) and iOS Simulator (MJPEG). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7-task plan covering package scaffolding, simulator streamer, ScrcpyService callback refactor, android streamer, StreamServer, monorepo integration, and docs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds startStreamWithCallback(), pipeCallbackStream(), stopCallbackStream(), and isCallbackStreaming() to enable multi-client broadcast via a FrameCallback instead of piping directly to a single WebSocket. Updates stopAll() to drain both session maps. Existing startStream() is unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix metadata polling race: use interval+timeout that rejects on timeout instead of silently resolving with fallback dimensions - Fix ghost sessions: queue WS clients in StreamServer until startStream() determines the platform, instead of registering on both streamers - Add missing codecName and fps fields to Android metadata messages - Fix stopStream race: delete stream entry after await, not before Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Late-joining browsers received metadata but no video frames because scrcpy only sends frames on screen changes. Cache SPS/PPS config and last keyframe per session so new WebSocket clients get the current screen immediately. Replace JMuxer with WebCodecs API in the POC viewer for proper H.264 decoding — prepend SPS/PPS to keyframes as required by WebCodecs spec. Add POC test app (poc-stream-only.ts + poc-viewer.html) for manual testing with a connected Android device. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cast videoStream.getReader() in pipeCallbackStream to match the native ReadableStreamDefaultReader type, same as pipeVideoStream already does. Fixes TS2322 on Node 20 where @yume-chan/stream-extra types diverge. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@device-stream/stream-onlypackage for headless video streaming from Android and iOS Simulator devicesStreamServer) with/devicesendpoint and/stream/:serialWebSocket routingAndroidStreamerwith multi-client broadcast, SPS/PPS + keyframe caching for late-joining browsersSimulatorStreamerfor iOS Simulator MJPEG streamingstartStreamWithCallbackadded toScrcpyServicefor decoupled frame deliveryTest plan
npm run build)🤖 Generated with Claude Code