Termux DLNA Server - Mobile Media Streaming
Termux DLNA Server
Run on your phone, serve Movies/TV Shows from SMB share to Kodi over DLNA with hardware-accelerated transcoding
Overview
The Termux DLNA Server is a Python-based media server that runs on Android devices via Termux. It serves movies and TV shows from an SMB (Samba) network share to Kodi media center over DLNA/UPnP, with automatic hardware-accelerated transcoding to h264/AAC 720p when needed.
This enables you to:
- Run a media server directly on your phone
- Access your SMB shared media library
- Stream to Kodi on Raspberry Pi, TV, or other devices
- Transcode incompatible formats on-the-fly using hardware acceleration
- Extract and serve forced subtitles
Architecture
┌─────────────────────────────────────────────────────────┐
│ Termux DLNA Server │
│ (Python on Android via Termux) │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │
│ │ main.py │ │ config.py │ │ server.py │ │
│ │ (Entry) │ │ (Settings) │ │ (HTTP Server) │ │
│ └──────┬──────┘ └────────────┘ └──────────┬─────────┘ │
│ │ │ │
│ ▼ ▼ ▼
│ ┌────────────────────┐ ┌────────────┐ ┌────────────┐
│ │ scanner.py │ │ ssdp.py │ │ cds.py │
│ │ (Library Scanner) │ │ (Discovery) │ │ (DLNA CDFS) │
│ └────────┬────────────┘ └────────────┘ └────────────┘
│ │ │
│ ▼ ▼
│ ┌────────────────────┐ ┌────────────────────────────┐
│ │ transcode.py │ │ db.py │
│ │ (Transcoding Logic) │ │ (SQLite Library Database) │
│ └────────┬────────────┘ └────────────────────────────┘
│ │
│ ▼
│ ┌────────────────────┐
│ │ smb_layer.py │
│ │ (SMB Access Layer) │
│ └────────────────────┘
│ │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Kodi (Client) │
│ - Discovers server via SSDP │
│ - Browses library via DLNA CDFS │
│ - Streams with forced subtitles │
└─────────────────────────────────────────────────────────┘
Features
Core Capabilities
| Feature | Description |
|---|---|
| DLNA/UPnP Server | Full DLNA ContentDirectory service implementation |
| SMB Client | Reconnect-on-failure wrapper for SMB access |
| Library Management | SQLite database for Movies/TV Shows/Seasons/Episodes tree |
| Automatic Scanning | Walks SMB share, populates DB, periodic rescan with mark-and-sweep |
| Format Detection | ffprobe inspection to determine video/audio codec, resolution, container |
| Hardware Transcoding | Uses h264_mediacodec for hardware-accelerated h264 encoding |
| Forced Subtitles | Extracts forced subtitles to SRT, advertises via DLNA |
| Direct Streaming | Byte-range passthrough for compatible files (no transcoding) |
Playback Decision Logic
The server makes intelligent decisions about when to transcode:
- Direct Stream (no ffmpeg): Video codec is h264, audio is AAC, height ≤720p, container is mp4/mkv
- Transcode (via ffmpeg): Any condition above fails → hardware-accelerated transcoding
- Forced Subtitles: Always extracted regardless of stream type
Requirements
Software
- Termux (Android)
- Python 3.x
- ffmpeg (with
h264_mediacodecsupport) - pip packages (see requirements.txt)
Hardware
- Android phone with Termux support
- SMB share accessible from phone
- Kodi client on LAN
Installation
1. Install Dependencies
pkg install ffmpeg python
pip install -r requirements.txt
2. Configure Server
Edit config.py with your settings:
# SMB Configuration
SMB_SERVER = "your.nas.server"
SMB_SHARE = "Media"
SMB_USERNAME = "your_username"
SMB_PASSWORD = "your_password"
SMB_MOVIES_PATH = "/Movies"
SMB_TVSHOWS_PATH = "/TV Shows"
# Server Configuration
HTTP_PORT = 8200
SSDP_PORT = 1900
UUID = "generated-uuid" # Run: python3 -c "import uuid; print(uuid.uuid4())"
Important: Keep UUID stable — Kodi uses it to identify the server across restarts.
3. Verify Hardware Encoder
ffmpeg -encoders | grep mediacodec
If nothing prints, h264_mediacodec isn’t in your ffmpeg build. Direct-stream playback still works, but transcoding won’t be available.
4. Run the Server
python3 main.py
First run does a full library scan before the server starts listening.
Usage
On Kodi
- Add UPnP source, or it should appear automatically under Videos → Add-ons → UPnP/DLNA devices
- Browse Movies/TV Shows
- Play files — direct stream for compatible files, transcoding for others
Configuration Tips
- SMB Paths: Use absolute paths from the share root
- UUID: Generate once and keep it stable
- Ports: Ensure HTTP (8200) and SSDP (1900) are not blocked
- Network: Phone and Kodi must be on the same LAN
Files
| File | Purpose |
|---|---|
config.py | Configuration — edit this first |
main.py | Entry point |
server.py | HTTP server (description.xml, SOAP control, raw SMB proxy, stream endpoint) |
smb_layer.py | SMB access with reconnect-on-failure wrapper |
db.py | SQLite library database (Movies/TV Shows/Season/Episode tree) |
scanner.py | Library scanner, periodic rescan with mark-and-sweep |
transcode.py | Transcode decision logic, ffmpeg command building, subtitle extraction |
cds.py | DLNA ContentDirectory service (Browse/DIDL-Lite XML) |
ssdp.py | SSDP discovery (multicast NOTIFY + M-SEARCH response) |
requirements.txt | Python dependencies |
README.md | This documentation |
Known Limitations
Current Gaps
- CaptionInfoEx Support: Has shifted across Kodi versions, not formally documented. Test against your actual Kodi version.
- No Forced Flag: Files without forced disposition flag won’t get subtitles. No automatic fix — would need manual override JSON.
- SMB Session Drops: Mid-stream drops (phone sleep, wifi doze) kill in-progress streams with no retry.
- Orphan Processes: Transcode path may leave orphan ffmpeg processes if client abandons stream.
- Movie-per-folder: Takes first video file found, ignores extras in same folder.
- No Authentication: HTTP server is open on LAN — suitable for home network only.
Testing Checklist
- ✅
ffmpeg -encoders | grep mediacodec— confirms transcode capability - ✅ Run
main.py, check for “SSDP listening” and “HTTP server listening” - ✅
curl http://<phone-ip>:8200/description.xml— confirms HTTP + description - ✅ Kodi finds server under UPnP devices — confirms SSDP
- ✅ Browse Movies/TV Shows in Kodi — confirms SOAP Browse + SQLite
- ✅ Play h264/AAC/720p file — confirms direct-stream
- ✅ Play incompatible file — confirms transcode path
- ✅ Play file with forced subtitles — confirms CaptionInfoEx
Performance
- Direct Stream: No transcoding, byte-range passthrough, minimal CPU usage
- Transcode: Hardware-accelerated via
h264_mediacodec, CPU usage depends on source - Library Scan: First run scans entire library, subsequent runs use mark-and-sweep
- Network: SMB access latency affects scan speed and streaming performance
Future Enhancements
- Add manual override for subtitle tracks (JSON mapping)
- Add retry logic for mid-stream SMB drops with seek recovery
- Add process cleanup on BrokenPipeError/socket close
- Add multi-video-file-per-folder support
- Add authentication for HTTP server
- Add HTTPS support
- Add DLNA profile compliance testing
- Add more codec/container support
Download
Complete source code:
Download Termux DLNA Server Source (Original archive)
Or copy from this directory.
License
This code is provided for educational and personal use. No warranty is provided. Use at your own risk.
Stream your media library from your phone — no dedicated server required.
Termux DLNA Server
Runs on your phone, serves Movies/TV Shows from an SMB share to Kodi over DLNA,
transcoding to h264/AAC 720p via h264_mediacodec only when the source file
needs it.
Files
config.py— edit this first. SMB creds, paths, ports, UUID.smb_layer.py— SMB access with reconnect-on-failure wrapper.db.py— SQLite library (Movies / TV Shows / Season / Episode tree).scanner.py— walks the SMB share, populates the DB, periodic rescan with mark-and-sweep.transcode.py— ffprobe inspection, transcode decision, ffmpeg command building, forced-subtitle extraction.cds.py— DLNA ContentDirectory service (Browse / DIDL-Lite XML).ssdp.py— SSDP discovery (multicast NOTIFY + M-SEARCH response).server.py— HTTP server tying it together: description.xml, SOAP control, raw SMB proxy, stream endpoint, subtitle endpoint.main.py— entry point.
Setup
pkg install ffmpeg python
pip install -r requirements.txt
Edit
config.py— at minimum:SMB_SERVER,SMB_SHARE,SMB_USERNAME,SMB_PASSWORD,SMB_MOVIES_PATH,SMB_TVSHOWS_PATH. Generate a real UUID forUUID(e.g.python3 -c "import uuid; print(uuid.uuid4())") and keep it stable — Kodi uses it to identify the server across restarts.