解説動画とスライド
テキストや 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 | ストーリーシーンのイラスト | ストーリーの表紙 | ストーリー共有、事例紹介 |
slides | PPT レイアウト(グリッド、プロセスフロー、大きな数字のヒーロー) | プレゼンテーションのタイトルページ | 会議のプレゼン、ビジネスレポート、カンファレンス講演 |
ワークフロー
エピソードを作成する
ソース、話者、使用したい 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.episodeIdimport 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" }
}リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
sources | array(1) | はい | コンテンツソース。ちょうど 1 件 |
sources[].type | string | はい | "text" または "url" |
sources[].content | string | はい | テキストコンテンツ、または type が "url" の場合は URL 自体 |
sources[].uri | string | いいえ | 受け付けられますが無視されます — url ソースではサーバーが content から uri を導出します |
sources[].metadata | object | いいえ | ソースのメタデータ |
speakers | array(1) | はい¹ | 音声設定。最大 1 件 |
speakers[].speakerId | string | はい | 話者 ID(話者 を参照) |
skipAudio | boolean | いいえ | デフォルトは false。true の場合は画像とテキストのみが生成され、ナレーション音声は作成されません |
language | string | いいえ | 言語コード(例:"en"、"zh")。デフォルトは en で、ソースからは推測されません |
mode | string | いいえ | "info"(デフォルト)、"story"、"slides" のいずれか |
style | string | いいえ | ビジュアルスタイル 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 のどこから始まるか)が含まれます。これらをダウンロードすれば、
動画をレンダリングせずに独自のデッキを組み立てたり編集したりできます。
レスポンスフィールド
| フィールド | 型 | 説明 |
|---|---|---|
episodeId | string | ポーリングに使用したエピソード ID |
mode | string | このエピソードが作成されたモード |
processStatus | string | 下記を参照 |
videoStatus | string | 下記を参照 |
credits | number | このエピソードがこれまでに消費したクレジット |
failCode | number | 失敗コード。processStatus が fail のときに含まれます |
message | string | 現在のステータスに関する、人間が読める詳細 |
title / cover | string | 生成されたタイトルとカバー画像 |
audioUrl / audioDuration | string / number | ナレーション音声と、その長さ(秒) |
videoUrl | string | レンダリングされた動画(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 を読み出します。