ListenHubDocs
API リファレンス解説動画とスライド

解説動画とスライド

テキストや URL を、ナレーション付きのページ集(解説、ストーリー、プレゼンテーションスライド)に変換し、動画としてレンダリングする 1 つのエンドポイントファミリーです。

解説動画、ストーリー動画、プレゼンテーションスライドは、1 つのエンドポイントファミリーの 3 つのモードです。ソースとボイスを送ると、ListenHub がナレーションを作成し、ページごとにビジュアルを生成します。生成されたページはそのまま素材として利用することも、ナレーション付きの動画にレンダリングすることもできます。

3 つのエンドポイントは、すべてのモードで共通です:

エンドポイント用途
POST /v1/storybook/episodesエピソードを作成します。mode で解説、ストーリー、スライドを選択します
GET /v1/storybook/episodes/{episodeId}進行状況をポーリングし、ページとアセット URL を読み出します
POST /v1/storybook/episodes/{episodeId}/video完成したページを動画にレンダリングします

本ページのすべてのエンドポイントは OpenAPI の Base URL https://api.marswave.ai/openapi を使用し、 Authorization: Bearer $LISTENHUB_API_KEY ヘッダーで API キーによる認証を行います。キーは listenhub.ai/settings/api-keys で作成できます。

モードを選ぶ

mode は任意で、デフォルトは info です。3 つのモード間で異なるのはこのフィールドだけで、 本ページのそれ以外の内容はいずれのモードにも当てはまります。

mode生成されるもの1 ページ目最適な用途
info (デフォルト)インフォグラフィック、イラスト、データビジュアライゼーション雑誌風の表紙知識解説、製品紹介
storyストーリーシーンのイラストストーリーの表紙ストーリー共有、事例紹介
slidesPPT レイアウト(グリッド、プロセスフロー、大きな数字のヒーロー)プレゼンテーションのタイトルページ会議のプレゼン、ビジネスレポート、カンファレンス講演

ワークフロー

エピソードを作成する

ソース、話者、使用したい mode を指定して POST /v1/storybook/episodes を呼び出します。返された episodeId を保存してください。

完了までポーリングする

最初に 60 秒待ってから、processStatus が success になるまで GET /v1/storybook/episodes/{episodeId} を 10 秒ごとにポーリングします。

素材を利用する(任意)

pages[] には、生成された画像とナレーション原稿が入っています。必要なものがそれだけなら、ここで終了です。

動画をレンダリングする

POST /v1/storybook/episodes/{episodeId}/video を呼び出して、各ページをナレーション付きの動画に合成します。

動画をポーリングする

videoStatus が success になるまでポーリングし、videoUrl をダウンロードします。

エピソードを作成する

POST /v1/storybook/episodes

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", "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', content: 'https://example.com/article' }],
      speakers: [{ speakerId: '<SPEAKER_ID>' }],
      language: 'en',
      mode: 'info',
    }),
  },
)
const { data } = await response.json()
const episodeId = data.episodeId
import os
import 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', 'content': 'https://example.com/article'}],
        'speakers': [{'speakerId': '<SPEAKER_ID>'}],
        'language': 'en',
        'mode': 'info',
    },
)
episode_id = response.json()['data']['episodeId']

レスポンス:

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

リクエストパラメータ

パラメータ型必須説明
sourcesarray(1)はいコンテンツソース。ちょうど 1 件
sources[].typestringはい"text" または "url"
sources[].contentstringはいテキストコンテンツ、または type が "url" の場合は URL 自体
sources[].uristringいいえ受け付けられますが無視されます — url ソースではサーバーが content から uri を導出します
sources[].metadataobjectいいえソースのメタデータ
speakersarray(1)はい¹音声設定。最大 1 件
speakers[].speakerIdstringはい話者 ID(話者 を参照)
skipAudiobooleanいいえデフォルトは false。true の場合は画像とテキストのみが生成され、ナレーション音声は作成されません
languagestringいいえ言語コード(例:"en"、"zh")。デフォルトは en で、ソースからは推測されません
modestringいいえ"info"(デフォルト)、"story"、"slides" のいずれか
stylestringいいえビジュアルスタイル ID。省略するとそのモードのデフォルトスタイルが使われます。指定可能な ID は公開契約の一部ではありません

¹ skipAudio が true の場合を除き speakers は必須で、true の場合は省略できます。

language はコンテンツから自動検出されません。省略すると、ソースの言語にかかわらず英語のエピソードが 生成されるため、英語以外のソースでは明示的に指定してください。

ビジュアルと原稿だけが必要な場合は skipAudio: true を指定してください。音声のレンダリングは 行われませんが、ページ画像とナレーションテキストはエピソードから取得できます。

エピソードをポーリングする

GET /v1/storybook/episodes/{episodeId}

返された episodeId を使って、processStatus が success になるまでポーリングします。

curl "https://api.marswave.ai/openapi/v1/storybook/episodes/{episodeId}" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY"

レスポンス(processStatus が success のとき):

{
  "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.app/covers/{episodeId}.png",
    "audioUrl": "https://assets.listenhub.app/storybook/{episodeId}.mp3",
    "audioDuration": 180,
    "videoUrl": "",
    "videoStatus": "not_generated",
    "pages": [
      {
        "text": "Artificial intelligence has transformed industries worldwide...",
        "pageNumber": 1,
        "imageUrl": "https://assets.listenhub.app/pages/{episodeId}-1.png",
        "audioTimestamp": 0
      },
      {
        "text": "From healthcare to finance, AI applications continue to expand...",
        "pageNumber": 2,
        "imageUrl": "https://assets.listenhub.app/pages/{episodeId}-2.png",
        "audioTimestamp": 25.3
      }
    ]
  }
}

素材:pages[] の各要素には imageUrl(生成されたビジュアル)、text(ナレーション原稿)、 audioTimestamp(そのページが audioUrl のどこから始まるか)が含まれます。これらをダウンロードすれば、 動画をレンダリングせずに独自のデッキを組み立てたり編集したりできます。

レスポンスフィールド

フィールド型説明
episodeIdstringポーリングに使用したエピソード ID
modestringこのエピソードが作成されたモード
processStatusstring下記を参照
videoStatusstring下記を参照
creditsnumberこのエピソードがこれまでに消費したクレジット
failCodenumber失敗コード。processStatus が fail のときに含まれます
messagestring現在のステータスに関する、人間が読める詳細
title / coverstring生成されたタイトルとカバー画像
audioUrl / audioDurationstring / numberナレーション音声と、その長さ(秒)
videoUrlstringレンダリングされた動画(videoStatus が success になった後)
pages[]arrayページごとの text、pageNumber、imageUrl、audioTimestamp

クレジットは事前に見積もりが提示されるのではなく、エピソード単位で報告されます。プラットフォームが生成をどのように課金するかは クレジットと料金 を参照してください。

processStatus

値意味
pending処理中
success完了
fail失敗 — failCode と message を確認し、エラー処理 を参照してください

videoStatus

値意味
not_generated動画生成がまだトリガーされていない
pending動画を生成中
success動画の準備完了(videoUrl が利用可能)
fail動画の生成に失敗

生成には通常 2–5 分かかります。推奨のポーリング方法:60 秒待ってから、10 秒ごとに ポーリングします。

動画をレンダリングする

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

完了したエピソードの動画生成をトリガーします。先に processStatus が success になっている必要があります。

curl -X POST "https://api.marswave.ai/openapi/v1/storybook/episodes/{episodeId}/video" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY"

レスポンス:

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

トリガー後は、videoStatus が success になるまで GET /v1/storybook/episodes/{episodeId} をポーリングし、 videoUrl を読み出します。

関連

このページの内容