Skip to content

Add Mosaic Poster plugin#743

Open
suzuhiroruri wants to merge 2 commits into
stashapp:mainfrom
suzuhiroruri:plugin/mosaic-poster
Open

Add Mosaic Poster plugin#743
suzuhiroruri wants to merge 2 commits into
stashapp:mainfrom
suzuhiroruri:plugin/mosaic-poster

Conversation

@suzuhiroruri

Copy link
Copy Markdown
Contributor

Description

Adds Mosaic Poster, a UI plugin that replaces the pre-playback scene poster with an N×N contact sheet — a whole-video overview sampled evenly across the file.

preview

Features

  • Toggle cover art ⇄ mosaic — global default in settings, with a per-scene override button on the poster.
  • Selectable grid size (3×3 up to 8×8) via a button on the poster or the setting.
  • Tap a cell to seek to that point in the video (optional setting; the hovered cell is highlighted). The centre play button still plays from the start.
  • Generated on first view (a small loading spinner shows in the toggle while it renders); results are cached with a configurable LRU limit.

Design

  • Daemon-free / cross-platform. Sheets are generated on demand by a Python backend invoked via runPluginOperation, and served by Stash from the plugin's ui.assets folder — no standalone service, no fixed port. ffmpeg/ffprobe and the generated-files path are read from Stash's own configuration, so it works on any OS.
  • Viewport-following pre-generation so browsing large scene lists stays responsive (only what you scroll past is generated).
  • Localized for every language Stash ships, with English as the fallback.

Validation

  • node ./validate.js --ciValidation passed.
  • Manually tested on a live Stash (native macOS build, v0.31.1): cover/mosaic toggle and per-scene override, grid sizes 3–8, first-view generation with the loading spinner, LRU cache, viewport pre-generation, tap-a-cell-to-seek, and the localized strings. Requires python 3 (standard library only) and ffmpeg/ffprobe (Stash's bundled binaries are used automatically).

LLM-assisted contribution disclosure

Per the repository's LLM policy: this plugin was written with LLM assistance (Claude). The code was human-reviewed and human-tested/validated on a live instance, and I take full responsibility for it (including license compliance).

Replaces the pre-playback scene poster with an N x N contact sheet of the
whole video. Toggle cover art / mosaic, selectable grid size (3-8), and tap a
cell to seek to that point. Daemon-free: sheets are generated on demand via
runPluginOperation and served by Stash. Localized for all Stash UI languages.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@suzuhiroruri
suzuhiroruri marked this pull request as ready for review July 16, 2026 23:53
@DogmaDragon

Copy link
Copy Markdown
Contributor

Any particular reason for not using scene sprites and instead adding additional generation overhead?

@DogmaDragon DogmaDragon added the type:plugin Plugins label Jul 17, 2026
@suzuhiroruri

Copy link
Copy Markdown
Contributor Author

@DogmaDragon
Good question! A few reasons:

  1. Resolution. Stash sprites are ~160px per cell — sized for the small seekbar hover preview, so they look quite blurry when shown at full poster size. Mosaic Poster renders a 1920×1080 sheet (384×216 per cell) from the source video to keep the poster crisp.
  2. Sprites aren't always present. They only exist if the user has run Generate → Sprites, so building from them wouldn't work on libraries without them. Generating on demand works on any scene.
  3. Selectable grid + exact seek. The grid is user-selectable (3×3–8×8) and each cell maps to an exact timestamp, so tap-to-seek lands on the shown frame — the sprite's fixed grid doesn't map as cleanly.

That said, the overhead is a fair point, and I tried to keep it bounded: generation is on demand (only the scene you open), one ffmpeg at a time, viewport pre-generation, and an LRU cache.

If a lighter footprint is preferred, I'm happy to add a "use sprites" mode that builds the sheet from the existing sprite/VTT entirely client-side (no generation) — either as an option, or as the default with ffmpeg hi-res as opt-in. Happy to go whichever direction the project prefers.

@DogmaDragon

Copy link
Copy Markdown
Contributor
  1. 160px is the default size, they are configurable in Stash.
  2. Neither are this contact sheet, but unlike it they could serve double purpose instead of just taking extra space for only this plugin.
  3. Scene sprites are configurable from interval to minimum/maximum sprites. And they are not stored in a grid, they are just arranged like that in the UI, so they can easily be spliced up whatever way you want.

I can merge the plugin as is, but your LLM seems to have made the plugin based on false assumptions either by lack of direction or pure stupidity.

Reuse the existing scene sprite + WebVTT to build the mosaic client-side
(instant, no ffmpeg, no extra storage). Tap-to-seek uses the sprite's real
VTT timestamps. ffmpeg generation is now an optional "High-res upgrade"
setting, off by default, that renders a higher-resolution sheet from the
video and swaps it in over the sprite when enabled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@suzuhiroruri

Copy link
Copy Markdown
Contributor Author

@DogmaDragon
Thanks — you're right, and I've reworked it accordingly (1d77fae).

By default the sheet is now built entirely in the browser from the existing scene sprite + VTT: the frames are spliced into the N×N grid on a canvas, using each thumbnail's real VTT timestamp for tap-to-seek. No ffmpeg and no extra storage — it's instant and reuses what Stash already generates.

The ffmpeg path is still available but is now an optional High-res upgrade setting, off by default, for a sharper sheet on large / hi-DPI displays; when enabled it just swaps a generated sheet in over the sprite.

Appreciate the details on the sprite config/layout — that's what made the sprite-first approach straightforward.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be excluded.

@@ -0,0 +1,51 @@
name: Mosaic Poster
description: Replaces the pre-playback poster on the scene detail page with a 5x5 contact sheet (a whole-video overview) sampled evenly across the video. A button at the top-right of the poster toggles cover art <-> mosaic in one click (the choice is remembered). List and card cover art is untouched.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Description is too verbose.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reformat to remove mid-sentence line breaks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants