# TeslaCam View A Flask web app for browsing and playing TeslaCam (Tesla Dashcam/Sentry) recordings from a local drive. It scans a TeslaCam folder for video files, categorizes them by camera view, and presents them in a dark, Tesla-styled web interface with synchronized multi-angle playback. ## Features - **Recursive scan** of the TeslaCam directory tree (`RecentClips`, `SavedClips`, `SentryClips`, etc.) for `.mp4` files matching the TeslaCam naming convention `YYYY-MM-DD_HH-MM-SS-${camera_view}.mp4`. - **Categorization by camera view** — front, left repeater, right repeater, rear, left pillar, right pillar — with friendly display names. - **Multi-angle synchronized playback** — clips sharing the same timestamp are grouped so you can switch between camera angles for the same moment. - **Search & sort** — filter clips by filename, sort oldest-first or A–Z. - **Safe streaming** — videos are served via Flask with path resolution relative to the configured TeslaCam root. - **Dark Tesla-themed UI** built with responsive HTML/CSS (no build step). ## Project Structure ```txt tesla-cam-view/ ├── videoplayer.py # Flask app: scanning, routing, video streaming ├── requirements.txt # Python dependencies ├── .env # Local configuration (git-ignored) ├── .env.example # Configuration template (committed) ├── .gitignore ├── templates/ │ ├── index.html # Main page: camera tabs, player, clip list │ └── camera_view.html # Single-camera view page └── README.md ``` ## Requirements - Python 3.x - See `requirements.txt`: Flask, python-dotenv, gunicorn ## Setup 1. Create and activate a virtual environment (optional but recommended): ```bash python -m venv venv # Windows venv\Scripts\activate # macOS/Linux source venv/bin/activate ``` 2. Install dependencies: ```bash pip install -r requirements.txt ``` 3. Configure the app via environment variables. Copy the example file and edit it: ```bash cp .env.example .env ``` `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`. ## Configuration All settings are read from environment variables, with sensible defaults. You can set them in a `.env` file, export them in the shell, or pass them to the process manager. | Variable | Default | Description | | -------------------- | --------------- | ----------------------------------------------- | | `TESLACAM_DIRECTORY` | `/mnt/TeslaCam` | Root directory of the TeslaCam USB drive | | `FLASK_RUN_HOST` | `0.0.0.0` | Bind address (local dev server only) | | `FLASK_RUN_PORT` | `5000` | Port (local dev server only) | | `FLASK_DEBUG` | `0` | Enable Flask debug mode (local dev server only) | | `SCAN_CACHE_TTL` | `3600` | Seconds to cache the directory scan. Hit | | | | `/refresh` to force a re-scan. | ## Usage ### Local development server ```bash 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 # Two workers are sufficient for this app gunicorn -w 2 -b 0.0.0.0:5000 'videoplayer:app' ``` Make sure `TESLACAM_DIRECTORY` is set for the gunicorn process, e.g.: ```bash export TESLACAM_DIRECTORY=/mnt/TeslaCam gunicorn -w 2 -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. ## Routes | Route | Description | | ------------------------ | ---------------------------------------------------- | | `/` | Main page with all videos categorized by camera view | | `/camera/` | All videos for a single camera view | | `/video/` | Streams a video file from the TeslaCam directory | | `/refresh` | Forces a re-scan of the TeslaCam directory | ## Camera Views | Key | Display Name | | ---------------- | -------------- | | `front` | Front | | `left_repeater` | Left Repeater | | `right_repeater` | Right Repeater | | `rear` | Rear | | `left_pillar` | Left Pillar | | `right_pillar` | Right Pillar | ## Notes - The directory scan is cached in memory for `SCAN_CACHE_TTL` seconds (default 3600) to avoid re-walking the tree on every request. Hit `/refresh` to force a re-scan after copying new clips onto the drive. - Under gunicorn with multiple workers, each worker keeps its own cache; a `/refresh` only refreshes the worker that handles the request. - 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.