ListenHubSDKs & CLI
JavaScript SDK

SDK 레퍼런스

OpenAPIClient와 ListenHubClient의 모든 메서드를 제품별로 묶어 시그니처, 엔드포인트, 반환값과 함께 정리했습니다.

@marswave/listenhub-sdk의 전체 메서드 레퍼런스입니다. 메서드는 제품별로 묶여 있습니다. 각 항목에는 시그니처, 동작을 설명하는 한 줄, 그리고 내부에서 호출되는 HTTP 엔드포인트가 적혀 있습니다.

SDK에는 두 개의 클라이언트가 들어 있습니다. 응답 처리는 공통이지만(code 0이면 data를 언래핑하고, 그렇지 않으면 ListenHubError를 던지며, 429는 자동 재시도) 대상 API 면과 인증 방식이 다릅니다.

OpenAPIClientListenHubClient
인증API 키(Authorization: Bearer)OAuth 사용자 액세스 토큰
Base URLhttps://api.marswave.ai/openapihttps://api.listenhub.ai/api
실행 주체내 계정 / 키 소유자로그인한 사용자
용도서버, 스크립트, CI사용자 대상 앱

OpenAPIClient공개 OpenAPI 제품이며, 이 레퍼런스의 중심입니다. ListenHubClient는 퍼스트파티 앱이 사용하는 OAuth 클라이언트이고, 해당 메서드는 문서 끝의 ListenHubClient 메서드에 정리되어 있습니다.

생성은 비동기입니다. create* 호출은 즉시 id를 반환합니다. 대응하는 get* 메서드를 폴링해서 processStatus(또는 태스크의 status)가 pending / generating에서 벗어날 때까지 기다리세요. 전체 루프는 퀵스타트를 참고하세요.

아래에서 사용하는 표기 규칙:

  • "엔드포인트" 경로는 클라이언트 base URL 기준 상대 경로입니다. OpenAPIClient의 경우 https://api.marswave.ai/openapi/입니다.
  • 메서드는 언래핑된 data 페이로드를 반환합니다. { code, message, data } 엔벨로프는 SDK가 처리합니다.
  • 일부 메서드는 원시 Response(바이너리 또는 스트림)를 반환하며, 해당 항목에는 명시해 두었습니다.
  • 크레딧 비용을 하드코딩하지 마세요. 대신 estimate*Credits 메서드와 getSubscription()을 사용하세요.

OpenAPIClient 메서드

Speakers(보이스)

보이스는 speakerId로 식별됩니다. 에피소드를 만들기 전에 보이스 목록을 조회하고 사용할 id를 전달하세요.

메서드엔드포인트반환값설명
listSpeakers(params?)GET v1/speakers/list{ items: OpenAPISpeaker[] }사용 가능한 보이스

listSpeakers 파라미터:

파라미터타입설명
languagestring언어로 필터링. 예: en, zh, ja
statusnumber이용 가능 여부 필터

OpenAPISpeakerspeakerId, name, gender, language, demoAudioUrl, 그리고 선택적인 profile(pitch, speed, traits, styles, scenes, accent, description)을 가집니다.

const { items } = await client.listSpeakers({ language: 'en' });
const speakerId = items[0].speakerId;

ListenHub Voice(AI 음성)

엔드투엔드 음성 생성(listenhub-voice-1.0)입니다. 단순 내레이션, 효과음, 단일 보이스 발화, 다중 화자 대화, 참조 클립 기반 보이스 클로닝, 이미지 기반 음성 생성을 지원합니다. 태스크를 만든 뒤 statussuccess가 될 때까지 getListenHubVoiceTask를 폴링하세요.

메서드엔드포인트반환값
createListenHubVoice(params)POST v1/listenhub-voice/generate{ taskId, status }
getListenHubVoiceTask(taskId)GET v1/listenhub-voice/tasks/{taskId}OpenAPIListenHubVoiceTaskDetail
listListenHubVoiceTasks(params?)GET v1/listenhub-voice/tasks{ items, page, pageSize, total }

createListenHubVoice 파라미터(OpenAPICreateListenHubVoiceParams):

파라미터타입설명
model'listenhub-voice-1.0'선택. 기본값은 listenhub-voice-1.0
textstring필수. 최대 1400자. 줄 앞에 @音频1 / @音频2를 붙여 여러 보이스에 배분
voicesArray<{ type: 'speaker'; id: string } | { type: 'reference'; url: string }>1~3개. 일반 텍스트 / 효과음이면 생략. image와 상호 배타
image{ url?: string; data?: string }이미지 기반 음성 생성용 참조 이미지. url(http/https) 또는 data(Base64) 중 하나를 전달. voices와 상호 배타
audioConfig{ speechRate?; loudnessRate?; pitchRate?; format? }speechRate / loudnessRate-50100, pitchRate-1212, format'mp3' | 'wav' | 'pcm' | 'ogg_opus'(기본 mp3)
durationHintnumber목표 길이 1110초. 크레딧 견적에 반영
watermarkboolean오디오 워터마크 추가

speaker 항목은 내장 보이스(ListenHub 보이스 코드 또는 플랫폼 voice_type)를 참조하고, reference 항목은 공개 오디오 URL에서 보이스를 클로닝합니다. 다중 화자 대화는 2~3개 보이스를 나열하고, 배열 순서대로 @音频N 접두사로 각 줄을 배정합니다.

OpenAPIListenHubVoiceTaskDetail에는 id, status(pendinggeneratinguploadingsuccess | failed), model, params(정제된 에코), audioUrl(success일 때), audioDuration(과금 기준 길이), creditCharged, creditRefunded, errorMessage(failed일 때), createdAt, updatedAt이 포함됩니다. listListenHubVoiceTasks{ page?, pageSize?, status?, keyword? }를 받습니다.

const { taskId } = await client.createListenHubVoice({
  text: 'Welcome to ListenHub. Here is your daily briefing.',
  voices: [{ type: 'speaker', id: 'zh_female_warm' }],
  durationHint: 20,
});

let task = await client.getListenHubVoiceTask(taskId);
while (task.status !== 'success' && task.status !== 'failed') {
  await new Promise((r) => setTimeout(r, 3000));
  task = await client.getListenHubVoiceTask(taskId);
}
if (task.status === 'success') console.log(task.audioUrl);

Voice Cloning(보이스 클로닝)

참조 오디오를 재사용 가능한 개인 보이스로 만듭니다. 업로드하고, 폴링하고, 확정하면 생성된 speakerIdspeech, tts, audioSpeech에서 사용할 수 있습니다. 업로드 방식만 지원하며, 대화형 녹음 플로우는 웹 전용입니다.

메서드엔드포인트반환값
createVoiceClone(params)POST v1/voice-clone/clone{ taskId, status }
getVoiceCloneTask(taskId)GET v1/voice-clone/clone/{taskId}OpenAPIVoiceCloneTaskDetail
confirmVoiceClone(params)POST v1/voice-clone/confirm{ speakerId }
listVoiceCloneSpeakers()GET v1/voice-clone/speakers{ speakers, quota, isLimitReached, maxSpeakers, remainingConfirmations }
getVoiceCloneSpeaker(speakerId)GET v1/voice-clone/speakers/{speakerId}OpenAPIVoiceCloneSpeaker
updateVoiceCloneSpeaker(speakerId, params)PUT v1/voice-clone/speakers/{speakerId}OpenAPIVoiceCloneSpeaker
deleteVoiceCloneSpeaker(speakerId)DELETE v1/voice-clone/speakers/{speakerId}{ speakerId }

createVoiceClone 파라미터(OpenAPICreateVoiceCloneParams) — SDK가 멀티파트로 전송합니다:

파라미터타입설명
audioFilesBlob[]필수. 1~6개 파일, 단일 파일 ≤5MB, 합계 ≤20MB
audioFilenamesstring[]선택적 파일명. 위치 순서대로 매칭
language'zh' | 'en' | 'ja'필수
consentConfirmedtrue필수. 클로닝 대상자의 동의를 보유하고 있음을 선언하며, 태스크와 함께 저장됨
autoConfirmboolean클로닝 완료를 감지한 폴링 안에서 바로 확정. namegender 필요
namestring보이스 이름, 최대 50자
gender'male' | 'female' | 'other'보이스 성별
useCreditsboolean무료 쿼터 소진 후 300 크레딧 과금을 승인. 기본값 false

OpenAPIVoiceCloneTaskDetail의 최종 형태는 세 가지입니다. errorCode / errorMessage를 동반한 status: 'failed', demoAudioUrl은 있고 speakerId는 없는 status: 'completed'(자동 확정이 보이스를 저장하지 못한 경우 confirmError 포함), 또는 speakerId가 존재해 보이스가 저장되었음을 뜻하는 형태입니다. 같은 계정에서 확정이 동시에 발생하면 429, 의존 서비스를 사용할 수 없으면 503이 반환됩니다. 둘 다 재시도 가능하며 과금되지 않습니다.

const { taskId } = await client.createVoiceClone({
  audioFiles: [referenceBlob],
  audioFilenames: ['reference.mp3'],
  language: 'en',
  consentConfirmed: true,
});

let task = await client.getVoiceCloneTask(taskId);
while (task.status === 'pending' || task.status === 'processing') {
  await new Promise((r) => setTimeout(r, 5000));
  task = await client.getVoiceCloneTask(taskId);
}
if (task.status === 'failed') throw new Error(task.errorMessage);

const { speakerId } = await client.confirmVoiceClone({
  taskId,
  name: 'My API Voice',
  gender: 'female',
});
await client.speech({ scripts: [{ content: 'Hello from my own voice.', speakerId }] });

Podcast(팟캐스트)

팟캐스트는 querysources로부터 생성되는 다중 화자 대화입니다. 생성한 뒤 processStatussuccess가 될 때까지 getPodcast를 폴링하세요.

메서드엔드포인트반환값
createPodcast(params)POST v1/podcast/episodes{ episodeId }
getPodcast(episodeId)GET v1/podcast/episodes/{episodeId}OpenAPIPodcastDetail
createPodcastTextContent(params)POST v1/podcast/episodes/text-content{ episodeId, message }
generatePodcastAudio(episodeId, params?)POST v1/podcast/episodes/{episodeId}/audio{ success, message, episodeId, status }
getPodcastTextStream(episodeId, event)GET v1/podcast/episodes/{episodeId}/text-stream원시 Response(스트림)

createPodcast 파라미터(OpenAPICreatePodcastParams):

파라미터타입설명
querystring에피소드가 다룰 내용
sourcesArray<{ type: 'text' | 'url'; content: string }>근거 자료. 원문 텍스트 또는 페이지 URL
speakersArray<{ speakerId: string }>필수. 보이스 하나당 항목 하나
languagestring출력 언어
modestring생성 깊이(예: quick, deep)

텍스트 먼저, 오디오 나중의 2단계 플로우를 쓰면 오디오 비용을 내기 전에 스크립트를 검토하거나 수정할 수 있습니다. createPodcastTextContent는 스크립트만 생성하고, 이어서 generatePodcastAudio(episodeId, { scripts })가 (원한다면 직접 고친) 스크립트로 오디오를 렌더링합니다. getPodcastTextStream(episodeId, 'script' | 'outline')은 실시간 스크립트/아웃라인 토큰을 위한 스트리밍 Response를 반환합니다.

OpenAPIPodcastDetail에는 processStatus, title, outline, cover, audioUrl, audioStreamUrl, subtitlesUrl, scripts(화자별 대사), credits, 그리고 실패 시 failCode가 포함됩니다.

Flow Speech / TTS

Flow speech는 텍스트나 URL을 하나 이상의 보이스로 내레이션한 오디오로 만듭니다. TTS 엔드포인트는 더 저수준으로, 명시적으로 준 스크립트를 음성으로 합성합니다.

Flow speech

메서드엔드포인트반환값
createFlowSpeech(params)POST v1/flow-speech/episodes{ episodeId }
getFlowSpeech(episodeId)GET v1/flow-speech/episodes/{episodeId}OpenAPIFlowSpeechDetail
createFlowSpeechTTS(params)POST v1/flow-speech/episodes/tts{ episodeId }
getFlowSpeechTextStream(episodeId, event)GET v1/flow-speech/episodes/{episodeId}/text-stream원시 Response(스트림)

createFlowSpeech 파라미터(OpenAPICreateFlowSpeechParams):

파라미터타입설명
sourcesArray<{ type: 'text' | 'url'; content?: string; uri?: string }>필수. 텍스트는 content, URL은 uri
speakersArray<{ speakerId: string }>필수
languagestring출력 언어
mode'smart' | 'direct'smart는 내레이션에 맞게 다시 쓰고, direct는 원문 그대로 읽음

createFlowSpeechTTSscripts: Array<{ content: string; speakerId: string }>와 선택적인 title을 받아 각 줄을 그대로 렌더링합니다. 텍스트 스트림의 event'script' | 'outline'입니다.

OpenAPIFlowSpeechDetail에는 processStatus, title, outline, cover, audioUrl, audioStreamUrl, subtitlesUrl, scripts, sourceProcessResult가 포함됩니다.

TTS / speech

메서드엔드포인트반환값
speech(params)POST v1/speechOpenAPISpeechResponse
tts(params)POST v1/tts원시 Response(오디오 바이트)
audioSpeech(params)POST v1/audio/speech원시 Response(오디오 바이트)

speechscripts: Array<{ content: string; speakerId: string }>를 받아 동기적으로 결과를 반환합니다: { audioUrl, audioDuration, subtitlesUrl?, taskId, credits }.

ttsaudioSpeech는 OpenAI 호환 단일 보이스 합성입니다. { input, voice, response_format? }를 받으며, response_formatmp3(기본), opus, aac, flac, wav, pcm 중 하나입니다. 오디오는 원시 Response로 반환되므로 .arrayBuffer()로 읽거나 .body를 스트리밍하세요.

const res = await client.tts({ input: 'Hello world', voice: speakerId, response_format: 'mp3' });
const audio = Buffer.from(await res.arrayBuffer());

Storybook(설명 영상 / 슬라이드)

Storybook은 페이지 기반 시각 콘텐츠, 즉 설명 영상과 슬라이드 덱을 만듭니다. mode로 형식을 고릅니다. 오디오는 skipAudio로 끌 수 있는 선택 사항입니다.

메서드엔드포인트반환값
createStorybook(params)POST v1/storybook/episodes{ episodeId }
getStorybook(episodeId)GET v1/storybook/episodes/{episodeId}OpenAPIStorybookDetail
generateStorybookVideo(episodeId)POST v1/storybook/episodes/{episodeId}/video{ success }

createStorybook 파라미터(OpenAPICreateStorybookParams):

파라미터타입설명
sourcesArray<{ type: 'text' | 'url'; content: string }>필수 근거 자료
speakersArray<{ speakerId: string }>선택. 오디오를 생성할 때만 필요
mode'info' | 'story' | 'slides'덱은 slides, 설명 영상은 info / story
skipAudiobooleantrue면 시각 자료만 출력
stylestring비주얼 스타일 힌트
languagestring출력 언어

에피소드가 성공한 뒤 generateStorybookVideo(episodeId)를 호출하면 페이지들로부터 다운로드 가능한 영상을 렌더링합니다. getStorybook을 폴링하며 videoStatus(not_generatedpendingsuccess / fail)를 확인하세요. 성공하면 videoUrl이 채워집니다.

OpenAPIStorybookDetail에는 mode, processStatus, title, cover, audioUrl, audioDuration, videoUrl, videoStatus, 그리고 pages(각각 text, pageNumber, imageUrl, audioTimestamp 포함)가 들어 있습니다.

Image(이미지)

단일 호출 이미지 생성입니다. OpenAPIClient에는 별도의 폴링 메서드가 없으며, 응답에 결과가 담겨 옵니다.

메서드엔드포인트반환값
createImage(params)POST v1/images/generationOpenAPICreateImageResponse

createImage 파라미터(OpenAPICreateImageParams):

파라미터타입설명
providerstring필수 이미지 프로바이더
modelstring프로바이더 모델
promptstring필수 텍스트 프롬프트
referenceImagesArray<{ fileData?; inlineData? }>참조 이미지 — fileData: { fileUri, mimeType } 또는 inlineData: { data, mimeType }(base64)
imageConfig{ imageSize?; aspectRatio? }imageSize: 1K | 2K | 4K, aspectRatio: 16:9 | 4:3 | 1:1 | 3:4 | 9:16 | 21:9

Video(SeeDance / HappyHorse + PixVerse)

두 비디오 계열은 폴링 / 목록 / 견적 메서드는 공유하지만, 생성 메서드와 파라미터가 다릅니다. SeeDance(doubao-seedance-2-*)와 HappyHorse는 content 배열을 쓰고, PixVerse는 capability 기반 형태를 씁니다.

SeeDance / HappyHorse

메서드엔드포인트반환값
createVideoGeneration(params)POST v1/video-generation/generate{ taskId, status }
getVideoGenerationTask(taskId)GET v1/video-generation/tasks/{taskId}OpenAPIVideoGenerationTaskDetail
listVideoGenerationTasks(params?)GET v1/video-generation/tasks{ items, page, pageSize, total }
estimateVideoCredits(params)POST v1/video-generation/estimate-credits{ tokens, credits }

createVideoGeneration 파라미터(OpenAPICreateVideoGenerationParams):

파라미터타입설명
model'doubao-seedance-2-pro' | 'doubao-seedance-2-fast' | 'happyhorse'기본값은 SeeDance 모델
contentVideoContentItem[]필수. 텍스트 / 이미지 / 비디오 / 오디오 항목 혼합(아래 참고)
resolution'480p' | '720p' | '1080p'1080pdoubao-seedance-2-pro에서만, happyhorse480p 없음
ratio'16:9' | '4:3' | '1:1' | '3:4' | '9:16' | '21:9' | '4:5' | '5:4'4:5 / 5:4happyhorse에서만
durationnumber초 단위. SeeDance 최소 4, HappyHorse 최소 3
generateAudioboolean오디오 트랙 생성
seednumber재현성을 위한 시드
inputVideoDurationnumber비디오 편집 입력용. SeeDance [2,15], HappyHorse [3,60]
audioSetting'auto' | 'origin'HappyHorse 비디오 편집 전용. contentvideo_url이 있을 때

content 항목은 다음 중 하나입니다:

  • { type: 'text', text }
  • { type: 'image_url', image_url: { url }, role: 'first_frame' \| 'last_frame' \| 'reference_image' }
  • { type: 'video_url', video_url: { url }, role: 'reference_video' }
  • { type: 'audio_url', audio_url: { url }, role: 'reference_audio' }

HappyHorse는 last_frameaudio_url 콘텐츠를 거부합니다. estimateVideoCredits{ model, resolution, duration, hasVideoInput?, inputVideoDuration?, ratio? }를 받습니다.

const { taskId } = await client.createVideoGeneration({
  model: 'doubao-seedance-2-pro',
  content: [{ type: 'text', text: 'A timelapse of a city at dusk' }],
  resolution: '1080p',
  duration: 5,
});

PixVerse

메서드엔드포인트반환값
createPixVerseVideoGeneration(params)POST v1/video-generation/pixverse/generate{ taskId, episodeId?, status }
estimatePixVerseVideoCredits(params)POST v1/video-generation/pixverse/estimate-credits{ tokens, credits }

PixVerse 태스크의 폴링과 목록 조회는 위의 getVideoGenerationTask / listVideoGenerationTasks 메서드를 그대로 사용합니다.

createPixVerseVideoGeneration 파라미터(OpenAPICreatePixVerseVideoParams):

파라미터타입설명
capability'text_to_video' | 'image_to_video' | 'transition' | 'multi_transition' | 'fusion' | 'restyle' | 'mimic' | 'lip_sync' | 'agent'필수. 생성 모드를 선택
model'pixverse' | 'v6' | 'v5' | 'v4.5'PixVerse 모델 버전
language'zh' | 'en'서비스 리전. en은 국제, zh는 중국 본토
promptstring텍스트 프롬프트
durationnumber초 단위(1–60, agent는 20/30/60)
aspectRatio'9:16' | '16:9' | '1:1' | '4:3' | '3:4'출력 종횡비
quality'360p' | '540p' | '720p' | '1080p'mimic은 720p 고정, agent는 720p/1080p 필요
sourceTaskIdstring이전에 성공한 태스크를 재사용(restyle / lip_sync)
images / videos / audiosArray<{ url; duration? }>입력 애셋
pixverseOpenAPIPixVerseOptionscapability별 중첩 옵션

중첩된 pixverse 객체는 agentType, motionMode, cameraMovement, templateId, multiTransition, imageReferences, tts, soundEffect*, lipSyncTts*, brandSticker, introOutroClip을 다룹니다. 어떤 항목이 유효한지는 capability에 따라 달라집니다. estimatePixVerseVideoCredits는 견적용으로 축소된 pixverse 형태와 함께 { capability, model?, language?, duration?, quality?, pixverse? }를 받습니다.

Music(음악)

음악 엔드포인트는 기본적으로 Mureka 프로바이더를 사용합니다. 비동기 엔드포인트는 태스크({ taskId, taskType, status })를 반환하므로 getMusicTask를 폴링하세요. 동기 엔드포인트(recognizeMusic, describeMusic, stemMusic)는 결과를 곧바로 반환합니다.

메서드엔드포인트반환값동기 여부
createMusicGenerate(params)POST v1/music/generateCreateMusicTaskResponse비동기
createMusicCover(params)POST v1/music/coverCreateMusicTaskResponse비동기(deprecated)
createMusicExtend(params)POST v1/music/extendCreateMusicTaskResponse비동기
createMusicRemix(params)POST v1/music/remixCreateMusicTaskResponse비동기
createMusicInstrumental(params)POST v1/music/instrumentalCreateMusicTaskResponse비동기
createMusicSoundtrack(params)POST v1/music/soundtrackCreateMusicTaskResponse비동기
createMusicTrack(params)POST v1/music/trackCreateMusicTaskResponse비동기
recognizeMusic(params)POST v1/music/recognizeRecognizeMusicResponse동기
describeMusic(params)POST v1/music/describeDescribeMusicResponse동기
stemMusic(params)POST v1/music/stemStemMusicResponse동기
getMusicTask(taskId)GET v1/music/tasks/{taskId}MusicTaskDetail
listMusicTasks(params?)GET v1/music/tasks{ items, page, pageSize, total }

주요 생성 파라미터:

  • createMusicGenerate: { prompt?, lyrics?, model?, style?, title?, instrumental?, vocalId? }. modelauto, mureka-7.6, mureka-8, mureka-9, mureka-o2 중 하나입니다.
  • createMusicExtend: { uploadUrl, model, continueAt, prompt?, style?, title?, instrumental?, negativeTags?, vocalGender?, styleWeight?, weirdnessConstraint?, audioWeight? }. 여기서 model은 Suno 버전(V4, V4_5, V4_5PLUS, V4_5ALL, V5, V5_5)입니다.
  • createMusicRemix: { audio?, audioFilename?, audioUrl?, providerSongId?, lyrics, prompt }. audio / audioUrl / providerSongId 중 정확히 하나만 전달하세요. deprecated된 createMusicCover 대신 이 메서드를 쓰세요.
  • createMusicInstrumental: { prompt?, referenceAudio?, referenceAudioFilename?, model? }. prompt 또는 referenceAudio 중 하나만 전달하세요.
  • createMusicSoundtrack: { image?, video?, prompt?, model? }. image 또는 video 중 하나만 전달하세요.
  • createMusicTrack: { audio?, providerSongId?, generateType, prompt, lyrics?, vocalGender?, generateStart?, generateEnd? }. generateType으로 스템을 고르며(Vocals, Instrumental, Drums, …), generateTypeVocals일 때는 lyrics가 필수입니다.

멀티파트 엔드포인트(remix, instrumental, soundtrack, track, recognize, describe, stem)는 오디오 / 이미지 / 비디오 필드로 Blob/File을 받습니다. Node 20+에서는 버퍼를 new Blob([buffer])로 감싸세요.

const { taskId } = await client.createMusicGenerate({
  prompt: 'lo-fi hip hop, mellow, rainy night',
  model: 'auto',
});
let task = await client.getMusicTask(taskId);
while (task.status === 'pending' || task.status === 'generating') {
  await sleep(10_000);
  task = await client.getMusicTask(taskId);
}
console.log(task.tracks[0]?.audioUrl);

동기 결과: recognizeMusic은 타임스탬프가 붙은 lyricsSections를, describeMusic{ description, tags, genres, instruments }를, stemMusic{ zipUrl, midiZipUrl, expiresAt }을 반환합니다(링크는 약 24시간 뒤 만료).

Content Extract(콘텐츠 추출)

URL에서 읽을 수 있는 콘텐츠(본문 텍스트, 선택적 요약)를 추출합니다. 비동기이므로 생성한 뒤 폴링하세요.

메서드엔드포인트반환값
createContentExtract(params)POST v1/content/extract{ taskId }
getContentExtract(taskId)GET v1/content/extract/{taskId}OpenAPIContentExtractDetail

createContentExtract 파라미터(OpenAPICreateContentExtractParams):

파라미터타입설명
source{ type: 'url'; uri: string }필수. 추출할 페이지
options{ summarize?; maxLength?; twitter? }summarize는 요약을 추가하고, twitter: { count? }로 스레드 깊이를 지정

statuscompleted가 될 때까지 getContentExtract를 폴링하세요. 상세 결과에는 data.content, data.metadata, data.references, credits가 담깁니다.

Subscription(구독)

메서드엔드포인트반환값
getSubscription()GET v1/user/subscriptionOpenAPISubscriptionInfo

크레딧 잔액과 플랜 정보를 반환합니다: totalAvailableCredits, 월간/영구/기간 한정 크레딧 내역, resetAt, renewStatus, paidStatus, subscriptionPlan. 비용이 큰 작업을 시작하기 전에 totalAvailableCredits로 잔액을 확인하세요.

Files(파일)

OpenAPIClient에는 전용 파일 업로드 메서드가 없습니다. 로컬 파일을 입력으로 쓰려면 공개 URL로 호스팅한 뒤 그 URL을 전달하세요(예: sourceuri, referenceImages.fileData.fileUri, 비디오의 image_url.url). 사전 서명 업로드 플로우는 ListenHubClient에 있습니다 — 아래 Files를 참고하세요.


ListenHubClient 메서드

ListenHubClient는 OAuth 사용자 액세스 토큰으로 인증하며 https://api.listenhub.ai/api를 대상으로 합니다. 퍼스트파티 앱 면을 노출합니다. 제품 형태는 OpenAPIClient와 다릅니다. 에피소드는 중첩된 template 객체를 사용하고, 생성 메서드는 제품별(팟캐스트, TTS, 설명 영상, 슬라이드)로 나뉩니다. 각 요청이 개별 로그인 사용자 명의로 실행될 때만 이 클라이언트를 쓰세요.

Auth & session(인증 및 세션)

메서드엔드포인트반환값
connectInit(params)POST v1/auth/connect/init{ sessionId, authUrl }
connectToken(params)POST v1/auth/connect/token{ accessToken, refreshToken, expiresIn }
refresh(params)POST v1/auth/token{ accessToken, refreshToken, expiresIn }
revoke(params)POST v1/auth/token/revokevoid

connectInit({ callbackPort })는 디바이스/OAuth 플로우를 시작하고 열어야 할 authUrl을 반환합니다. connectToken({ sessionId, code })는 그 결과를 토큰으로 교환합니다. refresh({ refreshToken })은 만료되어 가는 액세스 토큰을 갱신하고, revoke({ refreshToken })은 토큰을 무효화합니다.

Speakers(보이스)

메서드엔드포인트반환값
listSpeakers(params?)GET v1/settings/speakers{ items: Speaker[] }

파라미터: { language?, status? }. 반환 형태가 OpenAPIClient와 다르다는 점에 유의하세요. 각 SpeakerspeakerId가 아니라 speakerInnerId를 노출하며, personality, accessType, weight도 함께 제공합니다. 에피소드의 template.speakers 배열이 기대하는 값은 speakerInnerId입니다.

Voice Cloning(보이스 클로닝)

로그인한 사용자를 위한 퍼스트파티 클로닝 플로우입니다. 참조 오디오를 업로드하고, 폴링한 뒤, 개인 보이스로 확정합니다. 이 면은 zhen만 지원하며, confirmVoiceClone은 페이로드 없이 완료되므로 스피커 ID는 listVoiceCloneSpeakers에서 읽어야 합니다.

메서드엔드포인트반환값
createVoiceClone(params)POST v1/voice-clone/clone{ taskId, status }
getVoiceCloneTask(taskId)GET v1/voice-clone/clone/{taskId}{ status, demoAudioUrl? }
confirmVoiceClone(params)POST v1/voice-clone/confirmvoid
listVoiceCloneSpeakers()GET v1/voice-clone/speakers{ speakers, quota, isLimitReached, maxSpeakers, remainingConfirmations }
getVoiceCloneSpeaker(speakerId)GET v1/voice-clone/speakers/{speakerId}VoiceCloneSpeaker
updateVoiceCloneSpeaker(speakerId, params)PUT v1/voice-clone/speakers/{speakerId}VoiceCloneSpeaker
deleteVoiceCloneSpeaker(speakerId)DELETE v1/voice-clone/speakers/{speakerId}{ speakerId }

createVoiceClone{ audioFiles: Blob[], audioFilenames?: string[], language: 'zh' | 'en' }를 받고, confirmVoiceClone{ taskId, name, gender, useCredits? }를 받습니다. API 키 면과 달리, 클로닝이 실패하면 본문에 실패를 담아 반환하는 대신 ListenHubError로 거부되며, 자동 확정 기능은 없습니다.

Podcast(팟캐스트)

메서드엔드포인트반환값
createPodcast(params)POST v1/episodes/all-in-one{ episodeId }
listPodcasts(params?)GET v1/episodes(productId=aiPodcast)ListEpisodesResponse

createPodcast 파라미터(CreatePodcastParams):

파라미터타입설명
type'podcast-solo' | 'podcast-duo'1인 또는 2인 진행
querystring주제
sourcesContentSource[]{ type: 'url' | 'text'; uri?; content? }
template{ type: 'podcast'; mode; speakers; language }mode: quick | deep | debate, speakers: speakerInnerId[], language: en | zh | ja

Flow Speech / TTS

메서드엔드포인트반환값
createTTS(params)POST v1/episodes/flow-speech{ episodeId }
listTTS(params?)GET v1/episodes(productId=textToSpeech)ListEpisodesResponse

createTTS 파라미터(CreateTTSParams): { sources, template: { type: 'flowspeech', mode: 'smart' | 'direct', speakers, language } }.

Storybook(설명 영상 / 슬라이드)

메서드엔드포인트반환값
createExplainerVideo(params)POST v1/episodes/storybook{ episodeId }
createSlides(params)POST v1/episodes/storybook(mode: 'slides', skipAudio: true){ episodeId }
exportExplainerVideo(episodeId)POST v1/episodes/{episodeId}/storybook/videovoid
listExplainerVideos(params?)GET v1/episodes(productId=explainerVideo)ListEpisodesResponse
listSlides(params?)GET v1/episodes(productId=slideDeck)ListEpisodesResponse

createExplainerVideocreateSlides는 같은 형태를 공유합니다: { query?, sources?, style?, styleOverride?, skipAudio?, imageConfig?, template }. template에는 type: 'storybook', mode(설명 영상은 info / story, 덱은 slides), speakers, language, 그리고 선택적인 style, size(2K / 4K), aspectRatio(16:9 / 9:16 / 1:1), pageCount가 들어갑니다. createSlidesskipAudio 기본값을 true로 두고 modeslides로 고정합니다. exportExplainerVideo는 다운로드 가능한 영상 렌더링을 트리거합니다.

Episodes(공통)

ListenHubClient의 네 가지 제품 전반에서 동작합니다.

메서드엔드포인트반환값
getCreation(episodeId)GET v5/episodes/{episodeId}/detailEpisodeDetail
deleteCreations(params)DELETE v1/episodesvoid

getCreation은 전체 EpisodeDetail(상태, 스피커, 제목/아웃라인/오디오/비디오/페이지/스크립트가 담긴 topicDetail)을 반환합니다. deleteCreations({ ids })는 최대 100개 에피소드를 id로 일괄 소프트 삭제합니다. 비디오 에피소드 id를 전달하면 해당 비디오 태스크도 함께 소프트 삭제되고, 진행 중인 태스크의 크레딧은 환불됩니다. 제품별 list* 메서드는 모두 productId 필터와 함께 GET v1/episodes를 호출하며 { page?, pageSize? }를 받습니다.

Image(이미지)

메서드엔드포인트반환값
createAIImage(params)POST v1/images{ imageId }
getAIImage(imageId)GET v1/images/{imageId}AIImageItem
listAIImages(params?)GET v1/images{ items, pagination }
deleteAIImages(params)DELETE v1/imagesvoid

createAIImage 파라미터(CreateAIImageParams):

파라미터타입설명
promptstring필수
referenceImageUrlsstring[]참조 이미지 URL
language'auto' | 'en' | 'ja' | 'ko' | 'hi' | 'zh' | 'pt' | 'es'프롬프트 언어
aspectRatio'1:1' | '2:3' | '3:2' | '3:4' | '4:3' | '9:16' | '16:9' | '21:9' | …출력 비율
imageSize'1K' | '2K' | '4K'출력 해상도
model'gemini-3-pro-image' | 'gemini-3.1-flash-image'이미지 모델
isLosslessboolean무손실 인코딩
enableSearchboolean근거 확보를 위한 웹 검색 허용

생성은 비동기입니다. status가 최종 상태가 되고 imageUrl이 채워질 때까지 getAIImage(imageId)를 폴링하세요. deleteAIImages({ ids })는 최대 100개 이미지를 일괄 소프트 삭제합니다(소유자 범위로 제한되며, 알 수 없는 id는 무시).

Music(음악)

ListenHubClientOpenAPIClient와 동일한 음악 메서드 집합을 노출합니다(엔드포인트와 파라미터도 동일): createMusicGenerate, createMusicCover, createMusicExtend, createMusicRemix, createMusicInstrumental, createMusicSoundtrack, createMusicTrack, recognizeMusic, describeMusic, stemMusic, getMusicTask, listMusicTasks. 파라미터와 폴링 루프는 위의 Music을 참고하세요.

Lyrics(가사)

메서드엔드포인트반환값
createLyrics(params)POST v1/lyrics/generate{ taskId, status }
getLyricsTask(taskId)GET v1/lyrics/tasks/{taskId}LyricsTaskDetail
listLyricsTasks(params?)GET v1/lyrics/tasks{ items, page, pageSize, total }

createLyrics({ prompt })는 비동기 가사 태스크를 시작합니다. statussuccess가 될 때까지 getLyricsTask를 폴링한 뒤 variants(각각 { text, title, status })를 읽으세요.

Video Generation(비디오 생성)

ListenHubClientOpenAPIClient와 동일한 비디오 메서드를 노출하지만 이름이 하나 다릅니다. SeeDance/HappyHorse 견적 메서드는 estimateVideoGenerationCredits입니다(OpenAPIClient에서는 estimateVideoCredits).

메서드엔드포인트반환값
createVideoGeneration(params)POST v1/video-generation/generate{ taskId, status }
getVideoGenerationTask(taskId)GET v1/video-generation/tasks/{taskId}VideoGenerationTaskDetail
listVideoGenerationTasks(params?)GET v1/video-generation/tasks{ items, page, pageSize, total }
estimateVideoGenerationCredits(params)POST v1/video-generation/estimate-credits{ tokens, credits }
createPixVerseVideoGeneration(params)POST v1/video-generation/pixverse/generate{ taskId, episodeId?, status }
estimatePixVerseVideoCredits(params)POST v1/video-generation/pixverse/estimate-credits{ tokens, credits }

파라미터는 위의 Video 섹션과 같습니다.

Subscription & user(구독 및 사용자)

메서드엔드포인트반환값
getCurrentUser()GET v1/users/meUserProfile
getSubscription()GET v1/users/subscriptionSubscriptionInfo
getSettings()GET v2/settingsSettingsResponse

엔드포인트가 OpenAPIClient와 다르다는 점에 유의하세요(v1/users/subscription vs. v1/user/subscription). getSettings는 사용자가 저장해 둔 제품별 기본값(스피커, 언어, 길이, 모드, 스타일 이미지)을 반환합니다.

Checkin(출석 체크)

메서드엔드포인트반환값
checkinSubmit()POST v1/checkin{ checkinDate, rewardCredits }
checkinStatus()GET v1/checkin/statusCheckinStatusResponse

크레딧을 보상으로 받는 일일 출석 체크입니다. checkinStatushasCheckedInToday, lastCheckinTime, monthlyCheckinCount를 알려 줍니다.

Settings / API key

메서드엔드포인트반환값
getApiKey()GET v1/settings/api-key{ key }
regenerateApiKey()POST v1/settings/api-key/regenerate{ key }

로그인한 사용자가 자신의 OpenAPI 키를 읽거나 교체할 수 있게 합니다. regenerateApiKey는 이전 키를 무효화합니다.

Files(파일)

메서드엔드포인트반환값
createFileUpload(params)POST v1/files{ presignedUrl, fileUrl }
getFileDownloadUrl(fileUrl)GET v1/files{ downloadUrl }

createFileUpload({ fileKey, contentType, category })는 바이트를 PUTpresignedUrl과, 이후 참조에 사용할 fileUrl을 반환합니다. getFileDownloadUrl(fileUrl)은 저장된 파일 URL을 다시 서명해 유효 기간이 있는 downloadUrl로 바꿔 줍니다.


client.api 탈출구

ListenHubClient는 SDK가 감싸지 않은 엔드포인트를 위해 내부 ky 인스턴스를 client.api로 노출합니다. 동일한 인증, base URL, 재시도 동작이 적용되지만 응답 파싱은 직접 해야 합니다. 경로는 base URL 기준 상대 경로이며 앞에 /를 붙이지 않습니다(ky의 요구 사항):

const me = await client.api.get('v1/users/me').json();

OpenAPIClientclient.api를 노출하지 않습니다. SDK가 아직 다루지 않는 OpenAPI 엔드포인트는 동일한 Authorization: Bearer 헤더를 붙여 직접 만든 HTTP 클라이언트로 호출하세요 — OpenAPI 레퍼런스를 참고하세요.

에러

모든 메서드는 code가 0이 아니거나 HTTP 에러가 발생하면 ListenHubError를 던집니다. 이 에러는 status, code, requestId를 담고 있으니, 문제를 보고할 때 requestId를 함께 알려 주세요.

import { ListenHubError } from '@marswave/listenhub-sdk';

try {
  await client.getPodcast('nope');
} catch (err) {
  if (err instanceof ListenHubError) {
    console.error(`[${err.status}] code ${err.code} (request ${err.requestId})`);
  } else {
    throw err;
  }
}

다음 단계

이 페이지의 내용