Members

(static, constant) BUFFER_SAFETY_FACTOR

Percentage of buffer available for segment data (leaves room for metadata/overhead). Combined with BUFFER_SEGMENT_COUNT=2, each segment is allocated 37.5% of the total buffer.

Default Value
  • 0.75

(static, constant) BUFFER_SEGMENT_COUNT

Number of segments the buffer must hold simultaneously. Roku's player buffers multiple segments for look-ahead playback. The buffer must fit at least this many segments concurrently.

Default Value
  • 2

(static, constant) DEVICE_BUFFER_SIZE_LOW_MEMORY

Video buffer size for 512MB RAM devices (from error logs: max_wrap_allocation)

Default Value
  • 20553728

(static, constant) DEVICE_BUFFER_SIZE_NORMAL

Video buffer size for all other devices (from error logs: entire buffer size)

Default Value
  • 31616000

(static, constant) MAX_HLS_PLAYLIST_ENTRIES

Max HLS playlist entries before Roku's MPR rejects the playlist as too large. Exact Roku limit is undocumented - this is a conservative estimate. Tune this value based on testing if "mpr playlist file is too large" errors occur.

Default Value
  • 5000

Methods

(static) GetBitRateLimit(codec) → {object}

Parameters:
NameTypeDescription
codecstring
Returns:
Type: 
object

(static) GetDirectPlayProfiles() → {object}

Returns:
Type: 
object

(static) applyResolutionCapToProfile(codecProfile, maxHeight, maxWidth, isRequiredopt) → {void}

Apply a paired Height + Width resolution cap to a codec profile's Conditions. No-ops if a Height condition at or below maxHeight already exists. When the existing cap is wider than maxHeight, replaces it (avoids duplicate conditions that can confuse the server's condition evaluation order).

Parameters:
NameTypeAttributesDefaultDescription
codecProfileobject

{object} - The codec profile AA containing a Conditions array

maxHeightinteger

{integer} - The max height to cap at (e.g. 1080)

maxWidthinteger

{integer} - The max width to cap at (e.g. 1920)

isRequiredboolean<optional>
false

{boolean} - Whether the condition is required for direct play

Returns:
Type: 
void

(static) buildVideoTranscodingAudioCodecsForContainer(container, allSurroundCodecs, preferredCodec, decodableStereoFallbacks) → {object}

Build the AudioCodec list for a single HLS video transcoding profile container. Pure function — all inputs explicit so the full hardware matrix can be unit-tested without mocking roDeviceInfo or m.global.

Ordering rules (leftmost is the server's first-choice transcode target):

  1. AAC (universal Roku decode, in both ts and mp4 server target sets)
  2. User's preferredCodec if set, device-passthru-supported, and server-target
  3. Other surround codecs in priority order (eac3 > ac3 > dts > truehd), each gated by device passthru AND server-target for this container
  4. Stereo fallback codecs the device decodes (mp3 > flac > alac > opus), each gated by server-target for this container

at 2ch in this container (subset of mp3/flac/alac/opus)

Parameters:
NameTypeDescription
containerstring

"ts" or "mp4"

allSurroundCodecsobject

array of surround codec names with device passthrough

preferredCodecstring

user's playbackPreferredMultichannelCodec value, or "auto" / ""

decodableStereoFallbacksobject

stereo fallback codec names the device can decode

Returns:

array of codec name strings in preference order

Type: 
object

(static) calculateOptimalTranscodingParams(bitrateBps, videoDurationSeconds, bufferSizeBytes) → {object}

Calculates optimal HLS transcoding parameters to prevent buffer overflow and playlist errors.

Solves two constraints simultaneously:

  1. Buffer: (bitrate × segmentDuration) / 8 ≤ bufferSize × BUFFER_SAFETY_FACTOR
  2. Playlist: videoDuration / segmentDuration ≤ MAX_HLS_PLAYLIST_ENTRIES

Targets 6s segments for optimal startup and seek performance. Goes shorter if the buffer forces it, or longer (up to 9s) only when the playlist constraint requires it. Only reduces bitrate as a last resort when no segment length satisfies both constraints.

segmentLength: optimal HLS segment duration (1-9 seconds) maxBitrate: max streaming bitrate in bps (0 = no reduction needed)

Parameters:
NameTypeDescription
bitrateBpsLongInteger

Source media total bitrate in bits per second

videoDurationSecondsInteger

Video duration in seconds

bufferSizeBytesLongInteger

Device video buffer size in bytes

Returns:

{ segmentLength: Integer, maxBitrate: LongInteger }

Type: 
object

(static) canDeviceDecodeCodec(codec, channelCount) → {boolean}

Test if device can decode a specific codec at a given channel count This is a public wrapper for getActualCodecSupport that can be called from other files Returns true if the Roku can decode this codec at this channel count

Parameters:
NameTypeDescription
codecstring
channelCountinteger
Returns:
Type: 
boolean

(static) canPlay4k() → {boolean}

does this roku device support playing 4k video?

Returns:
Type: 
boolean

(static) convertHevcLevelToString(level) → {string}

Convert HEVC level from float format (e.g., 5.0, 5.1, 4.1) to Jellyfin string format HEVC levels are multiplied by 30 to convert to the integer representation Examples: 5.0 → "150", 5.1 → "153", 4.1 → "123"

Parameters:
NameTypeDescription
levelfloat
Returns:
Type: 
string

(static) filterCodecProfileConditions(codecProfiles, propertiesToRemove) → {object}

filterCodecProfileConditions: Removes conditions with specified properties from codec profiles Used for version compatibility - e.g., removing VideoRangeType for pre-10.9 servers

Parameters:
NameTypeDescription
codecProfilesroArray

Array of codec profile objects

propertiesToRemoveroArray

Array of property names to filter out

Returns:

Filtered codec profiles

Type: 
object

(static) getActualCodecSupport(codec, channelCount, di) → {boolean}

Override false positives from Roku API using known hardware limits Returns true if codec can actually decode/passthrough the specified channel count For surround codecs (>2ch), prioritizes PassThru check to detect receiver support Accepts Jellyfin codec names (e.g. "truehd") and translates to Roku API names internally

Parameters:
NameTypeDescription
codecstring
channelCountinteger
diobject
Returns:
Type: 
boolean

(static) getAnamorphicCondition() → {object}

Returns an IsAnamorphic codec profile condition when the user has enabled forced transcoding of anamorphic video. Returns empty object when disabled.

Returns:
  • Condition AA or empty AA
Type: 
object

(static) getCodecProfiles() → {object}

Returns:
Type: 
object

(static) getContainerProfiles() → {object}

Returns:
Type: 
object

(static) getDeviceBufferSize() → {longinteger}

Returns the device's video buffer size in bytes. 512MB RAM devices have a smaller buffer than all other devices.

Returns:

Buffer size in bytes

Type: 
longinteger

(static) getDeviceCapabilities() → {object}

Returns the Device Capabilities for Roku. Also prints out the device profile for debugging

Returns:
Type: 
object

(static) getDeviceProfile() → {object}

Returns:
Type: 
object

(static) getDeviceProfileV1(globalDevice) → {object}

V1 DeviceProfile for Jellyfin 10.7.x - 10.8.x servers Uses the full DeviceProfile format with Identification object

Parameters:
NameTypeDescription
globalDeviceobject
Returns:
Type: 
object

(static) getDeviceProfileV2(globalDevice) → {object}

V2 DeviceProfile for Jellyfin 10.9+ servers Uses the simplified DeviceProfile format without Identification object

Parameters:
NameTypeDescription
globalDeviceobject
Returns:
Type: 
object

(static) getHlsTranscodeTargetsForContainer(container) → {object}

Mirror of Jellyfin server's _supportedHlsAudioCodecs* from MediaBrowser.Model/Dlna/StreamBuilder.cs. Codecs outside these per-container sets get silently stripped by the server's HLS-codec filter when building the TranscodingUrl, leaving an empty AudioCodec field that triggers the server's InferAudioCodec("m3u8") fallback chain (issue #573). Listing only codecs the server will actually use as HLS transcode targets keeps the profile honest and prevents the bug class at the construction site.

Parameters:
NameTypeDescription
containerstring
Returns:
Type: 
object

(static) getResolutionConditions(isRequiredopt) → {object}

Parameters:
NameTypeAttributesDefaultDescription
isRequiredboolean<optional>
false
Returns:
Type: 
object

(static) getSubtitleProfiles() → {object}

Returns:
Type: 
object

(static) getSupportedPassthruCodecs(di, channelCount) → {object}

Get list of surround codecs that support passthrough, returned as Jellyfin codec strings. Returns array in priority order: eac3, ac3, dts, truehd, dtshd

Two groups due to differing Roku API behaviour: Group 1 (ChCnt-aware): eac3, ac3, dts, mat — checked with ChCnt + PassThru: 1 Group 2 (ChCnt N/A): dtshd — checked with PassThru: 1 only

mat is the Roku API name for TrueHD/Dolby MAT; returned here as "truehd" (Jellyfin name). dtsx (DTS:X) is an extension of DTS-HD MA — covered by dtshd; not added separately.

Parameters:
NameTypeDescription
diobject
channelCountinteger
Returns:
Type: 
object

(static) getSupportedRemoteCommands() → {object}

GeneralCommand-type actions JellyRock can enact. This capability is a GeneralCommandType[] and Jellyfin deserializes it STRICTLY — any value outside the GeneralCommandType enum 400s the whole /Sessions/Capabilities/Full POST. So it must NOT contain PlaystateCommands (Pause/Stop/Seek/…) or PlayCommands: those transport verbs are governed by SupportsMediaControl:true, not advertised here.

Returns:
Type: 
object

(static) getTranscodingProfiles() → {object}

Returns:
Type: 
object

(static) isWithinH264HardwareCeiling(videoStream) → {boolean}

Checks whether a video stream's resolution is within the h264 hardware decoding ceiling (1080p / 1920x1080). Returns true for non-h264 codecs since they have higher ceilings handled elsewhere. Handles Height/Width fields arriving as strings or integers, and defaults to 0 (within ceiling) when metadata is missing.

Parameters:
NameTypeDescription
videoStreamobject

{object} - MediaStream object with codec, Height, Width

Returns:
  • true if within ceiling or not h264, false if exceeds ceiling
Type: 
boolean

(static) jellyfinToRokuCodecName(codec) → {string}

Translate Jellyfin codec names to Roku API codec names where they differ. Covers both audio and video codecs. "h264" → "mpeg4 avc" (Jellyfin uses "h264"; Roku API uses "mpeg4 avc" with a space) "truehd" → "mat" (TrueHD/Dolby MAT — "truehd" is unknown to the Roku API) "mpeg1video"→ "mpeg1" (Jellyfin uses "mpeg1video"; Roku API uses "mpeg1")

Parameters:
NameTypeDescription
codecstring
Returns:
Type: 
string

(static) removeDecimals(value) → {string}

Remove all decimals from a string

Parameters:
NameTypeDescription
valuestring
Returns:
Type: 
string

(static) updateProfileArray(profileArray, videoCodec, videoProfile, profileLevelopt) → {object}

Receives and returns an assArray of supported profiles and levels for each video codec

Parameters:
NameTypeAttributesDefaultDescription
profileArrayobject
videoCodecstring
videoProfilestring
profileLevelstring<optional>
""
Returns:
Type: 
object