* feat(metadata,scanner): trailers and extras for movies and series Remote provider videos (TMDB trailers/teasers/featurettes/...) are fetched through the unified match/refresh pipeline into the new item_videos table, filtered per-library via media_folders.trailer_kinds, merged across providers with site/provider dedup, and lockable via FieldVideos. The movie scanner stops discarding supplemental directories (Trailers/, Featurettes/, Behind The Scenes/, ...) and classifies them — plus Jellyfin-style filename suffixes (-trailer, -behindthescenes, ...) and series-root supplemental dirs — into the new media_extras entity backed by ordinary media_files rows (extra_id ownership, content_id/episode_id NULL so existing version/matching queries stay structurally blind to extras). Series Extras/SxxExx season-0 mapping is unchanged. Extras are playable watch targets via a GetWatchDetail fallback tier (episodes precedent), with contentid.ForLocal minting stable ids. API: ItemDetail gains additive videos/extras arrays (single + batch parity); library settings expose trailer_kinds. jellycompat now populates RemoteTrailers, LocalTrailerCount/SpecialFeatureCount, and serves real /LocalTrailers + /SpecialFeatures items playable through PlaybackInfo. Requires silo-plugin-sdk v0.9.0 (VideoRecord) before go.mod can bump; builds locally via go.work against the SDK feat/metadata-videos branch. Part of trailers/extras capability work. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(web): trailers and extras sections, library trailer-kinds setting TrailersSection (YouTube thumbnails + youtube-nocookie modal) and ExtrasSection (plays extras through the standard watch controller) on movie and series detail pages; admin library form gains a trailer-kinds allow-list synced with the server default (all provider kinds), now also honored on library create. Part of trailers/extras capability work. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(scanner): scan extra_id in scanMediaFiles; review cleanups scanMediaFiles (the plural row scanner behind GetByContentID/GetByFolder/ GetByExtraID and 20+ other queries) was missing the scan destination for the new extra_id column, which would have failed every media-file read at runtime with a column/destination count mismatch. Also: extend the batch equivalence test to seed item_videos/media_extras so the new videos/extras prefetch wiring is actually proven; drop the one-off pgxRows interface for the repo-wide pgx.Rows convention; reuse formatClock instead of a third duration formatter in ExtrasSection. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore(deps): bump silo-plugin-sdk to v0.9.0 for VideoRecord Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(matching): exclude extras files from match queues and bulk content linking Dev verification caught extras media_files rows (content_id NULL by design) being swept into the movie/series match queues and the root-claim bulk relink: a '-featurette' suffix extra was matched onto its parent as a version, and a Trailers/ file minted a spurious local skeleton item that shadowed the extra's watch target. Add 'extra_id IS NULL' to the queue eligibility conditions, root/group claim relinks, observed-root content assignment, and the admin unmatched-files listing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(playback): authorize local extras files through their parent item Dev verification: playback/start (and the shared MediaFileAuthorizer used by markers/subtitles/ebook reader) resolved file ownership only via episode_id/content_id, so extras files (extra_id only) 404ed. Add an ExtraLookup tier that resolves media_extras and gates on the parent item's access, mirroring the episode->series pattern. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(catalog): resolve local extras through GetItemDetail for compat playback jellycompat PlaybackInfo (and any per-item consumer resolving arbitrary content ids) goes through GetItemDetail, which lacked the extras tier that GetWatchDetail has — so Jellyfin clients got zero MediaSources for extras. Add buildExtraItemDetail (minimal detail + ordinary playback surface, parent-gated access) as the fourth resolution tier, and map the extra type to Jellyfin's Video kind. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(web): allow youtube-nocookie embeds in CSP; trailer modal a11y The frontend CSP's frame-src blocked the trailer modal's youtube-nocookie.com iframe (found on dev verification). Also add the missing sr-only DialogDescription and drop the redundant allowFullScreen attribute. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: address PR review findings for trailers/extras - Extras watch/item detail no longer stamp SeriesID/SeriesTitle for movie-owned extras (players key episodic post-roll flows off series_id); series-owned extras keep them (Codex). - processExtraFiles resolves the parent and upserts media_extras before the unchanged fast-path, and the fast-path now also compares mtime, so rematched parents / reclassified kinds / same-size replacements converge (Codex + CodeRabbit). - media_files upsert clears content/episode linkage atomically when extra_id is set (ownership mutual exclusion in one statement); the now-redundant MarkFileAsExtra helper is removed (CodeRabbit). - ScanFile's extras branch runs syncPresentLibraryState + reconcileLibraryMemberships so converting a primary file to an extra cleans stale library membership immediately (CodeRabbit). - media_extras migration adds the media_files FK as NOT VALID + VALIDATE to avoid a full-scan exclusive lock on large tables (CodeRabbit). - trailer_kinds input is trimmed/lowercased/deduped and unknown values are dropped instead of silently widening the allow-list to 'other' (CodeRabbit). - Extras authorization branches match the episode branch's posture: unconfigured lookup is a config error, nil extra is a 404 (CodeRabbit). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
8.7 KiB
title, description, summary, tags, audience, last_reviewed, related
| title | description | summary | tags | audience | last_reviewed | related | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Supported Media Folder Structures and Naming | Accurate reference for the folder layouts and filename patterns Silo supports today. | Supported movie and series organization rules, naming conventions, and known ambiguous cases. |
|
|
2026-04-11 |
|
Supported Media Folder Structures and Naming
This page documents the folder layouts and filename conventions that Silo supports today.
It is based on the current scanner, naming, and metadata-matching code paths, plus a validation pass
against the dev anime library on 2026-04-11.
All examples in this page use generic placeholder names rather than real media titles.
Core Rules
- Movies and series do not have the same requirements.
- Series are expected to be contained within a single parent show folder.
- Movies can be stored either in a dedicated movie folder or as loose files.
- Mixed libraries are supported, but they rely on heuristics and are more likely to become ambiguous when names and folders are inconsistent.
- Provider ID tags such as
{tvdb-12345},{tmdb-12345}, or{imdb-tt1234567}are strongly recommended because they improve matching and reduce ambiguity.
Supported Series Layouts
Recommended series layout
/television/Show Name (2024) {tvdb-12345}/Season 01/Show Name - S01E01 - Pilot.mkv
This is the clearest and most reliable structure for series.
Also supported
Series content is supported in these layouts:
- Show folder with
Season XXdirectories. - Show folder with
Season XX - extra textdirectories, such as arc names. - Show folder with numeric season directories like
01when the surrounding context still looks like series content. - Show folder with
Specialsdirectories. - Show folder with
Extrasdirectories. Silo maps these to season0. - Show folder with episode files directly under the show folder when the filenames contain a
supported episodic token such as
S01E03.
Examples:
/tv/Series Name (2008)/Season 01/Series.Name.S01E01.mkv
/tv/Show Name/Specials/Show.Name.S00E01.mkv
/tv/Show Name/Extras/Show.Name.S00E01.mkv
/mixed/Show Name/01/Show Name S01E03.mkv
/mixed/Show Name/Show Name S01E03.mkv
One narrow edge case is worth calling out separately:
/television/anime/Series Name/Season 01 - Arc 01 - Arc Name/Series.Name.E01.1080p.mkv
That kind of path can still help Silo recognize the show root because the folder layout is
strong, but bare E01 is not a generally supported episode parsing format.
Supported Episode Filename Patterns
Silo currently treats SxxExx as the supported episode token.
Supported examples:
Show Name - S01E01 - Pilot.mkv
Show Name.S01E03.mkv
Show Name - S00E01 - Special.mkv
Show Name - S01E01.001 - Pilot [Bluray-1080p][x265].mkv
Important details:
- The parser only needs the
SxxExxpart. Extra text after it is tolerated. - Decimal suffixes such as
S01E01.001are supported because the parser still recognizes the leadingS01E01. - Release metadata and noisy suffixes after the episode token are tolerated as long as the file
still contains a valid
SxxExxtoken. SpecialsandExtrasuse season0, soS00E01is supported.
Representative validated pattern from the dev server:
Series Name (2017) - S01E01.001 - Episode Title [Bluray-1080p][10bit][x265][AC3 5.1][EN+JA]-GROUP][.mkv
Series Patterns That Are Not Reliably Supported
These patterns should be treated as unsupported or ambiguous:
- Unrelated episodes from different series thrown into the same folder.
- Episode files that use only absolute numbering, such as
Stone Ocean 24.mkv, withoutSxxExx. - Bare
E01filenames as a general naming convention. Silo has a narrow test case whereE01still helps identify a season-folder layout, but it is not a generally supported episode parsing format. - Series files with no clear show folder, no supported episode token, and no provider-tagged parent folder.
If a series library contains a flat dump of unrelated episodes, Silo can collapse them into the same inferred root because the current model assumes one parent show folder per series.
When Silo cannot confidently classify or reconcile a root, it can surface the content as an explicitly ambiguous item instead of auto-matching it. In practice, unsupported layouts often show up as ambiguous or pending items rather than as clean matches.
Supported Movie Layouts
Movies are more flexible than series.
Recommended movie layout
/movies/Movie Name (2016)/Movie.Name.2016.1080p.BluRay.mkv
Also supported
- Loose movie files in a movie library.
- Dedicated movie folders with provider tags.
- Release-style filenames inside a trusted movie folder.
Examples:
/movies/Movie Name (2016)/Movie.Name.2016.1080p.BluRay.mkv
/movies/Movie Name [imdbid-tt1234567]/Movie Name.mp4
/movies/Loose Movie.2024.2160p.WEB-DL.mkv
/movies/Movie Name {imdb-tt1234567} {tmdb-12345}/Movie.Name (2023) [Remux-1080p].mkv
Silo can infer a synthetic root for a truly loose movie file when there is no trusted movie folder around it.
Supported Mixed-Library Behavior
Mixed libraries are supported, but they are heuristic-driven.
Silo resolves mixed-library content roughly like this:
- If the path has season structure, it is treated as series.
- If the enclosing folder looks like a movie folder, it is treated as a movie.
- If the filename contains
SxxExx, it is treated as series. - Otherwise it falls back to movie.
This means mixed libraries can work well, but they are less deterministic than separate movie and series libraries.
Provider Tags
Provider tags are supported in folder names and are strongly recommended.
Supported formats include:
Series Name (2024) {tvdb-12345}
Movie Name (2024) {tmdb-12345}
Movie Name [imdbid-tt1234567]
Benefits of provider tags:
- More reliable initial skeleton creation.
- Better deduplication.
- Less ambiguity in mixed libraries.
- Better resilience when release filenames diverge from the human title.
Sidecar Files and Supplemental Files
Silo often sees sidecar files that mirror the media basename:
.nfo.bif-thumb.jpgtvshow.nfoseason.nfo- posters, banners, logos, and fanart
These are common and expected. Episode naming guidance in this page refers to the media files themselves, but sidecars may legitimately reuse the same stem.
Supplemental directories next to a movie (and directly under a series root) are scanned as extras attached to that item, following the Jellyfin/Plex folder convention:
Trailers,TeasersFeaturettesBehind the ScenesDeleted ScenesClips,Shorts,Interviews,ScenesExtras,Other
Filename suffixes on files sitting next to the movie are also recognized:
Movie (2020)-trailer.mkv, -teaser, -featurette, -clip,
-behindthescenes, -deleted, -interview, -short, -other.
Extras never appear as versions of the main title; they show in the item's
Extras section and play like any other file. Extras are bound to the item
owning the surrounding folder, so an extras directory at the library root is
ignored. For series libraries, Extras/ files carrying a valid SxxExx
token keep their documented season-0 mapping and are not treated as extras.
Noise content is still intentionally skipped:
Sample/Samplesdirectories andSample.mkv-style filesSubs/Subtitlesdirectories (handled by subtitle detection)
What The Dev Anime Library Validated
A large anime series library on the dev server was audited to validate that this page reflects real-world usage and not just unit tests.
Observed on 2026-04-11:
4038top-level show directories.4029show directories with at least oneSeason XXdirectory.1184show directories with aSpecialsdirectory.4036show directories with a provider tag in the folder name.474304files matchingSxxExx.xxx.87289.mkvfiles matchingSxxExx.xxx.
That makes SxxExx.xxx an important supported pattern, not a corner case.
Recommended Practices
- Put every series inside its own parent show folder.
- Use
Season XXandSpecialswhen possible. - Include the year in the top-level folder when it is known.
- Add provider tags when you can.
- Keep movies and series in separate libraries unless you specifically want mixed-library heuristics.
- Do not rely on flat folders of unrelated episodes.
Source References
internal/naming/filename.gointernal/naming/root_inference.gointernal/scanner/scanner.gointernal/metadata/service.gointernal/naming/filename_test.gointernal/scanner/root_observation_test.gointernal/metadata/service_test.go