本页目录(10 节)

多媒体 Provider

Spark Work 多媒体 Provider 配置:图片生成 / 编辑、语音合成 / 转写、视频生成 / 图生视频 / 视频编辑的统一能力注册表、平台适配器(APIMart / xAI / 火山 / 百炼 / 可灵 / Hailuo 等)。

阅读约 14 分钟最后核对 2026-06-29

Spark Work 的多媒体能力用「能力注册表 + 平台适配器 + Media Model Manifest」三层实现: Provider Profile 声明它支持哪些能力,适配器负责平台协议,manifest 负责单个模型的参数与 产物提取。图片、语音、视频共用同一套代码路径,画布、spark_media MCP 与 Provider 表单读的是同一份元数据。

1. 能力枚举与适配器

统一能力 id 共 11 个(不是 9 个),定义在 packages/protocol/src/media-config.ts 的 MEDIA_CAPABILITY_IDS。 括号里是 Provider 表单上的中文标签(providerMediaConfig.ts 的 MEDIA_CAPABILITY_LABELS)。

能力 id界面标签说明
image.generate生图文生图
image.edit图生图 / 图片编辑含多图合成
image.variations图片变体目前只有 Midjourney manifest 声明
audio.speech语音合成TTS
audio.music音乐生成Lyria / MiniMax 音乐 / 火山豆包音频生成
audio.transcription语音转写ASR,如 APIMart Whisper
video.generate文生视频—
video.image_to_video图生视频首帧驱动
video.reference_to_video参考图生视频参考图(非首帧)驱动
video.edit视频编辑按 prompt 改已有视频
video.extend视频扩展从末帧续拍

1.1 平台适配器枚举

mediaProvider 的合法值共 18 个(MEDIA_PROVIDER_KINDS)。 Provider 表单里的「平台适配器」下拉不是全量枚举,而是按模型类型裁剪: 生图 / 视频模型给 9 项,其余给 15 项。

mediaProvider表单标签协议实现
apimartAPIMart专用适配器 ApimartMediaAdapter
agnesAgnes AI专用适配器 AgnesMediaAdapter
xaixAI专用适配器 XaiMediaAdapter
openai-imagesOpenAI 多媒体专用适配器 OpenAiOfficialMediaAdapter
openai-compatibleOpenAI Compatible走 manifest 驱动的模板适配器
google-generative-aiGoogle Gemini / Veo / Lyria专用适配器(含 :predict / :predictLongRunning / /interactions)
omniOmni复用 Google 适配器,走 Omni 专用端点
bailian阿里百炼专用适配器 BailianMediaAdapter
volcengine-ark火山方舟 / Seedance专用适配器(content[] 嵌套请求体)
volcengine-speech火山豆包语音专用适配器(X-Api-Key 鉴权,区别于方舟的 Bearer)
klingKling6 个内置 manifest,走模板适配器
minimax-hailuoMiniMax Hailuo专用适配器(v1 恒 200 + base_resp、V2 OAI 协议)
midjourneyMidjourney 网关专用适配器 MidjourneyMediaAdapter
tencent-tokenhub腾讯云 TokenHub专用适配器(查询是 POST + body)
custom自定义模板适配器 + 自定义 manifest
pixverse / wan / happyhorsePixVerse / Wan / HappyHorse枚举里有值、有中文标签,但不在表单下拉里,也没有独立 manifest 种子;对应模型挂在 APIMart 下(如 pixverse-v6、happyhorse-1.0/1.1、wan2.7-image)

适配器注册是显式的:MediaRouterService 构造函数里 register() 了 12 个实例(含 Google 适配器注册两次,分别对应 google-generative-ai 与 omni)。路由时先看有没有专用适配器且它声明支持该能力,否则改用 manifest 驱动的模板适配器;两者都没有时抛 provider_not_configured: No adapter for provider kind ...。

openai-compatible 没有注册为独立适配器(openai-compatible-media.adapter.ts 是其他适配器的基类),所以这一类渠道必须绑定 manifest 才能调用。

2. Media Model Manifest

Manifest 是「模型元数据单一来源」:类型与 zod schema 在 packages/protocol/src/media-model-manifest.ts,内置种子共 167 条,覆盖 13 个 providerKind。

providerKind内置 manifest 数种子来源
apimart59media-model-manifest.ts 内的 APIMart 模型表
bailian22bailian-media-model-manifests.ts
tencent-tokenhub21tencent-tokenhub-media-model-manifests.ts
google-generative-ai13google-media-model-manifests.ts
openai-images12openai-media-model-manifests.ts
volcengine-ark12volcengine-ark-media-model-manifests.ts
minimax-hailuo9media-model-manifest.ts + 共享片段
xai6xai-media-model-manifests.ts(视频 1.5)+ 主文件
kling6media-model-manifest.ts
agnes3media-model-manifest.ts
volcengine-speech2volcengine-speech-media-model-manifests.ts
omni / midjourney各 1omni-media-model-manifests.ts / media-model-manifest.ts

一条 manifest 的关键字段:

  • id / providerKind / modelId / displayName / domains(image / audio / video / text …)。
  • capabilities[]:每条含 id、label、input.required、input.maxImages、output.types、paramSchema、defaults、aliases。
  • invocation:mode(sync / async_polling / async_callback / stream / file_job)、endpoint、method、contentType(json / multipart / binary)、requestTemplate、response、polling。
  • docs.sourceUrls + lastCheckedAt:记录参数是照着哪份官方文档核对的。
  • safety:maxPromptLength、allowLocalFiles、maxInputBytes。

Contract V2 增补了 contractVersion: 2、adapterMode(native / template)与 baseTemplate;后者在 Provider 表单的「配置自定义适配器」里有 4 个基底可选:完全自定义、OpenAI 接口协议基底、通用异步 JSON 任务(GET 轮询)、ToApis 图片全能力异步轮询。

持久化用两张表:media_model_manifests(manifest 本体)与 media_provider_models(某个 Provider 启用了哪些 manifest、本地默认参数覆盖), 见 packages/storage/migrations/033_media_model_manifests.sql。启动时由 MediaModelCatalogService.seedBuiltinManifests() 把内置种子写回 SQLite。

3. 配置步骤(真实界面)

  1. 打开 设置 → Provider,点「新建」(或「新增配置」)打开编辑面板。
  2. 模型类型选 4 项之一:对话模型 / 生图模型 / 语音模型 / 视频模型。对话模型属于附加能力场景,需要额外打开 附加生成能力开关才会出现多媒体面板。
  3. 选模板预设(如 APIMart、xAI、火山方舟),会预填 Base URL、默认模型、能力与轮询参数。
  4. 在多媒体面板里确认三件事:
    • 平台适配器:图片 / 视频模型从 9 个里选,其余从 15 个里选。
    • 支持能力:勾选本 Provider 真实支持的能力,别多勾——路由和调用方式都按它判断。
    • 调用方式:sync / async / auto。
  5. 模型清单里从内置目录勾选要启用的 manifest;自定义渠道可以手输模型 ID 并按 Enter 添加。
  6. 参数默认值填 size / 比例 / 质量 / 时长等;异步渠道再填 轮询间隔 ms 与 接口超时 ms。
  7. 填 API Key 保存。表单下方会给出「实际请求地址」预览,确认适配器拼出的 URL 与渠道文档一致。

注意:「测试连接」不是媒体链路验证。它发的是文本协议 ping (OpenAI 兼容走 /chat/completions,Anthropic 走 messages),纯图片 / 视频渠道 常常没有 chat 端点,因此测试失败不代表媒体不可用;反过来测试通过也不代表生图能跑通。请以 「实际请求地址」+ 一次真实生成为准。

4. 内置预设清单

当前共 64 个 Provider 预设,其中 35 个带多媒体配置。下表为真实 id 与默认模型 (预设定义在 packages/protocol/src/provider-presets.ts)。

预设 id名称类型mediaProvider / 调用方式默认模型
openai-imagesOpenAIimageopenai-images / autogpt-image-2
openai-sora-videoOpenAIvideoopenai-images / asyncsora-2
agnes-aiAgnes AImultimodalagnes / autoagnes-2.0-flash
apimart-imagesAPIMartimageapimart / autogpt-image-2
apimart-audio-whisperAPIMart Whispervoiceapimart / syncwhisper-1
apimart-audio-ttsAPIMart TTSvoiceapimart / synctts-1
apimart-video-veo3APIMart VEO 3videoapimart / asyncveo3.1-quality
apimart-video-sora2APIMart Sora 2videoapimart / asyncsora-2
apimart-video-collectionAPIMart 综合videoapimart / asynckling-v3
xai-imagine-imagexAIimagexai / syncgrok-imagine-image-quality
xai-imagine-videoxAIvideoxai / asyncgrok-imagine-video
xai-ttsxAIvoicexai / syncgrok-tts
bailian-images阿里云百炼imagebailian / asyncwan2.7-image-pro
bailian-video-happyhorse阿里云百炼 HappyHorsevideobailian / asynchappyhorse-1.1-t2v
bailian-video-wan-i2v阿里云百炼 Wanvideobailian / asyncwan2.7-t2v-2026-06-12
bailian-audio-tts阿里云百炼voicebailian / syncqwen3-tts-flash
volcengine-seedance-video火山方舟videovolcengine-ark / asyncdoubao-seedance-2-5-260628
volcengine-seedream-image火山方舟imagevolcengine-ark / syncdoubao-seedream-5-0-pro-260628
volcengine-speech-tts火山豆包语音合成voicevolcengine-speech / syncseed-tts-2.0
volcengine-speech-audio火山豆包音频生成voicevolcengine-speech / syncseed-audio-1.0
google-gemini-imagesGoogle Geminiimagegoogle-generative-ai / syncgemini-3.1-flash-image
google-veo-videoGoogle Gemini Veovideogoogle-generative-ai / asyncveo-3.1-generate-preview
google-omni-videoGoogle Gemini Omni Flashvideoomni / asyncgemini-omni-flash-preview
google-gemini-omni-videoGemini Omni Flash 官方videogoogle-generative-ai / asyncgemini-omni-flash-preview
google-lyria-musicGoogle Gemini Lyriavoicegoogle-generative-ai / synclyria-3-clip-preview
midjourney-gatewayMidjourney 网关imagemidjourney / asyncmidjourney
kling-videoKling 可灵视频videokling / asynckling-video-3.0
minimax-imageMiniMax 图片imageminimax-hailuo / syncimage-01
minimax-hailuo-speechMiniMax 语音voiceminimax-hailuo / syncspeech-2.8-hd
minimax-hailuo-musicMiniMax 音乐voiceminimax-hailuo / syncmusic-2.6
minimax-hailuo-videoMiniMax Hailuo 视频videominimax-hailuo / asyncMiniMax-Hailuo-2.3
minimax-h3-videoMiniMax H3 视频videominimax-hailuo / asyncMiniMax-H3
minimax-video-agentMiniMax 视频 Agentvideominimax-hailuo / asyncvideo-agent
tencent-tokenhub-image腾讯云imagetencent-tokenhub / autohy-image-v3.0
tencent-tokenhub-video腾讯云videotencent-tokenhub / asynchy-video-1.5

预设里的默认 Base URL(可直接对照渠道文档核对):

APIMart            https://api.apimart.ai/v1
xAI               https://api.x.ai/v1
OpenAI            https://api.openai.com/v1
Agnes AI          https://apihub.agnes-ai.com/v1
阿里百炼           https://dashscope.aliyuncs.com/api/v1/services/aigc
火山方舟           https://ark.cn-beijing.volces.com/api/v3
火山豆包语音        https://openspeech.bytedance.com(X-Api-Key,非方舟 Bearer)
Google Gemini     https://generativelanguage.googleapis.com/v1beta
Kling             https://api.klingai.com
MiniMax           https://api.minimaxi.com
腾讯云 TokenHub    https://tokenhub.tencentmaas.com
Midjourney 网关    https://your-midjourney-gateway.example/v1(占位,必须改成自建网关)

5. 默认值、超时与重试

项默认值可配置范围
视频异步任务总时限48 小时(DEFAULT_VIDEO_POLL_TIMEOUT_MS)mediaDefaults.timeoutMs / polling.timeoutMs:1000 ~ 172800000
轮询间隔5000 mspolling.intervalMs:250 ~ 300000
单次轮询 HTTP 超时30 s不单独配置,且不会超过任务剩余总时限
轮询间隔退避每次 ×1.3,上限 15 s代码内固定
轮询请求的瞬时错误重试最多 3 次,退避 1 s 起、每次 ×2、上限 8 smanifest 的 polling.retry(maxAttempts 0~20、backoffMs 0~300000)

重试只发生在异步轮询阶段:只有「网络层错误 / HTTP 5xx / 429」会重试,并会识别 响应里的 Retry-After(秒数或时间戳,上限 8 s);4xx 参数错误、 task_failed、task_timeout 不重试。一次性提交请求(create/submit) 本身不自动重试,失败会直接把错误交给调用方。

历史配置的超时会被迁移脚本抬高到当前口径:055_video_poll_timeout_30m.sql、056_image_poll_timeout_10m.sql、067_video_poll_timeout_48h.sql。 迁移只替换「仍等于旧默认值」的记录,你手填过的值不会被覆盖。

6. 产物、任务与错误码

  • 产物根目录是当前 workspace 下的 .spark-artifacts/media,按类型分成 images / audio / videos / text (语音转写落 text)。落盘前会把 .spark-artifacts 写进仓库本地忽略,避免被连带提交。
  • 每次调用都会被持久化成 media_generation_tasks(表在 029_media_generation_tasks.sql,恢复所需字段由 066_media_task_recovery.sql 补充)。运行时有 submit / inquire / cancel / materialize 四段接口。
  • media-task-recovery.service.ts 只按持久化的查询契约去问渠道「这个任务怎么样了」,不会重新提交 create/submit,所以重启应用不会重复计费。
  • 画布的模型调用详情面板会显示 Provider / Manifest / 模型 / 状态 / 反向提示词 / Request ID 以及本次实际参数。

代码里会出现的错误码(MediaProviderError.code):

  • provider_not_configured:渠道没配好,或该 mediaProvider 既没有专用 适配器也没有匹配到 manifest。
  • capability_not_supported:勾选的能力与实际调用不匹配。
  • api_key_missing / auth_required:凭据缺失或渠道返回鉴权失败。
  • invalid_input:参数被 manifest 校验拦下(常见于时长、分辨率越界)。
  • provider_http_error:渠道返回非 2xx,附带 statusCode。
  • task_failed / task_timeout:异步任务失败或超过总时限。
  • artifact_download_failed:任务成功但产物 URL 下载失败(签名过期、需要鉴权头)。

渠道错误响应还会被归一成 unsupported_parameter / invalid_parameter_value / missing_required_input / auth_failed / quota_exceeded / rate_limited / content_policy_blocked / bad_provider_response 这类语义码,便于判断 该改参数还是该充值。

7. spark_media MCP

会话只要存在可用的媒体 Provider,就会注入内部 stdio MCP server spark_media,共 14 个工具:

mcp__spark_media__list_models       列出已配置的模型与能力(可用 capability 过滤)
mcp__spark_media__describe_model     查看单个模型的参数 schema 与调用元数据
mcp__spark_media__generate_image     文生图 / 图生图
mcp__spark_media__edit_image         图片编辑 / 多图合成
mcp__spark_media__generate_audio     语音合成或音乐生成(取决于所选模型)
mcp__spark_media__transcribe_audio   语音转写
mcp__spark_media__generate_video     文生视频 / 图生视频 / 参考图生视频 / 视频编辑 / 扩展
mcp__spark_media__upload_file        上传文件到渠道文件平台
mcp__spark_media__get_file           查询渠道文件元数据
mcp__spark_media__list_files         列出渠道文件
mcp__spark_media__delete_file        删除渠道文件(需用户确认)
mcp__spark_media__list_tasks         列出渠道异步任务(百炼支持官方 24 小时查询窗口)
mcp__spark_media__get_task           查询任务(支持生成工具返回的 taskId 或百炼 task id)
mcp__spark_media__cancel_task        取消排队中/运行中的任务(百炼仅 PENDING 可远程取消)

文件四件套只在路由到 volcengine-ark 或 bailian 时暴露;其余渠道 工具列表里看不到它们。

  • 参数:model 支持「selectionKey(推荐)/ manifest id / 渠道模型 id」三种写法,selectionKey 形如 <providerProfileId>/<manifestId>。常用参数(size / aspectRatio / resolution / durationSeconds / mode / seed / output_format / prompt_optimizer 等)直接暴露,渠道私有字段走 extraJson,且会被按 manifest 裁剪,多余字段不会发给渠道。
  • 凭据隔离:运行时把 Provider 列表写进一个 0600 权限的临时配置文件(SPARK_MEDIA_CONFIG_FILE),API Key 不进文件,而是通过 SPARK_MEDIA_API_KEY_0、SPARK_MEDIA_API_KEY_1… 逐个注入子进程环境变量。 Agent 拿不到 Key,也没有工具能读出来。
  • 多档切换:每个模型保留自己 Provider 的 Key / endpoint / 适配器;生成工具靠 model 参数切换实际路由,同名模型必须用唯一 selectionKey 指定。
  • 单 Provider 环境变量(SPARK_MEDIA_PROVIDER / SPARK_MEDIA_MODEL / SPARK_MEDIA_API_TYPE / SPARK_MEDIA_BASE_URL / SPARK_MEDIA_OUTPUT_DIR)与 SPARK_MEDIA_MANIFESTS_JSON / SPARK_MEDIA_PROVIDERS_JSON 仍作为兼容回退保留。
  • 图片的旧链路 spark_image 只在「没有可解析的统一媒体配置」时才注入,避免两套工具 争抢模型选择;详见 图片生成 Provider。

8. 接入自定义渠道

两条路,先试第一条:

  1. UI 手工配置:Provider 表单里把「平台适配器」选成自定义, 会多出「自定义渠道适配器 → 配置自定义适配器」入口,用 ProviderManifestContractEditor 从 4 个基底模板改起(提交 / 鉴权 / Body / 上传 / 轮询 / 参数 / 错误契约)。适合渠道是「JSON 提交 + 可选轮询 + URL/base64/binary 产物」。
  2. 让 Agent 配置:Agent 侧有 5 个平台工具—— providers_media_guide(取能力枚举与起始契约)、 providers_media_validate(只读校验,不落库)、 providers_media_configure(校验通过后写入正式 Provider,Key 进 Keychain)、 providers_media_discover_models(打渠道 /models)、 providers_media_diagnose(分阶段诊断 401/404/400/轮询/产物解析)。诊断里的真实 生成调用需要用户显式确认。

只有在渠道需要自定义鉴权、multipart、回调、文件型 job 或特殊取消语义时,才需要写专用适配器: 新增 packages/agent-runtime/src/services/media/adapters/<vendor>-media.adapter.ts, 在 MediaRouterService 构造函数里 register(),并补 mediaProvider 枚举、表单标签与预设。给这个渠道写 manifest 的模型更适合走模板适配器。

9. 常见报错与排查

现象原因与处理
会话里没有 spark_media 工具检查 Provider 是否 enabled、是否填了 Key、modelType 是否为 image/voice/video 或声明了媒体能力、默认模型是否非空;任一不满足就不会注入。
No adapter for provider kind xxx这个 mediaProvider 没有专用适配器也没匹配到 manifest。改成模板能覆盖的渠道,或为该渠道补 manifest。
Video 任务一直 pending 到超时确认 polling.intervalMs 与 timeoutMs;默认 48 小时。渠道返回的 status 若不在 manifest 的 statusMap 里,默认按失败处理——除非把 unknownStatus 设为 running,此时视为继续等待。
任务成功但产物下载失败产物 URL 可能带签名时效或需要鉴权头。artifact_download_failed 表示任务成功、下载失败,重试「查询」而不是重新提交。
参数被静默丢弃manifest 的 paramPolicy 会裁剪当前模型不支持的字段;describe_model 能看到真实 schema。
「测试连接」失败但生成正常测试连接 ping 的是文本端点,纯媒体渠道本来就没有。忽略它,用一次真实生成验证。

速查表

统一能力 id
11 个:image.generate/edit/variations · audio.speech/music/transcription · video.generate/image_to_video/reference_to_video/edit/extend
mediaProvider 枚举
18 个:apimart/agnes/xai/openai-compatible/openai-images/google-generative-ai/bailian/volcengine-ark/volcengine-speech/kling/pixverse/minimax-hailuo/wan/happyhorse/omni/midjourney/tencent-tokenhub/custom
mediaApiType
sync / async / auto
内置 manifest
167 条 / 13 个 providerKind(表:media_model_manifests + media_provider_models,migration 033)
多媒体预设
35 条(Provider 预设共 64 条)
视频轮询默认
间隔 5s、退避 ×1.3 上限 15s、总时限 48h、瞬时错误最多重试 3 次(1s→8s)
产物目录
<workspace>/.spark-artifacts/media/{images,audio,videos,text}
MCP
spark_media(14 个工具;文件四件套仅 volcengine-ark / bailian)

常见问题

展开 6 条常见问题
  • 统一能力一共几个?我只看到 9 个的旧说法。

    11 个。除 image.generate / image.edit / image.variations / audio.speech / audio.transcription / video.generate / video.image_to_video / video.edit / video.extend 之外,还有 audio.music(音乐生成)和 video.reference_to_video(参考图生视频)。

  • mediaProvider 和 imageProvider 是什么关系?

    mediaProvider 是统一字段。保存 modelType=image 的 Provider 时,Spark 会按 imageProvider 推导并回写 mediaProvider / mediaApiType / mediaCapabilities,其中 openai→openai-compatible、seeddance→volcengine-ark、gemini→google-generative-ai,其余未知值兜底为 custom。

  • pixverse / wan / happyhorse 能选吗?

    不能直接选。它们是 mediaProvider 枚举里的值,但 Provider 表单的适配器下拉不含这三项,也没有对应 manifest 种子;这些模型在 APIMart 渠道下以模型 id 的形式提供(如 pixverse-v6、happyhorse-1.1、wan2.7-image)。

  • API Key 存在哪里?Agent 能看到吗?

    Key 通过 keystore 存储(macOS 上是单一 Keychain 条目 spark-agent / credential-vault-v1,Provider 只持有 keystore_ref)。调用时只注入到本地 MCP 子进程的环境变量,配置文件里不含 Key,Agent 与模型都看不到明文。

  • 应用重启后异步任务会重新提交吗?

    不会。任务持久化在 media_generation_tasks,恢复逻辑只按已保存的查询契约去渠道查询状态,从不调用 create/submit 端点。

  • 内置预设一共有多少条?

    64 条 Provider 预设,其中 35 条带多媒体配置(mediaProvider 非空)。