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:


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

FeatureDescription
DLNA/UPnP ServerFull DLNA ContentDirectory service implementation
SMB ClientReconnect-on-failure wrapper for SMB access
Library ManagementSQLite database for Movies/TV Shows/Seasons/Episodes tree
Automatic ScanningWalks SMB share, populates DB, periodic rescan with mark-and-sweep
Format Detectionffprobe inspection to determine video/audio codec, resolution, container
Hardware TranscodingUses h264_mediacodec for hardware-accelerated h264 encoding
Forced SubtitlesExtracts forced subtitles to SRT, advertises via DLNA
Direct StreamingByte-range passthrough for compatible files (no transcoding)

Playback Decision Logic

The server makes intelligent decisions about when to transcode:

  1. Direct Stream (no ffmpeg): Video codec is h264, audio is AAC, height ≤720p, container is mp4/mkv
  2. Transcode (via ffmpeg): Any condition above fails → hardware-accelerated transcoding
  3. Forced Subtitles: Always extracted regardless of stream type

Requirements

Software

Hardware


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

  1. Add UPnP source, or it should appear automatically under Videos → Add-ons → UPnP/DLNA devices
  2. Browse Movies/TV Shows
  3. Play files — direct stream for compatible files, transcoding for others

Configuration Tips


Files

FilePurpose
config.pyConfiguration — edit this first
main.pyEntry point
server.pyHTTP server (description.xml, SOAP control, raw SMB proxy, stream endpoint)
smb_layer.pySMB access with reconnect-on-failure wrapper
db.pySQLite library database (Movies/TV Shows/Season/Episode tree)
scanner.pyLibrary scanner, periodic rescan with mark-and-sweep
transcode.pyTranscode decision logic, ffmpeg command building, subtitle extraction
cds.pyDLNA ContentDirectory service (Browse/DIDL-Lite XML)
ssdp.pySSDP discovery (multicast NOTIFY + M-SEARCH response)
requirements.txtPython dependencies
README.mdThis documentation

Known Limitations

Current Gaps

  1. CaptionInfoEx Support: Has shifted across Kodi versions, not formally documented. Test against your actual Kodi version.
  2. No Forced Flag: Files without forced disposition flag won’t get subtitles. No automatic fix — would need manual override JSON.
  3. SMB Session Drops: Mid-stream drops (phone sleep, wifi doze) kill in-progress streams with no retry.
  4. Orphan Processes: Transcode path may leave orphan ffmpeg processes if client abandons stream.
  5. Movie-per-folder: Takes first video file found, ignores extras in same folder.
  6. No Authentication: HTTP server is open on LAN — suitable for home network only.

Testing Checklist

  1. ffmpeg -encoders | grep mediacodec — confirms transcode capability
  2. ✅ Run main.py, check for “SSDP listening” and “HTTP server listening”
  3. curl http://<phone-ip>:8200/description.xml — confirms HTTP + description
  4. ✅ Kodi finds server under UPnP devices — confirms SSDP
  5. ✅ Browse Movies/TV Shows in Kodi — confirms SOAP Browse + SQLite
  6. ✅ Play h264/AAC/720p file — confirms direct-stream
  7. ✅ Play incompatible file — confirms transcode path
  8. ✅ Play file with forced subtitles — confirms CaptionInfoEx

Performance


Future Enhancements


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.pyedit 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
  1. Edit config.py — at minimum: SMB_SERVER, SMB_SHARE, SMB_USERNAME, SMB_PASSWORD, SMB_MOVIES_PATH, SMB_TVSHOWS_PATH. Generate a real UUID for UUID (e.g. python3 -c "import uuid; print(uuid.uuid4())") and keep it stable — Kodi uses it to identify the server across restarts.

    Read more...