CLI 예제
listenhub CLI로 단발 생성, 배치 루프, 오디오 내보내기, CI 파이프라인을 처리하는 복사해서 바로 쓰는 셸 레시피 모음.
실제로 동작하는 셸 레시피 모음입니다. CLI를 설치하고 인증해 두었다면 각 레시피를 그대로 실행할 수 있습니다. 대부분의 예제는 스크립트와 CI에 적합한 API 키(listenhub openapi) 네임스페이스를 사용합니다 — 다만 로컬 파일 업로드가 필요한 레시피(커버 오디오, 이미지 레퍼런스)는 그 기능이 있는 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. 단발 팟캐스트
주제를 제출하고 에피소드가 준비될 때까지 대기합니다. 기본적으로 이 명령은 --timeout(기본값 300)까지 10초마다 폴링한 뒤 완성된 에피소드를 출력합니다.
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는 필수이며 반복 지정할 수 있습니다 — 두 번 전달하면 진행자 두 명짜리 에피소드가 됩니다. --query 대신, 또는 --query와 함께 --source-url이나 --source-text(둘 다 반복 지정 가능)로 콘텐츠에 근거를 더하세요.
2. bash 루프로 배치 생성
파일에서 주제를 읽어 각각을 --no-wait(ID를 즉시 반환)으로 실행하고, jq로 episodeId를 받아 둔 뒤 두 번째 단계에서 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
doneprocessStatus는 종료 상태에서 success 또는 failed가 되며, 그 밖의 값은 아직 실행 중이라는 뜻입니다. topics.txt는 한 줄에 주제 하나씩 적습니다.
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에서는 명령 하나가 몇 분씩 연결을 붙잡고 있는 상황을 보통 원하지 않습니다. --no-wait으로 제출하고 ID를 job 출력으로 남긴 뒤, 이후 단계(또는 이후 실행)에서 폴링하세요. 이 레시피는 종료 코드로 분기하는 방법도 함께 보여 줍니다.
#!/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에서 생성 명령 하나가 그대로 폴링하게 두면(--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). 숫자를 하드코딩하지 말고 조회하세요 — 비용은 모델, 해상도, 길이에 따라 달라집니다.