Skip to content

UMP and decoding

Part of SABR in the extractor. YouTube wraps SABR responses in UMP (Ultra-Minimal Playback). UMP frames are not protobuf; the payload of most control parts is protobuf and is summarized or decoded by SabrResponseDecoder.

UMP framing

UmpReader reads a sequence of parts:

text
[type: UMP-varint][size: UMP-varint][payload: size bytes] ...

readPayloadsUntil(InputStream, consumer) reads one part at a time from the network. readAll(byte[]) parses an already-buffered body, which is useful for small responses and tests. A clean EOF at a part boundary ends the stream; truncated headers or payloads raise SabrProtocolException.

UMP varints choose their length from the high bits of the first byte:

First byteTotal bytesValue
0x00–0x7F1byte value
0x80–0xBF2(b0 & 0x3f) + 64·b1
0xC0–0xDF3(b0 & 0x1f) + 32·(b1 + 256·b2)
0xE0–0xEF4(b0 & 0x0f) + 16·(b1 + 256·(b2 + 256·b3))
0xF0–0xFF5next four bytes, little-endian

UmpReader.UmpPart exposes the type, size and payload. Public data access is defensive; the streaming decoder uses the raw array internally to avoid copying large media parts.

Part identifiers

SabrResponseDecoder recognizes these identifiers. Rich control messages are kept as summaries or raw bytes in YoutubeSabrResponse; they are not modeled as one Java class per part.

IDConstantCurrent handling
10–12ONESIE_*generic summary
20MEDIA_HEADERdecode SabrMediaHeader
21MEDIAcount bytes by header id
22MEDIA_ENDclose a header id
30–34config/live hintsgeneric summary
35NEXT_REQUEST_POLICYkeep raw policy and read backoff field 4
36–38ustreamer metadatageneric summary
42FORMAT_INITIALIZATION_METADATAdecode generated metadata
43SABR_REDIRECTkeep the redirect URL
44SABR_ERRORdecode type/code summary
45SABR_SEEKgeneric summary
46RELOAD_PLAYER_RESPONSEset reloadRequested
47–51playback/format controlsgeneric summary
52–56request controlsgeneric summary
57SABR_CONTEXT_UPDATEkeep raw context update
58STREAM_PROTECTION_STATUSdecode status and max retries
59–65context/cache/connection controlskeep summary; 65 is prewarm
66–67debug/snackbargeneric summary

Unknown identifiers are recorded in the bounded diagnostic summary. Malformed control parts are retained as bounded diagnostics so valid media in the same response is not discarded.

The decode paths

SabrResponseDecoder.decode(byte[]) parses all parts first and then dispatches them. The normal application path uses SabrStreamingResponseReader.read(InputStream, consumer, startConsumer, spool): it keeps control parts in memory and feeds MEDIA_HEADER, MEDIA, and MEDIA_END directly to SabrMediaSegmentCollector.Incremental. Completed segments are delivered as soon as their MEDIA_END arrives, so a large 4K body does not have to remain in the heap.

Both paths count media bytes by header id. YoutubeSabrResponse.getIntegrityIssues() then detects duplicate headers, missing media, length mismatches, missing ends, media without a header, and ends without a header. The session retries only the classified incomplete-media cases within its bounded limit.

The decoded response

YoutubeSabrResponse exposes the HTTP response code and content type, UMP parts, completed segments, initialization metadata, live metadata, context updates, redirect/error/reload flags, protection status, backoff, byte counters and bounded summaries. summarizeForDiagnostics() reports structure and sizes, not PO-token or cookie contents.

Next: Media, segments, and the index.