Skip to content

bilbospocketses/ws-scrcpy-web

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

471 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

ws-scrcpy-web

ws-scrcpy-web

Browser-based Android screen mirroring and control, powered by scrcpy.

A modernized spiritual successor to ws-scrcpy, rebuilt with a focus on maintainability, modern tooling, and staying current with scrcpy releases.

Key Design Decisions

  • Vanilla scrcpy-server v3.x -- uses unmodified Genymobile scrcpy-server binaries. No Java patching, no custom forks. Drop in new versions as they release.
  • Node.js ADB proxy -- the server bridges ADB tunnels to WebSocket connections for the browser. The protocol layer is implemented in TypeScript.
  • WebCodecs only -- no WASM decoder fallbacks. Modern browsers only.
  • Pure browser code -- no Node.js Buffer polyfill or path-browserify in the browser bundle.
  • Focused feature set -- screen mirroring, touch/keyboard/UHID control, ADB shell, file management. No iOS support, no Chrome DevTools proxy.

Features

  • Real-time screen mirroring in the browser via WebSocket
  • Multi-codec video -- H.264, H.265 (HEVC), AV1 with automatic detection and smart encoder selection
  • Multi-codec audio -- Opus, AAC, FLAC, raw PCM via WebCodecs AudioDecoder
  • UHID keyboard/mouse -- hardware-level input via USB HID reports (pointer lock for mouse)
  • D-pad / Touch input modes -- toolbar toggle between D-pad mode (default, for TV apps like Peacock/Netflix) and Touch mode (for touch-aware apps). D-pad mode maps left-click to OK, scroll wheel to up/down, Shift+scroll to left/right
  • Scroll wheel support -- mouse wheel scrolling on the mirrored device, tuned for latent streams
  • Touch and keyboard input forwarding (classic scrcpy keycode mode)
  • Configure stream modal -- native <dialog> overlay with codec/encoder selection, device probe, and advanced settings
  • Redesigned toolbar -- compact controls with quick stats (FPS, resolution, codec), stream refresh button, and consistent alignment
  • Quality stats overlay -- real-time FPS, bitrate, resolution, codec, and encoder info
  • Stream modal -- native <dialog> overlay for the full mirroring experience (video, toolbar, audio, UHID input). Home page stays visible behind the backdrop — close the stream and you're right back at the device list
  • Viewport scaling -- video scales to fill available space with correct aspect ratio
  • Remote ADB shell -- native <dialog> terminal modal with xterm.js, close confirmation for active sessions, Escape/backdrop blocked (terminal needs both)
  • File browser -- native <dialog> modal with breadcrumb navigation, sortable columns (sticky header so size/date stay aligned when scrolling), SVG file type icons (6 types), configurable icon sizes, hover action icons sized to match, reserved actions column so columns never shift on hover, selection with bulk operations, drag-and-drop upload, download with progress, delete with confirmation, client-side filter
  • Programmatic stream API -- load ws-scrcpy.umd.js or ws-scrcpy.esm.js and call WsScrcpy.startStream(container, deviceId, options) to render a stream into any DOM element. Includes bundled TypeScript types (ws-scrcpy.d.ts). Also provides a thin /embed.html?device=<udid> wrapper for iframe consumers.
  • Device labels -- name your devices for easy identification, persisted across sessions in device-labels.json, inline edit from device cards or during network scan
  • Network device discovery -- two-channel scan for ADB devices on the local network: mDNS advertisement for modern devices plus TCP port-5555 sweep for older devices that don't advertise. Configuration dialog auto-detects your gateway subnet and accepts additional subnets (CIDR, bare IP, or IP range); subnets persist across sessions. Streaming progress chip with cancel support; scan skips already-connected devices and dedupes mDNS+TCP hits. Manual-add fallback for single-IP cases.
  • Device disconnect -- disconnect network devices directly from the device card
  • Sleep/wake toggle -- turn devices on or off from the device card; state polled server-side and pushed via WebSocket so buttons stay in sync even when the device sleeps on a timer or via the physical remote
  • Dark/light theme -- toggle between dark (default) and light modes, preference saved to localStorage
  • Responsive layout -- centered page container scales from mobile to 4K (up to 5 device cards)
  • In-app dependency updater -- check and update Node.js, ADB, and scrcpy-server from the home page
  • Server logging -- all server output logged to ws-scrcpy-web.log with timestamps, tag prefixes, and 5MB rotation
  • Docker support (Dockerfile included)

Requirements

Required for building from source. See Self-Contained Deployment for standalone installations that bundle everything.

  • Node.js 24 LTS or later
  • ADB installed and in PATH
  • Android device with USB debugging or wireless debugging enabled

Quick Start (Developer Mode)

For development and building from source:

npm install
npm start

Open http://localhost:8000 in your browser.

This mode requires Node.js and ADB installed on your system. See Self-Contained Deployment for a standalone installation that bundles everything.

Optional: npm run fetch-prebuilts

Pre-populates the node-pty native binary for air-gapped or offline setups. Normally unnecessary — npm start and npm test trigger this implicitly on first run via the resolver and vitest globalSetup respectively.

Self-Contained Deployment

ws-scrcpy-web can run as a fully self-contained application with no system-wide installations required. Everything lives in one folder -- no PATH changes, no global installs, no admin/root needed.

What's in the Box

ws-scrcpy-web/
  dist/                    -- compiled application (server + browser bundles)
    assets/
      scrcpy-server        -- Android-side binary, pushed to devices via ADB
    public/                -- browser UI (HTML, JS, CSS)
    index.js               -- server entry point
  dependencies/
    node/                  -- Node.js runtime + node-pty native files
    adb/                   -- ADB platform-tools
  start.cmd                -- Windows launcher
  start.sh                 -- Linux launcher

Initial Setup

  1. Download Node.js LTS and extract the binary to dependencies/node/
  2. Download ADB platform-tools and extract to dependencies/adb/
  3. Run start.cmd (Windows) or ./start.sh (Linux)
  4. Open http://localhost:8000

What Updates Automatically (In-App Updater)

The Dependencies panel on the home page lets you check for updates and install them with one click. These runtime dependencies are standalone binaries that can be safely swapped without recompiling the application:

Dependency What it does How it updates
Node.js + node-pty Runs the server; provides ADB shell terminal Downloads new binary from nodejs.org. Paired update -- both must match. Requires app restart (handled automatically by the launcher script).
ADB (platform-tools) Communicates with Android devices Downloads latest zip from Google, extracts, swaps files. ADB server is stopped and restarted automatically. No app restart needed.
scrcpy-server Runs on Android devices to capture screen and audio Downloads new binary from Genymobile/scrcpy releases. Replaces file in dist/assets/. No restart needed -- new binary is pushed to devices on next connection.

What Requires a New Release (Build-Time Dependencies)

These dependencies are compiled into the dist/ output during the build process. They cannot be updated independently -- a new version of ws-scrcpy-web must be built and deployed:

Dependency Why it's compiled in Update approach
ws (WebSocket library) Bundled into dist/index.js by webpack. This is the core communication layer between browser and server -- too critical to hot-swap without testing. A bad ws update could silently break all connections. Checked before each release (see docs/TECHNICAL_GUIDE.md section 12). Updated, tested, and shipped as part of a new ws-scrcpy-web version.
@xterm/xterm (terminal renderer) Bundled into dist/public/bundle.js. Major versions can change APIs that affect the shell feature. Updated during release builds.
TypeScript, webpack, Biome, css-loader, etc. Build toolchain only -- not shipped to users at all. These compile the source into dist/ and are never present in a deployment. Updated by developers before building a new release.

How the Launcher Works

The launcher scripts (start.cmd / start.sh) solve a specific problem: on Windows, you cannot replace a running executable. When the in-app updater downloads a new Node.js binary:

  1. The server renames the running node.exe to node.exe.old
  2. The server copies the new node.exe into place
  3. The server writes a .restart marker file and exits
  4. The launcher detects the marker, cleans up the old binary, and relaunches
  5. The browser automatically reconnects when the server comes back

On Linux, file locking is not an issue (running binaries can be overwritten), but the launcher still handles the restart loop for consistency.

Configuration

The server can be configured via environment variables or a config.json file:

Variable Default Description
PORT 8000 HTTP server port
ADB_PATH adb Path to ADB executable
CONFIG_PATH config.json Path to config file

Logging

The server logs all output to ws-scrcpy-web.log in the project root. Every line includes an ISO 8601 timestamp and a module tag (e.g., [ScrcpyConnection], [Server]). The log file rotates on startup when it exceeds 5MB, keeping one backup (.log.1). Console output is preserved alongside the file -- you still see everything in the terminal.

See docs/TECHNICAL_GUIDE.md section 15 for details on the Logger utility and adding logging to new modules.

Docker

docker build -t ws-scrcpy-web .
docker run -p 8000:8000 ws-scrcpy-web

Note: The container needs ADB access to Android devices. For network ADB (wireless), the devices must be reachable from the container network.

Acknowledgments

This project is based on ws-scrcpy by Sergey Volkov / Netris, JSC. See THIRD-PARTY-NOTICES.md for full license details.

Screen mirroring powered by scrcpy by Genymobile / Romain Vimont.

License

This project is licensed under the GNU General Public License v3.0.

About

Browser-based Android screen mirroring and tooling — spiritual successor to ws-scrcpy, powered by vanilla Genymobile/scrcpy

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors