SDK 方法参考
OpenAPIClient 与 ListenHubClient 的全部方法,按产品分组,附签名、端点和返回值。
这是 @marswave/listenhub-sdk 的完整方法参考,按产品分组。每个条目列出方法签名、一句话说明,以及底层调用的 HTTP 端点。
SDK 提供两个客户端。它们共用同一套响应处理(code 0 时解包 data,否则抛出 ListenHubError,并对 429 自动重试),但面向不同的 API 接口、采用不同的认证方式:
OpenAPIClient | ListenHubClient | |
|---|---|---|
| 认证 | API key(Authorization: Bearer) | OAuth 用户访问令牌 |
| Base URL | https://api.marswave.ai/openapi | https://api.listenhub.ai/api |
| 身份 | 你的账户 / key 所有者 | 已登录用户 |
| 适用 | 服务端、脚本、CI | 面向用户的应用 |
OpenAPIClient 是公开的 OpenAPI 产品,也是本参考的重点。ListenHubClient 是第一方应用使用的 OAuth 客户端,其方法列在末尾的 ListenHubClient 方法。
生成是异步的。create* 调用会立即返回一个 id;轮询对应的 get* 方法,直到 processStatus(或任务 status)离开 pending / generating。完整循环见 快速开始。
下文约定:
- "端点"路径是相对于客户端 Base URL 的。
OpenAPIClient的 Base URL 为https://api.marswave.ai/openapi/。 - 方法返回解包后的
data负载,{ code, message, data }信封已为你处理。 - 少数方法返回原始
Response(二进制或流式),文中会明确标注。 - 不要硬编码积分成本。请改用
estimate*Credits方法和getSubscription()。
OpenAPIClient 方法
Speakers(声音)
每个声音由其 speakerId 标识。创建任何 episode 前先列出可用声音,并传入需要的 id。
| 方法 | 端点 | 返回 | 说明 |
|---|---|---|---|
listSpeakers(params?) | GET v1/speakers/list | { items: OpenAPISpeaker[] } | 可用声音 |
listSpeakers 参数:
| 参数 | 类型 | 说明 |
|---|---|---|
language | string | 按语言过滤,如 en、zh、ja |
status | number | 可用状态过滤 |
每个 OpenAPISpeaker 包含 speakerId、name、gender、language、demoAudioUrl,以及可选的 profile(pitch、speed、traits、styles、scenes、accent、description)。
const { items } = await client.listSpeakers({ language: 'en' });
const speakerId = items[0].speakerId;Podcast(播客)
播客是由 query 和/或 sources 生成的多人对话。创建后轮询 getPodcast,直到 processStatus 为 success。
| 方法 | 端点 | 返回 |
|---|---|---|
createPodcast(params) | POST v1/podcast/episodes | { episodeId } |
getPodcast(episodeId) | GET v1/podcast/episodes/{episodeId} | OpenAPIPodcastDetail |
createPodcastTextContent(params) | POST v1/podcast/episodes/text-content | { episodeId, message } |
generatePodcastAudio(episodeId, params?) | POST v1/podcast/episodes/{episodeId}/audio | { success, message, episodeId, status } |
getPodcastTextStream(episodeId, event) | GET v1/podcast/episodes/{episodeId}/text-stream | 原始 Response(流) |
createPodcast 参数(OpenAPICreatePodcastParams):
| 参数 | 类型 | 说明 |
|---|---|---|
query | string | episode 要讲什么 |
sources | Array<{ type: 'text' | 'url'; content: string }> | 内容素材;原始文本或页面 URL |
speakers | Array<{ speakerId: string }> | 必填;每个声音一项 |
language | string | 输出语言 |
mode | string | 生成深度(如 quick、deep) |
先文本后音频的两步流程,可让你在付费生成音频前先审阅或修改脚本:createPodcastTextContent 只生成脚本,随后 generatePodcastAudio(episodeId, { scripts }) 用你可选改写的脚本渲染音频。getPodcastTextStream(episodeId, 'script' | 'outline') 返回流式 Response,用于实时获取脚本/大纲 token。
OpenAPIPodcastDetail 包含 processStatus、title、outline、cover、audioUrl、audioStreamUrl、subtitlesUrl、scripts(逐说话人的台词)、credits,失败时还有 failCode。
Flow Speech / TTS
Flow speech 把文本或 URL 转成由一个或多个声音朗读的音频。TTS 端点更底层:从明确的脚本合成语音。
Flow speech
| 方法 | 端点 | 返回 |
|---|---|---|
createFlowSpeech(params) | POST v1/flow-speech/episodes | { episodeId } |
getFlowSpeech(episodeId) | GET v1/flow-speech/episodes/{episodeId} | OpenAPIFlowSpeechDetail |
createFlowSpeechTTS(params) | POST v1/flow-speech/episodes/tts | { episodeId } |
getFlowSpeechTextStream(episodeId, event) | GET v1/flow-speech/episodes/{episodeId}/text-stream | 原始 Response(流) |
createFlowSpeech 参数(OpenAPICreateFlowSpeechParams):
| 参数 | 类型 | 说明 |
|---|---|---|
sources | Array<{ type: 'text' | 'url'; content?: string; uri?: string }> | 必填;文本用 content,URL 用 uri |
speakers | Array<{ speakerId: string }> | 必填 |
language | string | 输出语言 |
mode | 'smart' | 'direct' | smart 为朗读改写;direct 原样朗读 |
createFlowSpeechTTS 接收 scripts: Array<{ content: string; speakerId: string }> 及可选 title,逐字渲染台词。文本流的 event 为 'script' | 'outline'。
OpenAPIFlowSpeechDetail 包含 processStatus、title、outline、cover、audioUrl、audioStreamUrl、subtitlesUrl、scripts 和 sourceProcessResult。
TTS / speech
| 方法 | 端点 | 返回 |
|---|---|---|
speech(params) | POST v1/speech | OpenAPISpeechResponse |
tts(params) | POST v1/tts | 原始 Response(音频字节) |
audioSpeech(params) | POST v1/audio/speech | 原始 Response(音频字节) |
speech 接收 scripts: Array<{ content: string; speakerId: string }>,同步返回 { audioUrl, audioDuration, subtitlesUrl?, taskId, credits }。
tts 与 audioSpeech 是兼容 OpenAI 的单声音合成。它们接收 { input, voice, response_format? },response_format 取 mp3(默认)、opus、aac、flac、wav、pcm,并以原始 Response 返回音频——用 .arrayBuffer() 读取或流式读取 .body。
const res = await client.tts({ input: 'Hello world', voice: speakerId, response_format: 'mp3' });
const audio = Buffer.from(await res.arrayBuffer());Storybook(解说视频 / 幻灯片)
Storybook 产出基于页面的视觉内容——解说视频与幻灯片。mode 选择格式,音频可通过 skipAudio 跳过。
| 方法 | 端点 | 返回 |
|---|---|---|
createStorybook(params) | POST v1/storybook/episodes | { episodeId } |
getStorybook(episodeId) | GET v1/storybook/episodes/{episodeId} | OpenAPIStorybookDetail |
generateStorybookVideo(episodeId) | POST v1/storybook/episodes/{episodeId}/video | { success } |
createStorybook 参数(OpenAPICreateStorybookParams):
| 参数 | 类型 | 说明 |
|---|---|---|
sources | Array<{ type: 'text' | 'url'; content: string }> | 必填的内容素材 |
speakers | Array<{ speakerId: string }> | 可选;仅生成音频时需要 |
mode | 'info' | 'story' | 'slides' | slides 为幻灯片;info / story 为解说 |
skipAudio | boolean | 为 true 时仅出视觉内容 |
style | string | 视觉风格提示 |
language | string | 输出语言 |
episode 成功后,generateStorybookVideo(episodeId) 把页面渲染成可下载视频。轮询 getStorybook 并观察 videoStatus(not_generated → pending → success / fail),成功时出现 videoUrl。
OpenAPIStorybookDetail 包含 mode、processStatus、title、cover、audioUrl、audioDuration、videoUrl、videoStatus,以及 pages(每页含 text、pageNumber、imageUrl、audioTimestamp)。
Image(图片)
单次调用的图片生成。OpenAPIClient 上没有单独的轮询方法——响应即携带结果。
| 方法 | 端点 | 返回 |
|---|---|---|
createImage(params) | POST v1/images/generation | OpenAPICreateImageResponse |
createImage 参数(OpenAPICreateImageParams):
| 参数 | 类型 | 说明 |
|---|---|---|
provider | string | 必填的图片 provider |
model | string | provider 模型 |
prompt | string | 必填的文本提示 |
referenceImages | Array<{ fileData?; inlineData? }> | 参考图——fileData: { fileUri, mimeType } 或 inlineData: { data, mimeType }(base64) |
imageConfig | { imageSize?; aspectRatio? } | imageSize:1K | 2K | 4K;aspectRatio:16:9 | 4:3 | 1:1 | 3:4 | 9:16 | 21:9 |
Video(SeeDance / HappyHorse + PixVerse)
两类视频共用同一套轮询/列表/估算方法,但创建方法和参数不同。SeeDance(doubao-seedance-2-*)与 HappyHorse 使用 content 数组;PixVerse 使用基于 capability 的结构。
SeeDance / HappyHorse
| 方法 | 端点 | 返回 |
|---|---|---|
createVideoGeneration(params) | POST v1/video-generation/generate | { taskId, status } |
getVideoGenerationTask(taskId) | GET v1/video-generation/tasks/{taskId} | OpenAPIVideoGenerationTaskDetail |
listVideoGenerationTasks(params?) | GET v1/video-generation/tasks | { items, page, pageSize, total } |
estimateVideoCredits(params) | POST v1/video-generation/estimate-credits | { tokens, credits } |
createVideoGeneration 参数(OpenAPICreateVideoGenerationParams):
| 参数 | 类型 | 说明 |
|---|---|---|
model | 'doubao-seedance-2-pro' | 'doubao-seedance-2-fast' | 'happyhorse' | 默认为某个 SeeDance 模型 |
content | VideoContentItem[] | 必填;混合的 文本 / 图片 / 视频 / 音频 项(见下) |
resolution | '480p' | '720p' | '1080p' | 1080p 仅 doubao-seedance-2-pro;happyhorse 无 480p |
ratio | '16:9' | '4:3' | '1:1' | '3:4' | '9:16' | '21:9' | '4:5' | '5:4' | 4:5 / 5:4 仅 happyhorse |
duration | number | 秒;SeeDance 最小 4,HappyHorse 最小 3 |
generateAudio | boolean | 生成音轨 |
seed | number | 复现用种子 |
inputVideoDuration | number | 视频编辑输入;SeeDance [2,15],HappyHorse [3,60] |
audioSetting | 'auto' | 'origin' | 仅 HappyHorse 视频编辑,且 content 含 video_url 时生效 |
每个 content 项为以下之一:
{ type: 'text', text }{ type: 'image_url', image_url: { url }, role: 'first_frame' \| 'last_frame' \| 'reference_image' }{ type: 'video_url', video_url: { url }, role: 'reference_video' }{ type: 'audio_url', audio_url: { url }, role: 'reference_audio' }
HappyHorse 不接受 last_frame 和 audio_url 内容。estimateVideoCredits 接收 { model, resolution, duration, hasVideoInput?, inputVideoDuration?, ratio? }。
const { taskId } = await client.createVideoGeneration({
model: 'doubao-seedance-2-pro',
content: [{ type: 'text', text: 'A timelapse of a city at dusk' }],
resolution: '1080p',
duration: 5,
});PixVerse
| 方法 | 端点 | 返回 |
|---|---|---|
createPixVerseVideoGeneration(params) | POST v1/video-generation/pixverse/generate | { taskId, episodeId?, status } |
estimatePixVerseVideoCredits(params) | POST v1/video-generation/pixverse/estimate-credits | { tokens, credits } |
PixVerse 任务用上面同样的 getVideoGenerationTask / listVideoGenerationTasks 轮询和列举。
createPixVerseVideoGeneration 参数(OpenAPICreatePixVerseVideoParams):
| 参数 | 类型 | 说明 |
|---|---|---|
capability | 'text_to_video' | 'image_to_video' | 'transition' | 'multi_transition' | 'fusion' | 'restyle' | 'mimic' | 'lip_sync' | 'agent' | 必填;选择生成模式 |
model | 'pixverse' | 'v6' | 'v5' | 'v4.5' | PixVerse 模型版本 |
language | 'zh' | 'en' | 服务区域;en 国际,zh 中国大陆 |
prompt | string | 文本提示 |
duration | number | 秒(1–60;agent:20/30/60) |
aspectRatio | '9:16' | '16:9' | '1:1' | '4:3' | '3:4' | 输出宽高比 |
quality | '360p' | '540p' | '720p' | '1080p' | mimic 锁定 720p;agent 需 720p/1080p |
sourceTaskId | string | 复用此前成功的任务(restyle / lip_sync) |
images / videos / audios | Array<{ url; duration? }> | 输入素材 |
pixverse | OpenAPIPixVerseOptions | capability 相关的嵌套选项 |
嵌套的 pixverse 对象涵盖 agentType、motionMode、cameraMovement、templateId、multiTransition、imageReferences、tts、soundEffect*、lipSyncTts*、brandSticker、introOutroClip,是否生效取决于 capability。estimatePixVerseVideoCredits 接收 { capability, model?, language?, duration?, quality?, pixverse? },其中 pixverse 为用于估算的精简结构。
Music(音乐)
音乐端点默认使用 Mureka provider。异步端点返回任务({ taskId, taskType, status }),轮询 getMusicTask。同步端点(recognizeMusic、describeMusic、stemMusic)直接返回结果。
| 方法 | 端点 | 返回 | 同步? |
|---|---|---|---|
createMusicGenerate(params) | POST v1/music/generate | CreateMusicTaskResponse | 异步 |
createMusicCover(params) | POST v1/music/cover | CreateMusicTaskResponse | 异步(已弃用) |
createMusicExtend(params) | POST v1/music/extend | CreateMusicTaskResponse | 异步 |
createMusicRemix(params) | POST v1/music/remix | CreateMusicTaskResponse | 异步 |
createMusicInstrumental(params) | POST v1/music/instrumental | CreateMusicTaskResponse | 异步 |
createMusicSoundtrack(params) | POST v1/music/soundtrack | CreateMusicTaskResponse | 异步 |
createMusicTrack(params) | POST v1/music/track | CreateMusicTaskResponse | 异步 |
recognizeMusic(params) | POST v1/music/recognize | RecognizeMusicResponse | 同步 |
describeMusic(params) | POST v1/music/describe | DescribeMusicResponse | 同步 |
stemMusic(params) | POST v1/music/stem | StemMusicResponse | 同步 |
getMusicTask(taskId) | GET v1/music/tasks/{taskId} | MusicTaskDetail | — |
listMusicTasks(params?) | GET v1/music/tasks | { items, page, pageSize, total } | — |
主要创建参数:
createMusicGenerate:{ prompt?, lyrics?, model?, style?, title?, instrumental?, vocalId? }。model取auto、mureka-7.6、mureka-8、mureka-9、mureka-o2之一。createMusicExtend:{ uploadUrl, model, continueAt, prompt?, style?, title?, instrumental?, negativeTags?, vocalGender?, styleWeight?, weirdnessConstraint?, audioWeight? }。这里的model是 Suno 版本(V4、V4_5、V4_5PLUS、V4_5ALL、V5、V5_5)。createMusicRemix:{ audio?, audioFilename?, audioUrl?, providerSongId?, lyrics, prompt }。audio/audioUrl/providerSongId三者恰传其一。优先于已弃用的createMusicCover。createMusicInstrumental:{ prompt?, referenceAudio?, referenceAudioFilename?, model? }。prompt与referenceAudio二选一。createMusicSoundtrack:{ image?, video?, prompt?, model? }。image与video二选一。createMusicTrack:{ audio?, providerSongId?, generateType, prompt, lyrics?, vocalGender?, generateStart?, generateEnd? }。generateType选择音轨类型(Vocals、Instrumental、Drums…);generateType为Vocals时必须提供lyrics。
multipart 端点(remix、instrumental、soundtrack、track、recognize、describe、stem)的音频/图片/视频字段接收 Blob/File。在 Node 20+ 中,用 new Blob([buffer]) 包裹 buffer。
const { taskId } = await client.createMusicGenerate({
prompt: 'lo-fi hip hop, mellow, rainy night',
model: 'auto',
});
let task = await client.getMusicTask(taskId);
while (task.status === 'pending' || task.status === 'generating') {
await sleep(10_000);
task = await client.getMusicTask(taskId);
}
console.log(task.tracks[0]?.audioUrl);同步结果:recognizeMusic 返回带时间戳的 lyricsSections;describeMusic 返回 { description, tags, genres, instruments };stemMusic 返回 { zipUrl, midiZipUrl, expiresAt }(链接约 24 小时后过期)。
Content Extract(内容抽取)
从 URL 抽取可读内容(正文,可选摘要)。异步:先创建,再轮询。
| 方法 | 端点 | 返回 |
|---|---|---|
createContentExtract(params) | POST v1/content/extract | { taskId } |
getContentExtract(taskId) | GET v1/content/extract/{taskId} | OpenAPIContentExtractDetail |
createContentExtract 参数(OpenAPICreateContentExtractParams):
| 参数 | 类型 | 说明 |
|---|---|---|
source | { type: 'url'; uri: string } | 必填;要抽取的页面 |
options | { summarize?; maxLength?; twitter? } | summarize 追加摘要;twitter: { count? } 控制 thread 深度 |
轮询 getContentExtract,直到 status 为 completed。detail 携带 data.content、data.metadata、data.references 和 credits。
Subscription(订阅)
| 方法 | 端点 | 返回 |
|---|---|---|
getSubscription() | GET v1/user/subscription | OpenAPISubscriptionInfo |
返回积分余额与套餐信息:totalAvailableCredits、按月/永久/限时积分的明细、resetAt、renewStatus、paidStatus 和 subscriptionPlan。在执行昂贵任务前,用 totalAvailableCredits 检查余额。
Files(文件)
OpenAPIClient 没有专门的文件上传方法。要把本地文件作为输入,请先将其托管到一个公开 URL 并传入该 URL(例如作为 source 的 uri、referenceImages.fileData.fileUri,或视频的 image_url.url)。预签名上传流程在 ListenHubClient 上——见下文 Files。
ListenHubClient 方法
ListenHubClient 使用 OAuth 用户访问令牌认证,面向 https://api.listenhub.ai/api,暴露第一方应用接口。其产品结构与 OpenAPIClient 不同:episode 使用嵌套的 template 对象,创建方法按产品拆分(podcast、TTS、explainer、slides)。仅当每个请求都在某个已登录用户身份下运行时,才使用这个客户端。
Auth & session(认证与会话)
| 方法 | 端点 | 返回 |
|---|---|---|
connectInit(params) | POST v1/auth/connect/init | { sessionId, authUrl } |
connectToken(params) | POST v1/auth/connect/token | { accessToken, refreshToken, expiresIn } |
refresh(params) | POST v1/auth/token | { accessToken, refreshToken, expiresIn } |
revoke(params) | POST v1/auth/token/revoke | void |
connectInit({ callbackPort }) 启动 device/OAuth 流程并返回待打开的 authUrl;connectToken({ sessionId, code }) 用结果换取令牌。refresh({ refreshToken }) 轮换即将过期的访问令牌;revoke({ refreshToken }) 使其失效。
Speakers(声音)
| 方法 | 端点 | 返回 |
|---|---|---|
listSpeakers(params?) | GET v1/settings/speakers | { items: Speaker[] } |
参数:{ language?, status? }。注意返回结构与 OpenAPIClient 不同——每个 Speaker 暴露的是 speakerInnerId(而非 speakerId),并附 personality、accessType、weight。episode 的 template.speakers 数组期望的正是 speakerInnerId。
Podcast(播客)
| 方法 | 端点 | 返回 |
|---|---|---|
createPodcast(params) | POST v1/episodes/all-in-one | { episodeId } |
listPodcasts(params?) | GET v1/episodes(productId=aiPodcast) | ListEpisodesResponse |
createPodcast 参数(CreatePodcastParams):
| 参数 | 类型 | 说明 |
|---|---|---|
type | 'podcast-solo' | 'podcast-duo' | 单人或双人 |
query | string | 主题 |
sources | ContentSource[] | { type: 'url' | 'text'; uri?; content? } |
template | { type: 'podcast'; mode; speakers; language } | mode:quick | deep | debate;speakers:speakerInnerId[];language:en | zh | ja |
Flow Speech / TTS
| 方法 | 端点 | 返回 |
|---|---|---|
createTTS(params) | POST v1/episodes/flow-speech | { episodeId } |
listTTS(params?) | GET v1/episodes(productId=textToSpeech) | ListEpisodesResponse |
createTTS 参数(CreateTTSParams):{ sources, template: { type: 'flowspeech', mode: 'smart' | 'direct', speakers, language } }。
Storybook(解说视频 / 幻灯片)
| 方法 | 端点 | 返回 |
|---|---|---|
createExplainerVideo(params) | POST v1/episodes/storybook | { episodeId } |
createSlides(params) | POST v1/episodes/storybook(mode: 'slides'、skipAudio: true) | { episodeId } |
exportExplainerVideo(episodeId) | POST v1/episodes/{episodeId}/storybook/video | void |
listExplainerVideos(params?) | GET v1/episodes(productId=explainerVideo) | ListEpisodesResponse |
listSlides(params?) | GET v1/episodes(productId=slideDeck) | ListEpisodesResponse |
createExplainerVideo 与 createSlides 共用结构:{ query?, sources?, style?, styleOverride?, skipAudio?, imageConfig?, template }。template 携带 type: 'storybook'、mode(解说用 info / story,幻灯片用 slides)、speakers、language,以及可选的 style、size(2K / 4K)、aspectRatio(16:9 / 9:16 / 1:1)、pageCount。createSlides 默认 skipAudio 为 true 并固定 mode 为 slides。exportExplainerVideo 触发可下载视频的渲染。
Episodes(通用)
以下方法在 ListenHubClient 的四个产品间通用。
| 方法 | 端点 | 返回 |
|---|---|---|
getCreation(episodeId) | GET v5/episodes/{episodeId}/detail | EpisodeDetail |
deleteCreations(params) | DELETE v1/episodes | void |
getCreation 返回完整的 EpisodeDetail(状态、speakers、含 标题/大纲/音频/视频/页面/脚本 的 topicDetail)。deleteCreations({ ids }) 按 id 批量软删除至多 100 个 episode;传入视频 episode id 还会软删除其视频任务,并为进行中的任务退还积分。各产品的 list* 方法都命中 GET v1/episodes 并带 productId 过滤,接收 { page?, pageSize? }。
Image(图片)
| 方法 | 端点 | 返回 |
|---|---|---|
createAIImage(params) | POST v1/images | { imageId } |
getAIImage(imageId) | GET v1/images/{imageId} | AIImageItem |
listAIImages(params?) | GET v1/images | { items, pagination } |
deleteAIImages(params) | DELETE v1/images | void |
createAIImage 参数(CreateAIImageParams):
| 参数 | 类型 | 说明 |
|---|---|---|
prompt | string | 必填 |
referenceImageUrls | string[] | 参考图 URL |
language | 'auto' | 'en' | 'ja' | 'ko' | 'hi' | 'zh' | 'pt' | 'es' | 提示语言 |
aspectRatio | '1:1' | '2:3' | '3:2' | '3:4' | '4:3' | '9:16' | '16:9' | '21:9' | … | 输出宽高比 |
imageSize | '1K' | '2K' | '4K' | 输出分辨率 |
model | 'gemini-3-pro-image' | 'gemini-3.1-flash-image' | 图片模型 |
isLossless | boolean | 无损编码 |
enableSearch | boolean | 允许联网搜索做内容支撑 |
生成是异步的——轮询 getAIImage(imageId),直到 status 为终态且 imageUrl 已设置。deleteAIImages({ ids }) 批量软删除至多 100 张图片(限本人,未知 id 忽略)。
Music(音乐)
ListenHubClient 暴露的音乐方法集与 OpenAPIClient 相同(端点相同、参数相同):createMusicGenerate、createMusicCover、createMusicExtend、createMusicRemix、createMusicInstrumental、createMusicSoundtrack、createMusicTrack、recognizeMusic、describeMusic、stemMusic、getMusicTask、listMusicTasks。参数和轮询循环见上文 Music。
Lyrics(歌词)
| 方法 | 端点 | 返回 |
|---|---|---|
createLyrics(params) | POST v1/lyrics/generate | { taskId, status } |
getLyricsTask(taskId) | GET v1/lyrics/tasks/{taskId} | LyricsTaskDetail |
listLyricsTasks(params?) | GET v1/lyrics/tasks | { items, page, pageSize, total } |
createLyrics({ prompt }) 启动异步歌词任务;轮询 getLyricsTask 直到 status 为 success,再读取 variants(每项 { text, title, status })。
Video Generation(视频生成)
ListenHubClient 暴露与 OpenAPIClient 相同的视频方法,仅有一处命名差异:SeeDance/HappyHorse 的估算方法是 estimateVideoGenerationCredits(OpenAPIClient 上为 estimateVideoCredits)。
| 方法 | 端点 | 返回 |
|---|---|---|
createVideoGeneration(params) | POST v1/video-generation/generate | { taskId, status } |
getVideoGenerationTask(taskId) | GET v1/video-generation/tasks/{taskId} | VideoGenerationTaskDetail |
listVideoGenerationTasks(params?) | GET v1/video-generation/tasks | { items, page, pageSize, total } |
estimateVideoGenerationCredits(params) | POST v1/video-generation/estimate-credits | { tokens, credits } |
createPixVerseVideoGeneration(params) | POST v1/video-generation/pixverse/generate | { taskId, episodeId?, status } |
estimatePixVerseVideoCredits(params) | POST v1/video-generation/pixverse/estimate-credits | { tokens, credits } |
参数与上文 Video 一致。
Subscription & user(订阅与用户)
| 方法 | 端点 | 返回 |
|---|---|---|
getCurrentUser() | GET v1/users/me | UserProfile |
getSubscription() | GET v1/users/subscription | SubscriptionInfo |
getSettings() | GET v2/settings | SettingsResponse |
注意端点与 OpenAPIClient 不同(v1/users/subscription 对 v1/user/subscription)。getSettings 返回用户保存的各产品默认配置(speakers、language、duration、mode、风格图片)。
Checkin(签到)
| 方法 | 端点 | 返回 |
|---|---|---|
checkinSubmit() | POST v1/checkin | { checkinDate, rewardCredits } |
checkinStatus() | GET v1/checkin/status | CheckinStatusResponse |
每日签到领取奖励积分。checkinStatus 报告 hasCheckedInToday、lastCheckinTime 和 monthlyCheckinCount。
Settings / API key
| 方法 | 端点 | 返回 |
|---|---|---|
getApiKey() | GET v1/settings/api-key | { key } |
regenerateApiKey() | POST v1/settings/api-key/regenerate | { key } |
让已登录用户读取或轮换自己的 OpenAPI key。regenerateApiKey 会使旧 key 失效。
Files(文件)
| 方法 | 端点 | 返回 |
|---|---|---|
createFileUpload(params) | POST v1/files | { presignedUrl, fileUrl } |
getFileDownloadUrl(fileUrl) | GET v1/files | { downloadUrl } |
createFileUpload({ fileKey, contentType, category }) 返回用于 PUT 上传字节的 presignedUrl,以及之后用于引用的 fileUrl。getFileDownloadUrl(fileUrl) 把已存储的文件 URL 重新签名为带时效的 downloadUrl。
client.api 逃生舱
ListenHubClient 把其底层的 ky 实例暴露为 client.api,用于 SDK 尚未封装的端点。它应用相同的认证、Base URL 和重试行为,但需要你自己解析响应。路径相对于 Base URL——不带前导 /(ky 的要求):
const me = await client.api.get('v1/users/me').json();OpenAPIClient 不暴露 client.api。若某个 OpenAPI 端点 SDK 尚未覆盖,请用你自己的 HTTP 客户端、以相同的 Authorization: Bearer 头去调用——见 OpenAPI 参考。
错误
每个方法在 code 非零或 HTTP 出错时都会抛出 ListenHubError,携带 status、code 和 requestId——上报问题时请附上 requestId。
import { ListenHubError } from '@marswave/listenhub-sdk';
try {
await client.getPodcast('nope');
} catch (err) {
if (err instanceof ListenHubError) {
console.error(`[${err.status}] code ${err.code} (request ${err.requestId})`);
} else {
throw err;
}
}