ListenHubSDKs & CLI
JavaScript SDK

快速开始

安装 SDK、用 API key 鉴权、创建播客、轮询任务直至完成,并读取音频 URL。

本指南带你用 @marswave/listenhub-sdk JavaScript 客户端,从空项目走到一个完成的音频节目。你将安装 SDK、用 API key 构造一个 OpenAPIClient、发起一个播客、轮询任务直至成功,并读取最终的音频 URL。

生成是异步的。每个创建调用都会立即返回一个 episodeId;随后你轮询某个 get* 方法,直到 processStatus 离开 pending。完整的循环在本页末尾,可直接复制运行。

你需要一个 API key,在 listenhub.ai/settings/api-keys 创建。Key 形如 lh_sk_...。请放在服务端使用——绝不要把 key 打进浏览器或移动端代码。面向用户的应用请改用带 OAuth 的 ListenHubClient(见 鉴权)。

前置条件

步骤

安装 SDK

npm i @marswave/listenhub-sdk

设置 API key

当你不带参数构造 OpenAPIClient 时,它会从环境变量 LISTENHUB_API_KEY 读取 key。在 shell 中导出它:

export LISTENHUB_API_KEY=lh_sk_...

你也可以显式传入 key:new OpenAPIClient({ apiKey: 'lh_sk_...' })。优先用环境变量,避免把密钥写进源码仓库。

构造客户端

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

const client = new OpenAPIClient(); // 读取 LISTENHUB_API_KEY

该客户端指向 https://api.marswave.ai/openapi,并在每个请求上发送 Authorization: Bearer $LISTENHUB_API_KEY。它会替你拆开 { code, message, data } 信封,并自动重试 429 响应。要覆盖 base URL、超时或重试次数,见 配置

选择一个说话人

播客至少需要一个说话人。按语言列出可用的声音,并取一个 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' 传入原始文本,用 type: 'url' 指向一个让模型阅读的网页。

轮询直至完成

按固定间隔调用 getPodcast(episodeId)processStatus 初始为 pending;当它变化时,节目要么成功(出现 audioUrl),要么失败(检查 failCodemessage)。

let detail = await client.getPodcast(episodeId);

while (detail.processStatus === 'pending') {
  await sleep(5000); // 每 5 秒轮询一次
  detail = await client.getPodcast(episodeId);
  console.log(`Status: ${detail.processStatus}`);
}

读取音频 URL

轮询退出后,从 detail 读取 audioUrl。完成的节目还带有 titleoutlinescripts

if (detail.audioUrl) {
  console.log(`Title: ${detail.title}`);
  console.log(`Audio: ${detail.audioUrl}`);
} else {
  console.error(`Generation failed (failCode ${detail.failCode}): ${detail.message}`);
}

完整示例

一个可直接复制运行的脚本。它列出说话人、创建播客、轮询直到任务离开 pending、打印音频 URL,并报告剩余积分。

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

const client = new OpenAPIClient(); // 读取 LISTENHUB_API_KEY

// 1. 选择一个说话人。
const { items: speakers } = await client.listSpeakers({ language: 'en' });
const host = speakers[0];
console.log(`Using speaker: ${host.name}`);

// 2. 发起播客(立即返回)。
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. 轮询直到生成离开 "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. 读取结果。
if (detail.audioUrl) {
  console.log(`Title: ${detail.title}`);
  console.log(`Audio: ${detail.audioUrl}`);
} else {
  console.error(`Generation failed (failCode ${detail.failCode}): ${detail.message}`);
}

// 5. 查看剩余积分。
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 变成由一个或多个声音朗读的音频。形态相同——先创建,再轮询某个 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 错误时,方法会抛出携带 statuscoderequestIdListenHubError。捕获它以区分 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 参考

下一步

On this page