From a4202afe301820b380e8a471dca2b7e1fcf35d91 Mon Sep 17 00:00:00 2001 From: zwitschi Date: Fri, 24 Jul 2026 12:49:25 +0200 Subject: [PATCH] add .env.example and update README for environment variable configuration --- .env.example | 7 +++++++ .gitignore | 3 ++- README.md | 45 ++++++++++++++++++++++++++++++++++++++------- requirements.txt | 4 +++- videoplayer.py | 18 +++++++++++++++--- 5 files changed, 65 insertions(+), 12 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..b54a44a --- /dev/null +++ b/.env.example @@ -0,0 +1,7 @@ +# Root TeslaCam directory containing RecentClips/SavedClips/SentryClips +TESLACAM_DIRECTORY=/mnt/TeslaCam + +# Local dev server only (ignored when run under a WSGI server like gunicorn) +FLASK_RUN_HOST=0.0.0.0 +FLASK_RUN_PORT=5000 +FLASK_DEBUG=0 \ No newline at end of file diff --git a/.gitignore b/.gitignore index d288ad0..8f3873c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ __pycache__/ .mypy_cache/ .ruff_cache/ .github/AGENTS.md -.github/instructions/ \ No newline at end of file +.github/instructions/ +.env \ No newline at end of file diff --git a/README.md b/README.md index 6f1dbc6..e38dc3e 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ tesla-cam-view-1/ ## Requirements - Python 3.x -- Flask (see `requirements.txt`) +- Flask, python-dotenv, gunicorn (see `requirements.txt`) ## Setup @@ -46,17 +46,27 @@ tesla-cam-view-1/ pip install -r requirements.txt ``` -3. Configure the TeslaCam directory by editing `TESLACAM_DIRECTORY` in `videoplayer.py`: +3. Configure the TeslaCam directory via environment variables. Copy the example + file and edit it: - ```python - TESLACAM_DIRECTORY = r'W:\2026\USA2026\TeslaCam' + ```bash + cp .env.example .env ``` - Point this to the root folder containing your `RecentClips`, `SavedClips`, and `SentryClips` subfolders. + ```ini + TESLACAM_DIRECTORY=/mnt/TeslaCam + FLASK_RUN_HOST=0.0.0.0 + FLASK_RUN_PORT=5000 + FLASK_DEBUG=0 + ``` + + `TESLACAM_DIRECTORY` should point to the root folder containing your + `RecentClips`, `SavedClips`, and `SentryClips` subfolders. Variables set in + the real environment take precedence over `.env`. ## Usage -Run the app: +### Local development server ```bash python videoplayer.py @@ -64,6 +74,26 @@ python videoplayer.py Then open [http://localhost:5000](http://localhost:5000) in your browser. +### Production (WSGI server on Linux) + +For production, run the app behind a WSGI server such as **gunicorn**. The +`app` object in `videoplayer.py` is the WSGI entry point: + +```bash +gunicorn -w 4 -b 0.0.0.0:5000 'videoplayer:app' +``` + +`TESLACAM_DIRECTORY` is read from the environment (or `.env`), so make sure it +is set for the gunicorn process, e.g.: + +```bash +export TESLACAM_DIRECTORY=/mnt/TeslaCam +gunicorn -w 4 -b 0.0.0.0:5000 'videoplayer:app' +``` + +For a systemd service or other process manager, set the variable in the unit +file / environment rather than relying on `.env`. + - The **main page** lists all clips grouped by camera view with a player and searchable clip list. - Click a clip to play it; use the camera switch buttons to jump between angles for the same timestamp. - The `/camera/` route shows all clips for a single camera. @@ -89,6 +119,7 @@ Then open [http://localhost:5000](http://localhost:5000) in your browser. ## Notes -- The app runs with `debug=True` by default — disable this for production use. +- Debug mode is off by default (`FLASK_DEBUG=0`) and is only used by the local + dev server. It has no effect when running under a WSGI server like gunicorn. - The TeslaCam directory must be accessible from the machine running the app (e.g., a mounted USB drive or network share). - Filename parsing assumes the standard TeslaCam naming format; files not matching the regex are ignored. diff --git a/requirements.txt b/requirements.txt index 8ab6294..886c3db 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,3 @@ -flask \ No newline at end of file +flask +python-dotenv +gunicorn \ No newline at end of file diff --git a/videoplayer.py b/videoplayer.py index e922ad6..179bd04 100644 --- a/videoplayer.py +++ b/videoplayer.py @@ -11,12 +11,18 @@ play videos from different camera views. import os import re + +from dotenv import load_dotenv from flask import Flask, render_template, send_from_directory, abort +# Load variables from a .env file if present (does not override real env vars) +load_dotenv() + app = Flask(__name__) # Root TeslaCam directory containing RecentClips, SavedClips, SentryClips, etc. -TESLACAM_DIRECTORY = '/mnt/TeslaCam' +# Override via the TESLACAM_DIRECTORY environment variable (see .env.example). +TESLACAM_DIRECTORY = os.environ.get('TESLACAM_DIRECTORY', '/mnt/TeslaCam') # Regular expression matching TeslaCam filenames: YYYY-MM-DD_HH-MM-SS-${camera_view}.mp4 VIDEO_FILENAME_REGEX = re.compile( @@ -132,5 +138,11 @@ def serve_video(filepath): if __name__ == '__main__': - host = '0.0.0.0' - app.run(debug=True, host=host, port=5000) + # Local dev server. For production, run behind a WSGI server instead, e.g.: + # gunicorn -w 4 -b 0.0.0.0:5000 'videoplayer:app' + # or + # waitress-serve --host=0.0.0.0 --port=5000 videoplayer:app + host = os.environ.get('FLASK_RUN_HOST', '0.0.0.0') + port = int(os.environ.get('FLASK_RUN_PORT', '5000')) + debug = os.environ.get('FLASK_DEBUG', '0').lower() in ('1', 'true', 'yes') + app.run(debug=debug, host=host, port=port)