Media libraries are the foundation of Jellyfin’s content organization system. Each library represents a collection of media files of a specific type (movies, TV shows, music, etc.) that Jellyfin scans, indexes, and makes available for streaming.
Library Structure
Jellyfin organizes media into a hierarchical structure:
Root Folder
The AggregateFolder serves as the root container for all libraries. It aggregates all virtual folders configured by the administrator.
Virtual Folders
Each library is represented as a virtual folder with a specific collection type (Movies, TV Shows, Music, Books, etc.).
Physical Paths
Virtual folders map to one or more physical paths on disk where media files are stored.
Media Items
Individual files are resolved into typed items (Movie, Episode, Audio, etc.) with associated metadata.
Collection Types
Jellyfin supports several collection types, each with specialized handling:
Movies
TV Shows
Music
Books
Individual movie files
Movie folders with multiple versions/editions
Extras (trailers, behind-the-scenes, deleted scenes)
Multiple video formats
Series → Season → Episode hierarchy
Multi-episode files
Special episodes and season 0
Episode ordering options (aired, DVD, absolute)
Artist → Album → Track structure
Album artists and contributing artists
Disc numbers and multi-disc albums
Embedded and external lyrics
E-books (EPUB, PDF, MOBI, etc.)
Audiobooks with chapters
Comic books and manga
Book series support
Library Manager
The LibraryManager is the central service for managing media libraries:
Emby.Server.Implementations/Library/LibraryManager.cs
public class LibraryManager : ILibraryManager
{
private readonly ILogger < LibraryManager > _logger ;
private readonly IItemRepository _itemRepository ;
private readonly IUserManager _userManager ;
private readonly IFileSystem _fileSystem ;
private readonly NamingOptions _namingOptions ;
private readonly FastConcurrentLru < Guid , BaseItem > _cache ;
public AggregateFolder RootFolder
{
get
{
if ( _rootFolder is null )
{
lock ( _rootFolderSyncLock )
{
_rootFolder ??= CreateRootFolder ();
}
}
return _rootFolder ;
}
}
public event EventHandler < ItemChangeEventArgs >? ItemAdded ;
public event EventHandler < ItemChangeEventArgs >? ItemUpdated ;
public event EventHandler < ItemChangeEventArgs >? ItemRemoved ;
}
The LibraryManager uses an LRU cache to improve performance when accessing frequently requested items, reducing database queries.
When Jellyfin scans a library, it follows a multi-stage process:
File Discovery
The file system is traversed to discover media files based on naming conventions and file extensions. public BaseItem ? ResolvePath (
FileSystemMetadata fileInfo ,
Folder ? parent = null ,
IDirectoryService ? directoryService = null )
{
// Resolve files into BaseItem objects
}
Item Resolution
Resolvers determine the type of each media item (Movie, Episode, Audio, etc.). Jellyfin includes specialized resolvers:
MovieResolver - Identifies movie files
SeriesResolver - Identifies TV series folders
EpisodeResolver - Parses episode information from filenames
AudioResolver - Identifies audio tracks
Metadata Extraction
Metadata is extracted from:
Embedded tags (ID3, MP4, MKV metadata)
File naming patterns (episode numbers, years, etc.)
NFO files (Kodi-compatible XML metadata)
Provider Fetching
External metadata providers are queried:
TMDb (movies and TV shows)
MusicBrainz (music)
Open Subtitles (subtitles)
Local metadata providers
Database Persistence
Items and their metadata are saved to the database. await _itemRepository . SaveItems ( items , cancellationToken )
. ConfigureAwait ( false );
Post-Scan Tasks
Additional processing tasks run after the scan:
Image extraction and processing
Chapter image generation
People/actor validation
Naming Conventions
Jellyfin uses the Emby.Naming library to parse media files:
TV Show Naming
TV Shows/
├── Show Name (2020)/
│ ├── Season 01/
│ │ ├── Show Name - S01E01 - Episode Title.mkv
│ │ ├── Show Name - S01E02 - Episode Title.mkv
│ │ └── Show Name - S01E03-E04 - Multi-Episode.mkv
│ ├── Season 02/
│ │ └── ...
│ └── tvshow.nfo
Movie Naming
Movies/
├── Movie Name (2021)/
│ ├── Movie Name (2021).mkv
│ ├── Movie Name (2021)-trailer.mp4
│ ├── movie.nfo
│ └── poster.jpg
├── Another Movie (2022).mp4
Music Naming
Music/
├── Artist Name/
│ ├── Album Name (2020)/
│ │ ├── 01 - Track Name.flac
│ │ ├── 02 - Track Name.flac
│ │ ├── cover.jpg
│ │ └── album.nfo
Jellyfin supports multiple naming patterns. See the NamingOptions class for the full list of supported formats.
Library Options
Each library can be configured with specific options:
MediaBrowser.Model/Configuration/LibraryOptions.cs
public class LibraryOptions
{
// Enable/disable metadata providers
public bool EnablePhotos { get ; set ; }
public bool EnableRealtimeMonitor { get ; set ; }
public bool EnableChapterImageExtraction { get ; set ; }
public bool ExtractChapterImagesDuringLibraryScan { get ; set ; }
// Metadata downloaders
public string [] MetadataSavers { get ; set ; }
public string [] DisabledLocalMetadataReaders { get ; set ; }
public string [] LocalMetadataReaderOrder { get ; set ; }
// Content preferences
public string [] PreferredMetadataLanguage { get ; set ; }
public string PreferredImageLanguage { get ; set ; }
// Path settings
public string [] PathInfos { get ; set ; }
}
Real-Time Monitoring
Jellyfin can monitor libraries for changes in real-time:
MediaBrowser.Controller/Library/ILibraryMonitor.cs
public interface ILibraryMonitor
{
void Start ();
void Stop ();
void ReportFileSystemChangeBeginning ( string path );
void ReportFileSystemChangeComplete ( string path , bool refreshPath );
}
When real-time monitoring is enabled:
File system watchers detect new, modified, or deleted files
Changes are debounced to avoid excessive scanning
Only affected items are refreshed
Real-time monitoring can be resource-intensive on large libraries or network shares. Consider using scheduled scans for network-mounted storage.
Item Resolution
The resolution process uses a priority-based system of resolvers:
MediaBrowser.Controller/Library/ItemResolveArgs.cs
public class ItemResolveArgs
{
public Folder ? Parent { get ; set ; }
public FileSystemMetadata FileInfo { get ; set ; }
public string Path { get ; set ; }
public LibraryOptions LibraryOptions { get ; set ; }
public CollectionType ? CollectionType { get ; set ; }
public bool IsDirectory => FileInfo ? . IsDirectory ?? false ;
public bool IsVf => Parent is AggregateFolder ;
}
Resolvers are executed in priority order:
Priority Example
Example Resolver
public void AddParts (
IEnumerable < IResolverIgnoreRule > rules ,
IEnumerable < IItemResolver > resolvers ,
IEnumerable < IIntroProvider > introProviders ,
IEnumerable < IBaseItemComparer > itemComparers ,
IEnumerable < ILibraryPostScanTask > postScanTasks )
{
EntityResolutionIgnoreRules = rules . ToArray ();
EntityResolvers = resolvers . OrderBy ( i => i . Priority ). ToArray ();
MultiItemResolvers = EntityResolvers . OfType < IMultiItemResolver >(). ToArray ();
}
Metadata is fetched from multiple sources:
Local Providers
Remote Providers
Plugin Providers
NFO files : Kodi-compatible XML metadata
Embedded metadata : Tags in media files
Image files : poster.jpg, fanart.jpg, etc.
TMDb : Movies and TV shows
TVDB : TV series information
MusicBrainz : Music metadata
AudioDB : Album artwork and artist info
OMDB : Alternative movie database
Additional providers can be installed via plugins:
AniDB for anime
Trakt for watch history sync
Bookshelf for book metadata
Image Processing
Jellyfin processes and caches images for optimal delivery:
Primary images : Posters, covers
Backdrops : Background artwork
Logos : Transparent overlays
Thumbnails : Chapter images, episode stills
public interface IImageProcessor
{
Task < string > ProcessImage ( ImageProcessingOptions options );
string GetImageCacheTag ( BaseItem item , ItemImageInfo image );
ImageDimensions GetImageDimensions ( BaseItem item , ItemImageInfo image );
}
Images are automatically resized and cached based on client requirements to optimize bandwidth and loading times.
Library Events
The LibraryManager emits events for library changes:
// Subscribe to library events
library . ItemAdded += ( sender , args ) =>
{
_logger . LogInformation ( "Item added: {Name}" , args . Item . Name );
};
library . ItemUpdated += ( sender , args ) =>
{
_logger . LogInformation ( "Item updated: {Name}" , args . Item . Name );
};
library . ItemRemoved += ( sender , args ) =>
{
_logger . LogInformation ( "Item removed: {Name}" , args . Item . Name );
};
These events are propagated to connected clients via WebSocket.
Next Steps
Architecture Understand Jellyfin’s overall architecture
Users & Authentication Learn about user management
Plugins Extend library functionality with plugins
API Reference Access library data via the API