podcast
Creates podcasts based on topics, URLs, or text, supporting multiple trigger words for quick audio content generation.
npx skills add marswaveai/skills --skill podcastBefore / After Comparison
1 组Producing podcasts requires professional recording and editing equipment, which is time-consuming and labor-intensive. Content creation has a high barrier to entry, making it difficult to quickly convert text or topics into audio.
Quickly generate podcasts based on topics, URLs, or text, simplifying audio content creation. Significantly lower the barrier to podcast production and expand content distribution channels.
description SKILL.md
name: podcast description: | Create podcasts from topics, URLs, or text. Triggers on: "做播客", "podcast", "播客", "录一期节目", "chat about", "discuss", "debate", "dialogue", "make a podcast about". metadata: openclaw: emoji: "🎙️" requires: env: ["LISTENHUB_API_KEY"] primaryEnv: "LISTENHUB_API_KEY"
When to Use
- User wants to create a podcast episode on any topic
- User provides a URL or text and wants it turned into a podcast discussion
- User asks for a "debate", "dialogue", or "discussion" format
- User says "podcast", "播客", or "录一期节目"
When NOT to Use
- User wants text-to-speech reading (use
/speech) - User wants an explainer video with visuals (use
/explainer) - User wants to generate an image (use
/image-gen) - User only wants to extract content from a URL without generating audio (use
/content-parser)
Purpose
Generate podcast episodes with 1-2 AI speakers discussing a topic. Supports quick overviews, deep analysis, and debate formats. Input can be a topic description, URL(s), or text. Output is a full audio episode with transcript.
Hard Constraints
- No shell scripts. Construct curl commands from the API reference files listed in Resources
- Always read
shared/authentication.mdfor API key and headers - Follow
shared/common-patterns.mdfor polling, errors, and interaction patterns - Never hardcode speaker IDs — always fetch from the speakers API
- Never fabricate API endpoints or parameters
- Always read config following
shared/config-pattern.mdbefore any interaction - Always follow
shared/speaker-selection.mdfor speaker selection (text table + free-text input) - Never save files to
~/Downloads/— use.listenhub/podcast/from config
Step -1: API Key Check
Follow shared/config-pattern.md § API Key Check. If the key is missing, stop immediately.
Step 0: Config Setup
Follow shared/config-pattern.md Step 0.
If file doesn't exist — ask location, then create immediately:
mkdir -p ".listenhub/podcast"
echo '{"outputDir":".listenhub","outputMode":"inline","language":null,"defaultMode":null,"defaultMethod":null,"defaultSpeakers":{}}' > ".listenhub/podcast/config.json"
CONFIG_PATH=".listenhub/podcast/config.json"
# (or $HOME/.listenhub/podcast/config.json for global)
Then run Setup Flow below.
If file exists — read config, display summary, and confirm:
当前配置 (podcast):
输出方式:{inline / download / both}
语言偏好:{zh / en / 未设置}
默认模式:{quick / deep / debate / 未设置}
默认生成方式:{one-step / two-step / 未设置}
默认主播:{speakerName(s) / 未设置}
Ask: "使用已保存的配置?" → 确认,直接继续 / 重新配置
Setup Flow (first run or reconfigure)
Ask these questions in order, then save all answers to config at once:
-
outputMode: Follow
shared/output-mode.md§ Setup Flow Question. -
Language (optional): "默认语言?"
- "中文 (zh)"
- "English (en)"
- "每次手动选择" → keep
null
-
Mode (optional): "默认播客模式?"
- "Quick — 简短概述"
- "Deep — 深度分析"
- "Debate — 辩论对话"
- "每次手动选择" → keep
null
-
Method (optional): "默认生成方式?"
- "一步生成(推荐)" →
defaultMethod: "one-step" - "两步生成(先预览文本)" →
defaultMethod: "two-step" - "每次手动选择" → keep
null
- "一步生成(推荐)" →
After collecting answers, save immediately:
# Follow shared/output-mode.md § Save to Config
NEW_CONFIG=$(echo "$CONFIG" | jq --arg m "$OUTPUT_MODE" '. + {"outputMode": $m}')
echo "$NEW_CONFIG" > "$CONFIG_PATH"
CONFIG=$(cat "$CONFIG_PATH")
Note: defaultSpeakers are saved after generation (see After Successful Generation section).
Interaction Flow
Step 1: Topic / Content Source
Free text input. Ask the user:
What topic or content would you like to turn into a podcast?
Accept: topic description, URL, or pasted text.
Step 2: Mode
If config.defaultMode is set, pre-fill and show in summary — skip this question.
Otherwise ask:
Question: "What podcast generation mode?"
Options:
- "Quick" — Short, concise overview (~5 min)
- "Deep" — Thorough analysis with more detail (~10-15 min)
- "Debate" — Two speakers with opposing views (requires 2 speakers)
Step 3: Language
If config.language is set, pre-fill and show in summary — skip this question.
Otherwise ask:
Question: "What language?"
Options:
- "Chinese (zh)" — Content in Mandarin Chinese
- "English (en)" — Content in English
Step 4: Speaker Count
Question: "How many speakers?"
Options:
- "1 speaker (solo)" — Monologue style
- "2 speakers (dialogue)" — Conversation style
Note: Debate mode automatically sets 2 speakers.
Step 5: Speaker Selection
Follow shared/speaker-selection.md for the full selection flow, including:
- Default from
config.defaultSpeakers.{language}(skip step if set) - Text table + free-text input
- Input matching and re-prompt on no match
For 2-speaker mode (dialogue/debate): run selection twice (or until both are chosen).
Step 6: Reference Materials (optional)
Question: "Any reference materials to include?"
Options:
- "Yes, URL(s)" — Provide URLs to analyze
- "Yes, text" — Paste reference text
- "No references" — Generate from topic alone
Step 7: Generation Method
If config.defaultMethod is set, pre-fill and show in summary — skip this question.
Otherwise ask:
Question: "How would you like to generate?"
Options:
- "One step (recommended)" — Generate text + audio together, faster
- "Two steps (review first)" — Generate text, review/edit, then generate audio
Step 8: Confirm & Generate
Summarize all choices:
Ready to generate podcast:
Topic: {topic}
Mode: {mode}
Language: {language}
Speakers: {speaker name(s)}
References: {yes/no}
Method: {one-step/two-step}
Proceed?
Wait for explicit confirmation before calling any API.
Workflow
One-Step Generation
-
Submit (foreground):
POST /podcast/episodeswith collected parameters → extractepisodeId -
Tell the user the task is submitted
-
Poll (background): Run the following exact bash command with
run_in_background: trueandtimeout: 600000. Do NOT use python3, awk, or any other JSON parser — usejqas shown:EPISODE_ID="<id-from-step-1>" for i in $(seq 1 30); do RESULT=$(curl -sS "https://api.marswave.ai/openapi/v1/podcast/episodes/$EPISODE_ID" \ -H "Authorization: Bearer $LISTENHUB_API_KEY" 2>/dev/null) STATUS=$(echo "$RESULT" | tr -d '\000-\037\177' | jq -r '.data.processStatus // "pending"') case "$STATUS" in success|completed) echo "$RESULT"; exit 0 ;; failed|error) echo "FAILED: $RESULT" >&2; exit 1 ;; *) sleep 10 ;; esac done echo "TIMEOUT" >&2; exit 2 -
When notified of completion, Step 6: Present result
Read
OUTPUT_MODEfrom config. Followshared/output-mode.mdfor behavior.inlineorboth: DisplayaudioUrlas a clickable link.Present:
播客已生成! 在线收听:{audioUrl} 字幕:{subtitlesUrl}(如有) 时长:{audioDuration / 1000}s 消耗积分:{credits}downloadorboth: Also download the file.DATE=$(date +%Y-%m-%d) JOB_DIR=".listenhub/podcast/${DATE}-{episodeId}" mkdir -p "$JOB_DIR" curl -sS -o "${JOB_DIR}/{episodeId}.mp3" "{audioUrl}"Present the download path in addition to the above summary.
-
Offer to show transcript or provide download URL on request
Two-Step Generation
- Step 1 — Submit text (foreground):
POST /podcast/episodes/text-content→ extractepisodeId - Poll text (background): Use the exact
jq-based polling loop above (substitute endpointpodcast/episodes/text-content/{episodeId}if needed), withrun_in_background: trueandtimeout: 600000 - When notified, save draft to config output dir:
- Create
.listenhub/podcast/YYYY-MM-DD-{episodeId}/ - Write
{episodeId}-draft.md(human-readable:**{speakerName}**: {content}per line) - Write
{episodeId}-draft.json(rawscriptsarray) - Present the draft location and content preview
- Create
- STOP: Present the draft and wait for explicit user approval
- Step 2 — Submit audio (foreground, after approval):
- No changes:
POST /podcast/episodes/{episodeId}/audiowith{} - With edits:
POST /podcast/episodes/{episodeId}/audiowith modified{scripts: [...]}
- No changes:
- Poll audio (background): Same exact
jq-based loop,run_in_background: true,timeout: 600000 - When notified, download audio to same folder:
curl -sS -o .listenhub/podcast/{dir}/{episodeId}.mp3 {audioUrl}- Present final result (same format as one-step, folder now has draft + final files)
After Successful Generation
Update config with the choices made this session:
NEW_CONFIG=$(echo "$CONFIG" | jq \
--arg lang "{language}" \
--arg mode "{mode}" \
--arg method "{one-step/two-step}" \
--argjson speakers '{"{language}": ["{speakerId}"]}' \
'. + {"language": $lang, "defaultMode": $mode, "defaultMethod": $method, "defaultSpeakers": (.defaultSpeakers + $speakers)}')
echo "$NEW_CONFIG" > "$CONFIG_PATH"
API Reference
- Speaker list:
shared/api-speakers.md - Speaker selection guide:
shared/speaker-selection.md - Episode creation:
shared/api-podcast.md - Polling:
shared/common-patterns.md§ Async Polling - Config pattern:
shared/config-pattern.md
Composability
- Invokes: speakers API (for speaker selection)
- Invoked by: content-planner (Phase 3)
Example
User: "Make a podcast about the latest AI developments"
Agent workflow:
- Detect: podcast request, topic = "latest AI developments"
- Ask mode → user picks "Deep"
- Ask language → "English"
- Ask speakers → 1 speaker
- Fetch speakers list, user picks "cozy-man-english"
- No references
- One-step generation
curl -sS -X POST "https://api.marswave.ai/openapi/v1/podcast/episodes" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sources": [{"type": "text", "content": "The latest AI developments"}],
"speakers": [{"speakerId": "cozy-man-english"}],
"language": "en",
"mode": "deep"
}'
Poll until complete, then present the result with title and listen link.
forumUser Reviews (0)
Write a Review
No reviews yet
Statistics
User Rating
Rate this Skill