This Flask application serves a media library where users can browse, stream, and download video files. The application dynamically builds a library of video files using hashes and provides a web interface to access them.
-
Dynamic Media Crawling:
- Automatically generates a file tree and hashes filenames when the application starts if
tree.jsondoesn't exist.
- Automatically generates a file tree and hashes filenames when the application starts if
-
Library View:
- Displays a list of available media files with links to play them.
-
Media Playback:
- Streams video files via the browser and provides an option to download them.
-
Error Handling:
- Returns a 404 error if a requested file or hash doesn't exist.
.
├── app.py # Main Flask application
├── crawler.py # Contains the `crawl()` function to generate file tree and hashes
├── templates/ # HTML templates
│ ├── index.html # Displays the media library
│ └── play.html # Plays a selected media file
├── tree.json # Stores the media file tree and hashes
└── static/ # Static files (if any)
- Python 3.x
- Flask
- FFmpeg
- NGINX
-
Clone the repository:
git clone https://github.com/techymaj/box-office.git cd box-office -
Create a virtual environment
python3 -m venv bo-env
-
Activate virtual environment
source bo-env/bin/activate -
Install dependencies:
pip install -r requirements.txt
-
Install FFmpeg
sudp apt install update sudo apt install ffmpeg
-
Ensure the
tree.jsonfile exists or will be generated dynamically by the app. -
(Optional) Place your media files in the root directory or update the
MEDIA_FOLDERconfiguration.
-
Install nginx
sudo apt update sudo apt install nginx -y
-
Start and enable nginx
sudo systemctl start nginx sudo systemctl enable nginx -
Add the server block to
/etc/nginx/nginx.conf
inside the http block. The app knows it is behind a proxy, so you must add the server block for nginx to do its magic.
server {
listen 80;
server_name _;
location / {
proxy_pass http://127.0.0.1:8000/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Prefix /;
}
}-
Test your configuration
sudo nginx -t
You should see.
nginx: configuration file /etc/nginx/nginx.conf test is successful -
Reload nginx to apply the changes
sudo systemctl reload nginx
-
Know your IP Address
ip add
-
Start the gunicorn server with 4 workers. Adjust the number of workers depending on the cores available in your CPU
gunicorn -w 4 app:app
-
Access the application in your browser. Use the IP Address obtained from step 6 (Running the Application)
http://<IP_ADDRESS>
Redirects to the library view.
Displays a list of available media files with links to play them.

Streams the selected media file and provides its size and download link.

Serves media files directly for streaming or downloading.
Displays the media library:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Box Office</title>
</head>
<body>
{% for hash, filename in content.items() %}
<a href="/library/{{hash}}">{{filename}}</a>
{% endfor %}
</body>
</html>Streams and provides details for a selected media file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Box Office | Now Playing</title>
</head>
<body>
<h1>Now Playing</h1>
<p>{{file_path}}</p>
<p>Size: {{file_size}} bytes</p>
<video controls width="1200">
<source src="{{file_path}}" type="video/x-matroska" />
<source src="{{file_path}}" type="video/mp4" />
Download here:
<a href="{{file_path}}">Click to download</a>
</video>
</body>
</html>By default, the app assumes media files are in the root directory. Update the MEDIA_FOLDER configuration in app.py if your files are stored elsewhere:
app.config['MEDIA_FOLDER'] = '/path/to/your/media/files'Update the HTML <source> tags in play.html to include additional video formats as needed.
If tree.json is missing, the app automatically calls crawl() to generate the file structure.
- If a hash is not found, the app responds with
"No such hash found"and a 404 status. - If a file path is invalid, the app responds with a 404 error.
- File Access: Ensure
MEDIA_FOLDERis restricted to trusted directories to avoid serving sensitive files. - Remote Access: If exposing the app to the internet, consider using HTTPS and securing the server.
- Add authentication to restrict access to the library.
- Implement a search functionality for movies and series.
- Enhance error messages for better user experience.
- Use a database to store metadata and improve scalability.
This application provides a foundation for serving a media library and can be extended with additional features as needed.
Please, feel free to contribute.