A Django-based web-UI to manage IPTV streaming playlists (M3U) + EPG's (XMLTV), upstream and downstream. It is basically my first Django project and it is one of only few of my projects that have a real use and that others get to see, so please bear with me if the code is not very pythonic;-)
It is split up into a management service (Django based, port 8088) and a streaming proxy (Flask based, port 8089).
PS: Yes, the name is not very creative.
- Fully responsive web UI
- Multi-Client/Playlist/Proxy
- Complete docker-compose stack
- Distributed architecture
- (Basic) Session handling
- Channel icon cache and management
Here are some pictures:
- https://pasteboard.co/tgCR6zdVqiid.png
- https://pasteboard.co/qhEQno73k8Ty.png
- https://pasteboard.co/cIaUbT6eZtuP.png
- https://pasteboard.co/MsNCJs84tOYO.png
The setup currently works like this:
- You define upstream user agents; These strings will be sent to upstream servers when downloading files
- You define upstream playlists; These can origin from local files or a http(s) URL's. They use the user agents defined in the first step and can be further filtered before their channels and icons will be imported.
- The filters apply to the "group-title" attribute within M3U files and filter out all channels that belong to groups with these names (one group per line)
- Tip: Trigger a manual download and import via the actions above the list to populate your channels, icons and groups
- You define upstream proxy servers: These have an internal and external URL and port. If you are hosting the management server and the streaming proxy on the same host, you will leave the internal URL's pointing to the localhost and the default port, unless you've changed these settings. The external URL and port should match the URL's of the proxy servers and their ports.
- The information you're using for the internal network connection will be used only by the management server to connect to the proxy in case you want to drop a running streaming session
- The information for the external network connection will be inserted as a proxy for URL-entries in M3U's and XML's (for EPG's)
- You define downstream playlists; These will be assigned an upstream proxy created in the third step and will be dynamically assembled from the groups you enter here
- Tip: There is a "Get group list" button on the top right of the group admin page that returns all known groups as a text to copy & paste
- You can eventually also filter out further channels based on their names
- (Optional): Define upstream EPG's: You can proxy local or remote XMLTV files
Each defined downstream playlist and each EPG is available via individual URL's.
It is meant to allow you to import the set of channel groups you are interested in from your upstream, leaving out all the groups that you don't want anyways. You then define a playlist for each one of your clients by defining a set of channel groups they will receive. If these groups still contain individual channels you don't want them to receive, you can filter them out. You can also disable channel groups, channels and playlists individually to exclude them from playlists/downloads.
(Adjust the hostname, port and URI scheme according to your settings)
Web admin UI (default username: admin, default password: password)
http://localhost:8088/admin
URL for EPG (replace "<name>" with your EPG's name)
http://localhost:8088/manager/get/epg/<name>
URL for downstream playlist (replace "<name>" with your playlist's name)
http://localhost:8088/manager/get/playlist/<name>
- Code quality: I am no coder, especially not for Django. Expect a lot of dirty code. But what can i say? It works for me;)
- Encodings: I am bad at encodings, I am bad at http-headers and I am bad at writing files; I am sure that you will run into issues with more exotic characters and encodings
- Security: I am aware of a lot of conceptual security issues; This solution was designed to be deployed inhouse for my wife (and no, she would not know how to spoof anything or get around the firewall)
- Webserver: Right now, everything is based on the Django's and Flask's webservers; I would like to give interested parties at least the option to deploy this solution with their own webservers, but I don't know enough about WSGI and ASGI for that yet
- Dropping of sessions currently only works from the overview, but not from a session's details page
- It can also take up to ~45 seconds before the stream stalls
- Many more (especially as I have only one concurrent upstream connection to test with)
- Mean exceptions when dropping a stream;)
I wanted to use Django as a management UI once i learned about it and I had this plan for a rewrite of a proxy for a long time. I unfortunately had to find out that Django is not really streaming friendly, so I had to fall back to Flask for that. But hey, at laest we've gained support for distributed setups:)
- Overwrite handling: Allow for a convenient way to replace things such as channel name, channel groups, etc.
- Service files: Ship it with some systemd units
- It is far from complete, so probably many additional things
- Clone the git repository:
git clone https://github.com/coach1988/IPTV-Solution.git
- Edit the docker-compose.yml with the editor of your choice
- Build the docker images
docker-compose build
- Run the stack
docker-compose up -d
The docker container for the manager uses two volumes, one for the database, one for static files (icons, epg and playlists).
- Clone the git repository:
git clone https://github.com/coach1988/IPTV-Solution.git
- Edit the proxy.env and manager.env with the editor of your choice
- Create a venv for, activate it and install the requirements (for both programs)
python3 -m venv venv source venv/bin/activate python3 -m pip install -r requirements.txt
- Run the manager process
manager/run_local.sh
- Run the proxy process
proxy/run_local.sh
Name | Default | Usage |
ALLOWED_HOSTS | ['*'] | Django's list of allowed hosts |
TIME_ZONE | UTC | Timezone to use for Django
(see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) |
DJANGO_SUPERUSER_USERNAME | admin | Default admin login |
DJANGO_SUPERUSER_EMAIL | admin@admin.com | Default admin email address |
DJANGO_SUPERUSER_PASSWORD | password | Default admin password |
SECRET_KEY | Fill me in! | Some secret key for Django, e.g. from https://djecrety.ir/ |
DEBUG | True | Enable Django debugging; Should be set to "True" unless you want to deal with the static file management |
LOGLEVEL | DEBUG | Set log level, see this list |
ALLOWED_URL_SCHEMES | ['http', 'https', 'mmsh', 'mmst', 'mmsu', 'mms', 'rtmp', 'rtsp'] | Disable any channel on first import that does not use one of these URL schemes |
BLOCKED_PATH_TYPES | ['.m3u', '.m3u8', '.mpd'] | Disable any channel on first import that has a path ending with one of these suffixes |
BLOCKED_URL_REGEXS | ['output=playlist.m3u[8]?', 'www.youtube.com/', ] | Disable any channel on first import that has a URL matching one of these RegEx's |
SOCKET_ADDRESS | 0.0.0.0 | The IP to bind the socket to |
MANAGEMENT_URL | http://localhost | Used during M3U and EPG generation for icon URL prefixes |
INTERNAL_MANAGEMENT_PORT | 8088 | Used for the socket setup |
EXTERNAL_MANAGEMENT_PORT | 8088 | Used during M3U and EPG generation for icon URL prefixes |
INTERNAL_TIMEOUT | 1 | Timeout in seconds for internal control connections |
USER_AGENT_STRING | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36) | The User Agent string to use for communication to upstream playlist, epg and icon urls |
PLAYLIST_TIMEOUT | 120 | Download timeout for playlist files |
EPG_TIMEOUT | 120 | Download timeout for EPG files |
ICON_TIMEOUT | 15 | Download timeout for icon files |
Name | Default | Usage |
DEBUG | True | Flask debugging |
SOCKET_ADDRESS | 0.0.0.0 | Streaming proxy server's IP to bind the socket to |
REPORTING_URL | http://localhost | Reporting (Management) server URL |
REPORTING_PORT | 8088 | Reporting service port |
REPORTING_TIMEOUT | 5 | Used for reporting connections |
PROXY_NAME | IPTV-Proxy | Name to use when registering with the management server |
INTERNAL_PROXY_URL | http://localhost | Internal URL to use when registering with the management server (to receive connection control/drop requests from the server) |
INTERNAL_PROXY_PORT | 8089 | Internal port to use when registering with the management server (to receive connection control/drop requests from the server) |
EXTERNAL_PROXY_URL | http://localhost | External URL to use when registering with the management server (for URL's inside of playlists and EPG's) |
EXTERNAL_PROXY_PORT | 8089 | External port to use when registering with the management server (for URL's inside of playlists and EPG's) |
USER_AGENT_STRING | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36) | Defines the User Agent string to use for communication to upstream playlist, epg and icon urls |
STREAM_TIMEOUT | 15 | Seconds before connections to upstream sources time out and a server error is reported to the client |