Camera-background single-ghost preview reusing the hunt's render path
(WebM VP9+alpha VideoTexture -> WebP/GIF -> procedural wisp). Login gate
matches admin; ghost list via JWT-protected /api/admin/ghosts. Dropdown
to pick a ghost, sliders for distance/size, camera toggle.
- openGhost() previews stored media, preferring WebM video over still image
- showPreview/hidePreview swap between <img> and <video> elements
- Live local preview on file pick (handles mp4/webm)
- Ghost-table row thumbnail renders <video> when only a WebM exists
- Widen file input accept to include .webm/.mp4
- Add a <video> preview element alongside the <img> preview
- Update label and help text to mention server-side MP4 conversion
- Allow .mp4/.webm in addition to image types; raise upload limit to 64MB
- MP4 uploads are luma-keyed to a VP9+alpha WebM plus an animated WebP
fallback via lib/ghost-media.js; the raw MP4 is discarded
- Pre-made .webm uploads are stored directly
- All prior media (image/webm/webp) is cleaned up on replace and on delete
- WebP doubles as the still thumbnail for converted ghosts
Shells out to system ffmpeg with the same luma-key pipeline as ghostify.sh.
Produces a VP9+alpha WebM (browser-decoded primary) and an animated WebP
fallback. No new npm dependency; fails gracefully if ffmpeg is absent.
- Detect VP9-alpha WebM support once at load; iOS Safari falls back to <img>
- addGhost prefers data.webm via THREE.VideoTexture (browser-decoded, no
per-frame needsUpdate pump) when supported
- On video error, gracefully swap the billboard to the GIF/image texture
- Pause + release ghost <video> elements on capture and on hunt teardown to
avoid leaking decoders