Media generation
A production-ready CLI for multi-provider media generation. Generate images, videos, voice, and transcriptions through OpenAI, Google, Azure & others
npx -y skills add onimusya/media-gen --skill media-generationAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Generate and edit images, create videos, synthesize speech, transcribe and translate audio using multiple AI providers (OpenAI, Google, ElevenLabs, Deepgram, Fal, Luma, Replicate, Stability, Runway, OpenRouter, Edge TTS). Use when the user asks to create media assets, generate pictures, make videos, produce voiceovers, transcribe recordings, or work with any visual/audio content.
SKILL.md
8.4 KB, ~2.2k tokens by cl100k_base, as published. Nobody here has run it
Media Generation
Run the CLI at ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs with Node.js. Always use --json for parseable output.
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs <command> [options] --json
Commands
| Command | Purpose |
|---|---|
image generate | Generate images from text prompts |
image edit | Edit existing images with a prompt |
video generate | Generate video from text (async) |
video image-to-video | Animate an image into video |
video extend | Extend an existing video |
voice tts | Text to speech synthesis |
voice clone | Clone a voice from audio samples |
voice isolate | Isolate voice from background audio |
audio transcribe | Transcribe audio to text |
audio translate | Translate audio to another language |
providers list | List all providers with capabilities, models, and voices |
providers list --configured | List only configured providers |
providers list --capability <cap> | Filter by capability |
providers models | List all models across all providers |
providers models --provider <id> | List models/voices for a specific provider |
providers models --capability <cap> | Filter models by capability |
config init | Initialize project-level config |
config init --global | Initialize user-level config at ~/.media-gen/ |
config validate | Check which providers are configured |
job status | Check async job status |
job download | Download completed async job result |
Configuration
Defaults are set via .env (at project root or ~/.media-gen/.env for global). With defaults configured, --provider, --model, and --voice-id are all optional:
MEDIA_GEN_DEFAULT_PROVIDER=openrouter
MEDIA_GEN_DEFAULT_MODEL=openai/gpt-image-2
MEDIA_GEN_VOICE_PROVIDER=edge-tts
MEDIA_GEN_VOICE_MODEL=
MEDIA_GEN_VOICE_ID=en-US-EmmaMultilingualNeural
MEDIA_GEN_VIDEO_PROVIDER=google
MEDIA_GEN_VIDEO_MODEL=veo-3.1-generate-preview
MEDIA_GEN_AUDIO_PROVIDER=deepgram
MEDIA_GEN_AUDIO_MODEL=nova-3
MEDIA_GEN_LOG_LEVEL=error
Examples
Image generation
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs image generate \
--prompt "A pixel art fantasy arena" \
--output ./outputs/arena.png \
--json
Video generation (wait for result)
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs video generate \
--provider google \
--model veo-3.1-generate-preview \
--prompt "A cinematic card pack opening" \
--duration 8 \
--output ./outputs/video.mp4 \
--wait \
--json
Text to speech (Edge TTS - free, no API key)
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs voice tts \
--provider edge-tts \
--voice-id en-US-EmmaMultilingualNeural \
--text "Hello world" \
--output ./outputs/voice.mp3 \
--json
Text to speech (ElevenLabs)
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs voice tts \
--provider elevenlabs \
--voice-id JBFqnCBsd6RMkjVDRZzb \
--text "Welcome to the show" \
--output ./outputs/george.mp3 \
--json
Text to speech (Google Gemini TTS)
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs voice tts \
--provider google \
--model gemini-3.1-flash-tts-preview \
--voice-id Kore \
--text "Say cheerfully: Have a wonderful day!" \
--output ./outputs/gemini-voice.wav \
--json
Text to speech (OpenAI)
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs voice tts \
--provider openai \
--model gpt-4o-mini-tts \
--voice-id coral \
--text "Hello from OpenAI" \
--output ./outputs/openai-voice.mp3 \
--json
Text to speech (with defaults set, minimal)
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs voice tts \
--text "Just provide text when defaults are configured" \
--output ./outputs/speech.mp3 \
--json
Transcription
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs audio transcribe \
--input ./audio/recording.mp3 \
--output ./outputs/transcript.json \
--json
List supported providers and models
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs providers list --json
List voices for a TTS provider
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs providers models --provider edge-tts --json
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs providers models --provider elevenlabs --json
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs providers models --provider openai --json
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs providers models --provider google --json
Dry run (validate without calling API)
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs image generate \
--prompt "test" --dry-run --json
Async Video Jobs
Video generation is asynchronous. Providers return a job ID instead of a file.
Pattern 1: Wait for completion (simple)
Add --wait to block until the video is ready:
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs video generate \
--provider google \
--model veo-3.1-generate-preview \
--prompt "A cinematic scene" \
--output ./outputs/video.mp4 \
--wait \
--poll-interval 5000 \
--timeout 300000 \
--json
Returns the final file path when complete.
Pattern 2: Non-blocking (get job ID, check later)
Without --wait, the CLI returns immediately with a job ID:
# Start generation (returns instantly)
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs video generate \
--provider google \
--model veo-3.1-generate-preview \
--prompt "A cinematic scene" \
--json
# Returns: {"ok": true, "jobId": "operations/abc123", "status": "processing"}
# Check status later
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs job status \
--provider google \
--job-id "operations/abc123" \
--json
# Returns: {"ok": true, "jobId": "...", "status": "completed"}
# Download the result
node ${CLAUDE_SKILL_DIR}/scripts/media-gen.mjs job download \
--provider google \
--job-id "operations/abc123" \
--output ./outputs/video.mp4 \
--json
Async options
| Option | Default | Description |
|---|---|---|
--wait | false | Block until job completes |
--poll-interval | 5000 | Milliseconds between status checks |
--timeout | 600000 | Max wait time (10 minutes) |
Async providers
Google (Veo), Luma AI, Runway, Fal.ai, and Replicate all use async for video. Image and TTS are always synchronous.
Response format
Success:
{"ok": true, "type": "image", "provider": "openai", "model": "gpt-image-2", "outputFile": "./outputs/image.png", "durationMs": 1200}
Error:
{"ok": false, "error": {"code": "PROVIDER_NOT_CONFIGURED", "message": "Missing OPENAI_API_KEY", "suggestion": "Set OPENAI_API_KEY in .env"}}
Rules
- Use
--jsonfor all calls. - Use
--dry-runbefore expensive operations when unsure. - Never use
--overwriteunless the user confirms. - Keep outputs inside the project workspace.
- For video, use
--waitonly when the user wants the file immediately. - Check the
okfield in every response before proceeding. - On error, show the
suggestionfield to the user. - For TTS,
--voice-idis optional whenMEDIA_GEN_VOICE_IDis set in .env. - Edge TTS is free and requires no API key — prefer it for basic TTS tasks.
Provider Capabilities
| Provider | Image | Video | TTS | Transcribe | Translate | Clone | Isolate |
|---|---|---|---|---|---|---|---|
| openai | Yes | Yes | Yes | Yes | |||
| Yes | Yes | Yes | |||||
| azure | Yes | Yes | Yes | Yes | |||
| elevenlabs | Yes | Yes | Yes | ||||
| deepgram | Yes | Yes | Yes | ||||
| fal | Yes | Yes | |||||
| luma | Yes | ||||||
| replicate | Yes | Yes | |||||
| stability | Yes | ||||||
| runway | Yes | ||||||
| openrouter | Yes | Yes | |||||
| edge-tts | Yes (free) |
What ships with it: 9 files
543.7 KB alongside SKILL.md, 7 of them executable
scripts/
- install.cmdruns1023 B
- install.ps1runs1.7 KB
- install.shruns1.1 KB
- media-gen.cmdruns78 B
- media-gen.mjsruns533.3 KB
- media-gen.ps1runs145 B
- media-gen.shruns148 B
- LICENSE1.0 KB
- RELEASE_NOTES.md5.3 KB
Gives 0 of the 12 instructions most media documents skills give in ~2.2k tokens
Counted across 157 of the 158 authors here whose files we hold, read 2026-08-07
- Provide posting time recommendationsin 7 of 157, across 5 files
- Track metrics over time to identify trendsin 6 of 157, across 2 files
- Read marketing context file before startingin 6 of 157, across 5 files
- Choose platforms based on audience presencein 6 of 157, across 4 files
- Adapt tone for each platformin 6 of 157, across 4 files
- Ensure data completeness before analysisin 5 of 157, across 1 file
- Compare metrics within same time periodsin 5 of 157, across 1 file
- Account for platform-specific benchmarksin 5 of 157, across 1 file
- Separate organic and paid metricsin 5 of 157, across 1 file
- Include context when interpreting resultsin 5 of 157, across 1 file
- Keep tweets under 280 charactersin 5 of 157, across 3 files
- Download top-K results with an attribution sidecarin 5 of 157, across 2 files
Said here and by no other author read
- use --json for all calls
- check the ok field in every response
- show the suggestion field on error
- prefer edge-tts for basic tts tasks
- use --dry-run before expensive operations
- never use --overwrite unless user confirms
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.