diff --git a/src/matebot/sitegen.py b/src/matebot/sitegen.py index 2cbff4f..9beb58c 100644 --- a/src/matebot/sitegen.py +++ b/src/matebot/sitegen.py @@ -11,6 +11,8 @@ import importlib.resources import json import logging +import shutil +import subprocess from pathlib import Path from .slog import Shot, SlogError, parse_slog @@ -88,7 +90,21 @@ def _video_info(shots_dir: Path, out_dir: Path, sid: str) -> dict: offset = float(json.loads((shots_dir / f"{sid}.video.json").read_text())["offset"]) except (OSError, ValueError, KeyError): pass - return {"video": f"video/{sid}.mp4", "video_offset": offset} + info = {"video": f"video/{sid}.mp4", "video_offset": offset} + # poster frame: phones don't decode a frame until play, showing black + poster = out_dir / "video" / f"{sid}.jpg" + stale = not poster.exists() or poster.stat().st_mtime < mp4.stat().st_mtime + if stale and shutil.which("ffmpeg"): + proc = subprocess.run( + ["ffmpeg", "-hide_banner", "-loglevel", "error", "-y", "-ss", "0.5", + "-i", str(mp4), "-frames:v", "1", "-vf", "scale=640:-2", str(poster)], + capture_output=True, + ) + if proc.returncode != 0: + poster.unlink(missing_ok=True) + if poster.exists(): + info["poster"] = f"video/{sid}.jpg" + return info def generate(shots_dir: str | Path, out_dir: str | Path, *, title: str = "Shot Journal") -> int: diff --git a/src/matebot/web/app.js b/src/matebot/web/app.js index 01cc9b4..0dd456e 100644 --- a/src/matebot/web/app.js +++ b/src/matebot/web/app.js @@ -92,7 +92,7 @@ function renderDetail(id, shot, compareId, compare) { if (shot.video) { const holder = document.createElement("div"); holder.className = "chart-card video-card"; - holder.innerHTML = ` + holder.innerHTML = ` `; charts.appendChild(holder); VIDEO = holder.querySelector("video");