sceneGallerySync

:placard: Summary Automatically creates galleries for scenes on scan, syncs metadata (title / studio / performers / tags / date / rating / urls), imports poster + fanart, and auto-shares one gallery across multipart discs (CD1/CD2, -a/-B).
:link: Repository https://github.com/k6cc/stash-jav-tools/tree/main/sceneGallerySync
:information_source: Source URL https://k6cc.github.io/stash-plugins/plugins/main/index.yml
:open_book: Install How to install a plugin?

Hi stashers,

If you organize your scenes with extrafanart/ folders (Kodi-style library layout) and wish Stash would automatically turn those extrafanart sets into proper Galleries linked to their scene β€” this plugin does exactly that, hands-off on every scan.

Works great in combination with Binge (fork) (gallery thumbnails show up on scene cards in the Feed + performer profile backdrops) and nfoSceneParser (fork) (waits for NFO metadata before attaching title/studio/performers/tags/urls/date/rating to the gallery).


What it does

  • Automatic gallery creation on scan β€” Hooks into Scene.Update.Post. After a scene is scanned and nfoSceneParser writes the NFO, a lightweight one-shot background process fires up, waits for the scene metadata to settle (progressive backoff 3sβ†’15s, max 12 attempts), then creates or updates the matching gallery.

  • Full metadata sync β€” Gallery inherits the scene’s title, code, details, date, rating100, urls, studio, performers, tags. If you edit scene metadata later, the gallery’s existing images remain intact and only new images are appended (no destructive re-creation).

  • Poster + fanart auto-import β€” Searches {filename}-poster.jpg / folder.jpg for the gallery cover (sets it via setGalleryCover mutation) and {filename}-fanart.jpg / landscape.jpg as additional gallery images. Configurable filename patterns in config.py.

  • Multipart / multi-disc β†’ one shared gallery β€” Filenames ending in -cd1/-cd2, -disc1, -part1, -pt1, or single-letter -a/-B/-C all get stripped layer by layer (e.g. ABP-998-C-cd1 β†’ ABP-998-C β†’ ABP-998). All discs land in the same gallery. Four-tier gallery search (exact title match β†’ base filename match β†’ first-word INCLUDES β†’ title first-word INCLUDES) ensures consistency even with translation differences.

  • Manual creation button β€” A β€œCreate Gallery” button is injected next to the Galleries tab on every scene edit page. Bypasses the nfoSceneParser dependency; works at any time. Useful when you re-scanned a folder out of order or added extrafanart after the initial scan.

  • Early extrafanart guard (v1.6.0) β€” Before spawning the background process, the hook does a fast gql_findScene + filesystem check for the extrafanart/ folder. Scenes without the folder (e.g. /social/x/ scraped content in Binge, plain scene directories) skip instantly β€” no idle Python process, no 2-minute metadata timeout.

  • Non-blocking hook (v1.6.0) β€” Background subprocess redirects stdin/stdout to DEVNULL and stderr to a per-scene log file under .sgs_pending/. This fixes the infamous β€œedit spinner hangs for minutes / operation cancelled in log” issue that happens when a child process inherits the stash stdout pipe and keeps it open.

  • Low-power Docker friendly β€” Progressive backoff on all poll loops (3sβ†’5sβ†’7s… max 15s), GraphQL auto-retry with exponential backoff (connection errors + timeouts, up to 3 attempts), no resident daemon β€” each hook spawns a process that exits after completion, stale task/log files older than 1 hour are auto-pruned.


Directory layout it expects

extrafanart/ folder is the hard prerequisite β€” no folder = no gallery (this is checked before any background work starts):

SceneDirectory/
β”œβ”€ ABC-123.avi
β”œβ”€ ABC-123-poster.jpg      ← optional (gallery cover, priority 1)
β”œβ”€ folder.jpg              ← optional (gallery cover, priority 2)
β”œβ”€ ABC-123-fanart.jpg      ← optional
β”œβ”€ landscape.jpg           ← optional
└─ extrafanart/            ← REQUIRED, must contain images
   β”œβ”€ backdrop01.jpg
   β”œβ”€ backdrop02.jpg
   └─ ...

Supported image extensions: .jpg, .jpeg, .png, .gif, .webp (configurable). .gif files are correctly resolved even though Stash stores them internally as VideoFile visual assets.


Screenshots


Install

Option 1: Download Release

  1. Go to Releases
  2. Download the latest sceneGallerySync-vX.Y.Z.zip
  3. Unzip into your Stash plugins directory (files go directly in the sceneGallerySync folder):
    • Windows: %USERPROFILE%\.stash\plugins\sceneGallerySync\
    • Linux/macOS: ~/.stash/plugins/sceneGallerySync/
  4. Stash β†’ Settings β†’ Plugins β†’ Reload plugins

Option 2: Add plugin source

In Stash β†’ Settings β†’ Plugins β†’ Available Plugins β†’ Add Source, add:

Recommended (GitHub Pages):

https://k6cc.github.io/stash-plugins/plugins/main/index.yml

Fallback (raw URL, no Pages required):

https://raw.githubusercontent.com/k6cc/stash-plugins/main/plugins/main/index.yml

Then install sceneGallerySync from the list. This is the same unified source that carries Binge (cn), sceneTranslate, and studioTools β€” one source, install any.


Required runtime

Dependency Required Notes
nfoSceneParser (fork) Yes (auto mode only) Auto-trigger waits for NFO title before syncing metadata. Manual button works without it.
Python 3.x + requests Yes Stash official Docker image ships both out of the box. Windows: winget install Python.Python.3.12 β†’ pip install requests.

Companion plugins (mutually beneficial)

Plugin Synergy with sceneGallerySync
Binge (fork) Galleries created by this plugin show up as gallery thumbnail previews on Binge scene cards + performer profile backdrops. Recommended to install together.
nfoSceneParser (fork) The reason this plugin waits for a title before attaching metadata. Auto-mode depends on its enabled status.
sceneTranslate Translate scene title/details before gallery sync. Gallery inherits the translated text.
studioTools Merge studios / pull from StashDB β†’ changes cascade into galleries via scene β†’ studio foreign key.

Tech stack

Pure Python plugin (standard library + requests). Scene.Update.Post hook β†’ one-shot subprocess with start_new_session=True/DETACHED_PROCESS + stdio redirected to prevent pipe inheritance. All data access through Stash GraphQL with built-in retry. Config stored in config.py (no reload needed). Companion 12-line UI inject (jQuery) adds the manual button to the scene edit page. License: MIT.

All 4 plugins (Binge / sceneGallerySync / sceneTranslate / studioTools) share one plugin source β€” install whichever combination you need.

Feedback, bug reports, and PRs welcome. If you had the v1.5.0 β€œedit spinner hangs 3 minutes” issue, v1.6.0 should resolve it β€” give it a whirl and let me know if anything still stalls.


AI Development Statement

From project setup, fault debugging and architecture refactoring to the writing and polishing of all Markdown‑formatted documents, artificial intelligence runs through the entire development workflow of this project, and the whole project is developed with the help of AI.

1 Like

Stalking all your plugins. Interesting and thank you.

I’m curious, is there any Database or Website that actually support fanarts? Or it all manual download/creation.

I manually download the movies I’m interested in, then use mdc to download the metadata and images, and finally import them into Stash using the two plugins nfoSceneParser (fork) and sceneGallerySync.

1 Like

Untranslated? My stash is English

This button is available only in Chinese. The library is automatically created when scanning with nfoSceneParser (fork); you only need to click this button for any libraries that were missed.

v1.7.0 changed text buttons to graphic buttons and added detailed success/failure prompts. Enjoy using it!

1 Like

Now the plugin supports creating galleries for all scenes on the task page with just one click. Feel free to try it out and give us your feedback!

1 Like