-
-
Notifications
You must be signed in to change notification settings - Fork 688
Stream Expression Language
The Stream Expression Language (SEL) is a powerful feature in AIOStreams that allows you to write custom logic to filter, select, and evaluate lists of streams. It is used by features like Groups and Stream Expression Filters.
This page serves as the complete technical reference for SEL syntax, operators, and functions.
An expression in SEL is a combination of constants, functions, and operators that resolves to a specific value. The required result depends on the context where you use the expression:
-
Group Conditions require the expression to resolve to
trueorfalse. - Stream Selectors require the expression to resolve to an array (list) of streams.
These are used to compare values and combine logic.
-
Comparison:
==(equals),!=(not equals),>(greater than),<(less than),>=(greater than or equal),<=(less than or equal) -
Membership:
in(checks if a value is present in a sequence e.g.'Addon' in queriedAddons) -
Addition/Subtraction:
+(add),-(subtract) -
Logical:
and,or,not -
Conditional:
x ? y : z(Ternary conditional - if x is true, then y else z) -
Grouping:
()(used to control the order of operations, just like in math).
Most functions either take a list of streams as input or produce a list of streams as output. You can chain functions together to create powerful, multi-step filters. This is called nesting.
Example of Nesting: To get a count of only the 4K streams that are also cached, you would nest the functions like this:
count(resolution(cached(streams), '2160p'))
-
How it reads:
-
cached(streams): First, get a list of only the cached streams. -
resolution(..., '2160p'): Then, from that list, get a new list of only the ones that are 4K. -
count(...): Finally, count how many streams are in that final list.
-
The constants available to you depend on which AIOStreams feature you are using SEL with.
For Group Conditions:
-
previousStreams: A list of streams found by the last group that ran. -
totalStreams: A list of all streams found by all groups that have run so far. -
queryType: What you're searching for (e.g.,"movie","series"). -
previousGroupTimeTaken: How long the last group took (in milliseconds). -
totalTimeTaken: Total time spent so far (in milliseconds).
For Dynamic Exit Conditions:
-
totalStreams: A list of all streams found by all groups that have run so far. -
totalTimeTaken: Total time spent so far (in milliseconds). -
queryType: What you're searching for (e.g.,"movie","series","anime.series","anime.movie"). -
queriedAddons: A list of addon names that have been queried so far.
For Stream Expression Filters & Precache Selector:
-
streams: A list of all available streams that can be filtered. -
queryType: The type of media being queried (e.g.,"movie","series"). Defaults to''. -
isAnime:trueif the media is anime, otherwisefalse. Defaults tofalse. -
season: The season number. Defaults to-1. -
episode: The episode number. Defaults to-1. -
absoluteEpisode: The absolute episode number. Defaults to-1. -
genres: A list of genres (e.g.,['Action', 'Adventure']). Defaults to[]. -
title: The title of the media. Defaults to''. -
year: The release year of the media. Defaults to0. -
yearEnd: The end year for a series. Defaults to0. -
daysSinceRelease: Number of days since the media was released. Defaults to-1. -
runtime: The runtime in minutes. Defaults to0. -
originalLanguage: The original language of the media (e.g.,"English"). Defaults to''. -
hasSeaDex:trueif there are SeaDex results for this media, otherwisefalse. Defaults tofalse. -
hasNextEpisode:trueif there is a next episode for a series, otherwisefalse. Defaults tofalse. -
daysUntilNextEpisode: Number of days until the next episode airs. Defaults to-1. -
daysSinceFirstAired: Number of days since the first episode of a series aired. Defaults to-1. -
daysSinceLastAired: Number of days since the last episode of a series aired. Defaults to-1. -
latestSeason: The latest season number for a series. Defaults to-1. -
ongoingSeason:trueif you are viewing the latest season and there is a next episode, otherwisefalse. Defaults tofalse.
In AIOStreams, you can use SEL not just for filtering but also for advanced sorting through Preferred and Ranked Stream Expressions. To make your results more informative, you can assign names to these expressions, which can then be displayed using the Custom Formatter.
You can name any Stream Expression by adding a standard C-style comment to it. The text inside the comment will be used as the name.
-
Syntax:
/* Your Expression Name */ expression -
Example:
/* 4K Dolby Vision */ merge(resolution(streams, '2160p'), visualTag(streams, 'DV'))
You can even add multiple names to a single Ranked Stream Expression:
-
Example:
/* 4K */ resolution(streams, '2160p') /* High Quality */
If you want to add a comment for your own reference without it being used as a name in the formatter, simply start the comment text with a hash (#).
-
Example:
/*# This is just a test */ quality(streams, 'Bluray')
-
Preferred Stream Expressions: A stream will only match the first expression in your list that it satisfies. The name of this single matching expression is available in the formatter via
{stream.seMatched}. This is useful for creating a strict priority order. -
Ranked Stream Expressions (RSE): A stream can match multiple ranked expressions, and each match contributes to a total
Stream Expression Score. All names from all matching expressions are collected in an array, available in the formatter via{stream.rseMatched}. This allows for more flexible and powerful scoring logic. See Scored Sorting for more details.
-
negate(streamsToExclude: ParsedStream[], originalStreamList: ParsedStream[])-
Purpose: Returns a new list of streams from
originalStreamListthat are NOT present instreamsToExclude. -
Parameters:
-
streamsToExclude: An array of streams to exclude. -
originalStreamList: The complete array of streams to filter from.
-
- Returns: An array of stream objects.
-
Example:
negate(quality(streams, 'CAM', 'TS'), streams)returns all streams except for CAM and TS quality.
-
Purpose: Returns a new list of streams from
-
merge(streamArrays: ParsedStream[]...)- Purpose: Combines multiple arrays of streams into a single array, removing any duplicate streams.
-
Parameters:
-
streamArrays: Two or more arrays of stream objects.
-
- Returns: A single, merged array of stream objects.
-
Example:
merge(visualTag(streams, 'DV'), audioTag(streams, 'Atmos'))returns a single list of all streams that are either Dolby Vision or have Atmos audio.
-
slice(streams: ParsedStream[], start: number, end: number)- Purpose: Returns a section ("slice") of the streams parameter between the given indexes. For both start and end, a negative index can be used to indicate an offset from the end of the array. For example, -2 refers to the second to last element of the array.
-
Parameters:
-
streams: An array of streams to take a slice from -
start: The beginning index of the specified portion of the array -
end: The end index of the specified portion of the array. This is exclusive of the element at the index 'end'. If end is undefined/ommitted, then the slice extends to the end of the array.
-
- Returns: An array of stream objects
-
Example:
slice(addon(streams, 'TorBox'), 0, 5)returns the first 5 streams from the TorBox addon.
-
values(streams: ParsedStream[], attribute: string)-
Purpose: Extracts a specific numeric property from a list of streams and returns them as an array of numbers. This is designed to be passed into Math Functions like
avg,max, orstddev. -
Parameters:
-
streams: An array of stream objects. -
attribute: The name of the property to extract.-
Accepted Values:
'bitrate','size','folderSize','age','duration','seeders','seScore','regexScore'.
-
Accepted Values:
-
- Returns: An array of numbers.
-
Example:
avg(values(streams, 'bitrate'))
-
Purpose: Extracts a specific numeric property from a list of streams and returns them as an array of numbers. This is designed to be passed into Math Functions like
-
indexer(streams: ParsedStream[], ...indexerNames: string[])- Purpose: Filters streams by the name of the originating indexer.
-
Parameters:
-
streams: An array of stream objects. -
indexerNames(strings): One or more indexer names (case-sensitive).
-
- Returns: An array of stream objects.
-
Example:
indexer(streams, '1337x', 'RARBG')
-
resolution(streams: ParsedStream[], ...resolutionNames: string[])- Purpose: Filters streams by video resolution.
-
Parameters:
-
streams: An array of stream objects. -
resolutionNames(strings): One or more resolution strings.-
Accepted Values:
'2160p','1440p','1080p','720p','576p','480p','360p','240p','144p','Unknown'
-
Accepted Values:
-
- Returns: An array of stream objects.
-
Example:
resolution(streams, '2160p', '1080p')
-
quality(streams: ParsedStream[], ...qualityNames: string[])- Purpose: Filters streams by a general quality tag.
-
Parameters:
-
streams: An array of stream objects. -
qualityNames(strings): One or more quality strings.-
Accepted Values:
'Bluray REMUX','Bluray','WEB-DL','WEBRip','HDRip','HC HD-Rip','DVDRip','HDTV','CAM','TS','TC','SCR','Unknown'
-
Accepted Values:
-
- Returns: An array of stream objects.
-
Example:
quality(streams, 'Bluray', 'WEB-DL')
-
encode(streams: ParsedStream[], ...encodeNames: string[])- Purpose: Filters streams by video encoding format.
-
Parameters:
-
streams: An array of stream objects. -
encodeNames(strings): One or more encoding formats (e.g.,'H.264','H.265','HEVC','x264','x265').
-
- Returns: An array of stream objects.
-
Example:
encode(streams, 'H.265', 'HEVC')
-
type(streams: ParsedStream[], ...streamTypes: string[])- Purpose: Filters streams by their type.
-
Parameters:
-
streams: An array of stream objects. -
streamTypes(strings): One or more stream types.-
Accepted Values:
'debrid','usenet','http','live','p2p','external','youtube'
-
Accepted Values:
-
- Returns: An array of stream objects.
-
Example:
type(streams, 'debrid', 'p2p')
-
visualTag(streams: ParsedStream[], ...visualTagNames: string[])- Purpose: Filters streams by visual tags (e.g., HDR, DV).
-
Parameters:
-
streams: An array of stream objects. -
visualTagNames(strings): One or more visual tags (e.g.,'HDR','DV','HDR10').
-
- Returns: An array of stream objects.
-
Example:
visualTag(streams, 'HDR', 'DV')
-
audioTag(streams: ParsedStream[], ...audioTagNames: string[])- Purpose: Filters streams by audio format tags.
-
Parameters:
-
streams: An array of stream objects. -
audioTagNames(strings): One or more audio tags (e.g.,'Atmos','DTS','AC3').
-
- Returns: An array of stream objects.
-
Example:
audioTag(streams, 'Atmos', 'DTS-HD MA')
-
audioChannels(streams: ParsedStream[], ...audioChannelsNames: string[])- Purpose: Filters streams by audio channel configuration.
-
Parameters:
-
streams: An array of stream objects. -
audioChannelsNames(strings): One or more audio channel configurations (e.g.,'5.1','7.1','2.0').
-
- Returns: An array of stream objects.
-
Example:
audioChannels(streams, '7.1', '5.1')
-
language(streams: ParsedStream[], ...languageNames: string[])- Purpose: Filters streams by language.
-
Parameters:
-
streams: An array of stream objects. -
languageNames(strings): One or more languages (e.g.,'English','Spanish','French').
-
- Returns: An array of stream objects.
-
Example:
language(streams, 'English')
-
seeders(streams: ParsedStream[], minSeeders?: number, maxSeeders?: number)- Purpose: Filters streams by torrent seeder count.
-
Parameters:
-
streams: An array of stream objects. -
minSeeders(optional number): Minimum seeders required. -
maxSeeders(optional number): Maximum seeders allowed.
-
- Returns: An array of stream objects.
-
Example (minimum):
seeders(streams, 10) -
Example (range):
seeders(streams, 5, 100)
-
age(streams: ParsedStream[], minAge?: number, maxAge?: number)- Purpose: Filters streams by their age.
-
Parameters:
-
streams: An array of stream objects. -
minAge(optional number): Minimum age in hours allowed. -
maxAge(optional number): Maximum age in hours allowed.
-
- Returns: An array of stream objects.
-
Example (minimum):
age(streams, 24000)- Selects streams which have an age of 1000 days or greater -
Example (range):
age(streams, 24, 12000)- Selects streams which have an age between 1 - 500 days
-
size(streams: ParsedStream[], minSize?: string | number, maxSize?: string | number)- Purpose: Filters streams by file size.
-
Parameters:
-
streams: An array of stream objects. -
minSize(optional): Minimum size (e.g.,'1GB','500MB', or bytes as a number). -
maxSize(optional): Maximum size (e.g.,'5GB','2TB', or bytes as a number).
-
- Returns: An array of stream objects.
-
Example:
size(streams, '1GB', '10GB')
-
bitrate(streams: ParsedStream[], minBitrate?: string | number, maxBitrate?: string | number)- Purpose: Filters streams by bitrate range.
-
Parameters:
-
streams: An array of stream objects. -
minBitrate(optional): Minimum bitrate (e.g.,'5000kbps','5Mbps', or bits per second as a number). -
maxBitrate(optional): Maximum bitrate (e. g.,'20000kbps','20Mbps', or bits per second as a number).
-
- Returns: An array of stream objects.
- Note: You must provide at least one bitrate boundary (min or max).
-
Example (minimum):
bitrate(streams, '5Mbps') -
Example (range):
bitrate(streams, '1000kbps', '10000kbps')
-
service(streams: ParsedStream[], ...serviceNames: string[])- Purpose: Filters streams by a specific Debrid service.
-
Parameters:
-
streams: An array of stream objects. -
serviceNames(strings): One or more Debrid service identifiers.-
Accepted Values:
'realdebrid','debridlink','alldebrid','torbox','pikpak','seedr','offcloud','premiumize','easynews','easydebrid'
-
Accepted Values:
-
- Returns: An array of stream objects.
-
Example:
service(streams, 'realdebrid', 'premiumize')
-
cached(streams: ParsedStream[])- Purpose: Filters for streams that are marked as cached by a Debrid service.
-
Parameters:
-
streams: An array of stream objects.
-
- Returns: An array of stream objects.
-
Example:
cached(streams)
-
uncached(streams: ParsedStream[])- Purpose: Filters for streams that are not marked as cached.
-
Parameters:
-
streams: An array of stream objects.
-
- Returns: An array of stream objects.
-
Example:
uncached(streams)
-
releaseGroup(streams: ParsedStream[], ...releaseGroupNames: string[])- Purpose: Filters streams by the release group.
-
Parameters:
-
streams: An array of stream objects. -
releaseGroupNames(strings, optional): Zero or more release group names (case-sensitive). Not providing this will select streams with any release group.
-
- Returns: An array of stream objects.
-
Example:
releaseGroup(streams, 'FLUX', 'RARBG')
-
seasonPack(streams: ParsedStream[], mode: 'seasonPack' | 'onlySeasons' = 'onlySeasons')-
Purpose: Filters for streams that are identified as being part of a season pack. The behavior depends on the selected
mode. -
Parameters:
-
streams: An array of stream objects. -
mode(string, optional): The filtering mode. Defaults to'onlySeasons'.-
'seasonPack': Checks if the stream originates from a season pack torrent. This is true even if a specific file/episode is selected from within that pack (e.g., folder isShow.S02and file isShow.S02E01). This mode looks at both the torrent's title (folder name) and the file name. -
'onlySeasons': Checks if the stream's title only contains season information and no episode information (e.g., a title likeShow.S02.1080p). This is useful for identifying and potentially filtering out ambiguous season pack results where a specific file isn't referenced, as it's unclear which episode will play or if the pack is complete.
-
-
- Returns: An array of stream objects.
-
Example (find all streams from packs):
seasonPack(streams, 'seasonPack') -
Example (find ambiguous packs):
seasonPack(streams, 'onlySeasons')
-
Purpose: Filters for streams that are identified as being part of a season pack. The behavior depends on the selected
-
addon(streams: ParsedStream[], ...addonNames: string[])- Purpose: Filters streams by the addon name that provided it.
-
Parameters:
-
streams: An array of stream objects. -
addonNames(strings): One or more addon names (case-sensitive).
-
- Returns: An array of stream objects.
-
Example:
addon(streams, 'Torrentio', 'Knightcrawler')
-
library(streams: ParsedStream[])- Purpose: Filters for streams marked as being from a personal library.
-
Parameters:
-
streams: An array of stream objects.
-
- Returns: An array of stream objects.
-
Example:
library(streams)
-
message(streams: ParsedStream[], mode: 'exact' | 'includes', ...messages: string[])-
Purpose: Filters streams by their
messageproperty. -
Parameters:
-
streams: An array of stream objects. -
mode:'exact'for a perfect match or'includes'to check if the message contains the string. -
messages(strings): One or more message strings to check for.
-
- Returns: An array of stream objects.
-
Example (exact match):
message(streams, 'exact', 'Test message') -
Example (contains):
message(streams, 'includes', 'Test')
-
Purpose: Filters streams by their
-
seadex(streams: ParsedStream[], type?: 'best' | 'all')- Purpose: Filters for streams marked as a SeaDex stream. **Only shows once the SeaDex integration in Filters > Miscellaneous is enabled)
-
Parameters:
-
streams: An array of stream objects -
type: An optional type of SeaDex streams to filter by.bestgives only SeaDex "Best" streams, and leaving it blank, or set toallgives all SeaDex matched streams, regardless of type.
-
- Returns: Am array of stream objects**
-
Example:
seadex(streams, 'best')
-
regexMatched(streams: ParsedStream[], ...regexFilterNames: string[])- Purpose: Filters for streams that have matched one of your configured preferred or ranked regex filters.
-
Parameters:
-
streams: An array of stream objects. -
regexFilterNames(optional strings): If provided, returns streams that matched any of the specific Regex Filters by name. If omitted, returns streams that matched any Regex Filter.
-
- Returns: An array of stream objects.
-
Example (any match):
regexMatched(streams) -
Example (specific match):
regexMatched(streams, 'MyHighQualityFilter', 'MyOtherFilter') -
NOTE: **This function will not work in
Included Stream Expressionsas Regex matches are computed after filtering has already occurred (otherwise regex would be computed on potentially thousands of streams unnecessarily)
-
regexMatchedInRange(streams: ParsedStream[], min: number, max: number)- Purpose: Filters for streams where the matched Regex Filter's index is within a specified range.
-
Parameters:
-
streams: An array of stream objects. -
min(number): The minimum index (inclusive). -
max(number): The maximum index (inclusive).
-
- Returns: An array of stream objects.
-
Example:
regexMatchedInRange(streams, 0, 5) -
NOTE: **This function will not work in
Included Stream Expressionsas Regex matches are computed after filtering has already occurred (otherwise regex would be computed on potentially thousands of streams unnecessarily)
-
streamExpressionScore(streams: ParsedStream[], minScore?: number, maxScore?: number)- Purpose: Filters streams based on their score from Ranked Stream Expressions.
-
Parameters:
-
streams: An array of stream objects. -
minScore(optional number): The minimum score (inclusive). -
maxScore(optional number): The maximum score (inclusive).
-
- Returns: An array of stream objects.
-
Example:
streamExpressionScore(streams, 100, 200) -
NOTE: **This function will not work in
Included Stream Expressionsas stream expression matches are computed after filtering has already occurred (otherwise your expression would be computed on potentially thousands of streams unnecessarily)
-
regexScore(streams: ParsedStream[], minScore?: number, maxScore?: number)- Purpose: Filters streams based on their score from Ranked Regexes.
-
Parameters:
-
streams: An array of stream objects. -
minScore(optional number): The minimum score (inclusive). -
maxScore(optional number): The maximum score (inclusive).
-
- Returns: An array of stream objects.
-
Example:
regexScore(streams, 50) -
NOTE: **This function will not work in
Included Stream Expressionsas regex matches are computed after filtering has already occurred (otherwise your regex would be computed on potentially thousands of streams unnecessarily)
-
passthrough(streams: ParsedStream[], ...stages: string[])-
Purpose: Flags streams to bypass specific processing stages in the pipeline. Only takes effect when used within
Included Stream Expressions(ISE). While any stream selected via an ISE is already selected to not be filtered out, by default it only bypasses normal filters and not stages like deduplication, result limiting etc. Wrapping your ISE with this function allows you to expand the stages that the streams selected by the ISE will bypass. -
Parameters:
-
streams: An array of stream objects. -
stages(optional strings): One or more stage names to skip. If no stages are provided, it passes through all stages.-
Accepted Values:
filter,dedup,limit,excluded,required,title,year,episode,digitalRelease,language
-
Accepted Values:
-
- Returns: An array of stream objects (the same list, but with passthrough flags applied).
-
Example:
passthrough(streams, 'filters')
-
Purpose: Flags streams to bypass specific processing stages in the pipeline. Only takes effect when used within
These functions perform statistical calculations on lists of numbers. They are most commonly used in combination with the values() function to analyse properties of your stream list (e.g., finding the average bitrate or the median file size).
Note: Most math functions accept input in two ways:
-
As an array:
avg(values(streams, 'bitrate')) -
As individual arguments:
avg(1, 2, 3, 4)
-
count(arr: any[])-
Purpose: Returns the total number of items in the provided
arrarray. Primarily used in Group Conditions. -
Parameters:
-
arr: An array of items (e.g.,previousStreams,totalStreams, or the result of another filter function).
-
- Returns: A number.
-
Example (Group Condition):
count(previousStreams) < 5
-
Purpose: Returns the total number of items in the provided
-
max(numbers: number[] | ...number)- Purpose: Returns the largest number in the list.
- Returns: A number.
-
Example:
max(values(streams, 'bitrate'))
-
min(numbers: number[] | ...number)- Purpose: Returns the smallest number in the list.
- Returns: A number.
-
Example:
min(values(streams, 'size'))
-
avg(numbers: number[] | ...number)-
Alias:
mean - Purpose: Calculates the arithmetic mean (average) of the numbers.
- Returns: A number.
-
Example:
avg(values(streams, 'bitrate'))
-
Alias:
-
sum(numbers: number[] | ...number)- Purpose: Adds all the numbers together.
- Returns: A number.
-
Example:
sum(values(streams, 'size'))
-
median(numbers: number[] | ...number)-
Alias:
q2 - Purpose: Finds the middle value separating the higher half from the lower half of the data.
- Returns: A number.
-
Example:
median(values(streams, 'bitrate'))
-
Alias:
-
mode(numbers: number[] | ...number)- Purpose: Finds the most frequently occurring value in the list.
- Returns: A number.
-
Example:
mode(values(streams, 'resolution'))
-
range(numbers: number[] | ...number)-
Purpose: Calculates the difference between the largest and smallest values (
max - min). - Returns: A number.
-
Example:
range(values(streams, 'bitrate'))
-
Purpose: Calculates the difference between the largest and smallest values (
-
variance(numbers: number[] | ...number)- Purpose: Measures how far a set of numbers is spread out from their average value.
- Returns: A number.
-
Example:
variance(values(streams, 'bitrate'))
-
stddev(numbers: number[] | ...number)- Purpose: Calculates the standard deviation (the square root of the variance). Useful for identifying outliers.
- Returns: A number.
-
Example:
stddev(values(streams, 'bitrate'))
-
percentile(numbers: number[], p: number)- Purpose: Calculates the value below which a given percentage of observations falls.
-
Parameters:
-
numbers: An array of numbers. -
p: The percentile (0-100).
-
- Returns: A number.
-
Example:
percentile(values(streams, 'size'), 95)(The size that is larger than 95% of other streams).
-
q1(numbers: number[] | ...number)- Purpose: Calculates the First Quartile (25th percentile).
- Returns: A number.
-
Example:
q1(values(streams, 'bitrate'))
-
q3(numbers: number[] | ...number)- Purpose: Calculates the Third Quartile (75th percentile).
- Returns: A number.
-
Example:
q3(values(streams, 'bitrate'))
-
iqr(numbers: number[] | ...number)-
Purpose: Calculates the Interquartile Range (
q3 - q1). Represents the middle 50% of the data. - Returns: A number.
-
Example:
iqr(values(streams, 'bitrate'))
-
Purpose: Calculates the Interquartile Range (
-
skewness(numbers: number[] | ...number)-
Purpose: Measures the asymmetry of the data distribution.
- Positive value: Tail is on the right (mostly low values, few high outliers).
- Negative value: Tail is on the left (mostly high values, few low outliers).
- Returns: A number.
-
Example:
skewness(values(streams, 'bitrate'))
-
Purpose: Measures the asymmetry of the data distribution.
-
kurtosis(numbers: number[] | ...number)- Purpose: Measures the "tailedness" of the distribution (frequency of extreme outliers).
- Returns: A number.
-
Example:
kurtosis(values(streams, 'bitrate'))