ListenHubOpenAPI
API 레퍼런스

설명 영상

모든 콘텐츠를 AI가 생성한 비주얼과 음성 내레이션이 포함된 설명 영상으로 변환합니다.

설명 영상(Explainer Video)을 사용하면 텍스트나 URL에서 내레이션이 포함된 비주얼 콘텐츠를 만들 수 있습니다. 두 가지 모드를 제공합니다:

info(기본값)story
용도지식 설명, 제품 소개스토리 공유, 사례 연구
비주얼 스타일인포그래픽, 일러스트, 데이터 시각화스토리 장면 일러스트
1페이지매거진 스타일 표지스토리 표지

mode 파라미터는 선택 사항이며 기본값은 info입니다.


에피소드 생성

POST /v1/storybook/episodes

AI가 생성한 비주얼과 내레이션이 포함된 설명 영상 에피소드를 생성합니다.

sources는 최대 1개, speakers는 최대 1개까지 허용됩니다.

Info 모드(기본값):

curl -X POST "https://api.marswave.ai/openapi/v1/storybook/episodes" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sources": [
      {"type": "url", "uri": "https://example.com/article", "content": "https://example.com/article"}
    ],
    "speakers": [
      {"speakerId": "<SPEAKER_ID>"}
    ],
    "language": "en",
    "mode": "info"
  }'
const response = await fetch('https://api.marswave.ai/openapi/v1/storybook/episodes', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    sources: [{ type: 'url', uri: 'https://example.com/article', content: 'https://example.com/article' }],
    speakers: [{ speakerId: '<SPEAKER_ID>' }],
    language: 'en',
    mode: 'info',
  }),
});
const data = await response.json();
console.log(data);
import os, requests

response = requests.post(
    'https://api.marswave.ai/openapi/v1/storybook/episodes',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
    json={
        'sources': [{'type': 'url', 'uri': 'https://example.com/article', 'content': 'https://example.com/article'}],
        'speakers': [{'speakerId': '<SPEAKER_ID>'}],
        'language': 'en',
        'mode': 'info',
    }
)
print(response.json())

Story 모드:

curl -X POST "https://api.marswave.ai/openapi/v1/storybook/episodes" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sources": [
      {"type": "text", "content": "The founding story of a small startup that grew into a global platform..."}
    ],
    "speakers": [
      {"speakerId": "<SPEAKER_ID>"}
    ],
    "language": "en",
    "mode": "story"
  }'
const response = await fetch('https://api.marswave.ai/openapi/v1/storybook/episodes', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    sources: [{ type: 'text', content: 'The founding story of a small startup that grew into a global platform...' }],
    speakers: [{ speakerId: '<SPEAKER_ID>' }],
    language: 'en',
    mode: 'story',
  }),
});
const data = await response.json();
console.log(data);
import os, requests

response = requests.post(
    'https://api.marswave.ai/openapi/v1/storybook/episodes',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
    json={
        'sources': [{'type': 'text', 'content': 'The founding story of a small startup that grew into a global platform...'}],
        'speakers': [{'speakerId': '<SPEAKER_ID>'}],
        'language': 'en',
        'mode': 'story',
    }
)
print(response.json())

응답:

{
  "code": 0,
  "message": "",
  "data": {
    "episodeId": "{episodeId}"
  }
}

요청 파라미터

파라미터타입필수설명
sourcesarray(1)콘텐츠 소스. 최대 1개.
sources[].typestring"text" 또는 "url"
sources[].contentstring텍스트 콘텐츠 또는 URL
sources[].uristringtype이 url일 때 필수소스 URI
sources[].metadataobject아니요소스 메타데이터
speakersarray(1)음성 설정. 최대 1개.
speakers[].speakerIdstring화자 ID(화자 목록 참고)
languagestring아니요언어 코드(예: "en", "zh")
modestring아니요"info"(기본값) 또는 "story"
stylestring아니요비주얼 스타일 ID

에피소드 상태 조회

GET /v1/storybook/episodes/{episodeId}

반환된 episodeIdprocessStatussuccess가 될 때까지 폴링합니다.

curl "https://api.marswave.ai/openapi/v1/storybook/episodes/{episodeId}" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY"
const response = await fetch(
  `https://api.marswave.ai/openapi/v1/storybook/episodes/${episodeId}`,
  { headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` } }
);
const data = await response.json();
console.log('Status:', data.data.processStatus);
import os, requests

response = requests.get(
    f'https://api.marswave.ai/openapi/v1/storybook/episodes/{episode_id}',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'}
)
data = response.json()
print('Status:', data['data']['processStatus'])

응답(processStatussuccess일 때):

{
  "code": 0,
  "message": "",
  "data": {
    "episodeId": "{episodeId}",
    "createdAt": 1700000000,
    "mode": "info",
    "processStatus": "success",
    "credits": 30,
    "title": "How AI Is Changing the World",
    "cover": "https://assets.listenhub.ai/covers/{episodeId}.png",
    "audioUrl": "https://assets.listenhub.ai/storybook/{episodeId}.mp3",
    "audioDuration": 180,
    "videoUrl": "",
    "videoStatus": "not_generated",
    "pages": [
      {
        "text": "Artificial intelligence has transformed industries worldwide...",
        "pageNumber": 1,
        "imageUrl": "https://assets.listenhub.ai/pages/{episodeId}-1.png",
        "audioTimestamp": 0
      },
      {
        "text": "From healthcare to finance, AI applications continue to expand...",
        "pageNumber": 2,
        "imageUrl": "https://assets.listenhub.ai/pages/{episodeId}-2.png",
        "audioTimestamp": 25.3
      }
    ]
  }
}

원본 소재: pages[]의 각 항목에는 imageUrl(AI가 생성한 비주얼)과 text(내레이션 스크립트)가 들어 있습니다. 이 소재들은 개별적으로 다운로드해 자체 콘텐츠에 활용할 수 있습니다.

processStatus

의미
pending처리 중
success완료
fail실패(failCode 확인)

videoStatus

의미
not_generated영상 생성이 아직 트리거되지 않음
pending영상 생성 중
success영상 준비 완료(videoUrl 사용 가능)
fail영상 생성 실패

생성에는 보통 2–5분이 걸립니다. 권장 폴링 방식: 60초 대기 후 10초마다 폴링합니다.


영상 생성

POST /v1/storybook/episodes/{episodeId}/video

완료된 에피소드의 영상 생성을 트리거합니다. processStatussuccess여야 합니다.

이 엔드포인트를 호출하기 전에 processStatussuccess가 될 때까지 기다리세요.

curl -X POST "https://api.marswave.ai/openapi/v1/storybook/episodes/{episodeId}/video" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY"
const response = await fetch(
  `https://api.marswave.ai/openapi/v1/storybook/episodes/${episodeId}/video`,
  {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` },
  }
);
console.log(await response.json());
import os, requests

response = requests.post(
    f'https://api.marswave.ai/openapi/v1/storybook/episodes/{episode_id}/video',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'}
)
print(response.json())

응답:

{
  "code": 0,
  "message": "",
  "data": {
    "success": true
  }
}

트리거한 후에는 videoStatussuccess가 될 때까지 GET /v1/storybook/episodes/{episodeId}를 폴링합니다.


전체 워크플로

에피소드 생성

소스, 화자, 모드(info 또는 story)를 지정해 POST /v1/storybook/episodes를 호출합니다. 반환된 episodeId를 저장하세요.

완료까지 폴링

processStatussuccess가 될 때까지 GET /v1/storybook/episodes/{episodeId}를 10초마다 폴링합니다(최초 60초 대기 후).

원본 소재 활용(선택)

pages[] 배열에는 각 페이지의 AI 생성 이미지(imageUrl)와 내레이션 스크립트(text)가 들어 있습니다. 영상을 생성하지 않고도 바로 활용할 수 있습니다.

영상 생성

POST /v1/storybook/episodes/{episodeId}/video를 호출해 각 페이지를 내레이션이 포함된 영상으로 합성합니다.

영상 상태 폴링

videoStatussuccess가 될 때까지 폴링합니다. videoUrl 필드에 다운로드 링크가 들어 있습니다.

이 페이지의 내용