Skip to content

Add a segmentRequestHeaders option for DASH segment requests - #1881

Open
TomaszOszczepalski wants to merge 2 commits into
canalplus:devfrom
TomaszOszczepalski:feature/dash-segment-request-headers
Open

Add a segmentRequestHeaders option for DASH segment requests#1881
TomaszOszczepalski wants to merge 2 commits into
canalplus:devfrom
TomaszOszczepalski:feature/dash-segment-request-headers

Conversation

@TomaszOszczepalski

Copy link
Copy Markdown

Why

Some CDNs require an authorization header on audio and video segment
requests, while the Manifest request should remain unchanged.

A custom segmentLoader cannot handle this in low-latency mode because
RxPlayer intentionally uses its internal chunked fetch implementation when
lowLatencyMode is enabled.

What changed

This adds an optional segmentRequestHeaders property to loadVideo.

The configured headers are merged into built-in DASH requests for:

  • audio and video initialization segments
  • regular audio and video media segments
  • chunked low-latency audio and video media segments

The headers are not added to:

  • Manifest requests
  • license requests
  • text-track requests
  • thumbnail requests

RxPlayer's internally generated CMCD and Range headers remain authoritative.

The option is optional, so existing behavior is unchanged when it is absent.

Example

player.loadVideo({
  url: manifestUrl,
  transport: "dash",
  lowLatencyMode: true,
  segmentRequestHeaders: {
    "X-Content-Token": token,
  },
});

@peaBerberian

peaBerberian commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Hi,

Thanks for the proposal, I agree that this is a real use case, yet in that scenario I would prefer relying on the segmentLoader API solution to not add another API which may have edge cases (e.g. if a request doesn't go through HTTP, if both segmentRequestHeaders and a segmentLoader is present, if there are several CDN available etc.).

It's true we don't call it for low-latency content, I think ideally we should focus on that part and update the API to also answer your usage.

Why low-latency contents do not trigger the segmentLoader for now

Until now we didn't call it in that because some low-latency contents rely on progressively streaming the segment's body as the request is pending. This is unlike segment requests in non-low-latency contents where it is communicated to the rx-player once the HTTP request is complete (e.g. awaiting a fetch's response.arrayBuffer()). This is to be able to decode sub-parts of the segments before the whole segment is loaded.

So the current segmentLoader would break that usage here as it just proposes callbacks.resolve({ ... }) to communicate data (there's callbacks.progress({ ... }) but it's only intended for metrics right now).

Evolutions we could do on it

But I think there's nothing really blocking us, the question is only how to make the API easy-to-follow.
It could be another callback (onChunk?) or something like that.

Then the application would have to do the data streaming itself, something like:

const reader = response.body.getReader();
let size = 0;
return readBufferAndSendEvents();
async function readBufferAndSendEvents(): Promise<IFetchedStreamComplete> {
const data = await reader.read();


Alternatively to make it easier to do, we could also just add arguments to callbacks.fallback called from a segmentLoader, e.g. callbacks.fallback({ headers: { ... } }).

This would make it more similar to dash.js's RequestInterceptor or shaka's RequestFilter.

This solution has the advantage to be easy-to-understand for an application, but it does impose on the RxPlayer some supplementary restrictions (e.g. using HTTP, having some header ordering rules etc.).


Do you have thoughts on this?

I will personally explore both onChunk but also something like fallback({ headers: { (potentially having both) to simplify the work of applications. The main issue with the latter is to make sure it is free of edge cases and won't bother us even in future evolutions.

@TomaszOszczepalski

Copy link
Copy Markdown
Author

Hi,

Thanks for the detailed explanation. I agree that keeping segmentLoader as the extension point for segment loading and request customization is preferable to introducing a separate segmentRequestHeaders option.

I see fallback({ headers }) and an onChunk API as solutions to two separate problems: the first allows an application to customize RxPlayer’s internal request while retaining its default loader, whereas the second allows a fully custom segment loader to deliver segment data incrementally before the complete request has finished.

For our authorization use case, fallback({ headers }) would be sufficient. It would allow us to provide the required CDN headers while RxPlayer retains responsibility for its regular loading behaviour, including progressive low-latency loading where supported, retries, CDN selection, byte-range handling, cancellation and metrics.

From the RxPlayer API perspective, I think it would be important that:

  • segmentLoader is invoked for both initialization and media segments in low-latency mode.
  • fallback({ headers }) delegates to the same internal loader that RxPlayer would have used if no custom segmentLoader had been configured. This would preserve progressive loading where RxPlayer normally supports it.
  • Supplied headers are merged deterministically and case-insensitively with RxPlayer-generated headers such as Range and CMCD, with clearly documented collision precedence.
  • The supplied headers are applied to every underlying HTTP request needed to load the segment, including multiple range requests that may be required for an initialization segment.

An onChunk API could also support fully custom streaming loaders. Its contract should clarify what each chunk represents and how the loader signals completion, because network chunks do not necessarily align with decodable media chunks.

I can adapt our bridge to the resulting API, so my main concern is finding a solution that remains coherent and robust for RxPlayer itself. From that perspective, extending segmentLoader with these two independent capabilities sounds like a better direction than the static option I originally proposed.

@peaBerberian

peaBerberian commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

I see fallback({ headers }) and an onChunk API as solutions to two separate problems: the first allows an application to customize RxPlayer’s internal request while retaining its default loader, whereas the second allows a fully custom segment loader to deliver segment data incrementally before the complete request has finished.

Yes, I just think that if low-latency is a goal here, we have to also call the segmentLoader in lowLatencyMode which means we probably want a mechanism to let applications be able to progressively communicate data, that's why I went for "potentially both".

An onChunk API could also support fully custom streaming loaders. Its contract should clarify what each chunk represents and how the loader signals completion, because network chunks do not necessarily align with decodable media chunks.

Of course. In our case the RxPlayer knows how to detect decodable subparts so the application could just be streaming the chunk data as it becomes available to it.
For completion, I plan for now to keep resolve: its semantics wouldn't change (to call when the segment is loaded).

@peaBerberian

Copy link
Copy Markdown
Collaborator

I've attempted something: #1883

For your case it would be doing something like:

segmentLoader(_segmentInfo, callbacks) {
  callbacks.fallback({ headers: { authorization: "foo" } })
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants