When Riven marks an item asDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/rivenmedia/riven/llms.txt
Use this file to discover all available pages before exploring further.
Downloaded, there is nothing on your disk yet. The torrent exists only on the debrid provider’s servers. RivenVFS bridges that gap: it mounts a virtual directory that looks to your media server like a normal filesystem, but every read is transparently proxied to the debrid provider over HTTP. Files are never downloaded in full — they stream on demand.
How It Works
RivenVFS is implemented inprogram/services/filesystem/vfs/rivenvfs.py and extends pyfuse3.Operations — the Python binding for the Linux FUSE kernel interface.
VFSDirectory and VFSFile nodes indexed by inode. Path lookups are O(depth), not O(n), making directory listings fast even with large libraries.
Mount Path
The FUSE filesystem is mounted at the path configured byfilesystem.mount_path:
FilesystemService creates the RivenVFS instance and passes the mount path to pyfuse3.init(). If the path is already mounted (e.g., from a previous crash), RivenVFS attempts a graceful unmount with fusermount3/fusermount before re-mounting.
Chunk Cache
Streaming every byte on-the-fly would re-fetch identical data on every seek. RivenVFS maintains a configurable chunk cache — backed by an in-memory or tmpfs directory — so that recently read regions are served locally.| Setting | Default | Description |
|---|---|---|
filesystem.cache_dir | /dev/shm/riven-cache | Directory for cached chunks (tmpfs recommended) |
filesystem.cache_max_size_mb | 10240 (10 GiB) | Maximum total cache size. Clamped to 90 % of available free space if necessary |
filesystem.cache_ttl_seconds | 7200 (2 hours) | Time-to-live per cached chunk (used by TTL eviction) |
filesystem.cache_eviction | LRU | Eviction policy: LRU (least-recently-used) or TTL (time-based) |
filesystem.cache_metrics | true | Log cache hit/miss statistics |
Directory Structure and Library Profiles
RivenVFS always creates two top-level directories:is_anime, etc.) paired with a VFS path:
/mnt/riven/shows/ and /mnt/riven/anime/shows/. Non-anime items only appear under the default paths. Profile directories are never removed, even when empty.
A single item can match multiple profiles and will appear in each matching path. The underlying stream is shared — there is no data duplication.
Naming Templates
File and directory names inside the VFS are rendered from configurable Jinja-style templates:| Setting | Default template | Example output |
|---|---|---|
movie_dir_template | {title} ({year}) {{tmdb-{tmdb_id}}} | Inception (2010) {tmdb-27205} |
movie_file_template | {title} ({year}) | Inception (2010).mkv |
show_dir_template | {title} ({year}) {{tvdb-{tvdb_id}}} | Breaking Bad (2008) {tvdb-81189} |
season_dir_template | Season {season:02d} | Season 01 |
episode_file_template | {show[title]} - s{season:02d}e{episode:02d} | Breaking Bad - s01e01.mkv |
title, year, tmdb_id, tvdb_id, imdb_id, resolution, codec, hdr, audio, quality, season, and episode.
Subtitle Support
RivenVFS also surfaces subtitle files alongside media files. Subtitles are stored in the database (not fetched over HTTP) and served directly from there when a media client reads the.srt or similar file. Subtitle nodes share the parent directory of their associated video file.
Stream Lifecycle
Each open file handle in the VFS maps to aMediaStream object. The stream lifecycle is:
open()— a file handle is created; no HTTP connection is opened yet.read()— on the first byte request, RivenVFS looks up the streaming URL fromVFSDatabase, creates aMediaStream, and issues an HTTP Range request to the debrid CDN.release()— when the media client closes the file, the stream is shut down and its resources are freed.
_monitor_stream_timeouts) checks every 60 seconds for streams that have not received a read request recently and closes them proactively to reclaim memory and CDN connections.
API Endpoints
List VFS Files
Returns a flat map of all files currently visible in the VFS mount:VFS Statistics
Returns per-file streaming statistics (open count, bytes read, errors) collected byopener_stats:
Container Setup
A typical Docker Compose configuration for Riven alongside Plex looks like this:rshared on the Riven container means mount events inside the container are propagated to the host. rslave on the Plex container means it receives those propagated mounts without creating its own.