Skip to content

feat: Add image and video download support to rn-wechat-extract - #2

Open
runningZ1 wants to merge 6 commits into
Pluviobyte:mainfrom
runningZ1:main
Open

feat: Add image and video download support to rn-wechat-extract#2
runningZ1 wants to merge 6 commits into
Pluviobyte:mainfrom
runningZ1:main

Conversation

@runningZ1

@runningZ1 runningZ1 commented Jul 15, 2026

Copy link
Copy Markdown

Description

Adds enhanced versions of fetch_wechat.py that download images, native videos, and WeChat Channels (视频号) videos embedded in WeChat public account articles.

New Scripts

fetch_wechat_with_images.py

  • Downloads images from WeChat articles
  • Saves images to {title}_images/ directory

fetch_wechat_with_media.py

  • Downloads both images and directly-embedded (mpvideo.qpic.cn) videos

fetch_wechat_with_channels.py 🆕

  • All features from with_media
  • Resolves and downloads WeChat Channels (视频号) videos, which have no directly playable URL in the article HTML at all

Video Channel (视频号) Video Download

A 视频号 video embedded in an article only exposes an export_id (data-id="export/...") and object_nonce_id (data-nonceid) pair inside a <mp-common-videosnap> tag — neither is a usable download URL on its own, and object_nonce_id is not the TikHub object_id (an earlier version of this PR mixed these up).

Resolution pipeline (no manual copy-paste needed anymore):

  1. Extract export_id + object_nonce_id from the article HTML (or use a direct weixin.qq.com/sph/... share link if the article already has one).
  2. TikHub fetch_video_detail (export_id + object_nonce_id) → resolves the real numeric object_id.
  3. TikHub fetch_video_share_url (object_id) → weixin.qq.com/sph/xxx share link.
  4. Community worker sph.litao.workers.dev fetch_video_profile (share_url) → an h264/h265 CDN url carrying an X-snsvideoflag query param.
  5. Download that CDN url with WeChat headers.

Step 4's X-snsvideoflag param turns out to make WeChat's CDN return the plaintext, pre-transcoded stream (X-encflag: 0 in the response headers) instead of the ISAAC64-encrypted original that TikHub's own media.full_url points to — so this pipeline needs no video decryption step at all, despite 视频号 videos normally requiring WeChat's proprietary WASM-based decryptor to play.

Requires a TikHub API key (--tikhub-key or TIKHUB_API_KEY env var). Steps 2–3 cost $0.01 each ($0.02/video total); step 4 is free but is a third-party community service outside this project's control. Without a key, 视频号 videos are still detected and reported (export_id/object_nonce_id printed to stderr) but not downloaded — everything else still works.

Usage

# Text only (original)
python3 fetch_wechat.py "<url>" --output-dir "./output"

# With images
python3 fetch_wechat_with_images.py "<url>" --output-dir "./output"

# With images and native videos
python3 fetch_wechat_with_media.py "<url>" --output-dir "./output"

# With images, native videos, and 视频号 videos
python3 fetch_wechat_with_channels.py "<url>" --output-dir "./output" --tikhub-key "$TIKHUB_API_KEY"

Testing Results

Verified end-to-end (real network calls, real TikHub key) against 4 live articles, downloaded files checked with ffprobe for valid duration/codec/no corruption:

Article Images Native videos 视频号 video Result
三维图像声呐成果展示 17/17 ✅ 8/16 (rest: expired token, unrelated) 1/1 ✅ 720p, 1094.7s, h264+aac
公众号文章也能放视频号的视频 7/7 ✅ 1/1 ✅ 576×1024, 17.5s, h264+aac
收藏!世界杯淘汰赛完整对阵图 3/3 ✅ 1/1 ✅ 576×1024, 11.5s, h264+aac
早啊!新闻来了(央视新闻) 11/11 ✅ 1/1 ✅ 720×1280, 131.5s, h264+aac

4/4 视频号 videos resolved and downloaded successfully; all played back correctly and matched their expected duration.

Changes

  • Added scripts/fetch_wechat_with_images.py
  • Added scripts/fetch_wechat_with_media.py
  • Added/rewrote scripts/fetch_wechat_with_channels.py: replaced the old speculative wxv_/bare-finder/bare-nonceid detection with <mp-common-videosnap>-based export_id + object_nonce_id extraction, and a working TikHub + community-worker resolution and download pipeline
  • Updated SKILL.md with full documentation for all three enhanced versions, including the 视频号 resolution pipeline and its TikHub cost

Technical Details

Native videos (mpvideo.qpic.cn):

  • URLs contain an authentication token that expires; download can fail if the article HTML is stale — re-scrape close to download time (independent of the 视频号 pipeline above)

视频号 videos:

  • See resolution pipeline above. data-nonceid in the article HTML is object_nonce_id, not object_id — do not pass it directly to TikHub's fetch_video_share_url
  • Both TikHub and the sph.litao.workers.dev worker sit behind Cloudflare and reject Python's default urllib User-Agent (403); the script sends a browser UA

Limitations

  • 视频号 downloads require a paid TikHub API key ($0.02/video)
  • sph.litao.workers.dev is a third-party community deployment, not an official API — availability isn't guaranteed
  • Native video token expiry (pre-existing, unrelated to this update) is still unresolved

runningZ1 and others added 6 commits July 15, 2026 15:40
Added fetch_wechat_with_media.py - downloads both images and videos.

Features:
- Downloads images from WeChat articles (same as with_images)
- Downloads videos from mpvideo.qpic.cn CDN
- Saves videos to {title}_videos/ directory
- Handles authentication parameters for video URLs
- Updates Markdown with video references

Tested with article containing 6 images and 4 videos.
Successfully downloaded 6/6 images and 4/8 videos (4 require auth).

Technical details:
- Videos hosted on mpvideo.qpic.cn
- URLs extracted from JavaScript with escaped characters
- Some videos require authentication tokens (403 on expired tokens)
Enhanced fetch_wechat_with_media.py with video channel detection:
- Detects wxv_ video channel IDs
- Reports video channel IDs in output
- Downloads videos from video channels (when auth tokens are valid)

Tested with article containing:
- 17 images (all downloaded)
- 8 videos (downloaded)
- 2 video channel IDs detected:
  - wxv_4602687508227964933
  - wxv_4602682391613407239

Technical details:
- Video channels use wxv_ prefix for IDs
- Videos hosted on mpvideo.qpic.cn
- Auth tokens required (some may return 403)
Enhanced fetch_wechat_with_media.py with finder video detection:
- Detects finder usernames (username@finder)
- Detects finder video URLs (findermp.video.qq.com)
- Reports expired URLs (finder url expire!)

Tested with article: https://mp.weixin.qq.com/s/ELTM4oSlQkfqbJfbpQLHkQ

Results:
- 7/7 images downloaded
- 2 video channel usernames detected
- 2 finder video URLs detected (expired)

Technical details:
- Video channels use findermp.video.qq.com domain
- URLs have expiration tokens
- Expired URLs return 400 Bad Request with 'finder url expire!'
Added fetch_wechat_with_channels.py - enhanced version with video channel support.

Features:
- Detects video channel share links (weixin.qq.com/sph/xxx)
- Integrates with online parsing service: https://sph.litao.workers.dev/
- Detects finder usernames and export IDs
- Reports expired finder URLs

Based on ltaoo/wx_channels_download project:
- GitHub: https://github.com/ltaoo/wx_channels_download
- Online service: https://sph.litao.workers.dev/

Usage:
- Visit https://sph.litao.workers.dev/
- Paste video channel share link
- Get direct video download URL

Note: Direct download from HTML requires real-time parsing
as video URLs have expiration tokens.
WeChat Channels videos embedded in an article have no directly playable
URL, only an export_id/object_nonce_id pair in the <mp-common-videosnap>
tag. Resolve them through TikHub (fetch_video_detail -> real object_id,
fetch_video_share_url -> share link) and a community worker
(sph.litao.workers.dev) that returns a CDN url carrying an
X-snsvideoflag param — WeChat serves that url unencrypted
(X-encflag: 0), so no ISAAC64 decrypt step is needed.

Also fixes a prior bug where the script treated the embed's
data-nonceid as the TikHub object_id; it is actually object_nonce_id
and does not resolve on its own.

Verified end-to-end against four live articles (720p/1094s landscape,
two 576x1024 shorts, one 720x1280 clip); all downloaded as valid,
playable h264+aac mp4 confirmed with ffprobe.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Explicitly call out that the 视频号 download pipeline relies on two
services this project does not build or operate: TikHub (paid API,
requires the user's own key) and sph.litao.workers.dev (a free,
already-deployed public instance of the open-source project
ltaoo/wx_channels_download, run by a third party).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant