medeo-video

AI-powered video generation skill. Use when the user wants to generate videos from text descriptions, browse video recipes, upload assets, or manage video creation workflows.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "medeo-video" with this command: npx skills add one2x-ai/medeo-video-skill/one2x-ai-medeo-video-skill-medeo-video

Medeo Video Generator Skill

Generate AI videos from text. Medeo is an AI video agent that handles full storylines, multi-scene narratives, and screenplays in a single call — shot composition, transitions, pacing, and music are all automatic.

⚠️ Do NOT split stories into multiple calls. Pass the entire screenplay in one --message.

0. Pre-Flight Check (MANDATORY — run before anything else)

Before running any command, check if API key is configured:

python3 {baseDir}/scripts/medeo_video.py config 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print('ok' if d.get('apiKey') else 'missing')"
  • Output ok → proceed normally
  • Output missing (or command fails) → stop immediately, do NOT run any other commands. Send the setup message using the channel-appropriate method:

Feishu — use Feishu API directly (NOT message tool — it won't render cards):

import json, urllib.request
cfg = json.loads(open("/home/ec2-user/.openclaw/openclaw.json").read())
feishu = cfg["channels"]["feishu"]["accounts"]["default"]
token = json.loads(urllib.request.urlopen(urllib.request.Request(
    "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
    data=json.dumps({"app_id": feishu["appId"], "app_secret": feishu["appSecret"]}).encode(),
    headers={"Content-Type": "application/json"}
)).read())["tenant_access_token"]
card = {
    "config": {"wide_screen_mode": True},
    "header": {"title": {"tag": "plain_text", "content": "🎬 Video Generation — API Key Required"}, "template": "blue"},
    "elements": [{"tag": "div", "text": {"tag": "lark_md", "content": "You need a **Medeo API Key** to generate videos.\n\n**Steps:**\n1. Go to https://medeo.app/dev/apikey\n   - No account? You'll be guided to sign up. The key appears after login.\n2. Copy the key (starts with `mk_`) and send it back to me.\n\nOnce I have it, I'll configure everything for you."}}],
}
urllib.request.urlopen(urllib.request.Request(
    "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id",
    data=json.dumps({"receive_id": "<USER_OPEN_ID>", "msg_type": "interactive", "content": json.dumps(card)}).encode(),
    headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
))

Telegram / Discord / Other channels — send plain text via message tool (these channels support markdown natively):

🎬 Video Generation — API Key Required

Steps:
1. Go to https://medeo.app/dev/apikey (sign up if needed — the key appears after login)
2. Copy the key (starts with mk_) and send it back to me

Once I have it, I'll configure everything for you.

Once they provide the key: python3 {baseDir}/scripts/medeo_video.py config-init --api-key "mk_..."

1. First-Time Setup

If no API Key is configured, the script outputs "setup_required": true.

  1. Send the user this exact link: https://medeo.app/dev/apikey (this page auto-prompts registration if not logged in, then shows the API key)
  2. Once they provide the key: python3 {baseDir}/scripts/medeo_video.py config-init --api-key "mk_..."

2. Generate a Video (5-30 min, always async)

Users only need to know 3 ways to generate a video:

  1. Send text → generate video
  2. Send text + upload image → generate video using their image
  3. Send text + image URL → generate video using the URL image

The agent handles everything else silently.

IMPORTANT: Before spawning the generation task, immediately reply to the user with an acknowledgment like: "🎬 Starting video generation — I'll send you the result in about 5–10 minutes." Do NOT wait in silence. The user should know their request was received.

Usage 1: Text only

python3 {baseDir}/scripts/medeo_video.py spawn-task \
  --message "user's video description" \
  --deliver-to "oc_xxx" \
  --deliver-channel "feishu"

Usage 2: Text + uploaded image (user sends image in chat)

# First: upload-file to get media_id (see Section 3)
python3 {baseDir}/scripts/medeo_video.py spawn-task \
  --message "user's video description" \
  --media-ids "media_01..." \
  --asset-sources my_uploaded_assets \
  --deliver-to "oc_xxx" \
  --deliver-channel "feishu"

Usage 3: Text + image URL

python3 {baseDir}/scripts/medeo_video.py spawn-task \
  --message "user's video description" \
  --media-urls "https://example.com/photo.jpg" \
  --asset-sources my_uploaded_assets \
  --deliver-to "oc_xxx" \
  --deliver-channel "feishu"

Agent auto-behavior: When the user provides images (Usage 2 or 3), always pass --asset-sources my_uploaded_assets so Medeo uses their images instead of generating new ones. The user does not need to know this flag exists.

Internal Parameters (agent use only — never expose to users)

These are handled automatically by the agent. Do NOT mention them to users or ask users to provide them.

FlagWhen to useDefault behavior
--voice-id "voice_01..."When a specific voice is neededMedeo picks automatically
--video-style-id "style_01..."When a specific visual style is neededMedeo picks automatically
--asset-sourcesWhen user provides images: pass my_uploaded_assetsMedeo decides
--recipe-id "recipe_01..."When using a templateNone
--aspect-ratio "9:16"When user specifies portrait/landscape16:9
--duration-ms 30000When user specifies durationMedeo decides
--no-renderDebug only — skip renderingAlways render

Delivery Target (--deliver-to)

This is critical — determines where the generated video gets sent.

Context--deliver-to valueExample
Feishu group chatThe group's chat_id (starts with oc_). Extract from inbound metadata conversation_label or chat_idstrip the chat: prefix if present (e.g. chat:oc_xxxoc_xxx)oc_158fd3e54407cbe170697c6c954bd4f2
Feishu private chatThe user's open_id (starts with ou_). Extract from inbound metadata sender_idstrip the user: prefix if presentou_f7f458f4d7b4ff49ec1b8de22a1e3206
TelegramThe chat_id from the inbound message context-1001234567890
DiscordThe channel_id from the inbound message context1234567890123456

How to determine group vs private on Feishu:

  • Check is_group_chat in the inbound metadata
  • If true → use conversation_label / chat_id (the oc_ value)
  • If false → use sender_id (the ou_ value)

Step 2: Use sessions_spawn with the returned args (label: "medeo: <brief>", runTimeoutSeconds: 2400). Step 3: Tell user it's generating. Sub-agent auto-announces when done.

3. Upload Assets

3a. From URL (image already has a public URL)

python3 {baseDir}/scripts/medeo_video.py upload \
  --url "https://example.com/photo.jpg" \
  --project-id "project_01..."          # optional: associate media with existing project
  --no-wait                             # optional: return job_id immediately without polling

3b. From IM attachment (user sends image directly) ← NEW

Use upload-file when the user sends an image via Telegram, Discord, Feishu, or as a local file. This uses the direct upload API (prepare → S3 presigned PUT → register) instead of URL-based upload.

Trigger: Only when the user explicitly requests video generation AND sends an image attachment in the same message (e.g. "make a video with this photo"). Do NOT auto-upload on every image message — other skills or conversations may involve images unrelated to video generation.

# From local file (downloaded by OpenClaw from attachment)
python3 {baseDir}/scripts/medeo_video.py upload-file \
  --file /tmp/user_photo.jpg

# From direct URL (Discord CDN, etc.)
python3 {baseDir}/scripts/medeo_video.py upload-file \
  --url "https://cdn.discordapp.com/attachments/..."

# From Telegram (file_id from message.photo[-1].file_id)
# TELEGRAM_BOT_TOKEN must be set as env var — never pass as CLI arg (ps aux leaks it)
TELEGRAM_BOT_TOKEN="$TELEGRAM_BOT_TOKEN" python3 {baseDir}/scripts/medeo_video.py upload-file \
  --telegram-file-id "AgACAgIAAxk..."

# From Feishu (message_id + image_key from message content)
python3 {baseDir}/scripts/medeo_video.py upload-file \
  --feishu-message-id "om_xxx" \
  --feishu-image-key "img_v3_xxx" \
  --feishu-app-token "$FEISHU_APP_TOKEN"

Output: {"media_id": "media_01...", "filename": "photo.jpg"}

Then pass media_id to generation:

python3 {baseDir}/scripts/medeo_video.py spawn-task \
  --message "Create a video featuring this person" \
  --media-ids "media_01..."

Platform-Specific Image Extraction Guide

PlatformHow to get image sourceupload-file arg
Telegrammessage.photo[-1].file_id--telegram-file-id
Discordmessage.attachments[0].url (public CDN URL)--url
Feishumessage_id + image_key from message content JSON--feishu-message-id + --feishu-image-key
WhatsAppDownload attachment binary → save to /tmp--file
Generic URLAny direct image URL--url

Note: Discord attachment URLs are public CDN links — --url works directly. All other platforms require authentication to download.

3c. Inline in generate pipeline

# URL-based (existing behavior)
python3 {baseDir}/scripts/medeo_video.py spawn-task \
  --message "Product showcase for this sneaker" \
  --media-urls "https://example.com/front.jpg" "https://example.com/side.jpg"

Supports .jpg, .png, .webp, .mp4, .mov, .gif. Higher resolution + multiple angles = better results.

3d. Check Upload Status

After upload or upload-file, if you need to check the upload job:

python3 {baseDir}/scripts/medeo_video.py upload-status --job-id "job_01..."

Returns media status (processing, completed, failed) and media_id once done.

4. Low-Level Pipeline Commands (agent internal — never expose to users)

These are for agent debugging or manual intervention only. Users should never see these commands.

Pipeline flow:
  spawn-task (recommended, async)
      └── generate (blocking, same pipeline)
              ├── upload (if --media-urls)
              ├── compose → compose-status (poll)
              └── render → render-status (poll)
CommandWhat it doesKey args
generateBlocking full pipeline (upload→compose→render)Same as spawn-task minus deliver flags
composeCreate project only (no render)--message, --media-ids, --recipe-id
compose-statusPoll compose task--task-id "task_01..."
renderRender existing project--project-id "project_01..."
render-statusPoll render job--job-id "render_01..."
upload-statusPoll upload job--job-id "job_01..."

All commands support --no-wait to return immediately without polling.

5. Browse Recipes

python3 {baseDir}/scripts/medeo_video.py recipes              # list templates
python3 {baseDir}/scripts/medeo_video.py recipes --cursor <c>  # paginate

Use in generation: --recipe-id "recipe_01...". See docs/recipes.md.

6. Quick Commands Reference (for agent, not user-facing)

CommandDescriptionUser-visible?
recipesList video templatesYes — "what templates are available?"
last-jobLatest job statusYes — "is my last video done?"
historyJob history (last 50)Yes — "show my video history"
configShow current configurationNo
config-init --api-key "mk_..."Initialize API keyOnly during setup
upload --url "URL"Upload from public URLNo (agent internal)
upload-file --file PATHUpload from local fileNo (agent internal)
upload-file --url "URL"Download URL → uploadNo (agent internal)
upload-file --telegram-file-id "..."Upload Telegram attachmentNo (agent internal)
upload-file --feishu-image-key "..."Upload Feishu attachmentNo (agent internal)
upload-status --job-id "..."Check upload job statusNo (agent internal)
compose-status --task-id "..."Check compose task progressNo (agent internal)
render-status --job-id "..."Check render job progressNo (agent internal)

7. Key Rules

  1. Always asyncspawn-task + sessions_spawn for generation
  2. One call for stories — full storylines in one --message, never split
  3. Insufficient credits — share recharge link from error output
  4. IM image upload — Only upload images when the user explicitly asks for video generation with that image. Do NOT auto-upload every image message (user may have other skills installed). When triggered: run upload-file first → get media_id → pass to generation via --media-ids. Never ask the user for a URL if they already sent the image.
  5. IM-native delivery — After generation, deliver the video using the IM channel's native method (not just a URL). Each channel has a dedicated delivery script:
    • Feishu: python3 {baseDir}/scripts/feishu_send_video.py --video /tmp/result.mp4 --to "oc_xxx_or_ou_xxx" --cover-url "<thumbnail_url>" --duration <ms> (use oc_ chat_id for group chats, ou_ open_id for private chats; chat:oc_xxx and user:ou_xxx prefixed forms are also accepted)
    • Telegram: Download video, then send via telegram_send_video.py (token from env only):
      curl -sL -o /tmp/medeo_result.mp4 "<video_url>"
      TELEGRAM_BOT_TOKEN="$TELEGRAM_BOT_TOKEN" python3 {baseDir}/scripts/telegram_send_video.py \
        --video /tmp/medeo_result.mp4 \
        --to "<chat_id>" \
        --cover-url "<thumbnail_url>" \
        --duration <seconds> \
        --caption "🎬 Video ready!"
      
    • Discord: Use the message tool directly — download the video to /tmp/result.mp4 via curl -sL -o /tmp/result.mp4 "<video_url>", then call message(action="send", channel="discord", target="<channel_id>", message="🎬 Video ready!", filePath="/tmp/result.mp4"). For files >25 MB, send video_url as a plain link instead.
    • WhatsApp / Signal / Other: Use the message tool with media parameter, or share video_url as a link if native sending is unavailable.
    • Cover image URL: The generate output JSON includes thumbnail_url — the API always returns this field. Constructed as {ossBaseUrl}/{thumbnail_relative_path} (e.g. https://oss.prd.medeo.app/assets/medias/media_xxx.png).
    • Video URL: Same pattern — {ossBaseUrl}/{video_relative_path} (e.g. https://oss.prd.medeo.app/exported_video/v_xxx).
    • Security: Never pass bot tokens as CLI args (visible in ps). Always use env vars: TELEGRAM_BOT_TOKEN, DISCORD_BOT_TOKEN.
  6. Timeline completion — Medeo's backend is an AI agent. Generated images/videos must be added to the Timeline to trigger task completion and rendering. Always append to your prompt: "Add the generated video/image to the Timeline."

8. Error Handling

ErrorAction
setup_required: trueGuide user to register + configure key
upload_prep_rejectedFile format/size rejected; check supported formats
s3_put_failedS3 upload error; retry once
Insufficient creditsShare recharge link from error output, retry after top-up
Compose/render timeoutInform user, suggest retry. Complex scripts may take 15+ min
401/403Key may be invalid or expired, ask user to regenerate
Upload 404Some image hosts block server-side fetch; use upload-file --url to download first

9. Reference Docs

  • docs/recipes.md — Full recipe browsing and pagination
  • docs/assets-upload.md — All upload paths (URL, local file, IM attachments), platform-specific guides, upload vs upload-file comparison
  • docs/feishu-send.md — Sending generated video via Feishu (cover image, duration, compression)
  • docs/multi-platform.md — Multi-platform video delivery (Feishu, Telegram, Discord, WhatsApp)

10. Data Storage

All data in ~/.openclaw/workspace/medeo-video/: config.json (API key), last_job.json (latest job), history/ (last 50 jobs).

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

clinic-visit-prep

帮助患者整理就诊前问题、既往记录、检查清单与时间线,不提供诊断。;use for healthcare, intake, prep workflows;do not use for 给诊断结论, 替代医生意见.

Archived SourceRecently Updated
Automation

changelog-curator

从变更记录、提交摘要或发布说明中整理对外 changelog,并区分用户价值与内部改动。;use for changelog, release-notes, docs workflows;do not use for 捏造未发布功能, 替代正式合规审批.

Archived SourceRecently Updated
Automation

klaviyo

Klaviyo API integration with managed OAuth. Access profiles, lists, segments, campaigns, flows, events, metrics, templates, catalogs, and webhooks. Use this skill when users want to manage email marketing, customer data, or integrate with Klaviyo workflows. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).

Archived SourceRecently Updated
Automation

lifelog

生活记录自动化系统。自动识别消息中的日期(今天/昨天/前天/具体日期),使用 SubAgent 智能判断,记录到 Notion 对应日期,支持补录标记。 适用于:(1) 用户分享日常生活点滴时自动记录;(2) 定时自动汇总分析并填充情绪、事件、位置、人员字段

Archived SourceRecently Updated