Install
$ agentstack add skill-jianshuo-claude-skills-wjs-uploading-video ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
wjs-uploading-video
Push finished videos to YouTube. Defaults are tuned for this user's workflow (王建硕 channel, China network with local proxy, 1080p horizontal recordings from Riverside / multicam edits).
When to use
- User has one or more finished
.mp4files and wants them on YouTube - User points to a
final/directory with multiple segments and anUPLOAD_META.md - User wants a specific privacy / playlist / scheduled publish
Don't use for:
- 微信视频号 upload (no public API; user uploads manually via web)
- 抖音 / 小红书 / B 站 (different APIs, not yet implemented here)
- YouTube Shorts variants from horizontal source (use
wjs-reframing-videofirst to produce the 9:16 cut, then upload that via this skill)
Prerequisites (one-time per machine)
- Google Cloud OAuth client:
~/.config/youtube/credentials.jsonmust exist. Seereferences/credentials-setup.mdfor the 5-minute setup if missing. - Python deps:
pip3 install google-auth-oauthlib google-api-python-client requests(onlygoogle-auth+requestsare strictly needed at upload time, but the OAuth-lib pulls them). - First-ever upload opens a browser for Google consent and writes
~/.config/youtube/token.json. Subsequent runs reuse it silently.
How it works (and why it's not the stock youtube-uploader)
YouTube's resumable upload protocol issues a Location: URL after the metadata POST, then accepts the bytes in chunked PUT requests. The stock google-api-python-client runs this over httplib2, which under this user's local SOCKS+HTTP proxy stack throws [Errno 65] No route to host or socket.timeout on those follow-up PUTs and stalls indefinitely.
This skill bypasses httplib2: it does OAuth via google-auth, then drives the resumable upload manually with requests, passing the proxy explicitly. 8 MB chunks (not the stock 256 KB) — fewer round-trips through the proxy. Exponential-backoff retry on socket.timeout / ConnectionError / 5xx.
If you're tempted to "just call the YouTube API client directly," don't — it'll fail in this environment.
Usage
Batch upload a final/ directory
python3 ~/.claude/skills/wjs-uploading-video/scripts/upload_youtube.py \
--dir "/path/to/final" \
--meta "/path/to/final/UPLOAD_META.md"
The script:
- Reads
UPLOAD_META.mdand pairs each## NN · filename.mp4block to a video file in--dir - Skips videos already in
--results-file(default/.youtube_upload_results.json) — safe to re-run after failures - Uploads sequentially with progress every 8 MB
- Writes the final URL list to
--results-file
Single file
python3 ~/.claude/skills/wjs-uploading-video/scripts/upload_youtube.py \
--video /path/to/clip.mp4 \
--title "My Title" \
--description "Body text" \
--tags "tag1,tag2,tag3"
Common overrides
| Flag | Default | Notes | |---|---|---| | --privacy | public | private / unlisted / public | | --category | 28 | 28 = Science & Tech. 27 = Education. 24 = Entertainment. | | --made-for-kids | false | YouTube requires this declaration | | --playlist | none | Add each uploaded video to a playlist | | --publish-at | none | Schedule publish (requires --privacy private) | | --credentials | ~/.config/youtube/credentials.json | OAuth client JSON | | --token | ~/.config/youtube/token.json | Cached OAuth token | | --chunk-mb | 8 | Smaller chunks if uploads keep failing mid-flight | | --dry-run | off | Parse meta + list what would upload, don't touch network |
UPLOAD_META.md format
The parser expects the user's standard structure:
## 01 · segment_01_no-bugs.mp4
**短标题**
代码没有错误,只有意图不一致
**视频描述**
AI 时代屎山的重新定义...
—— 王建硕 × 任鑫《...》第 1 集
#王建硕 #AI编程 #ClaudeCode
---
Mapping:
## NN ·→ which video this block describes**短标题**(or**Title**) block → YouTube title, verbatim. Short titles work but consider that YouTube allows up to 100 chars — if you want a richer title with series name, write it that way in**短标题****视频描述**(or**Description**) block → YouTube description, verbatim, with the#taghashtags retained at the bottom- All
#wordtokens in the 视频描述 → comma-separated YouTube tags (each#is stripped; the user's channel name王建硕is auto-prepended per global instructions)
Filename in the heading must match an actual file in --dir. If a file exists but has no meta block, the script errors loudly — pass --allow-missing-meta to upload it with --title and empty description.
Sensible defaults this skill bakes in
- Privacy = public: videos go live immediately and appear in subscriber feeds + search. Override per call with
--privacy unlisted(link-only) or--privacy private(owner-only) when you want to review first - Category = 28 (Science & Tech): matches 王建硕 channel's main content; override with
--categoryper upload - selfDeclaredMadeForKids = false: YouTube requires this; the user's content is adult-targeted
- Chunk size = 8 MB: validated working size through this user's local proxy (256 KB stalled)
- Skip already-uploaded: results file is the source of truth; deleting it forces re-upload
Channel-name CTA rule
If you write description footers, signatures, or "subscribe to me" lines into a video's metadata, use 王建硕 (the user's channel name). Don't put a guest's name there — guests like 任鑫 belong inside the description body when they're the conversation partner, never in the channel-CTA slot.
Troubleshooting
| Symptom | Fix | |---|---| | access_denied 403 on consent screen | Add user's Google account to the OAuth client's Test users list in Google Cloud Console | | [Errno 65] No route to host mid-upload | Almost always a proxy issue — verify curl --max-time 10 https://upload.googleapis.com/upload/youtube/v3/videos returns a 4xx (any 4xx = proxy reachable); if 000, the proxy is down | | Upload stalls with no progress lines | The proxy is silently buffering. Lower --chunk-mb 4 or restart the proxy daemon | | quotaExceeded (API units) | YouTube Data API default quota is 10,000 units/day, each upload is 1,600 units — so ~6 uploads/day. Request a quota bump in Google Cloud Console, or split uploads across days | | 429 rateLimitExceeded · Video Uploads per day | A DIFFERENT, separate limit from API units — YouTube's per-project daily video-upload count (anti-abuse, tied to project verification status; can be very low). When hit, every upload in the batch fails init session failed: 429, none succeed. It is NOT a proxy/auth problem and can't be worked around. It resets at midnight US Pacific Time (not your local midnight). Options: wait for the PT reset and re-run (the results file was cleared so all retry); or upload via the YouTube Studio web UI, which does NOT consume this API limit; or get the GCP project verified to raise the cap. Earlier uploads the same PT-day (even manual API ones) eat into this count. | | Token refresh fails | Delete ~/.config/youtube/token.json and re-run; OAuth browser flow restarts |
After uploading
- Results saved to
--results-file(JSON: file, title, video id, URL) - Echo the URL list back to the user in a markdown table
- Videos are
publicby default — they're live the moment the upload completes. If the user wanted a review buffer, mention they can re-upload with--privacy unlisted(or flip back to unlisted in YouTube Studio) - If they mentioned a 合集 / series, offer to create a YouTube playlist and batch-add the new uploads (the user must give a playlist ID or let you create one)
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: jianshuo
- Source: jianshuo/claude-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.