@biggora/claude-plugins 1.1.1 → 1.2.2
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.
- package/.claude/settings.local.json +3 -1
- package/README.md +24 -17
- package/package.json +1 -1
- package/registry/registry.json +319 -244
- package/specs/coding.md +24 -0
- package/specs/pod.md +2 -0
- package/src/skills/captcha/README.md +221 -0
- package/src/skills/captcha/SKILL.md +355 -0
- package/src/skills/captcha/references/captcha-types.md +254 -0
- package/src/skills/captcha/references/services.md +172 -0
- package/src/skills/captcha/references/stealth.md +238 -0
- package/src/skills/captcha/scripts/solve_captcha.py +323 -0
- package/src/skills/captcha/scripts/solve_image_grid.py +350 -0
- package/src/skills/codex-cli/SKILL.md +21 -11
- package/src/skills/gemini-cli/SKILL.md +27 -13
- package/src/skills/gemini-cli/references/commands.md +21 -14
- package/src/skills/gemini-cli/references/configuration.md +23 -18
- package/src/skills/gemini-cli/references/headless-and-scripting.md +7 -17
- package/src/skills/gemini-cli/references/mcp-and-extensions.md +12 -6
- package/src/skills/google-merchant-api/SKILL.md +581 -0
- package/src/skills/google-merchant-api/references/accounts.md +247 -0
- package/src/skills/google-merchant-api/references/content-api-legacy.md +216 -0
- package/src/skills/google-merchant-api/references/datasources.md +233 -0
- package/src/skills/google-merchant-api/references/inventories.md +201 -0
- package/src/skills/google-merchant-api/references/migration.md +267 -0
- package/src/skills/google-merchant-api/references/products.md +316 -0
- package/src/skills/google-merchant-api/references/promotions.md +201 -0
- package/src/skills/google-merchant-api/references/reports.md +240 -0
- package/src/skills/lv-aggregators-api/SKILL.md +113 -0
- package/src/skills/lv-aggregators-api/references/integration-guide.md +368 -0
- package/src/skills/lv-aggregators-api/references/kurpirkt.md +103 -0
- package/src/skills/lv-aggregators-api/references/salidzini.md +122 -0
- package/src/skills/notebook-lm/SKILL.md +1 -1
- package/src/skills/screen-recording/SKILL.md +243 -213
- package/src/skills/screen-recording/references/design-patterns.md +4 -2
- package/src/skills/screen-recording/references/ffmpeg-recording.md +473 -0
- package/src/skills/screen-recording/references/{approach1-programmatic.md → programmatic-generation.md} +45 -22
- package/src/skills/screen-recording/references/python-fallback.md +222 -0
- package/src/skills/tailwindcss-best-practices/SKILL.md +180 -0
- package/src/skills/tailwindcss-best-practices/references/best-practices-utility-patterns.md +87 -0
- package/src/skills/tailwindcss-best-practices/references/core-installation.md +109 -0
- package/src/skills/tailwindcss-best-practices/references/core-preflight.md +200 -0
- package/src/skills/tailwindcss-best-practices/references/core-responsive.md +163 -0
- package/src/skills/tailwindcss-best-practices/references/core-source-detection.md +114 -0
- package/src/skills/tailwindcss-best-practices/references/core-theme.md +108 -0
- package/src/skills/tailwindcss-best-practices/references/core-utility-classes.md +59 -0
- package/src/skills/tailwindcss-best-practices/references/core-variants.md +204 -0
- package/src/skills/tailwindcss-best-practices/references/effects-form-controls.md +76 -0
- package/src/skills/tailwindcss-best-practices/references/effects-mask.md +91 -0
- package/src/skills/tailwindcss-best-practices/references/effects-scroll-snap.md +59 -0
- package/src/skills/tailwindcss-best-practices/references/effects-text-shadow.md +78 -0
- package/src/skills/tailwindcss-best-practices/references/effects-transition-animation.md +80 -0
- package/src/skills/tailwindcss-best-practices/references/effects-visibility-interactivity.md +82 -0
- package/src/skills/tailwindcss-best-practices/references/features-content-detection.md +175 -0
- package/src/skills/tailwindcss-best-practices/references/features-custom-styles.md +203 -0
- package/src/skills/tailwindcss-best-practices/references/features-dark-mode.md +137 -0
- package/src/skills/tailwindcss-best-practices/references/features-functions-directives.md +241 -0
- package/src/skills/tailwindcss-best-practices/references/features-upgrade.md +160 -0
- package/src/skills/tailwindcss-best-practices/references/layout-aspect-ratio.md +39 -0
- package/src/skills/tailwindcss-best-practices/references/layout-columns.md +80 -0
- package/src/skills/tailwindcss-best-practices/references/layout-display.md +110 -0
- package/src/skills/tailwindcss-best-practices/references/layout-flexbox.md +112 -0
- package/src/skills/tailwindcss-best-practices/references/layout-grid.md +87 -0
- package/src/skills/tailwindcss-best-practices/references/layout-height.md +97 -0
- package/src/skills/tailwindcss-best-practices/references/layout-inset.md +103 -0
- package/src/skills/tailwindcss-best-practices/references/layout-logical-properties.md +92 -0
- package/src/skills/tailwindcss-best-practices/references/layout-margin.md +126 -0
- package/src/skills/tailwindcss-best-practices/references/layout-min-max-sizing.md +63 -0
- package/src/skills/tailwindcss-best-practices/references/layout-object-fit-position.md +64 -0
- package/src/skills/tailwindcss-best-practices/references/layout-overflow.md +57 -0
- package/src/skills/tailwindcss-best-practices/references/layout-padding.md +77 -0
- package/src/skills/tailwindcss-best-practices/references/layout-position.md +85 -0
- package/src/skills/tailwindcss-best-practices/references/layout-tables.md +67 -0
- package/src/skills/tailwindcss-best-practices/references/layout-width.md +102 -0
- package/src/skills/tailwindcss-best-practices/references/transform-base.md +68 -0
- package/src/skills/tailwindcss-best-practices/references/transform-rotate.md +70 -0
- package/src/skills/tailwindcss-best-practices/references/transform-scale.md +83 -0
- package/src/skills/tailwindcss-best-practices/references/transform-skew.md +62 -0
- package/src/skills/tailwindcss-best-practices/references/transform-translate.md +77 -0
- package/src/skills/tailwindcss-best-practices/references/typography-font-text.md +142 -0
- package/src/skills/tailwindcss-best-practices/references/typography-list-style.md +65 -0
- package/src/skills/tailwindcss-best-practices/references/typography-text-align.md +60 -0
- package/src/skills/tailwindcss-best-practices/references/visual-background.md +76 -0
- package/src/skills/tailwindcss-best-practices/references/visual-border.md +108 -0
- package/src/skills/tailwindcss-best-practices/references/visual-effects.md +111 -0
- package/src/skills/tailwindcss-best-practices/references/visual-svg.md +82 -0
- package/src/skills/test-mobile-app/SKILL.md +11 -6
- package/src/skills/test-mobile-app/scripts/analyze_apk.py +15 -4
- package/src/skills/test-mobile-app/scripts/check_environment.py +5 -5
- package/src/skills/test-mobile-app/scripts/run_tests.py +1 -1
- package/src/skills/test-web-ui/SKILL.md +264 -84
- package/src/skills/test-web-ui/scripts/discover.py +25 -12
- package/src/skills/test-web-ui/scripts/run_tests.py +3 -2
- package/src/skills/tm-search/SKILL.md +242 -106
- package/src/skills/tm-search/references/scraping-fallback.md +60 -95
- package/src/skills/tm-search/scripts/tm_search.py +453 -375
- package/src/skills/vite-best-practices/SKILL.md +115 -0
- package/src/skills/vite-best-practices/references/build-and-ssr.md +255 -0
- package/src/skills/vite-best-practices/references/core-config.md +231 -0
- package/src/skills/vite-best-practices/references/core-features.md +222 -0
- package/src/skills/vite-best-practices/references/core-plugin-api.md +294 -0
- package/src/skills/vite-best-practices/references/environment-api.md +108 -0
- package/src/skills/vite-best-practices/references/rolldown-migration.md +242 -0
- package/src/skills/screen-recording/references/approach2-xvfb.md +0 -232
|
@@ -1,68 +1,76 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: screen-recording
|
|
3
3
|
description: >
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
Record the actual screen to video. Use this skill whenever a user asks to:
|
|
5
|
+
"record my screen", "capture my screen", "make a screen recording", "screencast",
|
|
6
|
+
"record what's on screen", "capture desktop", "record a video of my screen",
|
|
7
|
+
"take a video of my desktop", "screen capture to video", or anything involving
|
|
8
|
+
recording the actual display output to an MP4/video file.
|
|
9
|
+
Also supports creating synthetic demo videos programmatically when no real screen
|
|
10
|
+
capture is needed (product demos, animated presentations).
|
|
11
|
+
Always trigger this skill for any screen recording, screen capture, or video creation task.
|
|
11
12
|
---
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Autonomous video creation pipeline for the Agent. No user interaction required after initial brief.
|
|
16
|
-
|
|
17
|
-
## What this skill creates
|
|
18
|
-
|
|
19
|
-
- **Product demo videos** — animated walkthroughs showing features, UI flows, dashboards
|
|
20
|
-
- **Presentation videos** — slide-style videos with animated content and narration
|
|
21
|
-
- **Screen recordings** — capture of a virtual X11 display (Xvfb) with real browser/app content
|
|
22
|
-
- **Narrated screencasts** — video + TTS voiceover, fully automated
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## Architecture: 3 Confirmed Approaches
|
|
27
|
-
|
|
28
|
-
### Approach 1 — Programmatic Animation (RECOMMENDED)
|
|
29
|
-
**Best for**: product demos, feature showcases, presentation videos, marketing videos
|
|
30
|
-
|
|
31
|
-
Stack: `Pillow` → frame generation → `MoviePy` → video assembly → `pyttsx3+espeak` → narration
|
|
14
|
+
> **Requires FFmpeg** for primary recording. Install: `choco install ffmpeg` (Windows), `brew install ffmpeg` (macOS), `apt install ffmpeg` (Linux). Python fallback available if FFmpeg is not installed (no audio/cursor).
|
|
32
15
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
### Approach 2 — Virtual Display Recording
|
|
36
|
-
**Best for**: capturing real browser/app interactions, UI walkthroughs with live content
|
|
16
|
+
# Screen Recording Skill
|
|
37
17
|
|
|
38
|
-
|
|
18
|
+
Record the actual screen — full desktop, a specific region, or a named window — to MP4 video with optional audio and cursor capture.
|
|
39
19
|
|
|
40
|
-
|
|
20
|
+
## What this skill does
|
|
41
21
|
|
|
42
|
-
|
|
43
|
-
**
|
|
22
|
+
- **Screen recording** — capture what's actually on screen (primary purpose)
|
|
23
|
+
- **Region/window recording** — capture a specific area or application window
|
|
24
|
+
- **Audio capture** — record system audio alongside video
|
|
25
|
+
- **Synthetic video generation** — create animated demo videos programmatically (secondary)
|
|
44
26
|
|
|
45
27
|
---
|
|
46
28
|
|
|
47
|
-
## Quick Start
|
|
48
|
-
|
|
49
|
-
### Step 1 — Understand the request
|
|
50
|
-
Determine:
|
|
51
|
-
- What content to show (UI flow, feature list, data visualization, slides)
|
|
52
|
-
- Duration (default: 30–120 seconds)
|
|
53
|
-
- Has narration? (default: yes, using pyttsx3+espeak)
|
|
54
|
-
- Resolution (default: 1280×720 HD)
|
|
55
|
-
- Output format (default: MP4, H.264)
|
|
56
|
-
|
|
57
|
-
### Step 2 — Choose approach (see decision tree below)
|
|
58
|
-
|
|
59
|
-
### Step 3 — Generate video (see implementation guides)
|
|
29
|
+
## Quick Start
|
|
60
30
|
|
|
61
|
-
###
|
|
31
|
+
### Record full screen for 30 seconds
|
|
62
32
|
```python
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
33
|
+
import platform, subprocess, shutil, signal, os
|
|
34
|
+
|
|
35
|
+
def record_screen(output="recording.mp4", duration=30, fps=30, audio=False):
|
|
36
|
+
system = platform.system()
|
|
37
|
+
cmd = ["ffmpeg"]
|
|
38
|
+
|
|
39
|
+
if system == "Windows":
|
|
40
|
+
if audio:
|
|
41
|
+
cmd += ["-f", "dshow", "-i", "audio=Stereo Mix"]
|
|
42
|
+
cmd += ["-f", "gdigrab", "-framerate", str(fps), "-draw_mouse", "1",
|
|
43
|
+
"-i", "desktop"]
|
|
44
|
+
elif system == "Darwin":
|
|
45
|
+
devices = "0" if not audio else "0:1"
|
|
46
|
+
cmd += ["-f", "avfoundation", "-framerate", str(fps),
|
|
47
|
+
"-capture_cursor", "1", "-i", devices]
|
|
48
|
+
else: # Linux
|
|
49
|
+
if audio:
|
|
50
|
+
cmd += ["-f", "pulse", "-i", "default"]
|
|
51
|
+
display = os.environ.get("DISPLAY", ":0.0")
|
|
52
|
+
cmd += ["-f", "x11grab", "-framerate", str(fps), "-draw_mouse", "1",
|
|
53
|
+
"-i", display]
|
|
54
|
+
|
|
55
|
+
cmd += ["-c:v", "libx264", "-preset", "ultrafast", "-crf", "23",
|
|
56
|
+
"-pix_fmt", "yuv420p"]
|
|
57
|
+
if audio:
|
|
58
|
+
cmd += ["-c:a", "aac", "-b:a", "128k"]
|
|
59
|
+
if duration:
|
|
60
|
+
cmd += ["-t", str(duration)]
|
|
61
|
+
cmd += [output, "-y"]
|
|
62
|
+
|
|
63
|
+
print(f"Recording → {output}")
|
|
64
|
+
proc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
|
|
65
|
+
try:
|
|
66
|
+
proc.wait()
|
|
67
|
+
except KeyboardInterrupt:
|
|
68
|
+
proc.send_signal(signal.SIGINT)
|
|
69
|
+
proc.wait()
|
|
70
|
+
print(f"Saved: {output} ({os.path.getsize(output):,} bytes)")
|
|
71
|
+
return output
|
|
72
|
+
|
|
73
|
+
record_screen("recording.mp4", duration=30)
|
|
66
74
|
```
|
|
67
75
|
|
|
68
76
|
---
|
|
@@ -72,219 +80,236 @@ shutil.copy("/home/claude/output.mp4", "/mnt/user-data/outputs/demo.mp4")
|
|
|
72
80
|
```
|
|
73
81
|
User wants a video
|
|
74
82
|
│
|
|
75
|
-
|
|
76
|
-
│
|
|
77
|
-
│
|
|
83
|
+
├─ Record what's actually on screen?
|
|
84
|
+
│ ├─ FFmpeg installed? → Approach 1: FFmpeg (RECOMMENDED)
|
|
85
|
+
│ └─ No FFmpeg? → Approach 2: Python fallback (mss + OpenCV)
|
|
78
86
|
│
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
│
|
|
82
|
-
└── Mix of real UI + animated overlays?
|
|
83
|
-
└── YES → Approach 3 (Hybrid)
|
|
87
|
+
└─ Create a synthetic animated demo/presentation?
|
|
88
|
+
└─ YES → Approach 3: Programmatic generation (Pillow + MoviePy)
|
|
84
89
|
```
|
|
85
90
|
|
|
86
91
|
---
|
|
87
92
|
|
|
88
|
-
##
|
|
93
|
+
## Approach 1: FFmpeg Screen Recording (RECOMMENDED)
|
|
89
94
|
|
|
90
|
-
|
|
95
|
+
FFmpeg uses platform-native capture APIs for fast, high-quality recording with audio and cursor support.
|
|
91
96
|
|
|
92
|
-
|
|
93
|
-
```python
|
|
94
|
-
from moviepy import VideoClip, AudioFileClip
|
|
95
|
-
import numpy as np
|
|
96
|
-
from PIL import Image, ImageDraw
|
|
97
|
-
import pyttsx3, subprocess
|
|
97
|
+
Read `references/ffmpeg-recording.md` for the full platform reference including window capture, audio device detection, and quality tuning.
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
engine = pyttsx3.init()
|
|
101
|
-
engine.setProperty('rate', 140) # speaking speed
|
|
102
|
-
engine.save_to_file("Your narration text here", '/tmp/narration.wav')
|
|
103
|
-
engine.runAndWait()
|
|
104
|
-
subprocess.run(['ffmpeg', '-i', '/tmp/narration.wav', '-c:a', 'libmp3lame',
|
|
105
|
-
'/tmp/narration.mp3', '-y', '-loglevel', 'quiet'])
|
|
99
|
+
### Platform-specific input formats
|
|
106
100
|
|
|
107
|
-
|
|
108
|
-
|
|
101
|
+
| Platform | Input Format | Cursor | Audio | Region |
|
|
102
|
+
|----------|-------------|--------|-------|--------|
|
|
103
|
+
| Windows | `gdigrab` | `-draw_mouse 1` | `-f dshow -i audio="Stereo Mix"` | `-offset_x/-offset_y/-video_size` |
|
|
104
|
+
| macOS | `avfoundation` | `-capture_cursor 1` | Device index `"0:1"` | `-vf crop=w:h:x:y` |
|
|
105
|
+
| Linux X11 | `x11grab` | `-draw_mouse 1` | `-f pulse -i default` | `-video_size WxH -i :0.0+X,Y` |
|
|
106
|
+
| Linux Wayland | `wf-recorder` | Default | `-a` flag | `-g "x,y wxh"` |
|
|
109
107
|
|
|
110
|
-
|
|
111
|
-
img = Image.new('RGB', (1280, 720), BACKGROUND_COLOR)
|
|
112
|
-
draw = ImageDraw.Draw(img)
|
|
113
|
-
current_scene(draw, t) # draw current scene content
|
|
114
|
-
return np.array(img)
|
|
108
|
+
### Full screen recording
|
|
115
109
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
audio = AudioFileClip('/tmp/narration.mp3').with_duration(total_duration)
|
|
120
|
-
final = clip.with_audio(audio)
|
|
121
|
-
final.write_videofile("/home/claude/output.mp4", fps=24, logger=None)
|
|
110
|
+
**Windows:**
|
|
111
|
+
```bash
|
|
112
|
+
ffmpeg -f gdigrab -framerate 30 -draw_mouse 1 -i desktop -c:v libx264 -preset ultrafast -crf 23 -pix_fmt yuv420p -t 30 recording.mp4 -y
|
|
122
113
|
```
|
|
123
114
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
## Implementation: Approach 2 (Xvfb + x11grab)
|
|
127
|
-
|
|
128
|
-
Read `references/approach2-xvfb.md` for the full implementation guide.
|
|
129
|
-
|
|
130
|
-
**Key pattern:**
|
|
115
|
+
**macOS:**
|
|
131
116
|
```bash
|
|
132
|
-
|
|
133
|
-
Xvfb :99 -screen 0 1280x720x24 &
|
|
134
|
-
XVFB_PID=$!
|
|
135
|
-
|
|
136
|
-
# 2. Start recording
|
|
137
|
-
DISPLAY=:99 ffmpeg -f x11grab -video_size 1280x720 -i :99 \
|
|
138
|
-
-c:v libx264 -preset fast -r 24 /home/claude/recording.mp4 &
|
|
139
|
-
FFMPEG_PID=$!
|
|
140
|
-
|
|
141
|
-
# 3. Run your app/browser on DISPLAY=:99
|
|
142
|
-
DISPLAY=:99 chromium --no-sandbox --headless=new ...
|
|
143
|
-
# OR
|
|
144
|
-
DISPLAY=:99 python3 your_app.py
|
|
145
|
-
|
|
146
|
-
# 4. Stop recording
|
|
147
|
-
kill $FFMPEG_PID $XVFB_PID
|
|
117
|
+
ffmpeg -f avfoundation -framerate 30 -capture_cursor 1 -i "0" -c:v libx264 -preset ultrafast -crf 23 -pix_fmt yuv420p -t 30 recording.mp4 -y
|
|
148
118
|
```
|
|
149
119
|
|
|
150
|
-
|
|
120
|
+
**Linux (X11):**
|
|
121
|
+
```bash
|
|
122
|
+
ffmpeg -f x11grab -framerate 30 -draw_mouse 1 -i :0.0 -c:v libx264 -preset ultrafast -crf 23 -pix_fmt yuv420p -t 30 recording.mp4 -y
|
|
123
|
+
```
|
|
151
124
|
|
|
152
|
-
|
|
125
|
+
### Region recording
|
|
153
126
|
|
|
154
|
-
### pyttsx3 + espeak-ng (OFFLINE — always works)
|
|
155
127
|
```python
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
128
|
+
# Record a specific area: (x=100, y=200, width=800, height=600)
|
|
129
|
+
region = (100, 200, 800, 600)
|
|
130
|
+
|
|
131
|
+
if system == "Windows":
|
|
132
|
+
cmd += ["-offset_x", "100", "-offset_y", "200", "-video_size", "800x600", "-i", "desktop"]
|
|
133
|
+
elif system == "Darwin":
|
|
134
|
+
cmd += ["-i", "0", "-vf", "crop=800:600:100:200"] # crop after capture
|
|
135
|
+
else: # Linux
|
|
136
|
+
cmd += ["-video_size", "800x600", "-i", ":0.0+100,200"]
|
|
137
|
+
```
|
|
160
138
|
|
|
161
|
-
|
|
162
|
-
for v in engine.getProperty('voices'):
|
|
163
|
-
print(v.id, v.name)
|
|
139
|
+
### Window recording
|
|
164
140
|
|
|
165
|
-
|
|
166
|
-
|
|
141
|
+
**Windows** — by window title:
|
|
142
|
+
```bash
|
|
143
|
+
ffmpeg -f gdigrab -framerate 30 -i title="My App" -c:v libx264 -preset ultrafast recording.mp4 -y
|
|
167
144
|
```
|
|
168
|
-
Convert WAV→MP3: `ffmpeg -i /tmp/out.wav -c:a libmp3lame /tmp/out.mp3 -y -loglevel quiet`
|
|
169
145
|
|
|
170
|
-
|
|
171
|
-
```python
|
|
172
|
-
# Just skip the audio step, write video without audio
|
|
173
|
-
clip.write_videofile("/home/claude/output.mp4", fps=24, logger=None)
|
|
174
|
-
```
|
|
146
|
+
**macOS/Linux** — get window bounds, then record as region. See `references/ffmpeg-recording.md` for platform-specific window geometry detection.
|
|
175
147
|
|
|
176
|
-
|
|
148
|
+
### Audio capture
|
|
177
149
|
|
|
178
|
-
|
|
150
|
+
Audio device names vary per system. Detect available devices:
|
|
179
151
|
|
|
180
|
-
### Color Palettes (use consistently per video)
|
|
181
152
|
```python
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
#
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
SUBTEXT = (100, 100, 130)
|
|
153
|
+
import subprocess, platform
|
|
154
|
+
|
|
155
|
+
system = platform.system()
|
|
156
|
+
if system == "Windows":
|
|
157
|
+
# Lists DirectShow audio devices
|
|
158
|
+
subprocess.run(["ffmpeg", "-list_devices", "true", "-f", "dshow", "-i", "dummy"])
|
|
159
|
+
elif system == "Darwin":
|
|
160
|
+
# Lists AVFoundation devices (screens + audio)
|
|
161
|
+
subprocess.run(["ffmpeg", "-f", "avfoundation", "-list_devices", "true", "-i", ""])
|
|
162
|
+
else:
|
|
163
|
+
# PulseAudio sources
|
|
164
|
+
subprocess.run(["pactl", "list", "short", "sources"])
|
|
195
165
|
```
|
|
196
166
|
|
|
197
|
-
|
|
198
|
-
- `1280x720` — HD (default, fast)
|
|
199
|
-
- `1920x1080` — Full HD (for high-quality output)
|
|
200
|
-
- `1080x1920` — Vertical (mobile/social)
|
|
167
|
+
> **Windows note**: "Stereo Mix" must be enabled in Sound Settings → Recording tab. Right-click → Show Disabled Devices → Enable "Stereo Mix".
|
|
201
168
|
|
|
202
|
-
###
|
|
203
|
-
```python
|
|
204
|
-
# Smooth ease-in-out (0→1 over duration d, current time t from scene start)
|
|
205
|
-
def ease(t, d):
|
|
206
|
-
x = t/d
|
|
207
|
-
return x*x*(3-2*x)
|
|
169
|
+
### Stopping the recording
|
|
208
170
|
|
|
209
|
-
|
|
210
|
-
|
|
171
|
+
- **Duration-based**: Use `-t SECONDS` in the FFmpeg command
|
|
172
|
+
- **Manual stop**: Send `SIGINT` (Ctrl+C) to the FFmpeg process
|
|
173
|
+
- **From Python**: `proc.send_signal(signal.SIGINT)` then `proc.wait()`
|
|
174
|
+
|
|
175
|
+
---
|
|
211
176
|
|
|
212
|
-
|
|
213
|
-
x = int(-500 + 600 * ease(t, 0.8))
|
|
177
|
+
## Approach 2: Python Fallback (No FFmpeg)
|
|
214
178
|
|
|
215
|
-
|
|
216
|
-
|
|
179
|
+
When FFmpeg is not available, use `mss` for screenshots and `cv2.VideoWriter` to assemble them.
|
|
180
|
+
|
|
181
|
+
Read `references/python-fallback.md` for the full working template.
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
pip install mss opencv-python numpy
|
|
217
185
|
```
|
|
218
186
|
|
|
187
|
+
### Basic capture loop
|
|
188
|
+
```python
|
|
189
|
+
import mss, cv2, numpy as np, time
|
|
190
|
+
|
|
191
|
+
def record_screen_python(output="recording.mp4", duration=30, fps=20, region=None):
|
|
192
|
+
with mss.mss() as sct:
|
|
193
|
+
if region:
|
|
194
|
+
x, y, w, h = region
|
|
195
|
+
area = {"left": x, "top": y, "width": w, "height": h}
|
|
196
|
+
else:
|
|
197
|
+
mon = sct.monitors[1]
|
|
198
|
+
area = {"left": mon["left"], "top": mon["top"],
|
|
199
|
+
"width": mon["width"], "height": mon["height"]}
|
|
200
|
+
|
|
201
|
+
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
|
|
202
|
+
writer = cv2.VideoWriter(output, fourcc, fps, (area["width"], area["height"]))
|
|
203
|
+
interval = 1.0 / fps
|
|
204
|
+
start = time.time()
|
|
205
|
+
|
|
206
|
+
while time.time() - start < duration:
|
|
207
|
+
t0 = time.time()
|
|
208
|
+
frame = np.array(sct.grab(area))[:, :, :3]
|
|
209
|
+
writer.write(frame)
|
|
210
|
+
elapsed = time.time() - t0
|
|
211
|
+
if elapsed < interval:
|
|
212
|
+
time.sleep(interval - elapsed)
|
|
213
|
+
|
|
214
|
+
writer.release()
|
|
215
|
+
print(f"Saved: {output}")
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Limitations
|
|
219
|
+
- **No audio** — mss captures pixels only
|
|
220
|
+
- **No cursor** — cursor is not included in screenshots
|
|
221
|
+
- **Lower FPS** — typically 15-25 fps depending on resolution
|
|
222
|
+
- **Larger files** — mp4v codec is less efficient than H.264
|
|
223
|
+
|
|
219
224
|
---
|
|
220
225
|
|
|
221
|
-
##
|
|
226
|
+
## Approach 3: Synthetic Video Generation
|
|
227
|
+
|
|
228
|
+
For creating animated demo videos, product showcases, or presentations without recording the real screen.
|
|
222
229
|
|
|
223
|
-
|
|
230
|
+
Read `references/programmatic-generation.md` for the full implementation guide.
|
|
231
|
+
|
|
232
|
+
**Stack**: Pillow (frame drawing) → MoviePy (video assembly) → pyttsx3 (TTS narration)
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
pip install "moviepy>=2.0" pillow pyttsx3
|
|
236
|
+
```
|
|
224
237
|
|
|
238
|
+
**Key pattern:**
|
|
225
239
|
```python
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
"narration": "Welcome to our product demo.",
|
|
231
|
-
"draw": draw_intro_scene
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
"title": "Feature 1",
|
|
235
|
-
"duration": 5,
|
|
236
|
-
"narration": "Our AI detects issues automatically.",
|
|
237
|
-
"draw": draw_feature1_scene
|
|
238
|
-
},
|
|
239
|
-
# ...
|
|
240
|
-
]
|
|
241
|
-
|
|
242
|
-
# Build timeline
|
|
240
|
+
from moviepy import VideoClip, AudioFileClip
|
|
241
|
+
from PIL import Image, ImageDraw
|
|
242
|
+
import numpy as np
|
|
243
|
+
|
|
243
244
|
def make_frame(t):
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
245
|
+
img = Image.new('RGB', (1280, 720), (12, 12, 32))
|
|
246
|
+
draw = ImageDraw.Draw(img)
|
|
247
|
+
draw.text((100, 300), f"Frame at t={t:.1f}s", fill=(255, 255, 255))
|
|
248
|
+
return np.array(img)
|
|
249
|
+
|
|
250
|
+
clip = VideoClip(make_frame, duration=10)
|
|
251
|
+
clip.write_videofile("demo.mp4", fps=24, logger=None)
|
|
251
252
|
```
|
|
252
253
|
|
|
253
254
|
---
|
|
254
255
|
|
|
255
|
-
##
|
|
256
|
+
## Post-Processing (FFmpeg)
|
|
256
257
|
|
|
257
258
|
```bash
|
|
258
|
-
#
|
|
259
|
-
ffmpeg -i
|
|
259
|
+
# Compress for sharing
|
|
260
|
+
ffmpeg -i recording.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k compressed.mp4
|
|
261
|
+
|
|
262
|
+
# Trim (start at 5s, keep 30s)
|
|
263
|
+
ffmpeg -i recording.mp4 -ss 00:00:05 -t 00:00:30 -c copy trimmed.mp4
|
|
260
264
|
|
|
261
|
-
#
|
|
262
|
-
ffmpeg -i
|
|
265
|
+
# Convert to GIF (for docs/chat)
|
|
266
|
+
ffmpeg -i recording.mp4 -vf "fps=12,scale=960:-1:flags=lanczos" -loop 0 demo.gif
|
|
263
267
|
|
|
264
|
-
#
|
|
265
|
-
ffmpeg -i
|
|
268
|
+
# Add text overlay
|
|
269
|
+
ffmpeg -i recording.mp4 -vf "drawtext=text='Demo':fontcolor=white:fontsize=24:x=20:y=20" overlay.mp4
|
|
266
270
|
|
|
267
|
-
#
|
|
268
|
-
ffmpeg -i
|
|
271
|
+
# Extract audio
|
|
272
|
+
ffmpeg -i recording.mp4 -vn -c:a mp3 audio.mp3
|
|
269
273
|
|
|
270
|
-
# Concatenate
|
|
274
|
+
# Concatenate clips
|
|
271
275
|
# Create concat.txt: file 'clip1.mp4' \n file 'clip2.mp4'
|
|
272
276
|
ffmpeg -f concat -safe 0 -i concat.txt -c copy combined.mp4
|
|
273
277
|
```
|
|
274
278
|
|
|
275
279
|
---
|
|
276
280
|
|
|
277
|
-
## Installation
|
|
281
|
+
## Installation
|
|
282
|
+
|
|
283
|
+
### FFmpeg (required for Approach 1)
|
|
284
|
+
|
|
285
|
+
| Platform | Command |
|
|
286
|
+
|----------|---------|
|
|
287
|
+
| Windows | `choco install ffmpeg` or `winget install FFmpeg` or download from ffmpeg.org |
|
|
288
|
+
| macOS | `brew install ffmpeg` |
|
|
289
|
+
| Ubuntu/Debian | `sudo apt install ffmpeg` |
|
|
290
|
+
| Arch | `sudo pacman -S ffmpeg` |
|
|
291
|
+
|
|
292
|
+
Verify: `ffmpeg -version`
|
|
293
|
+
|
|
294
|
+
### Python packages
|
|
278
295
|
|
|
279
296
|
```bash
|
|
280
|
-
#
|
|
281
|
-
pip install
|
|
297
|
+
# For Approach 2 (Python fallback)
|
|
298
|
+
pip install mss opencv-python numpy
|
|
282
299
|
|
|
283
|
-
#
|
|
284
|
-
|
|
300
|
+
# For Approach 3 (synthetic video generation)
|
|
301
|
+
pip install "moviepy>=2.0" pillow pyttsx3
|
|
285
302
|
|
|
286
|
-
#
|
|
287
|
-
|
|
303
|
+
# On Linux, for TTS in Approach 3:
|
|
304
|
+
# sudo apt install espeak-ng
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Wayland (Linux)
|
|
308
|
+
|
|
309
|
+
If on Wayland (`echo $WAYLAND_DISPLAY` returns a value), install wf-recorder:
|
|
310
|
+
```bash
|
|
311
|
+
sudo apt install wf-recorder # Ubuntu
|
|
312
|
+
sudo pacman -S wf-recorder # Arch
|
|
288
313
|
```
|
|
289
314
|
|
|
290
315
|
---
|
|
@@ -292,18 +317,23 @@ python3 -c "from moviepy import VideoClip; import pyttsx3; print('OK')"
|
|
|
292
317
|
## Common Pitfalls
|
|
293
318
|
|
|
294
319
|
| Problem | Solution |
|
|
295
|
-
|
|
296
|
-
|
|
|
297
|
-
|
|
|
298
|
-
|
|
|
299
|
-
|
|
|
300
|
-
|
|
|
301
|
-
|
|
|
320
|
+
|---------|----------|
|
|
321
|
+
| FFmpeg not found | Install FFmpeg and ensure it's on PATH |
|
|
322
|
+
| Windows: no audio device | Enable "Stereo Mix" in Sound Settings → Recording → Show Disabled Devices |
|
|
323
|
+
| macOS: permission denied | Grant Screen Recording permission: System Settings → Privacy → Screen Recording |
|
|
324
|
+
| Linux: `x11grab` fails on Wayland | Use `wf-recorder` instead (see Wayland section) |
|
|
325
|
+
| Linux: no audio with x11grab | Install PulseAudio: `sudo apt install pulseaudio` |
|
|
326
|
+
| Black/empty video | Check DISPLAY variable on Linux (`echo $DISPLAY`), permissions on macOS |
|
|
327
|
+
| Recording too large | Re-encode: `ffmpeg -i big.mp4 -crf 28 -preset slow small.mp4` |
|
|
328
|
+
| Python fallback: low FPS | Reduce capture resolution or target FPS |
|
|
329
|
+
| Python fallback: no cursor | Known limitation — use FFmpeg approach for cursor capture |
|
|
330
|
+
| MoviePy import error | Use `from moviepy import VideoClip` (v2 syntax), install `moviepy>=2.0` |
|
|
302
331
|
|
|
303
332
|
---
|
|
304
333
|
|
|
305
334
|
## Reference Files
|
|
306
335
|
|
|
307
|
-
- `references/
|
|
308
|
-
- `references/
|
|
309
|
-
- `references/
|
|
336
|
+
- `references/ffmpeg-recording.md` — Full FFmpeg command reference per platform, audio devices, window capture, quality tuning
|
|
337
|
+
- `references/python-fallback.md` — Complete mss + OpenCV recording template with performance tips
|
|
338
|
+
- `references/programmatic-generation.md` — Pillow + MoviePy synthetic video generation (animated demos)
|
|
339
|
+
- `references/design-patterns.md` — UI components and animation patterns for synthetic videos
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Design Patterns for Screen Recording Videos
|
|
2
2
|
|
|
3
|
+
> **Font note**: All `draw.text()` examples below omit the `font=` parameter for brevity. Always pass a loaded TrueType font (see SKILL.md "Font Handling" section) to avoid tiny unreadable text.
|
|
4
|
+
|
|
3
5
|
## UI Component Library (Pillow)
|
|
4
6
|
|
|
5
7
|
### Rounded Rectangle
|
|
@@ -164,5 +166,5 @@ subprocess.run([
|
|
|
164
166
|
- [ ] `total_duration = sum(s["duration"] for s in SCENES)` is correct
|
|
165
167
|
- [ ] `make_frame` returns `np.array(img)` (not PIL Image)
|
|
166
168
|
- [ ] Audio `.with_duration(total_duration)` called
|
|
167
|
-
- [ ] Output path
|
|
168
|
-
- [ ] `apt-get install -y espeak-ng` was run if pyttsx3 is used
|
|
169
|
+
- [ ] Output path uses `os.getcwd()` or user-specified directory
|
|
170
|
+
- [ ] On Linux: `apt-get install -y espeak-ng` was run if pyttsx3 is used
|