Add project README
This commit is contained in:
parent
61d3204b34
commit
978ba234b6
1 changed files with 348 additions and 0 deletions
348
README.md
Normal file
348
README.md
Normal file
|
|
@ -0,0 +1,348 @@
|
||||||
|
# movmaker-webui
|
||||||
|
|
||||||
|
A small PHP web interface for publishing and managing **MVLog** videos on Bubulescu.Org.
|
||||||
|
|
||||||
|
The app has two sides:
|
||||||
|
|
||||||
|
- **Public landing page**: lists rendered videos from `out-dir/`.
|
||||||
|
- **Admin page**: creates and edits movmaker input directories in `in-dir/`.
|
||||||
|
|
||||||
|
Generated videos are rendered by the separate `movmaker` worker script and published back into this web app.
|
||||||
|
|
||||||
|
## Paths and URLs
|
||||||
|
|
||||||
|
Production location:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/var/www/html/mvlog
|
||||||
|
```
|
||||||
|
|
||||||
|
Public URLs:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://bubulescu.org/mvlog/
|
||||||
|
https://bubulescu.org/mvlog/new.php
|
||||||
|
https://bubulescu.org/mvlog/login.php
|
||||||
|
https://bubulescu.org/mvlog/feed.php
|
||||||
|
```
|
||||||
|
|
||||||
|
Important directories:
|
||||||
|
|
||||||
|
```text
|
||||||
|
in-dir/ Admin-created movmaker input directories
|
||||||
|
out-dir/ Rendered public videos
|
||||||
|
cache/ Cached video metadata
|
||||||
|
assets/ CSS assets, background image, fonts
|
||||||
|
thumbs/ Reserved for thumbnails
|
||||||
|
```
|
||||||
|
|
||||||
|
## Main files
|
||||||
|
|
||||||
|
```text
|
||||||
|
index.php Public video landing page
|
||||||
|
new.php Protected admin interface
|
||||||
|
login.php PHP session login page
|
||||||
|
logout.php Destroys admin session and redirects to login
|
||||||
|
feed.php RSS feed of latest videos
|
||||||
|
auth.php PHP session authentication helpers
|
||||||
|
config.php Main app config
|
||||||
|
style.css Site/admin styling
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### Public landing page
|
||||||
|
|
||||||
|
`index.php` lists videos from `out-dir/`.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
|
||||||
|
- Dark cinematic MVLog theme
|
||||||
|
- Sticky compact header
|
||||||
|
- RSS icon in the header
|
||||||
|
- One video per row
|
||||||
|
- Metadata display:
|
||||||
|
- title
|
||||||
|
- event date from embedded metadata
|
||||||
|
- location when available
|
||||||
|
- description when available
|
||||||
|
- video creation/publish timestamp in the top-right corner of each row
|
||||||
|
- Download discouraged with:
|
||||||
|
- `controlsList="nodownload"`
|
||||||
|
- right-click disabled on videos
|
||||||
|
- Video metadata cached in `cache/videos.json`
|
||||||
|
|
||||||
|
### RSS feed
|
||||||
|
|
||||||
|
`feed.php` exposes an RSS feed of recent videos:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://bubulescu.org/mvlog/feed.php
|
||||||
|
```
|
||||||
|
|
||||||
|
The feed includes video title, link, description, publication date, and video enclosure.
|
||||||
|
|
||||||
|
### New badges
|
||||||
|
|
||||||
|
Recent videos can be styled with a `New` badge. The CSS class is:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.new-badge
|
||||||
|
```
|
||||||
|
|
||||||
|
### Admin page
|
||||||
|
|
||||||
|
`new.php` is protected by PHP session login.
|
||||||
|
|
||||||
|
Admin tabs:
|
||||||
|
|
||||||
|
- **New**: create a new input directory
|
||||||
|
- **Edit**: edit existing input directories
|
||||||
|
- **Videos**: manage orphan videos not referenced by `.movmaker-state.json`
|
||||||
|
|
||||||
|
Admin can:
|
||||||
|
|
||||||
|
- Create input dirs
|
||||||
|
- Upload images/videos/audio
|
||||||
|
- Edit metadata
|
||||||
|
- Edit per-file captions for images/videos
|
||||||
|
- Remove media files
|
||||||
|
- Delete input dirs
|
||||||
|
- Optionally delete the generated output video associated with an input dir
|
||||||
|
- Delete orphan videos
|
||||||
|
|
||||||
|
Internal files such as `.movmaker-state.json` and `data.txt` are not shown as removable media files.
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
The admin area uses PHP sessions, not nginx Basic Auth.
|
||||||
|
|
||||||
|
Auth files:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/var/www/html/mvlog/auth.php
|
||||||
|
/etc/mvlog/auth.php
|
||||||
|
```
|
||||||
|
|
||||||
|
`/etc/mvlog/auth.php` stores username/password hashes outside the web root:
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
return [
|
||||||
|
'users' => [
|
||||||
|
'username' => 'password_hash_here',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
The password hash should be generated with PHP `password_hash()`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php -r 'echo password_hash("new-password", PASSWORD_DEFAULT), PHP_EOL;'
|
||||||
|
```
|
||||||
|
|
||||||
|
Then update `/etc/mvlog/auth.php`.
|
||||||
|
|
||||||
|
Logout:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/mvlog/logout.php
|
||||||
|
```
|
||||||
|
|
||||||
|
Logout destroys the PHP session and redirects to `login.php`.
|
||||||
|
|
||||||
|
## Input directory naming
|
||||||
|
|
||||||
|
New admin-created input directories must use:
|
||||||
|
|
||||||
|
```text
|
||||||
|
YYYYMMDD_slug-title
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
20260525_mohnesee
|
||||||
|
```
|
||||||
|
|
||||||
|
Do **not** include time in the directory name.
|
||||||
|
|
||||||
|
## `data.txt` format
|
||||||
|
|
||||||
|
Each input directory contains a `data.txt` file.
|
||||||
|
|
||||||
|
All entries use mandatory `key: value` syntax:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Title: My Movie Title
|
||||||
|
Location: Sønderborg
|
||||||
|
Date: 2026-05-25
|
||||||
|
Description: Short description of the video.
|
||||||
|
filename.jpg: Optional caption for this file
|
||||||
|
filename.mp4: Optional caption for this clip
|
||||||
|
```
|
||||||
|
|
||||||
|
Supported general keys:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Title
|
||||||
|
Location
|
||||||
|
Date
|
||||||
|
Description
|
||||||
|
```
|
||||||
|
|
||||||
|
Per-file captions are stored as:
|
||||||
|
|
||||||
|
```text
|
||||||
|
filename.ext: caption text
|
||||||
|
```
|
||||||
|
|
||||||
|
Audio files do not get captions in the admin UI.
|
||||||
|
|
||||||
|
## Worker integration
|
||||||
|
|
||||||
|
Rendering is handled by the separate `movmaker` project, especially:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/home/hbrain/source/movmaker/mvlog_worker.py
|
||||||
|
```
|
||||||
|
|
||||||
|
The worker:
|
||||||
|
|
||||||
|
1. Scans remote `in-dir/` directories.
|
||||||
|
2. Computes an input fingerprint.
|
||||||
|
3. Compares with `.movmaker-state.json`.
|
||||||
|
4. Renders changed jobs with `movmaker.py`.
|
||||||
|
5. Publishes MP4 files to `out-dir/`.
|
||||||
|
6. Updates `.movmaker-state.json`.
|
||||||
|
7. Clears `cache/videos.json` after publishing.
|
||||||
|
|
||||||
|
State file per input dir:
|
||||||
|
|
||||||
|
```text
|
||||||
|
in-dir/<job>/.movmaker-state.json
|
||||||
|
```
|
||||||
|
|
||||||
|
The state file maps an input dir to its generated output video. Orphan detection must rely on this state file only.
|
||||||
|
|
||||||
|
Systemd units on the worker machine:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/systemd/system/mvlog-worker.service
|
||||||
|
/etc/systemd/system/mvlog-worker.timer
|
||||||
|
```
|
||||||
|
|
||||||
|
Useful commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl status mvlog-worker.service --no-pager
|
||||||
|
systemctl status mvlog-worker.timer --no-pager
|
||||||
|
journalctl -u mvlog-worker.service -n 100 --no-pager
|
||||||
|
```
|
||||||
|
|
||||||
|
## Orphan video handling
|
||||||
|
|
||||||
|
The admin **Videos** tab shows generated videos in `out-dir/` that are not referenced by any input directory state file.
|
||||||
|
|
||||||
|
Important rule:
|
||||||
|
|
||||||
|
> Orphan detection must use `.movmaker-state.json` only. Do not infer ownership from metadata or title fallback.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
`config.php` returns the main app config:
|
||||||
|
|
||||||
|
```php
|
||||||
|
return [
|
||||||
|
"site_name" => "Movmaker WebUI",
|
||||||
|
"videos_dir" => __DIR__ . "/out-dir",
|
||||||
|
"thumbs_dir" => __DIR__ . "/thumbs",
|
||||||
|
"uploads_dir" => __DIR__ . "/in-dir",
|
||||||
|
"public_videos" => "out-dir",
|
||||||
|
"public_thumbs" => "thumbs",
|
||||||
|
"items_per_page" => 12,
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
## nginx/PHP requirements
|
||||||
|
|
||||||
|
The app runs under nginx + PHP-FPM.
|
||||||
|
|
||||||
|
Admin uploads require larger request limits. Production currently uses:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
client_max_body_size 512M;
|
||||||
|
```
|
||||||
|
|
||||||
|
PHP-FPM upload override:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
upload_max_filesize = 512M
|
||||||
|
post_max_size = 512M
|
||||||
|
max_file_uploads = 100
|
||||||
|
max_input_time = 600
|
||||||
|
max_execution_time = 600
|
||||||
|
```
|
||||||
|
|
||||||
|
Example file:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/php/8.2/fpm/conf.d/99-mvlog-upload.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
After changing nginx/PHP config:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
sudo systemctl restart php8.2-fpm
|
||||||
|
```
|
||||||
|
|
||||||
|
## Timezone
|
||||||
|
|
||||||
|
The public page and RSS feed explicitly use:
|
||||||
|
|
||||||
|
```php
|
||||||
|
date_default_timezone_set('Europe/Copenhagen');
|
||||||
|
```
|
||||||
|
|
||||||
|
This ensures displayed creation/publish times are Danish local time, not UTC.
|
||||||
|
|
||||||
|
## Permissions
|
||||||
|
|
||||||
|
Expected web ownership is generally:
|
||||||
|
|
||||||
|
```text
|
||||||
|
www-data:www-data
|
||||||
|
```
|
||||||
|
|
||||||
|
The git repo may be owned by `hbrain:www-data`.
|
||||||
|
|
||||||
|
State files should be group-writable so the worker can update them:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod 664 in-dir/*/.movmaker-state.json
|
||||||
|
```
|
||||||
|
|
||||||
|
The worker writes state files using a temp file and `chmod 664` to avoid permission problems.
|
||||||
|
|
||||||
|
## Git notes
|
||||||
|
|
||||||
|
Repository:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://git.novosel.dk/marijo/movmaker-webui.git
|
||||||
|
```
|
||||||
|
|
||||||
|
If git complains about ownership:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git config --global --add safe.directory /var/www/html/mvlog
|
||||||
|
sudo chown -R hbrain:www-data /var/www/html/mvlog/.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not commit generated media from `in-dir/` or `out-dir/`.
|
||||||
|
|
||||||
|
`AGENTS.md` is local assistant/project context and should remain ignored by git.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue