CLI サンプル
listenhub CLI による一発生成、バッチループ、音声の書き出し、CI パイプラインを、そのままコピーして使える shell レシピ集。
実際に動く shell レシピ集です。CLI のインストールと認証さえ済んでいれば、どれもそのまま実行できます。ほとんどの例は API キー(listenhub openapi)ネームスペースを使います。スクリプトと CI にはこちらが適しているからです。ただし、ローカルファイルのアップロードに依存するレシピ(カバー音声、参照画像)は、その機能がある OAuth ネームスペースを使います。各レシピには必要な認証モードを明記しています。
始める前に:
- インストール:
npm install -g @marswave/listenhub-cli(Node.js >= 20 が必要)。 openapiのレシピでは、LISTENHUB_API_KEYを設定する(CLI はこちらを先に読み取ります)か、listenhub openapi config set-keyを実行します。認証 を参照してください。- OAuth のレシピでは、
listenhub auth loginを一度実行します。
--json / -j は機械可読な出力を stdout に出し、エラーと進捗スピナーは stderr に流します。この分離があるおかげで jq へのパイプが安全に使えます。終了コードは 0 成功、1 エラー、2 認証、3 タイムアウト。スクリプトでは $? で分岐してください。
1. ポッドキャストを一発生成
トピックを送信し、エピソードが完成するまでブロックして待ちます。コマンドはデフォルトで 10 秒ごとにポーリングし、--timeout(デフォルト 300)まで待ってから、完成したエピソードを出力します。
export LISTENHUB_API_KEY="lh_sk_..."
# Pick a voice once, copy its ID
listenhub openapi speakers list --language en
listenhub openapi podcast create \
--query "AI agent trends in 2026" \
--speaker-id <speaker-id> \
--mode quick--speaker-id は必須で、繰り返し指定できます。2 回渡せばホスト 2 人のエピソードになります。内容の根拠を与えるには、--query の代わりに、あるいは --query に加えて --source-url や --source-text(どちらも繰り返し指定可能)を使います。
2. bash ループでのバッチ生成
ファイルからトピックを読み込み、それぞれを --no-wait(ID をすぐ返す)で投げ、jq で episodeId を取り出してから、2 周目で ID をポーリングします。こうすると送信が速く保たれ、時間のかかる生成ステップと切り離せます。
#!/usr/bin/env bash
set -euo pipefail
SPEAKER_ID="<speaker-id>"
ids=()
# Submit every topic, collect episode IDs
while IFS= read -r topic; do
[ -z "$topic" ] && continue
id=$(listenhub openapi podcast create \
--query "$topic" \
--speaker-id "$SPEAKER_ID" \
--mode quick \
--no-wait --json | jq -r '.episodeId')
echo "submitted: $topic -> $id"
ids+=("$id")
done < topics.txt
# Poll each episode until it leaves the running state
for id in "${ids[@]}"; do
while :; do
status=$(listenhub openapi podcast get "$id" --json | jq -r '.processStatus')
case "$status" in
success) echo "$id done"; break ;;
failed) echo "$id failed" >&2; break ;;
*) sleep 10 ;;
esac
done
done終了状態では processStatus は success か failed になります。それ以外の値はまだ実行中という意味です。topics.txt は 1 行 1 トピックです。
3. テキスト読み上げを音声ファイルに保存
openapi tts はバイナリ音声をそのままディスクへストリーミングします。ポーリングも --json も不要です。openapi speakers list で音声 ID を調べてから、MP3 を書き出します:
VOICE=$(listenhub openapi speakers list --language en --json | jq -r '.[0].speakerId')
listenhub openapi tts \
--text "Hello from ListenHub" \
--voice "$VOICE" \
--output hello.mp3
# ✓ Audio saved: /abs/path/hello.mp3 (42.3KB)--format は mp3(デフォルト)、opus、aac、flac、wav、pcm を受け付けます。ローカルファイルではなく音声 URL がほしい場合(audioUrl を含む JSON が返ります)は、openapi speech --script "..." --speaker-id "$VOICE" -j を使います。
4. 参照トラックから音楽を生成
既存のトラックからカバーを生成するにはローカルファイルのアップロードが必要で、この機能は OAuth ネームスペースにあります。listenhub music cover はローカルパスを自動検出して検証し、クラウドストレージへアップロードしたうえで、ジョブを送信してポーリングします。
# OAuth: run `listenhub auth login` first
listenhub music cover \
--audio ./original.mp3 \
--style "lo-fi" \
--title "My Cover" \
--json--audio は URL も受け付け、その場合はアップロードせずにそのまま渡されます。参照音声を取る完全に API キー駆動のフローがほしい場合は listenhub openapi music instrumental --reference-audio ./clip.mp3(モデルはデフォルトが適用されます)を、画像に曲を付けたい場合は listenhub openapi music soundtrack --image ./cover.png --prompt "..." を使います。
5. ローカル参照画像を使った AI 画像生成
openapi image create はローカルの参照ファイルを読み込み、base64 エンコードしてインラインで送信します。--reference は繰り返し指定でき、URL も受け付けます(URI としてそのまま渡されます)。--provider は必須です。
listenhub openapi image create \
--prompt "a dragon in watercolor style, inspired by this sketch" \
--provider google \
--reference ./sketch.png \
--ratio 16:9 \
--json | jq -r '.imageUrl // .'対応する参照画像の形式:.png、.jpg/.jpeg、.gif、.webp、.bmp。任意指定の --size は 1K、2K、4K。--ratio は 16:9、4:3、1:1、3:4、9:16、21:9 のいずれかです。
6. PixVerse のテキストから動画生成
PixVerse は openapi video pixverse generate から実行します。--capability は必須で、最も単純なのは text_to_video です。--language en(デフォルト)は国際版サービスに、--language zh は中国版サービスに接続します。
# Estimate credits first (never assume a fixed cost)
listenhub openapi video pixverse estimate \
--capability text_to_video --quality 720p --duration 5
# Submit and return the task ID without waiting
listenhub openapi video pixverse generate \
--capability text_to_video \
--prompt "A cat playing piano on a neon stage" \
--quality 720p \
--aspect-ratio 16:9 \
--duration 5 \
--no-wait --json--quality は 360p、540p、720p(デフォルト)、1080p。--duration は 1 から 60 までの整数です(デフォルト 5)。画像・動画・音声のアセットは、末尾に任意の :<seconds> という長さのサフィックスを付けられます(例:--image https://example.com/p.jpg:3)。
7. CI パイプライン:まず送信し、ポーリングは分ける
CI では通常、1 つのコマンドが何分も接続を握り続けるのは避けたいはずです。--no-wait で送信し、ID をジョブの出力として保存して、後のステップ(または後の実行)でポーリングします。このレシピでは終了コードによる分岐も示します。
#!/usr/bin/env bash
set -euo pipefail
# LISTENHUB_API_KEY is injected from CI secrets
# --- step: submit ---
EPISODE_ID=$(listenhub openapi podcast create \
--source-url "https://example.com/release-notes" \
--speaker-id "$LH_SPEAKER_ID" \
--no-wait --json | jq -r '.episodeId')
echo "episode_id=$EPISODE_ID" >> "$GITHUB_OUTPUT"
# --- step: poll with a hard cap ---
deadline=$(( $(date +%s) + 900 )) # 15 minutes
while :; do
status=$(listenhub openapi podcast get "$EPISODE_ID" --json | jq -r '.processStatus')
[ "$status" = "success" ] && break
if [ "$status" = "failed" ]; then
echo "generation failed" >&2
exit 1
fi
if [ "$(date +%s)" -ge "$deadline" ]; then
echo "timed out waiting for $EPISODE_ID" >&2
exit 3
fi
sleep 10
done
# --- step: fetch the audio URL ---
listenhub openapi podcast get "$EPISODE_ID" --json | jq -r '.audioUrl'CI で作成コマンド 1 つにポーリングさせると(--no-wait なし)、--timeout に達した時点で 3 で終了します。ただしジョブはサーバー側で動き続けます。後のステップから復帰できるよう、ID は必ず取得しておいてください。終了コード 2 は認証情報の問題として扱い、LISTENHUB_API_KEY をローテーションするか設定し直してください。
8. バッチ実行の前にクレジットを確認する
生成はクレジットを消費します。大きなバッチを走らせる前に、残高を確認し、その作業のコストを見積もってください。
# Remaining credits and plan
listenhub openapi subscription --json | jq '{credits: .totalAvailableCredits, plan: .subscriptionPlan.name}'
# Estimate one video task before multiplying it across a batch
listenhub openapi video estimate \
--model doubao-seedance-2-pro \
--resolution 1080p \
--duration 10 \
--json | jq '{credits, tokens}'従量課金のある製品にはすべて estimate コマンドがあります(openapi video estimate、openapi video pixverse estimate)。数値をハードコードせず、そのつど照会してください。コストはモデル、解像度、長さによって変わります。