No description
Find a file
2026-05-28 17:21:43 +02:00
assets Update header logo image 2026-05-26 07:55:45 +02:00
.gitignore Cache video metadata by mtime 2026-05-25 18:46:14 +02:00
auth.php Replace basic auth with PHP session login 2026-05-25 22:31:46 +02:00
config.php Refine admin status and notification controls 2026-05-26 20:31:04 +02:00
feed.php Show video creation time in admin edit list 2026-05-27 10:31:05 +02:00
index.php Match public header with admin layout 2026-05-27 22:35:10 +02:00
job_status.php Refine admin status and notification controls 2026-05-26 20:31:04 +02:00
login.php Responsive mobile layout and header word sizing 2026-05-28 07:47:34 +02:00
logout.php Redirect logout to login page 2026-05-25 22:39:55 +02:00
new.php Highlight stale renders on admin list 2026-05-28 17:21:43 +02:00
push_config.php Add web push notifications 2026-05-26 15:48:30 +02:00
push_subscribe.php Add web push notifications 2026-05-26 15:48:30 +02:00
README.md Add project README 2026-05-25 22:42:03 +02:00
style.css Highlight stale renders on admin list 2026-05-28 17:21:43 +02:00
sw.js Add web push notifications 2026-05-26 15:48:30 +02:00

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:

/var/www/html/mvlog

Public URLs:

https://bubulescu.org/mvlog/
https://bubulescu.org/mvlog/new.php
https://bubulescu.org/mvlog/login.php
https://bubulescu.org/mvlog/feed.php

Important directories:

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

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:

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:

.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:

/var/www/html/mvlog/auth.php
/etc/mvlog/auth.php

/etc/mvlog/auth.php stores username/password hashes outside the web root:

<?php
return [
    'users' => [
        'username' => 'password_hash_here',
    ],
];

The password hash should be generated with PHP password_hash().

Example:

php -r 'echo password_hash("new-password", PASSWORD_DEFAULT), PHP_EOL;'

Then update /etc/mvlog/auth.php.

Logout:

/mvlog/logout.php

Logout destroys the PHP session and redirects to login.php.

Input directory naming

New admin-created input directories must use:

YYYYMMDD_slug-title

Example:

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:

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:

Title
Location
Date
Description

Per-file captions are stored as:

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:

/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:

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:

/etc/systemd/system/mvlog-worker.service
/etc/systemd/system/mvlog-worker.timer

Useful commands:

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:

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:

client_max_body_size 512M;

PHP-FPM upload override:

upload_max_filesize = 512M
post_max_size = 512M
max_file_uploads = 100
max_input_time = 600
max_execution_time = 600

Example file:

/etc/php/8.2/fpm/conf.d/99-mvlog-upload.ini

After changing nginx/PHP config:

sudo nginx -t
sudo systemctl reload nginx
sudo systemctl restart php8.2-fpm

Timezone

The public page and RSS feed explicitly use:

date_default_timezone_set('Europe/Copenhagen');

This ensures displayed creation/publish times are Danish local time, not UTC.

Permissions

Expected web ownership is generally:

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:

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:

https://git.novosel.dk/marijo/movmaker-webui.git

If git complains about ownership:

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.