MJPEG Screenshot Stream
The UiAutomator2 driver supports streaming of screenshots over MJPEG. This feature allows real-time broadcasting of the device screen as a continuous stream of JPEG frames over HTTP, which can be used for screen recording, live viewing, or using the latest stream frame as the source for screenshot commands.
Overview¶
The UiAutomator2 server (running on the Android device) includes a built-in MJPEG broadcaster. It
captures the device screen at a configurable rate, encodes frames as JPEG, and serves them over TCP
using the multipart/x-mixed-replace format. This allows:
- Live viewing of the device screen by connecting to the stream (e.g. in a browser or a custom client).
- Screenshot from stream: if the driver is configured to use the MJPEG URL, the standard screenshot command returns the latest frame from the stream, instead of calling the server's screenshotting API.
The MJPEG server on the device is started automatically upon every session, and listens on a fixed
port on the device (default 7810).
Use Cases¶
| Use case | Description |
|---|---|
| Screen recording | The driver can use the MJPEG stream as input for host-side screen recording tooling (for example, via ffmpeg) to produce MP4 (or other) video files. |
| Screenshots from stream | If the appium:mjpegScreenshotUrl capability is set, the driver uses the latest frame from that MJPEG stream in the standard screenshot command, instead of calling the server's regular screenshot API. |
| Live viewing / custom tools | Any HTTP client (browser, script, or custom app) can connect to the MJPEG URL (after port forwarding, if needed) to view or process the live screen. |
Configuration¶
Capabilities¶
These capabilities control the MJPEG broadcaster that runs on the host machine.
appium:mjpegServerPort¶
- Type: integer (port number on the host)
- Description: The port on the host machine to which the device MJPEG server port is forwarded via ADB. If not set, no port forwarding is done, so the device MJPEG service is not reachable from the host.
- Use case: Set this when you want to connect to the device MJPEG stream from the host (e.g.
http://localhost:<mjpegServerPort>) or when using screen recording so the host can receive the stream. - Parallel sessions: Use a unique
mjpegServerPortper session when running multiple devices or parallel tests to avoid port conflicts.
appium:mjpegScreenshotUrl¶
- Type: string (URL)
- Description: URL of a service that provides real-time device screenshots in MJPEG format. If set, the driver creates an MJPEG client that consumes this URL; the standard screenshot command then returns the latest frame from that stream instead of calling the UiAutomator2 server’s
/screenshotendpoint. - Typical value: When you forward the device MJPEG port with
appium:mjpegServerPort, you can set this tohttp://localhost:<mjpegServerPort>(or the same host/port your client uses to reach the stream) so that screenshot uses the MJPEG stream. - Note: The driver starts the MJPEG stream client after the session is created and stops it on session end. If the stream has not yet produced a frame, the screenshot command may fall back to the regular server screenshot.
Settings¶
These settings control the MJPEG broadcaster that runs on the device under test (in the UiAutomator2 server).
Setting |
Range / values | Default | Description |
|---|---|---|---|
mjpegServerPort |
1024..65535 | 7810 | Port on the device where the MJPEG server listens. The driver forwards this to the host when appium:mjpegServerPort capability is set. |
mjpegServerFramerate |
1..60 | 10 | Maximum frames per second. Higher values increase CPU load on the device. |
mjpegScalingFactor |
1..100 | 50 | Scale factor in percent (100 = no scaling). Lower values reduce size and CPU use. |
mjpegServerScreenshotQuality |
1..100 | 50 | JPEG quality (100 = best). Higher values improve quality but use more CPU. |
mjpegBilinearFiltering |
true / false | false | Use bilinear filtering when scaling. Can improve scaled image quality with a small performance cost. |
How it Works¶
- When the UiAutomator2 server starts on the device, it starts an MJPEG server thread that listens on the configured device port (default 7810).
- For each TCP client that connects, the server sends an HTTP-like response with
Content-Type: multipart/x-mixed-replace; boundary=--BoundaryStringand then a continuous stream of JPEG frames (each frame preceded by a boundary andContent-Length). - Frames are produced by the device at the configured framerate; each frame is taken via
UiAutomation.takeScreenshot(), optionally scaled and compressed according to the settings above, then sent to all connected clients. - If no clients are connected, the server does not capture at full rate (it sleeps) to save CPU.
Using the Stream¶
Port Forwarding and Connecting¶
- Set the capability
appium:mjpegServerPortto a free port on the host (e.g.7810or any port you choose). - The driver will run
adb forward <host port> 7810(or the device port you set via themjpegServerPortsetting) so that the device MJPEG server is reachable athttp://localhost:<host port>(or your host IP if you need remote access). - Open that URL in a browser or use any MJPEG-capable client; you should see the live device screen.
- Optionally set
appium:mjpegScreenshotUrlto the same URL (e.g.http://localhost:7810) so that the driver’s screenshot command uses the latest frame from this stream.
Screenshot Behavior¶
- Without
appium:mjpegScreenshotUrl: The screenshot command is sent to the UiAutomator2 server (GET /screenshot), which takes a single screenshot on demand. - With
appium:mjpegScreenshotUrl: The driver keeps an MJPEG client connected to the given URL. The screenshot command returns the latest frame received from that stream (as base64 PNG). If no frame is available yet, the driver falls back to the regular server screenshot and logs a warning.
Parallel Testing¶
When running multiple sessions (e.g. parallel tests or multiple devices):
- Set a unique
appium:mjpegServerPortper session so each device’s MJPEG port is forwarded to a different host port. - This is especially important if you use screen recording or any tool that connects to the MJPEG stream.
Performance Considerations¶
- Higher
mjpegServerFrameratevalues increase the number of screenshots taken per second and therefore the CPU load. - Higher
mjpegServerScreenshotQualityvalues increase JPEG encoding cost and network bandwidth. - Higher
mjpegScalingFactorvalues (larger images) also increase encoding time and payload size. - Enabling
mjpegBilinearFilteringcan improve scaled image quality with a small extra performance cost.
For long-running or parallel streaming, start with moderate defaults (for example, framerate 10, scaling factor 50, quality 50) and then adjust as needed.
Other Screen Streaming Approaches¶
The driver also supports mobile: startScreenStreaming
and mobile: stopScreenStreaming.
These are different from the built-in device MJPEG server:
- They start or stop a host-side MJPEG server that uses GStreamer (and optionally ADB) to capture and broadcast the device screen. They require the
adb_screen_streamingfeature and GStreamer withgst-plugins-base,gst-plugins-good, andgst-plugins-badon the host. - The device MJPEG server described in this guide runs entirely on the device, is built into the UiAutomator2 server, and does not require GStreamer.
Use the device MJPEG server (with appium:mjpegServerPort and optionally appium:mjpegScreenshotUrl) when you only need a simple TCP MJPEG stream from the device. Use mobile: startScreenStreaming when you need the host-based GStreamer pipeline (e.g. for specific encoding or network options).
Requirements¶
- For device-side MJPEG streaming itself, no extra tools are required beyond a compatible Android device and the UiAutomator2 server; the broadcaster runs entirely on the device.
- For tools that consume the stream (for example, screen recording on the host), you must ensure whatever tool you use (such as
ffmpegor a custom recorder) understands MJPEG over HTTP and can connect to the forwarded MJPEG URL. - For
mobile: startScreenStreaming/stopScreenStreaming, which are host-side and GStreamer-based, you must have GStreamer withgst-plugins-base,gst-plugins-good, andgst-plugins-badinstalled and available on the hostPATH.
Summary¶
| What you want | What to use |
|---|---|
| Expose device screen as MJPEG on the host | Set appium:mjpegServerPort to a host port; connect to http://localhost:<port>. |
| Screenshot from the MJPEG stream | Also set appium:mjpegScreenshotUrl to that URL (e.g. http://localhost:<port>). |
| Tune framerate, size, or quality on the device | Use Settings API: mjpegServerFramerate, mjpegScalingFactor, mjpegServerScreenshotQuality, mjpegBilinearFiltering. |
| Host-side GStreamer-based streaming | Use mobile: startScreenStreaming / mobile: stopScreenStreaming. |