From process-video
Process and share videos. Optimize for web, transcribe audio, add subtitles, burn captions, and share via S3 or local tunnel with short unique URLs. Triggers on: "process video", "share video", "share latest", "video status", "stop sharing", "copy link", "/video".
How this skill is triggered — by the user, by Claude, or both
Slash command
/process-video:videoThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Process and share videos using ffmpeg, Deepgram Nova 3, and S3/tunnel sharing.
Process and share videos using ffmpeg, Deepgram Nova 3, and S3/tunnel sharing.
ffmpeg and ffprobe must be installedaws CLI must be available (for S3 uploads)<skill_dir>/scripts/ — all Python scripts and the player.html template~/.config/video-skill/ — persistent across plugin updates
deepgram_token — single-line Deepgram API keys3_credentials — key=value format (endpoint, bucket, access_key, secret_key)~/.config/video-skill/preferences.json — user choices saved across sessionsIf credentials are missing when needed, ask the user via AskUserQuestion:
Deepgram: Check DEEPGRAM_API_KEY env, then ~/.config/video-skill/deepgram_token file. If neither exists, ask the user and save to the file.
S3: Check env vars (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, S3_ENDPOINT, S3_BUCKET), then ~/.config/video-skill/s3_credentials. If missing, ask the user for endpoint, bucket, access_key, secret_key and save.
Important: Never pass credentials as CLI arguments. Scripts read them from files internally via --credential-dir ~/.config/video-skill.
{
"language": "en",
"last_folder": "/Users/example/screencasts",
"share_folder": "/Users/example/screencasts",
"sharing_method": "s3",
"optimization": "web-1080p",
"crf": 23,
"preset": "medium",
"audio": "aac-128k",
"subtitles": "track",
"subtitle_style": "modern",
"subtitle_font": "Helvetica Neue",
"target_language": "ru",
"download_button": true,
"passcode": true
}
Saving: After every interactive choice, update preferences.json. Always save last_folder after every run.
Loading: Read at start. Use saved values as "(Recommended)" defaults. In silent mode, use directly.
All scripts are in <skill_dir>/scripts/. They accept --credential-dir for credentials and print [PROGRESS] lines for status tracking.
| Script | Purpose | Key Args |
|---|---|---|
process_and_share.py | Main workflow: optimize + transcribe + render + upload | <video> --output-dir --share-folder --share s3|tunnel |
share_existing.py | Share a pre-processed folder | <folder> --share-folder --share s3|tunnel |
upload_s3.py | Upload folder to S3 | <folder> --key <key> --credential-dir |
render_page.py | Generate index.html from template | --output-dir --template --metadata |
manage_registry.py | Registry CRUD (add/remove/list/get/migrate) | <subcommand> --share-folder |
transcribe.py | Deepgram transcription → SRT + VTT | <video> --credential-dir [--language] |
burn_subtitles.py | Burn subtitles into video | <video> <srt> [--font --fontsize ...] |
share_server.py | Local HTTP server for tunnel sharing | <share_root> [--port] |
Commands:
/video → Interactive mode (Steps 1-5)/video process <path> → Interactive mode for specific file/video share → Silent mode: process latest + share/video share <path> → Silent mode: process specific file + share/video share <path> "context" → Silent mode with extra context for metadata/video start → Start sharing server + tunnel/video stop → Stop sharing/video status → List shared videos/video copy <key_or_name> → Copy link + passcode to clipboard/video remove <key_or_name> → Remove from registryShare registry: <share_folder>/.share_registry.json — managed by manage_registry.py.
start command:
share_folder. If not set, ask.pgrep -f share_server.py. If running, show status.python3 "<scripts>/share_server.py" "<share_folder>" --port 8080 &ssh -p 443 -R0:localhost:<port> -o StrictHostKeyChecking=no a.pinggy.io 2>&1 &<base_url>/v/<key>).stop command:
pkill -f share_server.py; pkill -f "ssh.*pinggy"; pkill -f "ngrok http"
status command:
python3 "<scripts>/manage_registry.py" list --share-folder "<share_folder>"pgrep -f share_server.py for tunnel status.copy command:
python3 "<scripts>/manage_registry.py" get --share-folder "<share_folder>" --key "<query>"<title>\n<url>\nPasscode: <code> → pbcopyremove command:
Run python3 "<scripts>/manage_registry.py" remove --share-folder "<share_folder>" --key "<query>"
/video share)One confirmation, one script execution, minimal interaction.
Flow:
Identify video (argument path or newest in last_folder / CWD)
Create output folder <share_folder>/<video_name>/
Generate passcode (random 6-digit or saved preference)
Show confirmation:
Quick share: demo.mov
→ 1080p, CRF 23, AAC 128k
→ Transcribe + subtitles (track)
→ Share via S3 (permanent link)
→ Passcode: 482910
Proceed?
Options: Proceed (Recommended) / Switch to interactive mode
Run the main workflow script:
python3 "<scripts>/process_and_share.py" "<video_path>" \
--output-dir "<output_folder>" \
--share-folder "<share_folder>" \
--credential-dir ~/.config/video-skill \
--resolution 1080p --crf 23 --preset medium --audio aac-128k \
--subtitles track \
--share s3 \
--passcode "<passcode>" \
[--context "<user_context>"]
Monitor stdout for METADATA_READY: — when the script prints this marker:
a. Read the TRANSCRIPT_PREVIEW: and METADATA_INFO: that preceded it
b. Parse METADATA_INFO: as JSON to get video_filename, vtt_filename, subtitle_lang
c. Generate title, description, and 4-8 chapters from the transcript preview
d. Write metadata.json to the output directory:
{
"title": "Generated Title",
"description": "Generated description...",
"chapters": [{"time": 0, "label": "Intro"}, ...],
"video_filename": "video_1080p.mp4",
"subtitle_tracks": [{"src": "video.vtt", "srclang": "en", "label": "English", "default": true}]
}
e. The script detects metadata.json and continues automatically.
Script finishes. Display result, link is already copied to clipboard.
Ask about original file: Move to output folder (Recommended) / Delete / Leave in place
If already-processed folder (has index.html): Run share_existing.py instead:
python3 "<scripts>/share_existing.py" "<folder>" \
--share-folder "<share_folder>" \
--credential-dir ~/.config/video-skill \
--share s3 \
[--passcode "<code>"]
/video or /video process)Full workflow with user choices at each step.
Ask via AskUserQuestion: English (Recommended), German, Russian, or Other.
Save to preferences. All subsequent communication in chosen language.
last_folder from preferences → CWD.mp4, .mkv, .avi, .mov, .webm, .m4v)AskUserQuestion<folder>/<video_name>/
Save last_folder to preferences.Ask two questions via AskUserQuestion:
Q1: Video optimization — Save to preferences.json → optimization
Q2: Subtitles — Save to preferences.json → subtitles
If web optimization selected, show default table and ask "Proceed or customize?"
| Setting | Value |
|---|---|
| Resolution | 1920×1080 (aspect ratio preserved) |
| Codec | H.264 (libx264) |
| CRF | 23 |
| Preset | medium |
| Audio | AAC 128 kbps |
| Faststart | Yes |
If custom: ask Resolution, CRF, Preset, Audio individually. Save each to preferences.
Build the confirmation summary:
Will process: video.mov (3840×2160, 3:44, 305 MB)
→ 1080p, CRF 23, medium, AAC 128k
→ Transcribe + subtitles as track
→ Share via S3
→ Passcode: 482910
User approves once, then run process_and_share.py with the chosen settings.
python3 "<scripts>/process_and_share.py" "<video_path>" \
--output-dir "<output_folder>" \
--share-folder "<share_folder>" \
--credential-dir ~/.config/video-skill \
--resolution <resolution> --crf <crf> --preset <preset> --audio <audio> \
--subtitles <track|burn|none> [--subtitle-lang <code>] \
--share <s3|tunnel|both|none> \
--passcode "<passcode>" \
[--download-button | --no-download-button]
Monitor stdout for METADATA_READY: — same as silent mode step 6.
If subtitles are set to "burn", the script handles it internally after transcription.
If translation was requested (Step 3), the translation itself is done by Claude after receiving the SRT content — this is the one case where more interaction is needed:
burn_subtitles.py manually if burning was requestedAfter the script completes, show summary table (ffprobe both files) and report results.
| Preset | Font | Size | Outline | Shadow | Bold | Color |
|---|---|---|---|---|---|---|
| Classic | Arial | 18 | 1 | 1 | 1 | White |
| Modern | Helvetica Neue | 18 | 1 | 1 | 1 | White |
| Cinematic | Georgia | 18 | 1 | 0 | 0 | White |
| High Contrast | Arial | 22 | 2 | 2 | 1 | Yellow |
Important: Never scale font sizes for higher resolutions. Always downscale to 1080p first.
brew install ffmpegAskUserQuestion, save to ~/.config/video-skill/deepgram_token, re-run~/.config/video-skill/s3_credentialsnpx claudepluginhub georg-malahov/claude-skills --plugin process-videoProcesses videos: download, trim, silence removal, audio extraction, transcription (Whisper), captions, speed change, concatenation, audio enhancement, upload to YouTube/Bunny.net, social posts. Requires ffmpeg, yt-dlp, and API keys.
Ingests video/audio from files, URLs, RTSP feeds, or desktop capture; indexes visual/spoken content for search; transcodes, edits timelines, generates assets, and creates real-time alerts.
Edits, processes, and renders videos using FFmpeg and Remotion. Handles stitching clips, transitions, captions, teasers, transcription via Whisper, and analysis with ffprobe.