nx_yt_captions_lib.nx
buildroot/runtime/nx_yt_captions_lib.nx
about
nx_yt_captions_lib.nx -- the YouTube TIMED-TEXT (caption/transcript) path, composed on the estate's
proven InnerTube + sovereign-TLS stack. It does NOT duplicate nx_yt_innertube: it COMPOSES yt_innertube
(the ANDROID_VR /youtubei/v1/player POST that self-heals against key rotation) to obtain the player
response, reads the captionTracks[] baseUrl out of THAT SAME response, and fetches the timedtext body
with nx_https_fetch_follow (the shared gzip-decoding, redirect-following GET). Parsers turn json3 and
srv1/XML timedtext into rows `startMs \t durMs \t text`, entities decoded through nx_html_entities.
WHY A SIBLING LIB, NOT AN EDIT TO nx_yt_innertube: that lib's header declares its subject as the stream
path (streamingData.formats[].url); captions are a distinct output read from the same response, so this
stays a NEW file that imports it (blast radius: zero -- nothing that imports innertube is touched).
WHY THE WEB baseUrl DOES NOT WORK (measured 2026-09-18 from the NAS): the WEB captionTracks baseUrl
scraped from a watch page answers status=200 with an EMPTY body -- it is IP-locked (ip=0.0.0.0) and
requires a proof-of-origin (pot) token the WEB client mints via BotGuard. The ANDROID_VR client's
baseUrl carries no such requirement, which is the whole reason this composes yt_innertube.
license_tier: ORIGINAL No hw writes (Rule 26). LIB (no main).
dependencies 5 imports · 2 importers
imports: nx_syscalls.nxnx_yt_innertube.nxnx_media_state.nxnx_https_fetch_follow.nxnx_html_entities.nx
imported by: nx_yt_transcript.nxnx_yt_transcript_gate.nx
structs
| none |
consts
| 25 | const YTC_CERTDATA_CAP: i64 = 4194304 |
| 29 | const YTC_PLAYER_CAP: i64 = 8388608 |
| 33 | const YTC_BODY_CAP: i64 = 67108864 |
| 35 | const YTC_URL_CAP: i64 = 8192 |
| 242 | const YTC_VOS_UA: *u8 = "Mozilla/5.0 (Macintosh; Intel Mac OS X 15_7_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Safari/605.1.15" |
functions
| 38 | func ytc_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } |
| 39 | func ytc_catn(dst: *u8, o: i64, v: i64, cap: i64) -> i64 |
| 49 | func ytc_hexval(c: i64) -> i64 |
| 56 | func ytc_utf8_emit(dst: *u8, o: i64, cp0: i64, cap: i64, strip: i64) -> i64 |
| 69 | func ytc_copy_jsonstr(src: *u8, start: i64, slen: i64, dst: *u8, o0: i64, cap: i64, strip: i64, out_end: *i64) -> i64 |
| 115 | func ytc_named_eq(src: *u8, s: i64, len: i64, lit: *u8) -> i64 |
| 123 | func ytc_html_decode(src: *u8, s: i64, e: i64, dst: *u8, o0: i64, cap: i64, strip: i64) -> i64 |
| 166 | func ytc_ct_array(pj: *u8, jlen: i64, arr: *u8, cap: i64) -> i64 |
| 173 | func ytc_pick(arr: *u8, alen: i64, want: *u8, wlen: i64, out_url: *u8, ucap: i64, out_kind: *u8, kcap: i64) -> i64 |
| 215 | func ytc_langs(arr: *u8, alen: i64, out: *u8, cap: i64) -> i64 |
| 234 | func ytc_load_store() -> i64 |
| 237 | func ytc_cat(dst: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[o] = s[i]; o = o + 1; i = i + 1 } return o } |
| 243 | func ytc_vos_body(vid: *u8, vidlen: i64, vd: *u8, vdlen: i64, out: *u8, cap: i64) -> i64 |
| 253 | func ytc_vos_req(vd: *u8, vdlen: i64, body: *u8, bl: i64, out: *u8) -> i64 |
| 265 | func ytc_dechunk(raw: *u8, n: i64, out: *u8, cap: i64) -> i64 |
| 285 | func ytc_vos_post(vid: *u8, vidlen: i64, vd: *u8, vdlen: i64, store: *TrustStore, cr: *u8, pk: *u8, now: i64, out: *u8, cap: i64) -> i64 |
| 306 | func ytc_player(url: *u8, ulen: i64, store: *TrustStore, out: *u8, cap: i64) -> i64 |
| 323 | func ytc_fetch(url: *u8, store: *TrustStore, out: *u8, cap: i64, status: *i64) -> i64 |
| 329 | func ytc_classify_body(body: *u8, blen: i64) -> i64 |
| 338 | func ytc_after_colon(b: *u8, i0: i64, end: i64) -> i64 |
| 346 | func ytc_json3_to_tsv(body: *u8, blen: i64, out: *u8, cap: i64, out_nseg: *i64) -> i64 |
| 388 | func ytc_secs_to_ms(src: *u8, s: i64, e: i64) -> i64 |
| 397 | func ytc_xml_to_tsv(body: *u8, blen: i64, out: *u8, cap: i64, out_nseg: *i64) -> i64 |
| 431 | func ytc_tsv_nseg(tsv: *u8, len: i64) -> i64 { var n: i64 = 0; var i: i64 = 0; while i < len { if (tsv[i]&0xff) == 10 { n = n + 1 } i = i + 1 } return n } |
| 433 | func ytc_tsv_monotonic(tsv: *u8, len: i64) -> i64 |
| 446 | func ytc_norm_ws(src: *u8, slen: i64, dst: *u8, cap: i64) -> i64 |
| 460 | func ytc_row_text(tsv: *u8, len: i64, idx: i64, dst: *u8, cap: i64) -> i64 |