nx_media_signal.nx source
↩ module page · 115 lines · 7116 B
1// nx_media_signal.nx -- the INTELLIGENT, SITE-RESILIENT media-URL classifier + ranker. Per-site extractors
2// (yt-dlp model) break when a site updates because they hardcode "stream URL = JSON path X on site Y". This
3// keys off UNIVERSAL media signals that survive a site restructure: (a) EXTENSION (.m3u8/.mpd/.mp4/...),
4// (b) PATH pattern (/videoplayback, /master, /manifest, /hls/, /chunklist -- extension-LESS URLs like
5// YouTube's), (c) CDN HOST (googlevideo/cloudfront/akamai/...), (d) media tokens. Multi-signal + confidence-
6// scored + ranked. Combined with the 4-layer fallback (static harvest -> embedded-state -> JS-exec ->
7// multi-round), a site change that breaks ONE signal/layer still resolves via the others. Also smart-naming
8// title extraction (og:title / <title> / "title": -- any of 3 universal signals). license_tier: ORIGINAL
9import "nx_syscalls.nx"
10
11const XT_NONE: i64 = 0
12const XT_AUDIO: i64 = 1
13const XT_SEGMENT: i64 = 2
14const XT_DASH: i64 = 3
15const XT_DIRECT: i64 = 5 // progressive mp4/webm = directly playable in a native HTML5 <video> -> HIGHEST on the playback path
16const XT_HLS: i64 = 4 // a raw .m3u8 manifest can't play in native <video> yet -> rank BELOW progressive (the HLS assembler will target XT_HLS explicitly)
17
18func xt_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
19func xt_find(hay: *u8, hl: i64, needle: *u8, nl: i64, from: i64) -> i64 {
20 if nl == 0 { return from }
21 var i: i64 = from; let last: i64 = hl - nl
22 while i <= last { var j: i64=0; var m: i64=1; while j<nl { if (hay[i+j]&0xff)!=(needle[j]&0xff) { m=0; j=nl } else { j=j+1 } } if m==1 { return i } i=i+1 }
23 return 0 - 1
24}
25func xt_has(hay: *u8, hl: i64, needle: *u8) -> i64 { if xt_find(hay, hl, needle, xt_slen(needle), 0) >= 0 { return 1 } return 0 }
26// a known media-CDN host? (host signal -- extension/path-independent)
27func xt_is_cdn(u: *u8, ul: i64) -> i64 {
28 if xt_has(u, ul, "googlevideo.com" as *u8) == 1 { return 1 }
29 if xt_has(u, ul, ".cloudfront.net" as *u8) == 1 { return 1 }
30 if xt_has(u, ul, "akamai" as *u8) == 1 { return 1 }
31 if xt_has(u, ul, ".fastly." as *u8) == 1 { return 1 }
32 if xt_has(u, ul, "bunnycdn" as *u8) == 1 { return 1 }
33 if xt_has(u, ul, "b-cdn.net" as *u8) == 1 { return 1 }
34 if xt_has(u, ul, ".cdn." as *u8) == 1 { return 1 }
35 return 0
36}
37// CLASSIFY a URL -> sets *kind (XT_*), returns CONFIDENCE 0-100. Multi-signal, strongest first.
38func xt_classify(u: *u8, ul: i64, kind: *i64) -> i64 {
39 // (a) extensions -- strongest, most stable signal
40 if xt_has(u, ul, ".m3u8" as *u8) == 1 { kind[0] = XT_HLS; return 95 }
41 if xt_has(u, ul, ".mpd" as *u8) == 1 { kind[0] = XT_DASH; return 95 }
42 if xt_has(u, ul, ".mp4" as *u8) == 1 { kind[0] = XT_DIRECT; return 90 }
43 if xt_has(u, ul, ".webm" as *u8) == 1 { kind[0] = XT_DIRECT; return 90 }
44 if xt_has(u, ul, ".mkv" as *u8) == 1 { kind[0] = XT_DIRECT; return 90 }
45 if xt_has(u, ul, ".mov" as *u8) == 1 { kind[0] = XT_DIRECT; return 88 }
46 if xt_has(u, ul, ".m4s" as *u8) == 1 { kind[0] = XT_SEGMENT; return 85 }
47 if xt_has(u, ul, ".ts" as *u8) == 1 { kind[0] = XT_SEGMENT; return 82 }
48 if xt_has(u, ul, ".mp3" as *u8) == 1 { kind[0] = XT_AUDIO; return 85 }
49 if xt_has(u, ul, ".m4a" as *u8) == 1 { kind[0] = XT_AUDIO; return 85 }
50 if xt_has(u, ul, ".aac" as *u8) == 1 { kind[0] = XT_AUDIO; return 82 }
51 // (b) PATH patterns -- catch extension-LESS stream URLs (YouTube, many APIs)
52 if xt_has(u, ul, "/videoplayback" as *u8) == 1 { kind[0] = XT_DIRECT; return 70 } // YouTube googlevideo
53 if xt_has(u, ul, "/master" as *u8) == 1 { kind[0] = XT_HLS; return 65 }
54 if xt_has(u, ul, "/playlist" as *u8) == 1 { kind[0] = XT_HLS; return 62 }
55 if xt_has(u, ul, "/chunklist" as *u8) == 1 { kind[0] = XT_HLS; return 62 }
56 if xt_has(u, ul, "/hls/" as *u8) == 1 { kind[0] = XT_HLS; return 60 }
57 if xt_has(u, ul, "/dash/" as *u8) == 1 { kind[0] = XT_DASH; return 60 }
58 if xt_has(u, ul, "/manifest" as *u8) == 1 { kind[0] = XT_DASH; return 55 }
59 // (c) CDN host + a video-ish token -- weakest, but a real signal for restructured sites
60 if xt_is_cdn(u, ul) == 1 {
61 if xt_has(u, ul, "video" as *u8) == 1 { kind[0] = XT_DIRECT; return 45 }
62 if xt_has(u, ul, "stream" as *u8) == 1 { kind[0] = XT_DIRECT; return 42 }
63 if xt_has(u, ul, "/media" as *u8) == 1 { kind[0] = XT_DIRECT; return 40 }
64 }
65 kind[0] = XT_NONE; return 0
66}
67// rank score: kind priority dominates, confidence breaks ties.
68func xt_score(kind: i64, conf: i64) -> i64 { return kind * 100 + conf }
69// pick the BEST candidate from a newline-separated URL list -> copy into out, set *kind, return confidence.
70func xt_best(list: *u8, listlen: i64, out: *u8, cap: i64, kind: *i64) -> i64 {
71 let line: *u8 = sys_mmap(4096)
72 let kb: *i64 = sys_mmap(8) as *i64
73 var best_score: i64 = 0
74 var best_conf: i64 = 0
75 var best_kind: i64 = XT_NONE
76 out[0] = 0 as u8
77 var p: i64 = 0
78 var go: i64 = 1
79 while go == 1 {
80 if p >= listlen { go = 0 }
81 else {
82 if (list[p] & 0xff) == 0 { go = 0 }
83 else {
84 var q: i64 = 0
85 var inl: i64 = 1
86 while inl == 1 {
87 let c: i64 = list[p] & 0xff
88 if c == 0 { inl = 0 } else { if c == 10 { inl = 0; p = p + 1 } else { if q < 4095 { line[q] = c as u8; q = q + 1 } p = p + 1 } }
89 }
90 line[q] = 0 as u8
91 if q > 0 {
92 let conf: i64 = xt_classify(line, q, kb)
93 let sc: i64 = xt_score(kb[0], conf)
94 if sc > best_score { best_score = sc; best_conf = conf; best_kind = kb[0]; var a: i64=0; while a<q { out[a]=line[a]; a=a+1 } out[q]=0 as u8 }
95 }
96 }
97 }
98 }
99 kind[0] = best_kind
100 return best_conf
101}
102// SMART NAMING: pull a human title from the page (og:title / "title":"..." / <title>). Site-agnostic.
103func xt_extract_title(html: *u8, hlen: i64, out: *u8, cap: i64) -> i64 {
104 let ogp: i64 = xt_find(html, hlen, "og:title" as *u8, 8, 0)
105 if ogp >= 0 {
106 let cp: i64 = xt_find(html, hlen, "content=\"" as *u8, 9, ogp)
107 if cp >= 0 { var s: i64 = cp + 9; var w: i64 = 0; while s < hlen { let c: i64 = html[s]&0xff; if c == 34 { s = hlen } else { if w < (cap-1) { out[w] = c as u8; w = w + 1 } s = s + 1 } } out[w] = 0 as u8; if w > 0 { return w } }
108 }
109 let jt: i64 = xt_find(html, hlen, "\"title\":\"" as *u8, 9, 0)
110 if jt >= 0 { var s: i64 = jt + 9; var w: i64 = 0; while s < hlen { let c: i64 = html[s]&0xff; if c == 34 { s = hlen } else { if c == 92 { s = s + 1 } else { if w < (cap-1) { out[w] = c as u8; w = w + 1 } s = s + 1 } } } out[w] = 0 as u8; if w > 0 { return w } }
111 let tt: i64 = xt_find(html, hlen, "<title>" as *u8, 7, 0)
112 if tt >= 0 { var s: i64 = tt + 7; var w: i64 = 0; while s < hlen { let c: i64 = html[s]&0xff; if c == 60 { s = hlen } else { if w < (cap-1) { out[w] = c as u8; w = w + 1 } s = s + 1 } } out[w] = 0 as u8; return w }
113 out[0] = 0 as u8
114 return 0
115}