クイックスタート
SDK をインストールし、API キーで認証し、ポッドキャストを作成し、完了までポーリングして、音声 URL を読み取ります。
本ガイドでは、@marswave/listenhub-sdk JavaScript クライアントを使って、空のプロジェクトから完成した音声エピソードまでを進めます。SDK をインストールし、API キーで OpenAPIClient を構築し、ポッドキャストを開始し、タスクが成功するまでポーリングして、生成された音声 URL を読み取ります。
生成は非同期です。作成系の呼び出しはすべてすぐに episodeId を返します。その後、processStatus が pending から変わるまで get* メソッドをポーリングします。完全なループはこのページの末尾にあり、コピー&ペーストでそのまま実行できます。
API キーが必要です。listenhub.ai/settings/api-keys で作成してください。キーは lh_sk_... のような形式です。サーバーサイドで保管し、ブラウザやモバイルのコードにキーを含めて配布しないでください。ユーザー向けアプリでは、代わりに OAuth を使う ListenHubClient を利用します(認証 を参照)。
前提条件
- Node.js >= 20(SDK は ESM のみ対応)。
- listenhub.ai/settings/api-keys で発行した API キー。
手順
SDK をインストールする
npm i @marswave/listenhub-sdkAPI キーを設定する
OpenAPIClient は引数なしで構築すると、環境変数 LISTENHUB_API_KEY からキーを読み取ります。シェルでエクスポートしてください:
export LISTENHUB_API_KEY=lh_sk_...キーを明示的に渡すこともできます:new OpenAPIClient({ apiKey: 'lh_sk_...' })。シークレットがソース管理に入らないよう、環境変数を優先してください。
クライアントを構築する
import { OpenAPIClient } from '@marswave/listenhub-sdk';
const client = new OpenAPIClient(); // reads LISTENHUB_API_KEYこのクライアントは https://api.marswave.ai/openapi を宛先とし、すべてのリクエストで Authorization: Bearer $LISTENHUB_API_KEY を送信します。{ code, message, data } のエンベロープは自動で展開され、429 レスポンスは自動でリトライされます。base URL、タイムアウト、リトライ回数を上書きするには 設定 を参照してください。
スピーカーを選ぶ
ポッドキャストには少なくとも 1 人のスピーカーが必要です。言語を指定して利用可能な音声を一覧し、speakerId を取得します:
const { items: speakers } = await client.listSpeakers({ language: 'en' });
const host = speakers[0];
console.log(`Using speaker: ${host.name} (${host.speakerId})`);ポッドキャストを作成する
createPodcast は、作りたい内容を記述した query、内容の根拠となる任意の sources、および speakers 配列を受け取ります。episodeId はすぐに返り、生成はバックグラウンドで実行されます。
const { episodeId } = await client.createPodcast({
query: 'Explain how transformers work in large language models',
sources: [
{
type: 'url',
content: 'https://en.wikipedia.org/wiki/Transformer_(deep_learning_architecture)',
},
],
speakers: [{ speakerId: host.speakerId }],
language: 'en',
});
console.log(`Created podcast: ${episodeId}`);各 source は { type: 'text' | 'url', content } です。生のテキストを渡すには type: 'text' を、モデルに読ませたい Web ページを指すには type: 'url' を使います。
完了までポーリングする
getPodcast(episodeId) を一定間隔で呼び出します。processStatus は最初 pending です。値が変わったとき、エピソードは成功している(audioUrl が存在する)か、失敗しています(failCode と message を確認してください)。
let detail = await client.getPodcast(episodeId);
while (detail.processStatus === 'pending') {
await sleep(5000); // poll every 5 seconds
detail = await client.getPodcast(episodeId);
console.log(`Status: ${detail.processStatus}`);
}音声 URL を読み取る
ポーリングを抜けたら、detail から audioUrl を読み取ります。完了したエピソードには title、outline、scripts も含まれます。
if (detail.audioUrl) {
console.log(`Title: ${detail.title}`);
console.log(`Audio: ${detail.audioUrl}`);
} else {
console.error(`Generation failed (failCode ${detail.failCode}): ${detail.message}`);
}完全な例
コピー&ペーストでそのまま実行できる 1 本のスクリプトです。スピーカーを一覧し、ポッドキャストを作成し、タスクが pending を抜けるまでポーリングし、音声 URL を出力して、残りのクレジットを報告します。
import { OpenAPIClient, ListenHubError } from '@marswave/listenhub-sdk';
const client = new OpenAPIClient(); // reads LISTENHUB_API_KEY
// 1. Pick a speaker.
const { items: speakers } = await client.listSpeakers({ language: 'en' });
const host = speakers[0];
console.log(`Using speaker: ${host.name}`);
// 2. Start the podcast (returns immediately).
const { episodeId } = await client.createPodcast({
query: 'Explain how transformers work in large language models',
sources: [
{
type: 'url',
content: 'https://en.wikipedia.org/wiki/Transformer_(deep_learning_architecture)',
},
],
speakers: [{ speakerId: host.speakerId }],
language: 'en',
});
console.log(`Created podcast: ${episodeId}`);
// 3. Poll until generation leaves "pending".
let detail = await client.getPodcast(episodeId);
while (detail.processStatus === 'pending') {
await sleep(5000);
detail = await client.getPodcast(episodeId);
console.log(`Status: ${detail.processStatus}`);
}
// 4. Read the result.
if (detail.audioUrl) {
console.log(`Title: ${detail.title}`);
console.log(`Audio: ${detail.audioUrl}`);
} else {
console.error(`Generation failed (failCode ${detail.failCode}): ${detail.message}`);
}
// 5. Check remaining credits.
const sub = await client.getSubscription();
console.log(`Credits remaining: ${sub.totalAvailableCredits}`);
function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}ポッドキャストの代わりに flow speech を使う
Flow speech は、テキストや URL を 1 つ以上の声によるナレーション音声に変換します。形は同じで——作成してから get* メソッドをポーリングします——変わるのはメソッド名だけです。司会者どうしの会話ではなく読み上げが欲しいときに使います。
const { episodeId } = await client.createPodcast({
query: 'Explain how transformers work in large language models',
speakers: [{ speakerId: host.speakerId }],
language: 'en',
});
let detail = await client.getPodcast(episodeId);
while (detail.processStatus === 'pending') {
await sleep(5000);
detail = await client.getPodcast(episodeId);
}
console.log(detail.audioUrl);const { episodeId } = await client.createFlowSpeech({
sources: [{ type: 'text', content: 'Hello world, this is ListenHub.' }],
speakers: [{ speakerId: host.speakerId }],
language: 'en',
});
let detail = await client.getFlowSpeech(episodeId);
while (detail.processStatus === 'pending') {
await sleep(5000);
detail = await client.getFlowSpeech(episodeId);
}
console.log(detail.audioUrl);エラーを処理する
code が 0 以外の場合や HTTP エラーが起きた場合、メソッドは status、code、requestId を持つ ListenHubError を投げます。これを捕捉して、API エラーとその他の失敗を区別します:
import { ListenHubError } from '@marswave/listenhub-sdk';
try {
await client.getPodcast('nonexistent-id');
} catch (err) {
if (err instanceof ListenHubError) {
console.error(`API error [${err.status}] code ${err.code} (request ${err.requestId})`);
} else {
throw err;
}
}生成する前にコストを確認する
クレジットのコストは製品、長さ、オプションによって変わるため、本ガイドでは具体的な数値を示しません。getSubscription()(totalAvailableCredits フィールド)で現在の残高を読み取り、コストの高いジョブに踏み切る前に該当する estimate-credits エンドポイント——たとえば estimateVideoCredits——を使ってください。どの製品が見積もり用エンドポイントを提供しているかは OpenAPI リファレンス を参照してください。