OwnTV
Your own IPTV player for Android TV
Fast · modern · remote-first — bring your own M3U, Xtream or Stalker (MAC) sources
OwnTV is a native Android TV IPTV player built with Kotlin, Jetpack Compose for TV, and a
dual playback engine — libmpv (FFmpeg) for movies/series and maximum compatibility, ExoPlayer
(Media3) for near-instant Live TV. It's a player only — you bring your own Xtream login, M3U playlist
(by URL or a local .m3u/.m3u8 file on the device), or Stalker/Ministra portal (Portal URL + MAC,
with optional Serial Number, Device IDs, and Signature), and OwnTV gives you a fast, modern,
remote-first way to browse and watch them.
⚠️ OwnTV does not provide any channels, playlists, subscriptions, streams, or media content. You are responsible for adding your own legally accessible sources.
This is an open-source project — the code is original (not derived from any other app) and was built with the help of AI. Contributions are welcome: clone, build, and test it freely. It targets Android TV only (leanback launcher, D-pad-first UI).
📖 New here? Read the User Guide & Hidden Features →
Long‑press to favourite, Left for the channel list (Left again to browse categories) and Right for recently watched, the MPV/EXO toggle's compatibility mode, catch‑up from the Guide, startup landing, A/V‑sync — all the remote shortcuts in one place.
💬 Community
Questions, ideas, bug reports — or just want to follow along? Join the OwnTV Telegram group:
👉 t.me/owntvplayer
Scan to join from your phone:
✨ Features
🎬 Playback
- Dual engine — libmpv (FFmpeg) for max compatibility + ExoPlayer for instant Live TV; per-channel toggle and automatic VOD fallback between them
- Zero-copy 4K HDR direct rendering · opt-in auto frame rate (off by default; 24/25/50/60 fps display matching, with the rate measured when a live stream doesn't declare one) · live buffering you control (Live latency drives the real buffer, plus a Pre-buffer gate that can be set per playlist) · context-aware channel zapping (D-pad/CH± stays in Favorites, History, All or the opened category) · self-correcting surround sound (Auto/Stereo only/Surround, with an audio-output watchdog that falls back to stereo if your TV or soundbar can't actually play it) + 150% volume boost
- Subtitles — text (SRT/ASS), image (PGS/VOBSUB/DVB), closed captions, preferred-language auto-selection and independent font/style controls, plus OpenSubtitles search and local files; dedicated OpenSubtitles settings sign in on one panel — username, password and optional API key/Worker together — filled in on the TV or handed over from another device by QR + PIN
- Resume prompts, next-episode auto-play, mini-player/PiP, audio-only mode, confirmed radio/audio-only item labelling, and a live codec/resolution/HDR stream-info overlay
- Behaves like a TV app — remote/headset/assistant transport keys via a system media session, and audio focus that ducks for a notification instead of pausing your film
- Diagnostics you can send — a playback log of failures and events, "Report this stream" from the info overlay, optional detailed trace, and a one-press export to
Download/owntv-playback-report.txt
🧭 Browse
- Continue Watching home with TMDB-enriched previews; Live / Movies / Series / Downloads / Guide sections
- Now Trending Home showcase — current TMDB movie/series rankings matched to titles your active provider can actually play, with trailers, full cast/details, provider language/quality/season signals, and flexible movie/series balancing; a dedicated Home setting turns it on/off, and it stays first when enabled
- Per-profile customizable rows, Favorites & History, bulk rename rules, custom combined categories, inline + global search, and a multi-playlist switcher
- Per-section panel widths for Live TV, Movies and Series, including a 0% option that completely hides the preview/poster panel while keeping the remaining panels at an exact 100% total
- Episode grid — browse a show by episode stills instead of text rows, with a show-artwork and episode-number fallback for episodes TMDB can't match; a whole show's episode details arrive in a single request
- TMDB posters, plots, cast photos & trailers in 40 languages; scales to ~50k channels / ~168k movies with priority + incremental syncing
- Dedicated Metadata settings show minute/hour/day shared allowance and support a personal TMDB key or self-hosted Worker, including remote hand-over over LAN (QR + PIN)
- Bring your own free TMDB key for unlimited metadata — send it from another device (phone, tablet or PC) over LAN (QR + PIN) instead of typing 32 characters with the remote; the built-in shared service works with no setup and gives every device a fair daily share
📥 Sources & EPG
- App-wide custom DNS — System, Google, Cloudflare, Quad9, custom DNS or DNS-over-HTTPS; the selected resolver persists across restarts
- Xtream, M3U (typed playlists), and Stalker/Ministra portals, including optional advanced device identification; add any source from another device (phone, tablet or PC) over LAN (QR + PIN) — including uploading an
.m3ufile straight from the computer - XMLTV TV Guide grid, Catch-up TV (up to 7 days) + live rewind, auto EPG matching, multiple guide sources
- Catch-up works without a guide — a Catch-up category listing every channel with an archive, plus Go back to… to jump to a time (or an exact day/hour/minute) instead of holding rewind
- Clock in every player, and while replaying a recording a second one showing when the programme originally aired, with a matching Playing / Then guide row
- Guide time offset — correct a guide published in another time zone, globally or per channel
- Optional guide channel logos — per EPG source, use that feed's own logos instead of your playlist's
- M3U extras honoured: per-item HTTP headers on live, movie and series entries (
#EXTVLCOPT/#EXTHTTP/#KODIPROP/ URL suffix) and theappend/shift/flussonic/xccatch-up styles - Protected (DRM) channels — Widevine and ClearKey over DASH/HLS, read from the playlist's
#KODIPROPlicence properties; uses the CDM built into the device, so there is nothing to configure and no licence to buy
👥 Profiles & Downloads
- Multiple profiles with own favorites/history/resume, PIN locks, and a "Who's watching?" gate; Kids mode hides adult provider folders/items and TMDB adult results throughout browsing, Guide and playback, while normal profiles keep the full catalogue
- Per-profile startup can open Home, resume last channel, enter Live Favorites, or immediately play a chosen Live channel selected with a searchable TV-friendly picker; profile selection and PIN locks are always respected
- Offline movies & episodes — pause/resume/retry, queue groups + storage bar, live poster status strip
🎨 Settings & Robustness
- Material 3 theming & accent, a user-chosen Focus highlight (colour via presets/palette/hex plus four ring thicknesses, applied app-wide in both solid and glass materials), unified browse panels, compact navigation, optional solid-mode Ambient Glow, and interaction-aware Glass Effect with Ultra Clear/Clear/Balanced/Tinted/Opaque/Custom presets, adaptive readability and real frost levels over your own background photo; searchable settings, sidebar/category customization, adjustable panel widths, external player, weather chip
- Font customization with 60%–140% app text sizing and separate main-interface/popup choices from the bundled font catalog plus system Monospace; settings are preserved in backup and restore, while subtitle font and styling remain independently configurable
- 24 complete interface languages with System default, an in-app searchable language picker, RTL-aware navigation, and a language-first welcome flow on fresh installations
- Backup & Restore locally or over Wi-Fi — a single
.ownfile carrying your background image and your downloaded subtitles, optionally encrypted end to end with your own password (older.jsonbackups still restore). Android's automatic backup is deliberately disabled, so app data only ever leaves the device through this screen — secrets ride only when you set a backup password. Plus in-app updates; memory-safe buffers, no-ANR threading, auto-reconnect, resilient imports & offline detection
📖 Full details: player reference → · user guide →
📸 Screenshots
![]() Home — Continue Watching |
![]() Series — episodes |
![]() Live TV — preview playing |
![]() Movies |
![]() "Who's watching?" profile gate |
![]() Downloads |
![]() Settings |
![]() TV Guide (EPG) |
More in extras/screenshots/ — playlist management, EPG & profile settings.
🧱 Tech stack
| Area | Choice |
|---|---|
| Language | Kotlin 2.3.21 (no kotlin-android plugin) |
| Build | AGP 9.3.1 / Gradle 9.7.0, KSP2 2.3.11 |
| UI | Jetpack Compose for TV (androidx.tv:tv-material 1.1.0), Compose BOM 2026.06.01 |
| Media | libmpv (FFmpeg) — dev.jdtech.mpv:libmpv · ExoPlayer/Media3 1.11.0 (Live TV + image subs) |
| Database | Room 2.8.4 + Paging 3.5.0 + FTS4 (WAL) |
| DI | Koin 4.1.1 |
| Networking | OkHttp 5 (okhttp-android) |
| Images | Coil 3.3.0 |
| Preferences | DataStore |
minSdk 26, targetSdk 36, applicationId tv.own.owntv.
Build note: there is no
kotlin-androidplugin. AGP 9 ships its own Kotlin, but the Compose compiler plugin pulls the Kotlin Gradle plugin up to thekotlinversion pinned ingradle/libs.versions.toml— that is what actually compiles the app, so keep the Compose compiler plugin on exactly that version. KSP must track the same Kotlin line for Room codegen to work.
⚙️ How it works (backend)
- Parsing & sync — M3U playlists are line-streamed and Xtream
player_apiJSON is read withandroid.util.JsonReader, so huge provider payloads are never fully buffered.SyncManagerdoes a clear-then-insert refresh in ~500-row chunked transactions with Flow progress and cancellation. - Storage — a 27-entity Room schema: profiles & sources (
ProfileSourceCrossReffor sharing), content (categories/channels/movies/series/seasons/episodes), per-profile favorites/history/progress/ downloads, EPG channels/programmes, external-subtitle cache/selection/timing/links, and FTS4 search tables. Totals come from indexedCOUNTqueries. - Lists — Paging 3 with a bounded
maxSizekeeps memory flat across 50k+ item lists. - EPG — bulk XMLTV is stream-parsed (gzip-aware) into a rolling now→+48h window and pruned.
- Player — two engines behind a small
PlaybackEngineinterface: libmpv (movies/series, and any live stream ExoPlayer can't open) and ExoPlayer/Media3 (Live TV — instant HLS). Live "promotes" the running preview straight to full-screen (no reload); the shell hoists the active surface across full ↔ mini-player. Player state is published asStateFlows for the Compose HUD. - DI — Koin modules (
appModule,databaseModule,dataModule,playerModule).
Project layout
tv.own.owntv/
├── core/ database (Room), network, parser (M3U/Xtream/XMLTV), stalker (MAC portal), repository, sync, util
├── player/ libmpv + ExoPlayer engines (PlaybackEngine) + Compose surfaces + HUD + mini-player
├── ui/ theme + reusable components (focus surface, cards, state views, avatars)
├── features/ setup, shell, live, movies, series, search, downloads, epg, profiles, settings
└── di/ Koin modules
📚 Docs & design (extras/)
- 📄 Complete Feature Document — the full as-built feature reference: playback, browse, EPG, profiles, architecture, and tech stack.
- 📺 Player design reference — an interactive Material 3 mockup of the player UI.
- 🖼️
extras/logo.png— the OwnTV logo.
📥 Installing (Fire TV / Android TV)
Grab the signed APK from the latest release and sideload it. A fixed link always points at the newest signed build:
https://github.com/ahXN00/OwnTV/releases/latest/download/OwnTV.apk
- Fire TV — install the Downloader app (by AFTVnews) from the Amazon Appstore, then enter the
Downloader code
4308278(oraftv.news/4308278, which always points at the latest signedOwnTV.apk). Enable Apps from Unknown Sources if prompted. - Android TV / Google TV — the Downloader app is also on Google Play, so the same code
4308278works here too. (If Downloader doesn't show in search, open the Play Store on the TV — you can reach it via Settings → Apps → See all apps → Show system apps → Google Play Store — and install it from there.) Or just sideload the APK with your tool of choice (Send files to TV, a USB drive, oradb install OwnTV.apk).
Only install the APK from this repository's official Releases (or the
…/releases/latest/download/OwnTV.apklink above). It's the build signed by this project's CI — third-party re-hosts aren't endorsed.Releases ship two APKs:
OwnTV-vX.X.X.apk/OwnTV.apk(arm:arm64-v8a+armeabi-v7a— for all real Fire TV / Android TV devices, and what the Downloader code fetches), andOwnTV-x86_64-vX.X.X.apk(for emulators / rare Intel boxes). Real devices always want the arm build.
🛠️ Building & running
Only needed if you want to build from source. Most people can just install the ready-made APK instead — no build tools required.
What you need first
- Android Studio (a recent version that supports AGP 9.x) — this bundles the JDK and Android SDK, so you don't install those separately.
- A build target: either a real Android TV / Fire TV device (with USB or wireless debugging turned on), or an Android TV emulator created from Android Studio's Device Manager.
Steps
- Get the code — click the green Code button on GitHub → Download ZIP (and unzip it), or run
git clone https://github.com/ahXN00/OwnTV.git. - Open it — in Android Studio choose Open, pick the project folder, and wait for the first Gradle sync to finish (it downloads dependencies; give it a few minutes the first time).
- Pick the right build variant — open Build Variants (left sidebar) and choose the flavor that matches your target:
standard— real TV/phone/Fire TV devices and arm emulators (arm64-v8a+armeabi-v7a)x86_64— x86_64 emulators only- This matters: the native libmpv player only loads on a matching ABI, so the wrong choice = no playback.
- Press Run (▶) with your device/emulator selected. The app installs and launches. It shows up in the TV launcher on Android TV, and as a normal app icon on phones/tablets too (minimum Android 8.0 / API 26).
Prefer the command line? From the project folder run ./gradlew assembleDebug (use gradlew.bat assembleDebug on Windows). The APK lands in app/build/outputs/apk/.
First launch — choose the app language (or keep System default) before pressing Get Started. The modern four-page onboarding then takes you through the disclaimer, profile/backup choice, and adding a source (M3U, Xtream, or Stalker/MAC portal). You can also restore a local backup or send one from another device. Change the interface language later under Settings → Look & Feel → Language; this is separate from the TMDB metadata-language setting. After a source imports, browse from the sidebar and open the Guide for the EPG.
Tested on: a real TCL Google TV, and the Android Studio emulator (both the Android TV and Google TV system images).
🤝 Contributing
Contributions, bug reports, and ideas are welcome — open an issue or a pull request. Please keep the project's player-only, bring-your-own-source positioning, and match the existing code style.
Help translate OwnTV
If your language is already available, contribute interface translations across OwnTV's six Android resource components on Hosted Weblate. If it is not listed, open a language request ticket first. A maintainer will review the request, register the locale, and prepare its base translation files on Hosted Weblate. Once the language appears on Hosted Weblate, you can start translating it there. See the language contributor guide for identifiers, validation, and promotion policy.
🙏 Credits
Movie & series metadata and trailers are provided by TMDB. This product uses the TMDB API but is not endorsed or certified by TMDB.
Subtitle search & download is powered by OpenSubtitles.com. This product uses the OpenSubtitles API but is not endorsed or certified by OpenSubtitles. You sign in with your own OpenSubtitles account and are subject to their terms and download quotas.
▶️ Playback engines
- mpv (via libmpv, built on FFmpeg) — the default engine, for the widest IPTV/codec, audio and HDR support.
- Media3 / ExoPlayer — the fast-start engine for Live TV preview and HLS.
Which of the two starts a stream is yours to set, separately for Live TV and for Movies & Series (Settings → Video Player): either order, or one engine only with the automatic handover turned off.
🧩 Built with
Jetpack Compose for TV · Room · Koin · OkHttp · Coil · ZXing — and the wider Kotlin / AndroidX open-source ecosystem. Thank you to all their maintainers. See each project for its own license.
⚖️ Legal
OwnTV is a media player only. It ships with no channels, playlists, subscriptions, or content, and does not endorse or facilitate access to unauthorized streams. Users are solely responsible for the sources they add and for complying with the laws and rights that apply to them.
📄 License
Released under the GNU General Public License v3.0 (GPLv3) — see LICENSE.
In short: you're free to use, study, modify, and redistribute OwnTV, including commercially — but any redistributed version (including forks and commercial products built on it) must also be licensed under GPLv3 and its source made available.
OwnTV is an open-source, player-only project, built with the help of AI.









