Open-source project
AkiChase/scrcpy-mask avatar
AkiChase/scrcpy-mask

Scrcpy Mask: a scrcpy client with editable key and mouse mappings

A Scrcpy client in Rust, Bevy and React, aimed at providing mouse and key mapping to control Android device, similar to a game emulator

1,107 stars82 forksRustApache-2.0

At a glance

What is it?
Scrcpy Mask is a Rust and Bevy desktop client for controlling Android devices over the scrcpy protocol, with a visual editor for taps, swipes, direction pads and scripts. It suits someone who wants to drive a phone from a desktop with custom bindings, and it sits on a modified scrcpy server rather than stock scrcpy.
Who is it for?
Adopt Scrcpy Mask if you need to drive an Android device from a desktop with bindings that stock scrcpy cannot express, because the visual mapping editor, the scripting system and the extended server are the whole point of the project. Do not adopt it if you only need plain screen mirroring and no mapping layer on top.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 19 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A scrcpy client, and a server that was changed to suit it

Scrcpy Mask is a cross-platform desktop client built with Rust, Bevy and React, designed for efficient control of Android devices. The stated purpose is an intuitive visual interface for configuring mouse and keyboard mappings, enabling multi-touch operations similar to Android emulators.

The relationship to scrcpy is stated plainly in the README. The project gives special thanks to the scrcpy developers and says scrcpy lays the solid foundation for remote Android control, and that Scrcpy Mask builds upon that architecture and extends it with enhanced mouse and keyboard control.

The important detail is that the extension goes deeper than the client. The README says the original scrcpy-server was extended and optimised to better support the interaction between Scrcpy Mask and Android devices, leading to a separate branch project, scrcpy-mask-server. That means the wire protocol on the device side is not stock scrcpy, and pairing this client with an unmodified scrcpy installation is not the intended setup.

The feature list covers the protocol surface in two lines, one for the scrcpy control protocol which is the input mapping, and one for the scrcpy video protocol which is the screen mirroring. Both are marked as supported, and the migration note says that since v0.7.0 the project has been fully migrated to the Bevy game engine, bringing screen mirroring, combo key mapping and a more flexible built-in scripting system and external control mechanism. The legacy branch based on Rust with Tauri and Vue is no longer maintained.

The release history is recent: v0.9.0 on 2026-06-28, v0.8.3 on 2026-06-21 and v0.8.2 on 2026-06-20, with the last push on 2026-10-04.

The mapping vocabulary, and what the visual editor produces

The mouse and keyboard mapping feature is the core of the project, and the README lists the vocabulary it supports: taps, repeat taps, multi-taps, swipes, direction pads, cast-spell controls, FPS or fire controls, RawInput, scripts, and more.

That list is the practical specification. A tap is a click. A repeat tap holds the equivalent of a key. A multi-tap is a gesture with several fingers, which is how you reach a zoom or a multi-select control on a phone that has no mouse equivalent. A direction pad is an on-screen d-pad with configurable directions, and cast-spell controls are the ability to cast a spell, which is a game specific term that says something about the intended use. RawInput is the option for bypassing the operating system's pointer acceleration, and FPS or fire controls are for games where the mouse button has to act as a trigger.

The mapping configuration is visual, and the screenshots show a Mapping screen, a Devices screen, a Screen Casting screen and a Settings screen. The two other configuration features are input randomization, which the README describes as including randomized touch offsets, swipe paths, random anchors and micro-jitter, and an optional experimental UHID touchscreen backend for up to 10 simultaneous contacts.

That UHID line is the one that matters for anyone doing multi-touch work. Ten simultaneous contacts is a hardware level input path rather than a software approximation, and it is marked experimental, so it is a capability to test rather than a promise.

Scripting and an HTTP and WebSocket control surface

Two features move Scrcpy Mask beyond a mapping editor: a built-in scripting system and an external control mechanism.

The scripting support is documented separately, in a Script Syntax Guide in the scripts-help.md file, and the repository carries a scripts/ directory alongside the Chinese version of that guide. A scripting system is what turns the mapping from a static table into something that can react, and it is the difference between binding a key to a tap and binding it to a sequence that depends on what is on screen.

External control is documented as going through an HTTP API plus a WebSocket, covering devices, mapping configs and app settings, with a window-sync example and its own repository, scrcpy-mask-external-control. The dependency list backs this up: axum is present with the macros and ws features, which is the Rust web framework that provides the HTTP server and the WebSocket upgrade in one stack, along with tower and tower-http for the middleware and the static file serving with the fs, cors and set-header features.

The presence of a WebSocket server and an HTTP API in a desktop application is a design decision with consequences. It means something else on the network can drive the device, so the API surface and its binding behaviour are part of your security posture. It also means the tool can be driven by a script or a companion app, which is how you would automate a repeatable sequence of input against a device.

The feature list is honest about what is not finished. Game controller mapping is unchecked and marked as awaiting sponsorship, and documentation is also unchecked. The maintainer's contributing note says that due to limited personal time and resources they may not be able to respond to all feedback promptly.

Building it: a Rust app, a React frontend and a bundled FFmpeg

The build is a three-part job, and the justfile at the repository root is the entry point. A justfile is a command runner, and this one is written for cross-platform use with a Windows shell setting at the top.

The setup recipe installs the frontend dependencies and builds FFmpeg:

code
pnpm --dir frontend install
code
just build-ffmpeg

The frontend has its own recipes, a dev server with hot reload and a build that type checks and runs a vite build:

code
pnpm --dir frontend dev
code
pnpm --dir frontend build

The check recipe verifies the Rust compile and runs the frontend lint, and the run recipe starts the app. The FFmpeg and packaging steps are platform specific shell or PowerShell scripts under scripts/, chosen by an os() check, so the same justfile works on Windows, macOS and Linux.

The Rust side explains why FFmpeg is needed at all. The dependency list includes ffmpeg-next at 7.1.0 with the codec, format, software-resampling and static features, and rodio for playback, and wgpu and pollster for graphics. Building FFmpeg statically rather than linking against a system copy is a deliberate choice, and it is the reason the setup step exists.

The rest of the dependency list is wide and specific: adb_client for talking to the device, axum and tower for the control API, reqwest with rustls-tls for outbound HTTP, tokio for the async runtime, rust-i18n for the internationalisation the feature list claims, rand for the input randomisation, and seq-macro, paste and strum for the code generation the project relies on.

Bevy as the shell, and what that costs

Using a game engine to build a device control client is the most surprising choice in the project, and it is worth taking seriously rather than dismissing.

Since v0.7.0 the whole application runs on Bevy, with bevy and bevy_ui_render both pinned at 0.19.0-rc.2, a release candidate. Bevy gives the project a retained-mode UI framework, an input system, an audio path, and a renderer, all of which a tool that mirrors a screen and maps keys would otherwise have to assemble. The rodio and ffmpeg-next dependencies sit alongside it for the audio side, and the justfile's separate frontend dev server suggests that some of the interface is still React, served into the Bevy window.

The cost of that choice is the dependency list and the release candidate pin. A Bevy release candidate can change under you, and the fact that the project depends on a pre-release means an upgrade can change behaviour. The edition is 2024 and the Rust version implied by it is recent, so the toolchain requirement is current.

The upside is in the feature set that the migration note claims. Screen mirroring, combo key mapping, a flexible scripting system and external control all arrived with the Bevy move, which suggests the engine was not a skin but the reason those features were practical.

For a user, the practical question is whether a Bevy application is acceptable in their environment. It is a native desktop binary, it wants a GPU for the wgpu renderer, and the licence is Apache 2.0 with a LICENSE file in the repository root, so redistribution is unencumbered in the usual way.

Editorial conclusion

Adopt Scrcpy Mask if you need to drive an Android device from a desktop with bindings that stock scrcpy cannot express, because the visual mapping editor, the scripting system and the extended server are the whole point of the project. Do not adopt it if you only need plain screen mirroring and no mapping layer on top. Before you start, note that the build pulls in FFmpeg and needs the frontend built too, that the dependency set pins Bevy to a release candidate, and that the documentation checkbox in the feature list is still unticked, so expect to read the source for details the README does not cover.

Frequently asked questions

What can Scrcpy Mask map on an Android device?

The README lists taps, repeat taps, multi-taps, swipes, direction pads, cast-spell controls, FPS and fire controls, RawInput and scripts, all configured through a visual mapping editor. There is also an optional experimental UHID touchscreen backend for up to 10 simultaneous contacts.

Do I need a modified scrcpy server to use Scrcpy Mask?

The README says the original scrcpy-server was extended and optimised for better interaction with Android devices, which led to a separate branch project called scrcpy-mask-server. It also credits the scrcpy developers for the foundation and says the project extends that architecture with enhanced mouse and keyboard control.

How do I build Scrcpy Mask from source?

The justfile is the entry point. Run `pnpm --dir frontend install` and `just build-ffmpeg` for setup, `pnpm --dir frontend dev` for the frontend dev server, `pnpm --dir frontend build` for the frontend bundle, and the build and run recipes to package and start the application. The Rust side pins Bevy to 0.19.0-rc.2 and uses the 2024 edition.

Can Scrcpy Mask be controlled from another program?

Yes. The feature list describes external control via an HTTP API plus a WebSocket for devices, mapping configs and app settings, with a window-sync example in a separate scrcpy-mask-external-control repository. The Rust dependencies include axum with the macros and ws features for the server side.

Official sources

  1. AkiChase/scrcpy-mask on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/akichase-scrcpy-mask.svg)](https://hysenlabs.com/projects/akichase-scrcpy-mask)

Was this useful?