Skip to content

Custom Formatter

Viren070 edited this page Feb 25, 2026 · 54 revisions

Here is a complete reference to the custom formatter system

A custom format allows you to fully control the output of the streams. You can test your formats live at the configuration page using the Preview.

When writing your format, you have access to specific objects, known as variables, each with their own properties. The format to access a variable is as follows:

{variableName.propertyName}.

You may also apply specific "modifiers". The available modifiers depend on the type of properties. i.e. strings, numbers, lists, each have their own modifiers.

Variables

Config

Access Type Description
{config.addonName} string The name of the AIOStreams instance (the value of the ADDON_NAME environment variable)

Stream

Access Type Description
{stream.proxied} boolean Whether the stream is proxied using MediaFlow proxy
{stream.type} string Type of the stream e.g. debrid, usenet, http, live, youtube, p2p
{stream.filename} string Filename of the stream or media file
{stream.folderName} string The folder name of the stream, usually only available to specific addons.
{stream.size} number Size of the stream/file in bytes
{stream.bitrate} number Bitrate of the stream in bits per second
{stream.folderSize} number Size of the folder/torrent in bytes
{stream.library} boolean Whether the stream is considered to be a stream from a personal library (e.g. debrid account
{stream.quality} string Quality indicator of the stream
{stream.resolution} string Video resolution (e.g., "1080p", "4K")
{stream.languages} string[] Available audio languages
{stream.seeders} number Number of seeders (for torrents)
{stream.private} boolean true if the torrent is from a private tracker.
{stream.freelech} boolean true if the torrent is freeleech.
{stream.age} string Age of the stream since release
{stream.ageHours} number The age of the stream in hours.
{stream.duration} number Duration of the media in seconds
{stream.infoHash} string Info hash for torrent streams
{stream.message} string Additional information or status message
{stream.languageEmojis} string[] Available audio languages in emoji form
{stream.languageCodes} string[] Available audio languages in ISO 639
{stream.smallLanguageCodes} string[] Available audio languages in small caps
{stream.uLanguages} string[] Available audio languages (that are also defined in your language settings)
{stream.uLanguageEmojis} string[] Available audio languages in emoji form (that are also defined in your language settings)
{stream.uLanguageCodes} string[] Available audio languages in ISO 639 (that are also defined in your language settings)
{stream.uSmallLanguageCodes} string[] Available audio languages in small caps (that are also defined in your language settings)
{stream.visualTags} string[] Tags related to video characteristics
{stream.audioTags} string[] Tags related to audio characteristics
{stream.audioChannels} string[] List of detected audio channels
{stream.releaseGroup} string Name of the group that released the content
{stream.encode} string Encoding format (e.g., "x264", "HEVC")
{stream.edition} string Special edition information (e.g., "Director's Cut", "Extended Edition", "Anniversary Edition")
{stream.remastered} boolean Whether the content is remastered
{stream.repack} boolean Whether the release is a repack
{stream.uncensored} boolean Whether the content is uncensored
{stream.unrated} boolean Whether the content is unrated
{stream.upscaled} boolean Whether the content has been upscaled
{stream.network} string Source network or streaming service (e.g., "Netflix", "Disney+")
{stream.container} string File container format (e.g., "mkv", "mp4", "avi")
{stream.extension} string File extension (e.g., "mkv", "mp4", "avi", ".iso", "m2ts")
{stream.indexer} string Source indexer that provided the stream
{stream.title} string The title of the movie or show, extracted from the filename
{stream.year} string Any year contained in the filename
{stream.seasonPack} boolean true if the stream is part of a season pack.
{stream.seasonEpisode} string[] A list of pre-formatted season and episode strings, e.g. ['S01', 'E201'], use the join modifier on this.
{stream.seasons} number[] A list of seasons detected
{stream.formattedSeasons} string A formatted season string e.g. S01 or S01-05
{stream.folderSeasons} number[] A list of seasons detected from the folderName, if available and different from seasons.
{stream.formattedFolderSeasons} string A formatted season string from the folderName e.g. S01 or S01-05.
{stream.episodes} number[] A list of episode numbers detected
{stream.formattedEpisodes} string A formatted episode string e.g. E01 or E01-05
{stream.folderEpisodes} number[] A list of episode numbers detected from the folderName, if available and different from episodes.
{stream.formattedFolderEpisodes} string A formatted episode string from the folderName e.g. E01 or E01-05.
{stream.seadex} boolean Whether the stream is one of the best/alternative releases on SeaDex for that anime.
{stream.seadexBest} boolean Whether the stream is one of the best releases on SeaDex for that anime.
{stream.regexMatched} string The name of the highest preferred regex that was matched
{stream.rankedRegexMatched} string[] A sorted list of all Regex Filter names that were matched.
{stream.regexScore} number The score from the matched Regex Filter.
{stream.nRegexScore} number The regex score normalised to a 0-100 scale with 100 being relative to the highest Regex Score from all your results.
{stream.seScore} number The score from the matched Stream Expression sort rule.
{stream.nSeScore} number The Stream Expression score normalised to a 0-100 scale with 100 being relative to the highest Stream Expression Score from all your results.
{stream.seMatched} string The name of the Preferred Stream Expression that matched this stream. Name is extracted from the first comment that appears in the expression.
{stream.rseMatched} string[] A list of all names of the Ranked Stream Expressions that this stream matched. The names for each RSE is taken from the comments that appear in the expression.

Service

Access Type Description
{service.id} string Unique identifier of the service (e.g. realdebrid)
{service.shortName} string Abbreviated name of the service (e.g. RD)
{service.name} string Full name of the provider (e.g. Real-Debrid)
{service.cached} boolean Whether the stream is cached

Addon

Access Type Description
{addon.presetId} string The ID of the preset that the addon was generated from
{addon.name} string Display name of the addon
{addon.manifestUrl} string The manifest URL of the addon

Metadata

Access Type Description
{metadata.queryType} string The type of media being queried for (e.g. movie, series).
{metadata.title} string The title of the media being queried for.
{metadata.runtime} number The runtime of the movie in minutes.
{metadata.episodeRuntime} number The runtime of the episode in minutes.
{metadata.genres} string[] A list of genres for the media.
{metadata.year} number The release year of the media.

Debug

Access Type Description
{debug.json} string Raw JSON string representation of data
{debug.jsonf} string Formatted JSON string representation of data

Modifiers

To apply a modifier, use it on a variable like so:

{variableName.propertyName::modifier}

You can apply as many modifiers as you want to the same variable. They will be applied in order from left to right.

String Modifiers

  • ::upper - Convert string to uppercase.
  • ::lower - Convert string to lowercase.
  • ::smallcaps - Convert string to ꜱᴍᴀʟʟ ᴄᴀᴘꜱ.
  • ::title - Title case the string (capitalise the first letter of each word).
  • ::replace('find', 'replaceWith') - Replaces all occurrences of find with replaceWith.
  • ::truncate(N) - Truncate the string to N characters and append .
  • ::length - Return the length of the string.
  • ::reverse - Reverses the string.

Number Modifiers

  • ::bytes / ::bytes10 - Format number as bytes using base 10 (e.g., KB, MB, GB).
  • ::sbytes / ::sbytes10 - Format number as "smart" bytes using base 10 (e.g., KB, MB, GB), which is more concise.
  • ::bytes2 - Format as number of bytes using base 2 (e.g., KiB, MiB, GiB).
  • ::sbytes2 - Format number as "smart" bytes using base 2 (e.g., KiB, MiB, GiB).
  • ::rbytes / ::rbytes10 - Same as bytes but rounds to the nearest integer.
  • ::rbytes2 - Same as bytes2 but rounds to the nearest integer.
  • ::bitrate - Format as bitrate using appropriate unit (e.g., Kbps, Mbps).
  • ::rbitrate - Same as bitrate but rounds to the nearest integer.
  • ::sbitrate - Format as "smart" bitrate, providing a more concise output (e.g., 5.2 Mbps).
  • ::time - Format number of seconds as human-readable time (e.g., 1h 30m).
  • ::star - Displays a star rating (out of 5) based on an expected input of a number between 0-100 (e.g., from nSeScore or nRegexScore).
  • ::pstar - Same as star but pads with empty stars to always show 5 total stars (e.g., ★★★☆☆).
  • ::hex - Encode the number to hexadecimal.
  • ::octal - Encode the number to octal.
  • ::binary - Encode the number to binary.
  • ::string - Convert the number to a string

Array Modifiers

  • ::join('separator') - Join array elements with the specified separator.
  • ::slice(start, end) - Returns a section of the array. end is optional.
  • ::length - Return the number of elements in the array.
  • ::first - Return the first element of the array.
  • ::last - Return the last element of the array.
  • ::random - Returns a single random element from the array.
  • ::sort - Sorts the array. For strings, it's alphabetical; for numbers, it's numerical.
  • ::rsort - Sorts the array in reverse order.
  • ::lsort - Sorts the array lexicographically (alphabetically, case-sensitive).
  • ::reverse - Reverses the order of elements in the array.
  • ::string - Convers the array to a string.

Conditional Modifiers

Conditional modifiers evaluate to true or false and are used to create dynamic text. The format is:

{variable::conditionalModifier["trueString"||"falseString"]}

For example, to show the number of seeders only if it's greater than 1, you would do:

  • {stream.seeders::>1["Seeders: {stream.seeders}"||""]}
Modifier Description Applicable Types Example Usage
istrue Checks if a boolean value is true. boolean `{service.cached::istrue["Cached"
isfalse Checks if a boolean value is false. boolean `{service.cached::isfalse["Not Cached"
exists Checks if a value is not null, undefined, an empty string, or an empty array. string, array, any `{stream.folderName::exists["Folder: {stream.folderName}"
$X Checks if a string starts with X or if the first element of an array is X. string, string[] {stream.filename::$ShowName[...]}
^X Checks if a string ends with X or if the last element of an array is X. string, string[] {stream.filename::^.mkv[...]}
~X Checks if a string or an array of strings includes X. string, string[] {stream.languages::~English[...]}
=X Checks if a value is exactly equal to X. string, number {stream.resolution::=1080p[...]}
>=X Checks if a number is greater than or equal to X. number {stream.seeders::>=100[...]}
>X Checks if a number is greater than X. number {stream.seeders::>50[...]}
<=X Checks if a number is less than or equal to X. number {stream.size::<=5GB[...]}
<X Checks if a number is less than X. number {stream.ageHours::<24[...]}

Note

The istrue and isfalse modifiers both evaluate to false when the property is null or undefined. To handle this, you must use two conditional modifiers when wanting to show an output depending on whether a value is true or false but not null e.g. {service.cached::istrue["Cached"||""]}{service.cached::isfalse["Uncached"||""]}

Conditionals

You can also create conditional statements using one of and, or, and xor. Like so:

{variableName.propertyName::conditionalModifier::conditional::variableName.propertyName::conditionalModifier["trueString"||"falseString"]}

You can continue chaining together conditionals as many times as you want, they are applied left to right so the statement (x and y or z) is evaluated as ((x and y) or (z)) whereas if written like (y or z and x) is evaluated as ((y or z) and x).

  • and - both expressions must evaluate to true
  • or - at least one of the expressions must evaluate to true
  • xor - exactly one of the expressions must evaluate to true

For example:

{service.cached::isfalse::or::stream.type::=p2p::and::stream.seeders::>0["Seeders: {stream.seeders}"||""]}

Only show seeders when the stream is either uncached or P2P.

Tools

You also have a few formatting tools available through the following syntax:

{tools.toolName}

Access Description
{tools.newLine} Will add a newline wherever placed. Use this when you want an empty line.
{tools.removeLine} Will remove the entire line wherever found

Note

While {tools.newLine} is provided to you here and it will correctly display in the formatter preview, how it displays in Stremio is not controlled by AIOStreams. It is known that new lines are not respected in the name field on many platforms and as such it is recommended that you do not build your name template relying on {tools.newLine}

Chillio

For Chillio, it won't display your name / description fields exactly like Stremio. The ChillLink protocol supports a title field, this corresponds to the name template. The other means of displaying information is via the metadata field. Here, AIOStreams can offer a list of attributes. To form this list, AIOStreams splits the output produced by the description template by line; each line in the description template gets its own metadata string.

Examples

If you would like to see some examples of formatters, join the Discord Server to see all the formats that have been created by the community.

You may also see the definitions for the built-in formatters at https://github.com/Viren070/AIOStreams/blob/main/packages/core/src/formatters/predefined.ts

Clone this wiki locally