npx skills add https://github.com/marswaveai/skills --skill podcast/speech)/explainer)/image-gen)/content-parser)生成由 1-2 位 AI 主播讨论某个主题的播客节目。支持快速概览、深度分析和辩论格式。输入可以是主题描述、URL 或文本。输出是完整的音频节目及文字稿。
shared/authentication.md 以了解 API 密钥和请求头shared/common-patterns.md 中关于轮询、错误和交互模式的说明广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
shared/speaker-selection.md 中的内置默认值作为后备方案;当用户想要更改声音时,应从 speakers API 获取shared/config-pattern.md 读取配置shared/speaker-selection.md 进行主播选择(文本表格 + 自由文本输入)~/Downloads/ 或 .listenhub/ — 将产物保存到当前工作目录,并使用基于主题的友好名称(参见 shared/config-pattern.md § 产物命名)遵循 shared/config-pattern.md § API 密钥检查。如果密钥缺失,立即停止。
遵循 shared/config-pattern.md 步骤 0(零问题启动)。
如果文件不存在 — 静默创建默认配置并继续:
mkdir -p ".listenhub/podcast"
echo '{"outputMode":"inline","language":null,"defaultMode":"quick","defaultMethod":"one-step","defaultSpeakers":{}}' > ".listenhub/podcast/config.json"
CONFIG_PATH=".listenhub/podcast/config.json"
CONFIG=$(cat "$CONFIG_PATH")
请勿询问任何设置问题。 直接进入交互流程。
如果文件存在 — 静默读取配置并继续:
CONFIG_PATH=".listenhub/podcast/config.json"
[ ! -f "$CONFIG_PATH" ] && CONFIG_PATH="$HOME/.listenhub/podcast/config.json"
CONFIG=$(cat "$CONFIG_PATH")
仅在用户明确要求重新配置时运行。显示当前设置:
当前配置 (podcast):
输出方式:{inline / download / both}
语言偏好:{zh / en / 未设置}
默认模式:{quick / deep / debate / 未设置}
默认生成方式:{one-step / two-step}
默认主播:{speakerName(s) / 使用内置默认}
然后按顺序询问以下问题并保存:
outputMode : 遵循 shared/output-mode.md § 设置流程问题。
语言(可选): "默认语言?"
null模式(可选): "默认播客模式?"
null方法(可选): "默认生成方式?"
defaultMethod: "one-step"defaultMethod: "two-step"null收集答案后,立即保存:
NEW_CONFIG=$(echo "$CONFIG" | jq --arg m "$OUTPUT_MODE" '. + {"outputMode": $m}')
# 如果用户选择了语言(不是"每次手动选择"),则保存
if [ "$LANGUAGE" != "null" ]; then
NEW_CONFIG=$(echo "$NEW_CONFIG" | jq --arg lang "$LANGUAGE" '. + {"language": $lang}')
fi
# 如果用户选择了模式,则保存
if [ "$MODE" != "null" ]; then
NEW_CONFIG=$(echo "$NEW_CONFIG" | jq --arg mode "$MODE" '. + {"defaultMode": $mode}')
fi
# 如果用户选择了方法,则保存
if [ "$METHOD" != "null" ]; then
NEW_CONFIG=$(echo "$NEW_CONFIG" | jq --arg method "$METHOD" '. + {"defaultMethod": $method}')
fi
echo "$NEW_CONFIG" > "$CONFIG_PATH"
CONFIG=$(cat "$CONFIG_PATH")
使用 AskUserQuestion 将主题和可选的参考资料在一个问题中一起询问,包含两个子问题,或者使用单个自由文本提示:
您想将什么主题制作成播客?如果您有参考资料(URL 或文本),也请一并提供。
接受:主题描述、URL、粘贴的文本或任何组合。
有效输入示例:
默认:"quick" — 跳过此问题,除非:
config.defaultMode 设置为其他值 → 静默使用该值仅当用户意图不明确且未配置默认模式时才询问此问题。在大多数情况下,直接使用 "quick"。
默认:匹配用户的交互语言。 根据用户在步骤 1 中使用的语言进行检测:
zhenconfig.language → 使用该值切勿询问此问题。 始终静默推断。在确认摘要中显示,以便用户在需要时可以覆盖。
默认:2 位主播(对话) — 最常见且最吸引人的格式。
跳过此问题。辩论模式需要 2 位主播。对于 quick/deep 模式,也默认使用 2 位主播。
仅当用户明确要求独白或单人格式时,才使用 1 位主播。
遵循 shared/speaker-selection.md:
config.defaultSpeakers.{language} → 静默使用已保存的主播shared/speaker-selection.md 中的内置默认值(不询问问题)对于 2 主播模式(对话/辩论):使用该语言的主播和副主播默认值。
默认:"one-step" — 跳过此问题,除非:
config.defaultMethod → 静默使用该值总结所有选择:
Ready to generate podcast:
Topic: {topic}
Mode: {mode}
Language: {language}
Speakers: {speaker name(s)}
References: {yes/no + brief description}
Method: {one-step/two-step}
Proceed?
在调用任何 API 之前,等待明确的确认。用户可以在此处确认前调整任何参数。
提交(前台) : POST /podcast/episodes 并附带收集的参数 → 提取 episodeId
告知用户任务已提交
轮询(后台) : 运行以下精确的 bash 命令,设置 run_in_background: true 和 timeout: 600000。请勿使用 python3、awk 或任何其他 JSON 解析器 — 按所示使用 jq:
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"
-H "X-Source: skills" 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
当收到完成通知时,执行步骤 6:呈现结果
从配置中读取 OUTPUT_MODE。遵循 shared/output-mode.md 中的行为说明。
inline 或 both:将 audioUrl 显示为可点击链接。
呈现:
播客已生成!
在线收听:{audioUrl}
字幕:{subtitlesUrl}(如有)
时长:{audioDuration / 1000}s
消耗积分:{credits}
download 或 both:同时下载文件。按照 shared/config-pattern.md § 产物命名 生成主题 slug。
SLUG="{topic-slug}" # 例如 "ai-developments"
NAME="${SLUG}-podcast.mp3"
# 去重:如果文件存在,则追加 -2, -3 等
BASE="${NAME%.*}"; EXT="${NAME##*.}"; i=2
while [ -e "$NAME" ]; do NAME="${BASE}-${i}.${EXT}"; i=$((i+1)); done
curl -sS -o "$NAME" "{audioUrl}"
呈现:
已保存到当前目录:
{NAME}
5. 根据请求提供文字稿或下载链接
POST /podcast/episodes/text-content → 提取 episodeIdjq 的轮询循环(如果需要,替换端点 podcast/episodes/text-content/{episodeId}),设置 run_in_background: true 和 timeout: 600000shared/config-pattern.md § 产物命名 生成主题 slug{slug}-podcast/ 文件夹(如果存在则去重)draft.md(人类可读格式:每行 **{speakerName}**: {content})draft.json(原始 scripts 数组)POST /podcast/episodes/{episodeId}/audio 附带 {}POST /podcast/episodes/{episodeId}/audio 附带修改后的 {scripts: [...]}jq 轮询循环,run_in_background: true,timeout: 600000curl -sS -o {slug}-podcast/podcast.mp3 {audioUrl}使用本次会话所做的选择更新配置:
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"
shared/api-speakers.mdshared/speaker-selection.mdshared/api-podcast.mdshared/common-patterns.md § 异步轮询shared/config-pattern.md用户:"Make a podcast about the latest AI developments"
代理工作流程:
curl -sS -X POST "https://api.marswave.ai/openapi/v1/podcast/episodes" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Source: skills" \
-d '{
"sources": [{"type": "text", "content": "The latest AI developments"}],
"speakers": [{"speakerId": "cozy-man-english"}],
"language": "en",
"mode": "deep"
}'
轮询直到完成,然后呈现带有标题和收听链接的结果。
每周安装次数
365
仓库
GitHub 星标
24
首次出现
11 天前
安全审计
安装于
codex361
gemini-cli359
cursor359
opencode359
kimi-cli358
amp358
/speech)/explainer)/image-gen)/content-parser)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.
shared/authentication.md for API key and headersshared/common-patterns.md for polling, errors, and interaction patternsshared/speaker-selection.md as fallback only; fetch from the speakers API when the user wants to change voiceshared/config-pattern.md before any interactionshared/speaker-selection.md for speaker selection (text table + free-text input)~/Downloads/ or .listenhub/ — save artifacts to the current working directory with friendly topic-based names (see shared/config-pattern.md § Artifact Naming)Follow shared/config-pattern.md § API Key Check. If the key is missing, stop immediately.
Follow shared/config-pattern.md Step 0 (Zero-Question Boot).
If file doesn't exist — silently create with defaults and proceed:
mkdir -p ".listenhub/podcast"
echo '{"outputMode":"inline","language":null,"defaultMode":"quick","defaultMethod":"one-step","defaultSpeakers":{}}' > ".listenhub/podcast/config.json"
CONFIG_PATH=".listenhub/podcast/config.json"
CONFIG=$(cat "$CONFIG_PATH")
Do NOT ask any setup questions. Proceed directly to the Interaction Flow.
If file exists — read config silently and proceed:
CONFIG_PATH=".listenhub/podcast/config.json"
[ ! -f "$CONFIG_PATH" ] && CONFIG_PATH="$HOME/.listenhub/podcast/config.json"
CONFIG=$(cat "$CONFIG_PATH")
Only run when the user explicitly asks to reconfigure. Display current settings:
当前配置 (podcast):
输出方式:{inline / download / both}
语言偏好:{zh / en / 未设置}
默认模式:{quick / deep / debate / 未设置}
默认生成方式:{one-step / two-step}
默认主播:{speakerName(s) / 使用内置默认}
Then ask these questions in order and save:
outputMode : Follow shared/output-mode.md § Setup Flow Question.
Language (optional): "默认语言?"
nullMode (optional): "默认播客模式?"
nullMethod (optional): "默认生成方式?"
defaultMethod: "one-step"defaultMethod: "two-step"nullAfter collecting answers, save immediately:
NEW_CONFIG=$(echo "$CONFIG" | jq --arg m "$OUTPUT_MODE" '. + {"outputMode": $m}')
# Save language if user chose one (not "每次手动选择")
if [ "$LANGUAGE" != "null" ]; then
NEW_CONFIG=$(echo "$NEW_CONFIG" | jq --arg lang "$LANGUAGE" '. + {"language": $lang}')
fi
# Save mode if user chose one
if [ "$MODE" != "null" ]; then
NEW_CONFIG=$(echo "$NEW_CONFIG" | jq --arg mode "$MODE" '. + {"defaultMode": $mode}')
fi
# Save method if user chose one
if [ "$METHOD" != "null" ]; then
NEW_CONFIG=$(echo "$NEW_CONFIG" | jq --arg method "$METHOD" '. + {"defaultMethod": $method}')
fi
echo "$NEW_CONFIG" > "$CONFIG_PATH"
CONFIG=$(cat "$CONFIG_PATH")
Ask topic and optional reference materials together in a single question using AskUserQuestion with two sub-questions, or a single free-text prompt:
What topic would you like to turn into a podcast? If you have reference materials (URLs or text), include them here too.
Accept: topic description, URL(s), pasted text, or any combination.
Examples of valid input:
Default: "quick" — skip this question unless:
config.defaultMode is set to something else → use that value silentlyOnly ask this question if the user's intent is ambiguous AND no default is configured. In most cases, just use "quick".
Default: match the user's interaction language. Detect from the language the user used in Step 1:
zhenconfig.language is set → use that valueNever ask this question. Always infer silently. Show in the confirmation summary so the user can override if needed.
Default: 2 speakers (dialogue) — the most common and engaging format.
Skip this question. Debate mode requires 2 speakers. For quick/deep, default to 2 speakers as well.
Only use 1 speaker if the user explicitly requests a monologue or solo format.
Follow shared/speaker-selection.md:
config.defaultSpeakers.{language} is set → use saved speakers silentlyshared/speaker-selection.md (no question asked)For 2-speaker mode (dialogue/debate): use Primary + Secondary defaults for the language.
Default: "one-step" — skip this question unless:
config.defaultMethod is set → use that value silentlySummarize all choices:
Ready to generate podcast:
Topic: {topic}
Mode: {mode}
Language: {language}
Speakers: {speaker name(s)}
References: {yes/no + brief description}
Method: {one-step/two-step}
Proceed?
Wait for explicit confirmation before calling any API. The user can adjust any parameter here before confirming.
Submit (foreground) : POST /podcast/episodes with collected parameters → extract episodeId
Tell the user the task is submitted
Poll (background) : Run the following exact bash command with run_in_background: true and timeout: 600000. Do NOT use python3, awk, or any other JSON parser — use jq as 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"
-H "X-Source: skills" 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_MODE from config. Follow shared/output-mode.md for behavior.
inline or both: Display audioUrl as a clickable link.
Present:
播客已生成!
在线收听:{audioUrl}
字幕:{subtitlesUrl}(如有)
时长:{audioDuration / 1000}s
消耗积分:{credits}
download or both: Also download the file. Generate a topic slug following shared/config-pattern.md § Artifact Naming.
SLUG="{topic-slug}" # e.g. "ai-developments"
NAME="${SLUG}-podcast.mp3"
# Dedup: if file exists, append -2, -3, etc.
BASE="${NAME%.*}"; EXT="${NAME##*.}"; i=2
while [ -e "$NAME" ]; do NAME="${BASE}-${i}.${EXT}"; i=$((i+1)); done
curl -sS -o "$NAME" "{audioUrl}"
Present:
已保存到当前目录:
{NAME}
5. Offer to show transcript or provide download URL on request
POST /podcast/episodes/text-content → extract episodeIdjq-based polling loop above (substitute endpoint podcast/episodes/text-content/{episodeId} if needed), with run_in_background: true and timeout: 600000shared/config-pattern.md § Artifact Naming{slug}-podcast/ folder (dedup if exists)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"
shared/api-speakers.mdshared/speaker-selection.mdshared/api-podcast.mdshared/common-patterns.md § Async Pollingshared/config-pattern.mdUser : "Make a podcast about the latest AI developments"
Agent workflow :
curl -sS -X POST "https://api.marswave.ai/openapi/v1/podcast/episodes" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Source: skills" \
-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.
Weekly Installs
365
Repository
GitHub Stars
24
First Seen
11 days ago
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
codex361
gemini-cli359
cursor359
opencode359
kimi-cli358
amp358
超能力技能使用指南:AI助手技能调用优先级与工作流程详解
41,800 周安装
draft.md**{speakerName}**: {content}draft.json (raw scripts array)POST /podcast/episodes/{episodeId}/audio with {}POST /podcast/episodes/{episodeId}/audio with modified {scripts: [...]}jq-based loop, run_in_background: true, timeout: 600000curl -sS -o {slug}-podcast/podcast.mp3 {audioUrl}