Philips Ambilight-style ambient lighting for any TV or monitor — using a Tapo L920 LED strip with NO EXTRA HARDWARE!!!
AmbilightTV turns a Tapo L920 LED strip into a real-time ambient light synced to your screen.
- A Kotlin app running on your Android TV captures screen-edge colors
- Then streams them over UDP to a Python script on your laptop
- This scipt then drives the strip to match what's on screen (all with no microcontrollers, no custom firmware)
Demo_showcase.mp4
Main — Start/Stop screen-rec service and an IP feild for the receiver device's address.
Demo Mode — The Android TV app includes a built-in demo that cycles through colors so you can instantly see your strip respond in real time without any content playing.
Settings — Let's you tweak screen capture fps and the resolution at which color data is streamed.
┌─────────────────────────┐ UDP ┌──────────────────────────┐ Tapo API ┌─────────────┐
│ Android TV │ ───────────▶ | Python Script (Laptop) │ ──────────▶ │ Tapo L920 │
│ (Kotlin App) │ low-res │ │ single RGB │ LED Strip │
│ Screen Edge Sampling │ pixel array │ Color Analysis Engine │ color └─────────────┘
└─────────────────────────┘ └──────────────────────────┘
- Captures the whole/edges of the TV screen at low resolution (~30 FPS) using Android's screen capture API
- Packages the pixel array and streams it to the laptop over UDP
- Includes a Demo Mode that cycles through colors for setup/testing without needing any content to be playing
- Receives the pixel array from the TV app over UDP
- Runs a color analysis algorithm to determine the best single color for the strip — configurable via the UI:
- Most dominant color across the frame
- Screen edge sampling focus
- Smoothing, saturation boost, brightness floor, and stability controls
- Sends the resulting color to the Tapo L920 via its local network API
The Tapo L920 is controlled as a single color unit — the whole strip outputs one color at a time. The algorithm's job is to find the best representative color from the screen at any moment.
NOTE: The strip itself is addresible, although the Tapo API for addresible color mapping is unfit as it introduces an on/off strobing glitch.
The python script also has it's own native screen-rec function that let's it work without the TV app.
| Mode | Use Case | Input Source |
|---|---|---|
| TV Mode | Android TV with LED strip behind it | UDP stream from Kotlin app |
| Screen Mode | PC/laptop as main display (or PC connected to TV via HDMI) | Direct screen capture on the laptop |
In Screen Mode, the Python script captures your laptop screen directly — no Android app needed. This is ideal if your PC is connected to a TV via HDMI or you just want ambilight on your monitor.
AmbilightTV/
├── app/ # Android TV Kotlin app
│ └── src/main/java/
│ ├── MainActivity.kt # UI + service control
│ ├── ScreenCaptureService.kt # Screen edge sampling
│ └── UdpSender.kt # UDP streaming
├── Laptop python script/ # Python controller
│ └── ... # Color analysis + Tapo API control
└── README.md
- Android TV running the Kotlin app
- Laptop/PC on the same local network as the TV and the Tapo L920
- Tapo L920 LED strip set up via the Tapo app
- Build and sideload the APK onto your Android TV via Android Studio
- Open the app and enter your laptop's local IP address (e.g.
192.168.1.xx) - Tap START SERVICE — the app will begin streaming screen data
-
Install dependencies:
pip install -r requirements.txt
-
Enter your Tapo L920's IP address along with Tapo login credentials and then press Enter
# ===================== CONFIG & DEFAULTS ===================== DEFAULT_IP = "192.168.1.xx" TAPO_EMAIL = "TAPO_EMAIL" TAPO_PASSWORD = "TAPO_PASSWORD"
-
Run the controller:
python main.py
-
Select your input source:
SCREEN (TV)— receives UDP from the Android appSCREEN (PC)— captures your laptop screen directly
-
Tune the color parameters to your taste and hit START
I've highlighed in bold the options that give the best output in my trial runs.
| Parameter | Description |
|---|---|
| Input Source | TV Receiver or Direct screen capture |
| Scan Logic | Entire Screen or Only Edges |
| Color Smoothing | Python-Based Smoothing or Tapo Native Smoothing (in-app settings) |
| Min Brightness | Floor brightness to control dynamic range (keep 60-80) |
| Saturation Boost | Punch up colors for more vivid output (personally 1.6) |
| Stability % | How dominant a color needs to be before it's considered the main color (keep at 1%) |
| Calculation | Default (avg of colors and black) or Vivid (avg of only colors, blacks will be ignored) |
