56 lines
4.8 KiB
Markdown
56 lines
4.8 KiB
Markdown
# Analysis — the chain, overlaps, stacks
|
|
|
|
## The chain
|
|
|
|
```
|
|
camera owners (Dishub/bank/operator cameras)
|
|
→ operator/government stream servers (HLS: Ant Media, MediaMTX, datarhei, custom)
|
|
→ government portals publish catalogs (HTML/JSON; some embed player iframes)
|
|
→ transit.oyenza.com harvests + verifies + curates → static catalog in its bundle
|
|
→ visitor's browser plays the owner's HLS URL directly (hotlink, no proxy)
|
|
```
|
|
|
|
## Evidence per source (cross-match against oyenza's catalog)
|
|
|
|
Method: extract oyenza's view URLs from `asset-cctv.json`; extract the portal's camera identifiers from its page/JSON; compare sets exactly (case-insensitively where the portal is inconsistent).
|
|
|
|
- **DKI — 46/46.** Portal `cards` iframes carry `<camera-id>/embed.html`; oyenza lists `<camera-id>/index.fmp4.m3u8` + the same `embed.html` as "owner page". Every oyenza DKI path appears in the portal set (52 cameras at capture). Example id: `501844_JKP_DISHUB_JL.-MH.-THAMRIN-C01_CCTV-01`.
|
|
- **Toll — 190/190.** BPJT's inline JSON carries `streamhls` values; after unescaping (`\/`) and cleaning a few literal `\r\n` artifacts, **all 190** oyenza toll view URLs appear verbatim. BPJT page at capture: 1,530 records → 1,415 unique URLs across ~39 hosts.
|
|
- **Bekasi — 23/23.** oyenza's 23 stream filenames all match `list.json` `name` values exactly.
|
|
- **Bogor — 51/51.** All 51 unique detail-link IDs (`/cctv/<id>/detail`) used by oyenza appear on the BSW page (96 IDs total). Strongest link: the Alun-Alun detail page (id 82) embeds exactly `https://restreamer2.kotabogor.go.id/memfs/c07c1926-288c-46e4-a19c-9f51022edc5d.m3u8` — the URL oyenza lists for that camera.
|
|
|
|
Interpretation: oyenza is a **curated mirror**, not a re-publisher with its own pipeline to the cameras. The catalog is rebuilt and re-verified (footer "Daftar diperiksa 13 Oktober 2026"; `checkedAt` 2026-10-12T22:07:39Z).
|
|
|
|
## Selection logic (the 154 toll cams)
|
|
|
|
oyenza's toll subset = 190 views / 154 cams from 9 operators: Hutama Karya 58, Trans Bumi Serbaraja 29, Cimanggis-Cibitung 19, Cibitung-Tanjung Priok 19, JTD 8, Marga Mandalasakti 7, KKDM 6, Jakarta Lingkar Baratsatu 5, CMNP 3.
|
|
|
|
Not simple geography: 589 BPJT cams fall inside a Jabodetabek bounding box, but only ~190 views were taken. Conspicuous exclusions, with live checks:
|
|
|
|
- **Jasa Marga (~605 cams) — absent.** `jmlive.jasamarga.com` returned HTTP 200 with an **empty body** (manifest not publicly served to us). Exclusion is consistent with "dead unless probed from a permitted vantage".
|
|
- **BSD Toll — absent.** `stream.bsdtol.com` → nginx **502** at capture.
|
|
- **Waskita (`wbw`, 55) — absent** even though its streams work (playlist verified) → curation beyond pure liveness (coverage-area choice).
|
|
|
|
**Confidence:** Stream-liveness exclusions (JM, BSD) = established via probes. "Verify-then-pick + Jabodetabek coverage" selection rule = strong inference; the exact rule isn't observable from outside.
|
|
|
|
## Stream-stack fingerprints (observed live)
|
|
|
|
- `/LiveApp/streams/<id>.m3u8` → **Ant Media Server** — HK (Cloudflare-fronted), Serbaraja, CCT. 2 s TS segments.
|
|
- `server: mediamtx` → **MediaMTX** — CTP. Master playlist → `stream.m3u8`.
|
|
- `/memfs/<uuid>.m3u8` (+ `?session=` on sub-playlists) → **datarhei Restreamer** — all Bogor servers (also bsdtol, PPTR).
|
|
- `index.fmp4.m3u8` + `tracks-v1/` + `X-Sid`/`X-Run-Time` headers, `server: Streamer 26.04.1` → **Bali Tower custom** — DKI.
|
|
- nginx + `X-Powered-By: Express` packagers → JTD, KKDM. Plain nginx/Apache HLS → MMS, JORRW1, Citramarga, Bekasi.
|
|
|
|
## Playback path (from the site's own code)
|
|
|
|
- Catalog fetched at runtime: `fetch("/assets/asset-cctv-<hash>.json")`.
|
|
- Views mapped to `{label, hls, page}`; on tap: `import("/assets/lib-E4YH4VVH.js")` (hls.js) → `hls.loadSource(view.hls); hls.attachMedia(video)`; Safari falls back to native `canPlayType("application/vnd.apple.mpegurl")` → `video.src`.
|
|
- "Buka Layar penuh" opens `view.page` — the owner's page (portal or `embed.html`).
|
|
- No proxy: streams load from the owner host in the visitor's browser. Probed hosts sent `Access-Control-Allow-Origin: *`, and returned 200 even without `Origin`/`Referer` — no hotlink protection at capture.
|
|
- The site's own claim ("Video diputar langsung dari server pemilik kamera dan tidak kami simpan") matches the code path.
|
|
|
|
## Anti-overclaim notes
|
|
|
|
- The static catalog proves what the client understands (URLs, labels, owner pages). It does not prove the operator's exact checker tooling — no public repo was found; `checkedAt` + redeploy hashes = inference of a periodic probe + rebuild.
|
|
- Uptime varies: one host timed out once and answered on retry. Treat single probes as readings, not facts — timestamp them (done: Oct 13, 2026).
|
|
- Access policy can change at any time; CORS `*` today ≠ CORS `*` forever.
|