-
-
Notifications
You must be signed in to change notification settings - Fork 669
Custom Formatter
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.
| Access | Type | Description |
|---|---|---|
{config.addonName} |
string |
The name of the AIOStreams instance (the value of the ADDON_NAME environment variable) |
| 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.folderSize} |
number |
Size of the folder that the file is in |
{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.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.regexMatched} |
string |
The name of the highest sort regex that was matched |
{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.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.episodes} |
number[] |
A list of episode numbers detected |
{stream.formattedEpisodes} |
string |
A formatted episode string e.g. E01 or E01-05
|
{stream.seasonPack} |
||
{stream.seeders} |
number |
Number of seeders (for torrents) |
{stream.private} |
||
{stream.age} |
string |
Age of the stream since release |
{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 |
| 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 |
| 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 |
| Access | Type | Description |
|---|---|---|
{debug.json} |
string |
Raw JSON string representation of data |
{debug.jsonf} |
string |
Formatted JSON string representation of data |
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.
-
::upper- Convert string to uppercase -
::lower- Convert string to lowercase -
::title- Title case the string (capitalise the first letters) -
::replace('valueToReplace', 'newValue')- Replace the first occurrence ofvalueToReplacewithnewValue -
::truncate(N)- Truncate the string to N characters and append... -
::length- Return the length of the string -
::reverse- Reverses the string
-
::bytes- Format number as bytes with appropriate unit (KB, MB, GB) -
::bytes2- Format as number of bytes using base 2 (KiB, MiB, GiB) -
::rbytes- Same asbytesbut rounds to the nearest integer -
::rbytes2- Same asbytes2but rounds to the nearest integer -
::time- Format number of seconds as human-readable time -
::hex- Encode the number to hex -
::octal- Encode the number to octal -
::binary- Encode the number to binary
-
::join('separator')- Join array elements with specified separator -
::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
To use conditional modifiers, you need to add them after the variable with a double colon ::, like normal modifiers but with a different format:
{variableName.property::conditionalModifier["trueString"||"falseString"]}
For example, to show the seeders if greater than 1, you would do the following:
{stream.seeders::>1["{stream.seeders}"||""]}
| Modifier | Description | Types | Variables |
|---|---|---|---|
| istrue | If the boolean is true | boolean | None |
| isfalse | If the boolean is false | boolean | None |
| exists | Whether the element exists | string, array | None |
| $X | If the string starts with X | string | X = string |
| ^X | If the string ends with X | string | X = string |
| ~X | If the string/array includes X | string, array | X = string |
| =X | If the value equals to X | string, number | X = string or number |
| >=X | If the number is greater or equal to X | number | X = number |
| >X | If the number is greater than X | number | X = number |
| <=X | If the number is lesser or equal to X | number | X = number |
| <X | If the number is lesser than X | number | X = number |
Note
The istrue and isfalse modifiers returns false when the property is null. Therefore, you must use two conditional modifiers when wanting to show an output depending on whether a value is true or false but not null.
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:
{serivce.cached::isfalse::or::stream.type::=p2p::and::stream.seeders::>0["Seeders: {stream.seeders}"||""]}
Only show seeders when the stream is either uncached or P2P.
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}
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