Found via emulator smoke that channelInfo was returning empty
recent_videos list, breaking the subscriptions feed.
Two root causes:
1. First browse of a channel by browseId lands on the HOME tab in
2026 YT, not Videos. Home uses sectionListRenderer, not the
richGridRenderer my parser expected. The Videos tab in the
response carries an empty content block (you need a SECOND
browse with the params token to populate it).
2. Channel video items on the Videos tab migrated from
videoRenderer to lockupViewModel (YT made the switch ~2024).
My old parser only handled videoRenderer.
Fix:
* fetch_channel_browse now does TWO browses — first for Home
(header + metadata), second with params='EgZ2aWRlb3PyBgQKAjoA'
for the Videos tab. Same magic constant NPE uses (audit Track
A §2.4).
* parse_videos_tab handles BOTH videoRenderer (legacy/fallback)
AND lockupViewModel (current). lockupViewModel parse extracts:
- contentId → video ID
- metadata.lockupMetadataViewModel.title.content → title
- metadataRows[].metadataParts[].text.content → view-count
('1.1m views') + relative-age ('2 years ago') + uploader
- contentImage.thumbnailViewModel.overlays[]
.thumbnailBottomOverlayViewModel.badges[]
.thumbnailBadgeViewModel.text → duration ('3:14:08')
- contentImage.thumbnailViewModel.image.sources[] → thumbnails
* parse_videos_continuation pulls the continuation token from the
Videos tab grid for pagination.
Second browse is best-effort: if it fails, recent_videos stays
empty and the channel header still populates from the first.
Verified the YT response shape by probing live channel
UCwwtUfy0-CqN50HfaFDzL0w (NCS Spektrem) — got 30+ lockup-style
video items with the expected fields.
|
||
|---|---|---|
| .. | ||
| js | ||
| linkhandler | ||
| potoken | ||
| channel.rs | ||
| client_request.rs | ||
| constants.rs | ||
| itag.rs | ||
| mod.rs | ||
| parsing.rs | ||
| playlist_extractor.rs | ||
| search_extractor.rs | ||
| stream_extractor.rs | ||
| stream_helper.rs | ||
| suggestion_extractor.rs | ||