Skip to content

Replace re-encoded copies with YouTube-style video versions - #56

Merged
davior merged 2 commits into
mainfrom
claude/determined-johnson-ci4a3k
Oct 29, 2026
Merged

davior merged 2 commits into
mainfrom
claude/determined-johnson-ci4a3k

Conversation

@davior

@davior davior commented Oct 29, 2026

Copy link
Copy Markdown
Owner

What

Two commits:

  1. Reverts #55, which made every re-encode a separate asset holding a copy of the original's metadata.
  2. Adds versions instead. A video asset gets a Versions tab listing the original and a row for each standard size below it (4K, 1440p, 1080p, 720p, 480p, 360p). Each size is created by hand with Create. A version is a file belonging to the one asset, stored in a new assetversion table, not an asset of its own. Name, tags, attribution, transcript and clips stay on the asset, so nothing is copied.

Decisions

  • Make original swaps a version's file in as the asset's own and deletes the big original. This is how space comes back. The row and id stay the same, so tags, transcript, clips and links all carry on. The timeline doesn't change, so clip in/out points and transcript timestamps stay correct. It asks to confirm first because it can't be undone.
  • The encode is the one from Re-encode a video to a smaller resolution as a new asset #55:
    • the target is the frame's short side, so a portrait 4K becomes 1080×1920 (GVC renders 9:16 and 1:1);
    • it only scales down;
    • setsar=1 keeps pixels square;
    • ffmpeg's -progress output drives the percent, keeps the job from being swept as stale, and is where Cancel takes effect.
  • One version is made at a time per video. A version job blocks deleting the video and Make original, because the job reads the original's file when it starts.
  • Deleting the video deletes its versions (rows and files).
  • File counts and sizes:
    • versions are their own group ("Video versions") in the storage panel and count in the library's total files and bytes;
    • "Largest files" ranks by original plus versions and says how much is versions;
    • the stray sweep treats version files as referenced. Without that, an admin cleanup would have deleted every version file.
  • Open: GVC doesn't pick a version yet. GET /api/assets/{id}/versions is what it would read to use the 1080p file in a 1080p project.

Migration

assetversion is a new table; nothing existing changes. Run alembic upgrade head (the Docker entrypoint does this).

Tests

  • backend/tests/test_versions.py (22 tests):
    • route refusals;
    • real ffmpeg runs: landscape, portrait, odd aspect, cancel, garbage input, full disk;
    • delete and make-original, with tags and clips surviving;
    • storage counts, largest ranking, and the stray sweep.
  • VersionsTab.test.tsx and new StoragePanel cases.
  • Run locally: backend pytest -q 1468 passed; frontend format:check, lint, npm test (454) and build all clean.

Generated by Claude Code

Each re-encode became a separate asset with a copy of the original's
metadata. What is wanted instead is YouTube-style versions: one asset,
with standard-resolution files hanging off it. The next commit builds that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V1geD6HjkZNo9XQSHdawSb
A video asset gets a Versions tab: the original, and a row per standard
size below it (4K, 1440p, 1080p, 720p, 480p, 360p), each made by hand
with Create. A version is a file of the one asset (new `assetversion`
table), not an asset of its own, so there is nothing to copy or keep in
step: name, tags, attribution, transcript and clips stay on the asset.

- One ffmpeg run in the job queue (`make_version`), the encode from #55:
  short side as the target (portrait 4K -> 1080x1920), setsar=1 for square
  pixels, and ffmpeg's -progress driving percent, liveness and Cancel.
- "Make original" swaps a version's file in as the asset's own and
  deletes the big original: how space comes back. Same row and id, so
  tags, transcript and clips carry on; the timeline does not change.
- Deleting the asset deletes its versions and their files. A version
  being made blocks the delete and make-original.
- File counts and sizes: versions are their own group in the storage
  panel and in the library total, "Largest files" ranks by original
  plus versions and says how much is versions, and the stray sweep
  counts version files as referenced rather than deleting them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V1geD6HjkZNo9XQSHdawSb
@davior
davior marked this pull request as ready for review October 29, 2026 04:46
@davior
davior merged commit db953fa into main Oct 29, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants