Aller au contenu

Resolution profiles

Ce contenu n’est pas encore disponible dans votre langue.

A master playlist lists several rungs — say 1080p, 720p and 480p — and an ordinary player picks between them by measuring its own throughput. When a headend consumes that playlist, no such adaptation is meaningful: the stream is going to a fixed multicast group serving a fixed set of televisions, at whatever quality the first rung the engine likes happens to be.

In practice the origin’s ordering decides, and origins list their best rung first. The routine outcome is a 1080p rung being pulled continuously to feed standard-definition panels in guest rooms. It is not a small waste: it is several times the bandwidth for a picture nobody can see the benefit of, multiplied by every channel on the appliance, on precisely the constrained uplinks where it hurts most.

Setting a resolution profile on the channel takes that decision away from the origin.

ProfileTarget heightAlso accepted
4k2160uhd, 2160p
fullhd10801080p
hd720720p
sd576576p, 480p
mobile360360p, low
(empty)Default. The master playlist is handed to the engine unchanged.

Empty is the default and is what every pre-existing channel has. That matters: adding this feature changed nothing about any channel already configured. A profile is something you opt into per channel, not a behaviour that arrived and started reinterpreting your playlists.

Closest height wins. Ties go to the higher bitrate.

Castmux reads the master playlist, takes the declared RESOLUTION of each variant, and picks the one whose height is nearest the profile’s target. If two variants are equally distant, the one with the higher advertised bandwidth is chosen.

Deliberately, this is not exact-match-or-fail. Origins publish whatever ladder they please, and 576p in particular is uncommon in the wild — most publish 480p instead. A channel that refuses to start because nobody serves exactly 576 lines is strictly worse than a channel that streams 480p and tells you it did. Failing to find a perfect match is not an error condition; it is the normal case.

The channel card header shows both halves of the decision: what you asked for, and what the origin actually had.

BadgeMeaning
HD720p was requested and a 720p rung exists. Exact match.
4K (1080p)4K was requested; the best the origin offers is 1080p, and that is what is being streamed. Shown in amber.
SD (480p)576 lines were requested; 480p was the closest rung. Shown in amber.

Amber is information, not a fault. It says the profile could not be satisfied exactly and tells you what was used instead. A channel showing an amber badge is working correctly. Treating amber as an alarm condition produces a wall of false positives on any realistic set of origins, because most ladders will not line up exactly with any fixed set of profile heights.

Where a lookup could not be completed at all, the badge carries the reason in its tooltip. That is the first place to look when a channel is not streaming the rung you expected.

The substitution is per start, never persisted

Section titled “The substitution is per start, never persisted”

The configuration always holds the master playlist URL you entered. When a channel starts, Castmux resolves the variant and hands that URL to the engine for that run only. Nothing is written back.

This is worth being firm about, because writing the variant URL into the configuration looks like an obvious optimisation and is a trap for two separate reasons:

  • It would pin the channel to a rung the origin may withdraw. Ladders change. An origin that drops its 480p rung next month leaves a pinned channel fetching a URL that now returns 404, forever, with no way back to the master playlist short of an operator re-typing it.
  • It would be indistinguishable from an operator’s own choice. Once a variant URL is sitting in the configuration file, nothing records whether a human put it there deliberately or the software substituted it. Any later attempt to re-resolve would risk overwriting a deliberate decision.

Resolving on every start costs one cached playlist read and keeps the channel following the origin’s ladder wherever it goes.

Profile resolution sits on the streaming path, so it degrades to the configured behaviour rather than to a black screen. All of the following leave the configured URL alone, log the reason, and start the channel:

  • The origin is unreachable or the fetch times out.
  • The URL turns out to be a media playlist, not a master — there is no ladder to choose from.
  • The master carries no RESOLUTION attributes, so no height can be compared.
  • The playlist is malformed in any way that prevents variants being read.

In each case the channel streams exactly as it would have without a profile set. The reason is not silent: it is logged, and it is carried in the badge tooltip so you can see from the dashboard why a profile is not being applied.

Results are cached — roughly ten minutes on success, one minute after an error — and refreshed in the background. Rendering a page or answering a status poll reads the cache and schedules a refresh if the entry is stale; it never waits. The only place that waits for a live lookup is a completely cold engine start, where there is nothing to stream from anyway.

The arithmetic is the reason. Twenty-five channels, each with an eight-second fetch timeout, on every page load and every poll, is an interface that hangs for minutes whenever an origin is slow — and origins are slow at exactly the moments an operator is trying to look at the dashboard. The shorter cache lifetime after an error exists so a temporarily broken origin is retried promptly rather than being written off for ten minutes.

Both of these exist because the naive implementation puts a broken channel on air while reporting success.

Many ladders include an audio-only rendition. It carries no RESOLUTION attribute, so its height reads as zero, and a naive closest-height comparison against the mobile profile’s target of 360 makes it the winner over every real video rung. The channel then starts, reports healthy, produces packets, and puts a playlist with no video on air.

Variants without a RESOLUTION attribute are therefore excluded from selection entirely.

If the master declares audio with #EXT-X-MEDIA:TYPE=AUDIO and that declaration has its own URI=, the audio is not inside the video segments. It is a separate rendition the client is expected to fetch alongside the video and combine itself.

Selecting one video variant from such a ladder would hand the engine a playlist containing video and nothing else. The result is silent video on air — a channel that looks perfect on every meter and has no sound.

So Castmux refuses. A channel whose master advertises a demuxed audio ladder keeps its master URL, the master’s own audio handling continues to apply, and the badge states the reason. There is no partial workaround: an engine given one URL cannot re-join two renditions, and making it do so needs a second input and explicit stream mapping, which changes the shape of the channel entirely.

Resolution profiles apply to HLS sources and nothing else. SRT and RTMP deliver a single fixed encode with no ladder to choose from, so there is nothing to look up.

This is not merely “the setting is ignored”. No HTTP request is made at all for a non-HLS channel. That distinction matters because the failure mode when it is got wrong is unpleasant and quiet: firing an HTTP GET at an srt:// URL on every page render and every status poll, for every SRT channel on the appliance, producing latency and log noise that appears to come from nowhere.

An origin publishes this ladder:

#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=5200000,RESOLUTION=1920x1080
v1080.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2800000,RESOLUTION=1280x720
v720.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1400000,RESOLUTION=854x480
v480.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=96000,CODECS="mp4a.40.2"
audio.m3u8

The channel is set to resolution_profile: sd, which targets 576 lines.

  1. The audio-only rendition is discarded first: it has no RESOLUTION attribute. Without that step it would score a height of zero and win outright on the mobile profile.
  2. Distances from 576 are computed for the remainder: 1080p is 504 away, 720p is 144 away, 480p is 96 away.
  3. 480p is closest, so v480.m3u8 is handed to the engine for this run. The configuration still holds the master URL.

The card header reads SD (480p) in amber: 576 was requested, 480p was the nearest thing the origin had, and the channel is streaming it correctly.