@renoise/plugin 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/.claude-plugin/marketplace.json +15 -0
  2. package/.claude-plugin/plugin.json +23 -0
  3. package/README.md +53 -0
  4. package/hooks/check-api-key.sh +28 -0
  5. package/hooks/hooks.json +28 -0
  6. package/hooks/session-start.sh +40 -0
  7. package/index.mjs +1 -0
  8. package/openclaw.plugin.json +22 -0
  9. package/package.json +22 -0
  10. package/skills/director/SKILL.md +269 -0
  11. package/skills/director/references/narrative-pacing.md +257 -0
  12. package/skills/director/references/style-library.md +179 -0
  13. package/skills/file-upload/SKILL.md +79 -0
  14. package/skills/file-upload/scripts/upload.mjs +103 -0
  15. package/skills/gemini-gen/SKILL.md +236 -0
  16. package/skills/gemini-gen/scripts/gemini.mjs +220 -0
  17. package/skills/product-sheet-generate/SKILL.md +75 -0
  18. package/skills/renoise-gen/SKILL.md +364 -0
  19. package/skills/renoise-gen/references/api-endpoints.md +142 -0
  20. package/skills/renoise-gen/references/video-capabilities.md +524 -0
  21. package/skills/renoise-gen/renoise-cli.mjs +723 -0
  22. package/skills/scene-generate/SKILL.md +52 -0
  23. package/skills/short-film-editor/SKILL.md +478 -0
  24. package/skills/short-film-editor/examples/mystery-package-4shot.md +260 -0
  25. package/skills/short-film-editor/references/continuity-guide.md +170 -0
  26. package/skills/short-film-editor/scripts/analyze-beats.py +271 -0
  27. package/skills/short-film-editor/scripts/batch-generate.sh +150 -0
  28. package/skills/short-film-editor/scripts/split-grid.sh +70 -0
  29. package/skills/tiktok-content-maker/SKILL.md +140 -0
  30. package/skills/tiktok-content-maker/examples/dress-demo.md +86 -0
  31. package/skills/tiktok-content-maker/references/ecom-prompt-guide.md +266 -0
  32. package/skills/video-download/SKILL.md +161 -0
  33. package/skills/video-download/scripts/download-video.sh +91 -0
@@ -0,0 +1,86 @@
1
+ # Full Example: Keep Resistance Loop Bands — 15s E-commerce Video
2
+
3
+ ## Input
4
+
5
+ - Product image: Keep brand resistance loop bands, 3-pack (pink/blue/green), pastel macaron colors
6
+ - Model reference: Athletic female, blonde ponytail, sports bra + fitted shorts (for analysis only, NOT uploaded to Renoise)
7
+
8
+ ## Product Analysis Result
9
+
10
+ ```json
11
+ {
12
+ "product": {
13
+ "type": "Resistance loop bands",
14
+ "color": "Pink 10lb, Blue 15lb, Mint green 20lb",
15
+ "material": "TPE elastic, matte finish, soft and skin-friendly",
16
+ "highlights": "Three bands with progressive resistance for training, foldable and portable, pastel macaron color scheme",
17
+ "brand_tone": "Youthful athletic, trendy fitness"
18
+ },
19
+ "model": {
20
+ "gender": "female",
21
+ "age_range": "25-30",
22
+ "hair": "Blonde high ponytail",
23
+ "outfit": "Black sports bra + black fitted shorts",
24
+ "vibe": "Confident, energetic, professional fitness feel"
25
+ },
26
+ "scene_suggestions": [
27
+ "Bright modern living room morning workout",
28
+ "Hotel room travel fitness",
29
+ "Bedroom bedtime stretching"
30
+ ],
31
+ "selling_points": [
32
+ "Three resistance levels for progressive training, suitable for beginners to advanced",
33
+ "Compact and portable, folds to fit in a bag for anytime/anywhere workouts",
34
+ "Pastel macaron color scheme, won't roll up during use"
35
+ ]
36
+ }
37
+ ```
38
+
39
+ ## Generated Script
40
+
41
+ ### 1. Video Prompt (English, with dialogue)
42
+
43
+ > The product is a set of three Keep brand elastic resistance loop bands — flat, wide, smooth matte TPE material with a soft rubbery texture, each band approximately 5cm wide and forming a closed loop. Colors: pastel pink (lightest resistance), sky blue (medium), mint green (heaviest). Each band has a small white "Keep" logo printed on the surface. The bands must match the reference image exactly in color, width, shape, material finish, and logo placement throughout every frame of the video. A fit young woman in her mid-twenties with blonde hair in a high ponytail, light tan skin, athletic build, wearing a black sports bra and black fitted shorts, holds the three pastel-colored Keep resistance bands fanned out in her hand — camera starts extreme close-up on the bands showing their flat wide shape and matte surface then whip pans up to her face as she says "Stop scrolling — I threw out all my gym equipment for these three bands." Morning sunlight from a large window catches the smooth TPE finish. Camera does a fast snap dolly in on her hands as she stretches the blue band taut, the flat wide band maintaining its shape and thickness as it stretches, she says "Ten, fifteen, twenty pounds — I started pink, now I am on green, and they never roll up on you." She has the mint green band already looped around both ankles, camera pulls back to medium shot as she performs side leg raises, the wide flat band visible around her ankles keeping its shape, she says "I do legs in my living room, arms on work trips — they fold smaller than my phone" while transitioning into a squat pulse with the pink band above her knees. Without stopping she grabs all three bands, folds them into a tiny square and tucks them into a small gym bag pocket, camera pushes in tight, then she looks straight into the camera with a knowing grin and says "Honestly the best forty bucks I have spent this year," the pastel colors pop against her black outfit, warm golden backlight creates a soft halo, frame holds steady.
44
+
45
+ ### 2. Dialogue Script (English)
46
+
47
+ ```
48
+ [0-3s] "Stop scrolling — I threw out all my gym equipment for these three bands."
49
+ [3-8s] "Ten, fifteen, twenty pounds — I started pink, now I'm on green, and they never roll up on you."
50
+ [8-12s] "I do legs in my living room, arms on work trips — they fold smaller than my phone."
51
+ [12-15s] "Honestly the best forty bucks I've spent this year."
52
+ ```
53
+
54
+ ### 3. BGM / Sound Design Suggestions
55
+
56
+ - **BGM**: High-energy trap-pop beat, BPM 125-135, bass drop synced with the 0s hook
57
+ - **Sound effects**:
58
+ - [0s] Band snap/recoil sound — paired with opening impact
59
+ - [3s] Fast whoosh transition
60
+ - [8s] Workout rhythm drum accent
61
+ - [12s] Bass swell + freeze-frame hit
62
+
63
+ ## Renoise Submission
64
+
65
+ ```bash
66
+ # 1. Upload product image (product image only, NOT the model image)
67
+ node renoise-cli.mjs material upload <product-image-path>
68
+ # → returns material id, e.g. 194
69
+
70
+ # 2. Submit task (with product image material, all-in-one)
71
+ node renoise-cli.mjs task generate \
72
+ --prompt "<Video Prompt above>" \
73
+ --model renoise-2.0 --duration 15 --ratio 9:16 \
74
+ --tags ecom,keep,resistance-band \
75
+ --materials "194:image1"
76
+ ```
77
+
78
+ ## Multi-Scene Batch Generation
79
+
80
+ Reuse the same material ID for the same product, swap scenes to generate multiple videos:
81
+
82
+ | Scene | Hook Dialogue | Scene Keywords |
83
+ |-------|--------------|----------------|
84
+ | Outdoor park morning workout | "This tiny thing replaced my entire gym bag." | sunlit park lawn, golden hour, dewy grass |
85
+ | Hotel room travel fitness | "Business trip day three and I still have not skipped a workout." | hotel room, city skyline, suitcase |
86
+ | Bedroom bedtime stretching | "My nighttime routine that actually changed my body." | cozy bedroom, string lights, yoga mat |
@@ -0,0 +1,266 @@
1
+ # E-commerce Short Video Prompt Guide
2
+
3
+ ## 15-Second E-commerce Video Prompt Template
4
+
5
+ ### Core Structure: One Continuous 15-Second Narrative
6
+
7
+ Unlike Apple's "Don't Blink" rapid-cut style, e-commerce product videos are **one continuous shot** that uses camera movement changes to showcase the product and model.
8
+
9
+ **Writing order**: Timeline narrative + Ad-6D elements interspersed
10
+
11
+ ```
12
+ [Opening 0-3s] HOOK — Product MUST appear in Frame 1 + fast camera movement + start speaking immediately. Never build up slowly.
13
+ [Showcase 3-8s] Product close-up + material details + model interaction
14
+ [Scene 8-12s] Lifestyle scenario + usage effect + atmosphere
15
+ [Close 12-15s] Model faces camera + product freeze frame + natural ending
16
+ ```
17
+
18
+ ### Product Anchoring (Start of Prompt, One Sentence)
19
+
20
+ Product appearance is conveyed by the reference image. The prompt only needs **one sentence** stating what the product is + its use case:
21
+
22
+ ```
23
+ The product is a [brand] [product type] for [primary use case], shown in the reference image.
24
+ The product must match the reference image exactly in every frame. Do not invent any packaging, box, or container unless the reference image shows one.
25
+ ```
26
+
27
+ **Examples**:
28
+ - `The product is a K brand lightweight gym tote bag for fitness and daily commute, shown in the reference image.`
29
+ - `The product is a Keep peanut-shaped massage ball for back and muscle recovery, shown in the reference image.`
30
+
31
+ **Key**: Do not repeat product color, material, shape, or logo descriptions in the prompt — that information is already in the reference image. Save prompt space for the hook and visual narrative.
32
+
33
+ ### Model Consistency Description
34
+
35
+ Immediately after the product anchoring, anchor the model's appearance:
36
+
37
+ ```
38
+ A [age_range]-year-old [gender] with [hair description], [skin tone], [body type], wearing [outfit description]...
39
+ ```
40
+
41
+ **Note**: Models are described entirely through text — never upload real person reference images (privacy detection will block images containing realistic human faces).
42
+
43
+ ## Category-Specific Keywords
44
+
45
+ ### Clothing
46
+
47
+ - **Fabric**: flowing silk, crisp cotton, soft cashmere, stretchy knit, lightweight chiffon, structured tweed
48
+ - **Motion**: fabric sways gently, hem flutters in breeze, pleats catch light, drape follows body movement
49
+ - **Showcase**: twirls to show full skirt volume, adjusts collar detail, runs fingers along seam
50
+ - **Scene**: sunlit café terrace, cherry blossom garden path, minimalist white studio, golden hour rooftop
51
+
52
+ ### Electronics
53
+
54
+ - **Material**: anodized aluminum, gorilla glass surface, matte finish, chamfered edges catch light
55
+ - **Motion**: screen illuminates face, finger glides across display, device rotates to reveal thin profile
56
+ - **Showcase**: holds up to camera showing screen, taps interface with precision, places on wireless charger
57
+ - **Scene**: modern desk setup, coffee shop workspace, commuter holding device, bedside nightstand
58
+
59
+ ### Beauty
60
+
61
+ - **Texture**: dewy finish, velvety matte, glossy sheen, shimmering particles, creamy texture
62
+ - **Motion**: applies with brush stroke, blends with fingertip, lips press together, eyelids flutter
63
+ - **Showcase**: close-up of application, before-after glow, product swatch on skin, mirror reflection
64
+ - **Scene**: vanity mirror with ring light, bathroom morning routine, getting ready for night out
65
+
66
+ ### Food
67
+
68
+ - **Texture**: steam rises, sauce glistens, crispy golden crust, juice drips, cheese stretches
69
+ - **Motion**: pours into bowl, breaks apart to reveal filling, scoops with spoon, bites with satisfaction
70
+ - **Showcase**: overhead flat lay, cross-section reveal, slow-motion pour, garnish placement
71
+ - **Scene**: rustic kitchen counter, outdoor picnic, cozy dining table, street food stall
72
+
73
+ ### Home
74
+
75
+ - **Material**: warm wood grain, soft linen texture, smooth ceramic, brushed brass hardware
76
+ - **Motion**: hand caresses surface, opens drawer smoothly, arranges on shelf, light shifts across surface
77
+ - **Showcase**: styled vignette, before-after room transformation, detail close-up, scale with hand
78
+ - **Scene**: morning light through curtains, minimalist living room, cozy bedroom corner, modern kitchen
79
+
80
+ ## Model-Product Interaction Vocabulary
81
+
82
+ ### General Actions
83
+ - **Showcase**: holds up to camera, presents with both hands, turns to show different angle
84
+ - **Touch**: runs fingers along, gently touches, traces the outline of
85
+ - **Wear/Use**: puts on, adjusts, styles with
86
+ - **Activate**: opens, activates, applies
87
+ - **Emotion**: smiles confidently, looks surprised, nods approvingly, expresses delight
88
+
89
+ ### Clothing-Specific
90
+ - twirls gracefully, walks toward camera, poses with hand on hip, flips hair to show neckline, adjusts sleeve cuff, smooths fabric over hip, turns to reveal back detail
91
+
92
+ ### Electronics-Specific
93
+ - unboxes with anticipation, swipes through interface, holds up comparing to face size, places in pocket to show portability, tilts to catch light on screen
94
+
95
+ ### Beauty-Specific
96
+ - applies with practiced motion, checks reflection, touches cheek feeling texture, pouts showing lip color, blinks showing eye makeup
97
+
98
+ ## Dialogue Writing Guidelines
99
+
100
+ **Core principle**: Dialogue must be in English, embedded within the video prompt. Do not output subtitles separately.
101
+
102
+ **Embedding format** (forced lip-sync):
103
+ ```
104
+ Spoken dialogue (say EXACTLY, word-for-word): "..."
105
+ Mouth clearly visible when speaking, lip-sync aligned.
106
+ ```
107
+ Using `Spoken dialogue (say EXACTLY, word-for-word):` instead of simply `says "..."` significantly improves lip-sync accuracy. Follow each dialogue line with `Mouth clearly visible when speaking, lip-sync aligned.` to ensure the mouth is visible.
108
+
109
+ **Style**: Best-friend casual tone — like recommending to a friend, not reading ad copy. Every sentence carries specific information (numbers, comparisons, usage scenarios) — no filler.
110
+
111
+ ### Hook Dialogue (0-3s) — First Line to Stop the Scroll
112
+
113
+ **Subversive** (most effective):
114
+ - "Stop scrolling — I threw out all my gym equipment for these three bands."
115
+ - "This tiny thing replaced my entire gym bag."
116
+ - "Business trip day three and I still have not skipped a workout."
117
+
118
+ **Personal experience**:
119
+ - "My nighttime routine that actually changed my body."
120
+ - "The one thing I have been recommending to literally everyone."
121
+
122
+ **Key**: Start speaking fast, paired with fast camera movement (whip pan / snap dolly in). Never start slow.
123
+
124
+ ### Selling Point Dialogue (3-8s) — Specific Specs + Personal Experience
125
+
126
+ - "Ten, fifteen, twenty pounds — I started pink, now I am on green, and they never roll up on you."
127
+ - "Three resistance levels, folds flat, weighs literally nothing — this is my entire travel gym."
128
+ - Must include: specific numbers + personal usage experience + differentiating advantage
129
+
130
+ ### Scene Dialogue (8-12s) — Where to Use + Portability / Versatility
131
+
132
+ - "I do legs in my living room, arms on work trips — they fold smaller than my phone."
133
+ - "Park, backyard, hotel balcony — I have zero excuses now."
134
+ - Must include: at least 2 usage scenarios + portability/versatility
135
+
136
+ ### Closing Dialogue (12-15s) — Natural Personal Recommendation, No Hard Sell
137
+
138
+ **Good closings** (recommended):
139
+ - "Honestly the best forty bucks I have spent this year."
140
+ - "Trust me just start — future you will be so grateful."
141
+ - "Best thing I ever packed."
142
+ - "You are welcome."
143
+
144
+ **Avoid these closings** (too pushy):
145
+ - ~~"Link below — grab yours before they sell out."~~
146
+ - ~~"Click the link for a special discount."~~
147
+ - ~~"Limited stock, hurry up!"~~
148
+
149
+ ## Hook Strategy (The First 3 Seconds)
150
+
151
+ **Data**: 63% of high-CTR TikTok videos capture users in the first 3 seconds. Users make the "watch or swipe" decision in just **1.7 seconds**. Videos with 65%+ 3-second retention rate get **4-7x** more impressions.
152
+
153
+ ### Visual Hook Techniques (pick one for prompt opening)
154
+
155
+ | Technique | Prompt Phrasing | Effect |
156
+ |-----------|----------------|--------|
157
+ | **Snap zoom-in** | `Camera snaps in extreme close-up on the [product]` | Product in Frame 1, maximum impact |
158
+ | **Product slides in** | `The [product] slides into frame from the right` | Sudden appearance creates micro-suspense |
159
+ | **Hand thrust** | `A hand thrusts the [product] toward the camera` | Direct, strong UGC feel |
160
+ | **Close-up → wide reveal** | `Extreme macro on [texture detail], camera rapidly pulls back to reveal...` | Hook curiosity with detail, then reveal full picture |
161
+ | **Whip pan in** | `Camera whip-pans with motion blur and lands on the [product]` | Strong rhythm, visual impact |
162
+
163
+ ### Hook Core Rules
164
+
165
+ 1. **Product MUST appear in Frame 1** — never start with someone walking, opening a door, or establishing the environment
166
+ 2. **Frame 1 MUST have motion** — static opening = instant swipe
167
+ 3. **Model MUST start speaking within the first 2 seconds** — audio retains more than visuals
168
+ 4. **Hook dialogue should feel like stopping a friend** — not reading ad copy
169
+
170
+ ### Hook Dialogue Formulas (ranked by effectiveness)
171
+
172
+ 1. **Result-first**: "This $30 bag replaced my gym bag AND my purse." — Show the result directly
173
+ 2. **Subversive**: "Stop carrying two bags to the gym — you only need this one." — Challenge existing habits
174
+ 3. **Social proof**: "200K people bought this last month and I finally get why." — FOMO
175
+ 4. **Pain point question**: "Why is your gym bag always so heavy?" — Hit the pain point directly
176
+ 5. **Personal story**: "I was that person with three bags until I found this." — Relatability
177
+
178
+ ## Camera Movement Pacing (15s Continuous Shot)
179
+
180
+ ```
181
+ [0-3s] HOOK — Product in Frame 1! Fast camera movement + start speaking immediately
182
+ Recommended: extreme close-up snap in / whip pan / product slides into frame
183
+ Avoid: camera slowly pushes in, person walking as buildup, empty establishing shot
184
+ Pacing: Complete the first camera change within 1-2 seconds
185
+
186
+ [3-8s] SHOWCASE — Close-up → medium shot transition, showcase product details
187
+ Recommended: fast snap dolly in on details,
188
+ camera orbits or slides to reveal texture
189
+
190
+ [8-12s] SCENE — Pull back to medium/wide shot, show usage scenario
191
+ Recommended: camera pulls back to reveal full scene,
192
+ natural movement as model interacts with environment
193
+
194
+ [12-15s] CLOSE — Return to medium shot, face camera, freeze
195
+ Recommended: camera pushes in tight, then settles,
196
+ model faces camera, product in frame,
197
+ frame holds steady (this final hold is important)
198
+ ```
199
+
200
+ ## BGM Instructions (Specified in Prompt)
201
+
202
+ The video model can generate background music within the video. **Always add a BGM instruction at the end of the prompt**:
203
+
204
+ ```
205
+ Background music: [genre/mood description], [tempo], [energy level].
206
+ ```
207
+
208
+ **BGM Selection Guide**:
209
+
210
+ | Product Category | Recommended BGM | Prompt Phrasing |
211
+ |-----------------|-----------------|-----------------|
212
+ | Sports / Fitness | Rhythmic electronic / lo-fi | `Background music: upbeat electronic lo-fi beat, medium-fast tempo, energetic and motivating.` |
213
+ | Beauty / Skincare | Warm R&B / chill pop | `Background music: warm chill R&B, slow-medium tempo, soft and intimate.` |
214
+ | Electronics | Clean minimal / tech | `Background music: clean minimal electronic, medium tempo, modern and sleek.` |
215
+ | Fashion | Indie pop / trendy | `Background music: trendy indie pop, medium tempo, stylish and confident.` |
216
+ | Home | Acoustic / ambient | `Background music: warm acoustic guitar, slow tempo, cozy and relaxing.` |
217
+ | Food | Jazz / feel-good | `Background music: feel-good jazz, medium tempo, cheerful and appetizing.` |
218
+
219
+ **Key**: BGM should match the video pacing — the hook segment needs energy, the closing can ease up. Music style should match the product's brand tone.
220
+
221
+ ## Prompt Writing Style: Director Dictation
222
+
223
+ Prompts should be written as if a director is dictating on set — 6-10 English sentences, each doing only one thing. Avoid packing multiple actions into one long sentence.
224
+
225
+ **Good writing** (one action/camera instruction per sentence):
226
+ ```
227
+ Camera snaps in on a close-up of the pink peanut massage ball sitting on a yoga mat.
228
+ A 25-year-old woman with a high ponytail and black leggings walks into frame.
229
+ She picks up the ball and holds it up to the camera.
230
+ Spoken dialogue (say EXACTLY, word-for-word): "This little thing saved my back after deadlifts."
231
+ Mouth clearly visible when speaking, lip-sync aligned.
232
+ She places the ball on the mat and lies down on it, rolling her spine.
233
+ Camera pulls back to a medium shot showing the full living room scene.
234
+ ...
235
+ ```
236
+
237
+ **Bad writing** (too many actions crammed in one sentence):
238
+ ```
239
+ A woman enters carrying a pink ball while the camera pans and she says "..." as she lies down and rolls.
240
+ ```
241
+
242
+ ## Prompt Quality Checklist
243
+
244
+ - [ ] Pure English director-dictation style paragraph (6-10 sentences, one thing per sentence)
245
+ - [ ] **Product anchoring at the start** (one sentence: what the product is + use case + match reference image + no-packaging lock)
246
+ - [ ] Model appearance anchoring description immediately after
247
+ - [ ] **Dialogue uses `Spoken dialogue (say EXACTLY, word-for-word):` format** (English, 4 lines, best-friend casual tone)
248
+ - [ ] `Mouth clearly visible when speaking, lip-sync aligned.` after each dialogue line
249
+ - [ ] Hook dialogue in the first sentence, paired with fast camera movement
250
+ - [ ] Closing dialogue is natural, no hard sell
251
+ - [ ] Includes specific product material/texture descriptors
252
+ - [ ] At least 3 camera movement changes
253
+ - [ ] Includes lighting/atmosphere description
254
+ - [ ] Model has clear physical interaction with product
255
+ - [ ] Ending frame holds steady
256
+ - [ ] Overall pacing: fast open → detailed showcase → scene → freeze
257
+ - [ ] **BGM instruction at the end** (`Background music: [genre], [tempo], [energy]`)
258
+ - [ ] Hook segment has product in Frame 1, no buildup
259
+
260
+ ## Renoise Submission Notes
261
+
262
+ - **Must upload product image** as material (image1) — product accuracy improves significantly
263
+ - **Never upload real person/model images** — privacy detection will block them (error: PrivacyInformation)
264
+ - Model appearance is controlled entirely by prompt text description
265
+ - Product images should ideally be clean white-background product photos, avoid images with marketing text overlays
266
+ - For batch generation: upload the product image once, reuse the material ID and swap scenes/dialogue
@@ -0,0 +1,161 @@
1
+ ---
2
+ name: video-download
3
+ description: >
4
+ Downloads videos from YouTube, TikTok, Douyin, Bilibili, Instagram, XiaoHongShu and 1000+ platforms.
5
+ Primary: yt-dlp. Fallback: agent-browser + GreenVideo for Douyin/TikTok when yt-dlp fails.
6
+ Use when user says "download video", "save video", "grab video", "watermark-free download",
7
+ or pastes a video URL. Do NOT use for AI video generation or video editing.
8
+ allowed-tools: Bash
9
+ metadata:
10
+ author: renoise
11
+ version: 0.2.0
12
+ category: utility
13
+ tags: [download, youtube, tiktok, douyin, yt-dlp, greenvideo]
14
+ ---
15
+
16
+ # Video Download
17
+
18
+ Download videos from YouTube, TikTok, and other platforms to local MP4 files using yt-dlp. Handles format selection, platform-prefixed dedup, and TikTok cookie fallback automatically.
19
+
20
+ ## Prerequisites
21
+
22
+ Verify yt-dlp is installed:
23
+
24
+ ```bash
25
+ yt-dlp --version
26
+ ```
27
+
28
+ If missing: `brew install yt-dlp` (macOS) or `pip install yt-dlp`.
29
+
30
+ ### Optional (for Douyin/TikTok fallback)
31
+
32
+ - `agent-browser` installed globally (`npm install -g agent-browser`)
33
+ - Chrome for Testing installed (`agent-browser install`)
34
+
35
+ ## Usage
36
+
37
+ ### Single Video
38
+
39
+ Run the download script with the video URL:
40
+
41
+ ```bash
42
+ bash ${CLAUDE_SKILL_DIR}/scripts/download-video.sh '<URL>'
43
+ ```
44
+
45
+ The script handles everything automatically:
46
+ - Extracts a platform-prefixed video ID (`yt-dQw4w9WgXcQ`, `tk-7571284267028729101`, `vid-aHR0cHM6Ly93d3`)
47
+ - Saves to `resources/references/<video_id>.mp4`
48
+ - Skips download if file already exists (dedup)
49
+ - Retries TikTok downloads with `--cookies-from-browser chrome` on failure
50
+ - Removes zero-byte leftovers from interrupted downloads
51
+
52
+ ### Custom Output Directory
53
+
54
+ ```bash
55
+ bash ${CLAUDE_SKILL_DIR}/scripts/download-video.sh '<URL>' 'path/to/output'
56
+ ```
57
+
58
+ ### Batch Download
59
+
60
+ Run the script in a loop:
61
+
62
+ ```bash
63
+ for URL in '<URL1>' '<URL2>' '<URL3>'; do
64
+ bash ${CLAUDE_SKILL_DIR}/scripts/download-video.sh "$URL"
65
+ done
66
+ ```
67
+
68
+ ## Script Output
69
+
70
+ The script prints one of three status lines:
71
+
72
+ | Output | Meaning |
73
+ |--------|---------|
74
+ | `ALREADY_EXISTS: <path>` | File already downloaded, skipped |
75
+ | `DOWNLOADED: <path>` | Download succeeded |
76
+ | `FAILED: <message>` | Download failed (exit code 1) |
77
+
78
+ ## Troubleshooting
79
+
80
+ | Error | Solution |
81
+ |-------|----------|
82
+ | `HTTP Error 403` (TikTok/Douyin) | Script auto-retries with cookies. If still failing, use **GreenVideo Fallback** below |
83
+ | `--max-filesize` skipped | Video exceeds 200M limit. Download manually with `-f 'best[height<=720]'` |
84
+ | `is not a valid URL` | Ensure URL is wrapped in single quotes |
85
+ | `Requested formats are incompatible` | yt-dlp auto-transcodes, no action needed |
86
+
87
+ ## Video ID Logic
88
+
89
+ | Platform | Pattern | Example ID |
90
+ |----------|---------|------------|
91
+ | YouTube | `watch?v=`, `shorts/`, `embed/`, `youtu.be/` → 11-char ID | `yt-dQw4w9WgXcQ` |
92
+ | TikTok | 15+ digit numeric ID in URL | `tk-7571284267028729101` |
93
+ | Other | Base64url of URL, first 16 chars | `vid-aHR0cHM6Ly93d3` |
94
+
95
+ ---
96
+
97
+ ## GreenVideo Fallback (for Douyin/TikTok)
98
+
99
+ When yt-dlp fails for Douyin or TikTok URLs (common with 403 errors or region-restricted content), use GreenVideo as a browser-based fallback. Requires `agent-browser` (see Prerequisites).
100
+
101
+ ### Decision Logic
102
+
103
+ ```
104
+ User gives URL → Try yt-dlp first
105
+ ↓ fails (403 / no result)
106
+ Is it Douyin/TikTok?
107
+ ↓ yes
108
+ Use agent-browser + GreenVideo
109
+ ↓ no
110
+ Report error, suggest manual download
111
+ ```
112
+
113
+ ### Step 1: Open GreenVideo
114
+
115
+ ```bash
116
+ agent-browser open "https://greenvideo.cc/en/"
117
+ ```
118
+
119
+ ### Step 2: Paste URL and Parse
120
+
121
+ ```bash
122
+ agent-browser snapshot
123
+ # Find the input textbox ref (e.g., @e63)
124
+ agent-browser fill <input-ref> "<video-url>"
125
+ agent-browser click <start-button-ref>
126
+ ```
127
+
128
+ Wait 5 seconds for parsing to complete, then snapshot to verify results.
129
+
130
+ ### Step 3: Extract Video Direct URL
131
+
132
+ The video URL is stored in Nuxt state. Extract it with:
133
+
134
+ ```bash
135
+ agent-browser eval "
136
+ (function() {
137
+ const nuxtData = window.__NUXT__;
138
+ if (!nuxtData) return 'ERROR: No Nuxt data found';
139
+ const str = JSON.stringify(nuxtData);
140
+ const mp4Match = str.match(/https?:[^\\\"]*(?:mp4|video|play|aweme|douyinvod|bilivideo)[^\\\"]{0,500}/g);
141
+ if (mp4Match && mp4Match.length > 0) return mp4Match[0];
142
+ return 'ERROR: No video URL found in Nuxt state';
143
+ })()
144
+ "
145
+ ```
146
+
147
+ ### Step 4: Download and Cleanup
148
+
149
+ ```bash
150
+ curl -L -o ~/Downloads/<filename>.mp4 "<extracted-video-url>"
151
+ agent-browser close
152
+ ```
153
+
154
+ ### GreenVideo Troubleshooting
155
+
156
+ | Issue | Solution |
157
+ |-------|----------|
158
+ | Parse fails or no result | Check URL is valid and publicly accessible. Some `/user/self` URLs need the direct video URL |
159
+ | No video URL in Nuxt state | Try clicking download button and check for `<video>` elements: `agent-browser eval "document.querySelectorAll('video').length"` |
160
+ | Download fails (403) | Video URLs expire quickly — extract and download immediately. Try adding `-H "Referer: https://greenvideo.cc/"` to curl |
161
+ | agent-browser not responding | Run `agent-browser close` then `agent-browser open "https://greenvideo.cc/en/"` |
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env bash
2
+ # download-video.sh — Download video to resources/references/ with dedup and platform detection
3
+ #
4
+ # Usage:
5
+ # download-video.sh <URL> [output_dir]
6
+ #
7
+ # Features:
8
+ # - Extracts platform-prefixed video ID (yt-xxx, tk-xxx, vid-xxx)
9
+ # - Skips download if file already exists (dedup)
10
+ # - Auto-retries TikTok with --cookies-from-browser chrome on 403
11
+ # - Outputs final file path on success
12
+
13
+ set -euo pipefail
14
+
15
+ URL="${1:?Usage: download-video.sh <URL> [output_dir]}"
16
+ OUTPUT_DIR="${2:-resources/references}"
17
+
18
+ # --- Video ID extraction ---
19
+
20
+ extract_video_id() {
21
+ local url="$1"
22
+
23
+ # YouTube: watch?v=, shorts/, embed/, youtu.be/
24
+ if [[ "$url" =~ (youtube\.com/(watch\?v=|shorts/|embed/)|youtu\.be/)([\w-]{11}|[A-Za-z0-9_-]{11}) ]]; then
25
+ local yt_id
26
+ yt_id=$(echo "$url" | grep -oE '(watch\?v=|shorts/|embed/|youtu\.be/)([A-Za-z0-9_-]{11})' | grep -oE '[A-Za-z0-9_-]{11}$')
27
+ echo "yt-${yt_id}"
28
+ return
29
+ fi
30
+
31
+ # TikTok: numeric ID (15+ digits)
32
+ if [[ "$url" =~ tiktok\.com ]]; then
33
+ local tk_id
34
+ tk_id=$(echo "$url" | grep -oE '[0-9]{15,}' | head -1)
35
+ if [[ -n "$tk_id" ]]; then
36
+ echo "tk-${tk_id}"
37
+ return
38
+ fi
39
+ fi
40
+
41
+ # Fallback: base64url-encoded URL, first 16 chars
42
+ local b64
43
+ b64=$(echo -n "$url" | base64 | tr '+/' '-_' | tr -d '=' | head -c 16)
44
+ echo "vid-${b64}"
45
+ }
46
+
47
+ VIDEO_ID=$(extract_video_id "$URL")
48
+ OUTPUT="${OUTPUT_DIR}/${VIDEO_ID}.mp4"
49
+
50
+ # --- Dedup check ---
51
+
52
+ if [[ -f "$OUTPUT" && $(stat -f%z "$OUTPUT" 2>/dev/null || stat -c%s "$OUTPUT" 2>/dev/null) -gt 0 ]]; then
53
+ echo "ALREADY_EXISTS: $OUTPUT"
54
+ exit 0
55
+ fi
56
+
57
+ # Remove zero-byte leftover from interrupted download
58
+ [[ -f "$OUTPUT" ]] && rm -f "$OUTPUT"
59
+
60
+ mkdir -p "$OUTPUT_DIR"
61
+
62
+ # --- Download ---
63
+
64
+ YT_DLP_ARGS=(
65
+ -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best'
66
+ --merge-output-format mp4
67
+ --no-playlist
68
+ --max-filesize 200M
69
+ -o "$OUTPUT"
70
+ )
71
+
72
+ echo "Downloading: $URL"
73
+ echo "Output: $OUTPUT"
74
+
75
+ if yt-dlp "${YT_DLP_ARGS[@]}" "$URL"; then
76
+ echo "DOWNLOADED: $OUTPUT"
77
+ exit 0
78
+ fi
79
+
80
+ # --- TikTok 403 retry with cookies ---
81
+
82
+ if [[ "$URL" =~ tiktok\.com ]]; then
83
+ echo "Retrying TikTok with browser cookies..."
84
+ if yt-dlp "${YT_DLP_ARGS[@]}" --cookies-from-browser chrome "$URL"; then
85
+ echo "DOWNLOADED: $OUTPUT"
86
+ exit 0
87
+ fi
88
+ fi
89
+
90
+ echo "FAILED: Could not download $URL"
91
+ exit 1