前面第 12 篇和第 13 篇,我们分别分析了 Pixelle-Video 的两条媒体生成路线:
text
selfhost:
本地 ComfyUI 工作流
runninghub:
RunningHub 云端工作流
这两种方式都有一个共同点:它们都是基于 workflow 的。
也就是说,Pixelle-Video 把 prompt、width、height、duration、seed 等参数交给一个工作流,再由工作流去完成图片或视频生成。
但 Pixelle-Video 还有第三条路线:
text
api/...:
直连图像 / 视频模型 API
这一篇我们就分析:
Pixelle-Video 如何绕过 ComfyUI 和 RunningHub,直接调用 OpenAI、Wan、Kling、Seedance 等媒体模型?
一、为什么需要直连 API 媒体模型?
先说结论:直连 API 是为了降低工作流依赖。
ComfyUI 很强,但它有门槛:
text
需要安装 ComfyUI
需要下载模型
需要配置节点
需要维护工作流
本地还可能需要显卡
RunningHub 解决了没有本地显卡的问题,但它仍然依赖云端 workflow。
而直连 API 的思路更简单:
text
Pixelle-Video
↓
直接调用图像 / 视频模型服务商 API
↓
拿到图片或视频文件
Pixelle-Video 的 config.example.yaml 里也明确说明,api_providers 是可选配置,用于"不经过 ComfyUI workflow,直接调用 provider 生成 image / video / VLM 内容"。
所以,直连 API 的定位是:
不想维护 ComfyUI 工作流时,可以直接用云厂商媒体模型完成素材生成。
二、三条媒体生成路线的区别
到第 14 篇为止,Pixelle-Video 的媒体生成路线可以整理成三类:
text
1. selfhost workflow
本地 ComfyUI 执行 workflow
2. runninghub workflow
RunningHub 云端执行 workflow
3. api/provider/model
直接调用媒体模型 API
它们的共同目标都是生成素材:
text
prompt → image / video
但执行方式不同:
text
selfhost:
workflow 文件路径 → ComfyKit → 本地 ComfyUI
runninghub:
workflow_id → ComfyKit → RunningHub 云端
api:
api/provider/model → APIProviderMediaService → ImageClient / VideoClient
Pixelle-Video 在 MediaService 中专门判断:如果选中的 workflow 以 api/ 开头,就不再走 ComfyUI workflow,而是转交给 core.api_media 处理;否则才继续解析本地或 RunningHub workflow。
这就是直连 API 的入口。
三、api_providers 配置:直连 API 的配置入口
直连 API 的配置入口在 config.yaml 的 api_providers 部分。
示例配置中包含:
yaml
api_providers:
common:
print_model_input: false
local_proxy: ""
openai:
api_key: ""
base_url: "https://api.openai.com/v1"
use_proxy: false
dashscope:
api_key: ""
base_url: "https://dashscope.aliyuncs.com/api/v1"
use_proxy: false
ark:
api_key: ""
base_url: "https://ark.cn-beijing.volces.com/api/v3"
use_proxy: false
kling:
base_url: "https://api-beijing.klingai.com"
access_key: ""
secret_key: ""
use_proxy: false
这里有几个重点。
openai 主要对应 OpenAI 的图像能力。
dashscope 对应阿里 DashScope,也就是 Wan 等模型所在的调用路线。
ark 对应火山方舟,Seedance / Seedream 这类模型通常走这个 provider 配置。
kling 比较特殊,它不是普通 api_key,而是 access_key + secret_key。配置和 schema 中也单独定义了 AccessSecretProviderConfig,用于保存 base_url、access_key、secret_key 和 use_proxy。
所以 Pixelle-Video 的直连 API 配置不是统一一个 key,而是按 provider 区分认证方式。
四、APIProviderMediaService:直连 API 的核心适配器
真正负责直连 API 的类是:
text
pixelle_video/services/api_media.py
文件开头的注释就写明了它的职责:Direct API provider media generation adapter,也就是直连 API provider 的媒体生成适配器。APIProviderMediaService 的类注释也说明,它负责把 Pixelle 的媒体调用适配到 direct provider API clients。
可以把它理解成:
text
MediaService
负责统一媒体生成入口
APIProviderMediaService
负责 api/... 路线
ImageClient
负责具体图片 API 调用
VideoClient
负责具体视频 API 调用
也就是说,上层 pipeline 不需要知道 OpenAI、Wan、Kling、Seedance 的接口细节。
它只需要传:
text
prompt
workflow
media_type
width
height
duration
output_path
image_path
剩下的 provider 差异由 APIProviderMediaService 处理。
五、api/provider/model:把 API 模型伪装成 workflow
Pixelle-Video 的直连 API 设计里,最巧妙的一点是:
它把 API 模型也包装成 workflow。
APIProviderMediaService.list_workflows() 会遍历 IMAGE_MODELS 和 VIDEO_MODELS,然后为每个 provider/model 生成一个 workflow 信息。生成的 key 格式是:
text
api/{provider}/{model}
例如:
text
api/openai/gpt-image-2
api/dashscope/wan2.7-image
api/dashscope/wan2.7-t2v
api/kling/kling-v3
api/seedance/doubao-seedance-2-0-260128
源码中 _workflow_info() 会生成包含 name、display_name、source、provider、model、media_type、path、key 等字段的结构,其中 source 固定是 "api"。如果是视频模型,还会附加 capabilities、ability_type、adapter_ability_types、api_contract_verified 等能力信息。
这就让 UI 和 pipeline 可以用同一种方式选择媒体来源:
text
selfhost/image_flux.json
runninghub/image_flux.json
api/openai/gpt-image-2
api/kling/kling-v3
前两个是 workflow 文件。
后两个是直连 API 模型。
但在 Pixelle-Video 的选择器里,它们都可以被当成"可用媒体生成选项"。
六、当前支持哪些直连 API 模型?
从 APIProviderMediaService 的源码看,图片模型和视频模型分别维护在两个字典里。
图片模型包括:
text
dashscope:
wan2.7-image
wan2.7-image-pro
wan2.6-t2i
openai:
gpt-image-2
seedream:
doubao-seedream-5-0-260128
doubao-seedream-4-5-251128
doubao-seedream-4-0-250828
视频模型包括:
text
dashscope:
wan2.7-t2v
happyhorse-1.0-t2v
wan2.7-i2v
wan2.7-r2v
wan2.7-videoedit
wan2.6-i2v-flash
happyhorse-1.0-i2v
happyhorse-1.0-r2v
happyhorse-1.0-video-edit
kling:
kling-v3
kling-v2-6
kling-v2-5-turbo
seedance:
doubao-seedance-2-0-260128
doubao-seedance-2-0-fast-260128
seedance-1-0-pro
seedance-1-0-lite
这些列表定义在 api_media.py 的 IMAGE_MODELS 和 VIDEO_MODELS 中。
这里要注意一个点:
标题里说的 Wan,本质上在 Pixelle-Video 代码中是放在 dashscope provider 下的模型。
标题里说的 Seedance,则是视频模型 provider;它在 client 创建时会复用 ark 相关配置进入 VideoClient。
七、MediaService 如何把 api/... 转交给 APIProviderMediaService?
在 MediaService.__call__() 中,代码会先取出 selected_workflow:
python
selected_workflow = workflow or self.config.get("default_workflow")
然后判断:
python
if selected_workflow and selected_workflow.startswith("api/"):
return await self.core.api_media(...)
转交时会把当前媒体生成所需参数全部传进去:
text
prompt
workflow
media_type
width
height
duration
output_path
image_path
negative_prompt
steps
seed
cfg
sampler
**params
这段逻辑说明,直连 API 模型并不是独立于媒体生成流程之外的"外挂功能",而是直接嵌入了 MediaService 的统一入口。
所以,从上层看,调用仍然是:
python
media = await self.core.media(
prompt=frame.image_prompt,
workflow="api/openai/gpt-image-2",
media_type="image",
width=1080,
height=1920,
)
或者:
python
media = await self.core.media(
prompt=frame.image_prompt,
workflow="api/kling/kling-v3",
media_type="video",
width=1080,
height=1920,
duration=5,
)
区别只是 workflow key 变成了 api/...。
八、APIProviderMediaService 如何解析 provider 和 model?
进入 APIProviderMediaService.__call__() 后,第一步是:
python
info = self.resolve_workflow(workflow)
provider = info["provider"]
model = info["model"]
resolved_media_type = info.get("media_type") or media_type
resolve_workflow() 会从 list_workflows() 生成的 API workflow 列表里查找传入的 key,找到后返回对应 info;找不到就抛出错误,并列出可用 API workflows。
例如传入:
text
api/kling/kling-v3
会解析出:
text
provider = kling
model = kling-v3
media_type = video
传入:
text
api/openai/gpt-image-2
会解析出:
text
provider = openai
model = gpt-image-2
media_type = image
这样后续代码就知道应该走图片生成还是视频生成。
九、图片生成路线:_generate_image()
如果 resolved_media_type == "image",APIProviderMediaService.__call__() 会调用 _generate_image()。
源码中 _generate_image() 会创建 ImageClient,计算保存目录、视频比例和分辨率,然后用 asyncio.to_thread() 调用同步的 client.generate_image()。传入参数包括 prompt、image_paths、model、save_dir、session_id、video_ratio、resolution。生成完成后,如果没有返回路径就抛错;如果有结果,就取第一张图片,并返回 MediaResult(media_type="image", url=result_path)。
它的流程可以简化为:
text
api/openai/gpt-image-2
↓
resolve_workflow()
↓
provider = openai
model = gpt-image-2
media_type = image
↓
_create_image_client()
↓
client.generate_image()
↓
保存图片
↓
MediaResult(media_type="image", url=result_path)
这里的重点是:
图片 API 的返回结果会被统一包装成 MediaResult。
后续 FrameProcessor 不需要知道图片来自 OpenAI、DashScope 还是 Seedream。
它只需要拿到 media_type="image" 和 url。
十、ImageClient 的 provider 配置从哪里来?
_create_image_client() 会从 config_manager.get_api_providers_config() 读取 provider 配置。
源码中它会把这些配置传给 ImageClient:
text
dashscope_api_key
dashscope_base_url
dashscope_local_proxy
gpt_api_key
gpt_base_url
local_proxy
ark_api_key
ark_base_url
ark_local_proxy
也就是说,OpenAI 图像模型走 openai 配置,DashScope 图像模型走 dashscope 配置,Seedream 这类火山系模型则走 ark 配置。
这就是为什么 api_providers 要分 provider 配置。
不同媒体模型虽然在上层都叫 api/...,但底层的认证和 base_url 不一样。
十一、视频生成路线:_generate_video()
如果 resolved_media_type 不是 image,就进入 _generate_video()。
视频生成比图片生成复杂很多,因为视频模型可能支持不同输入模式:
text
text_to_video
image_to_video
reference_to_video
video_editing
action_transfer
digital_human
源码中 _generate_video() 会先读取:
text
first_clip_path
reference_image_path
reference_image_paths
reference_video_paths
然后根据模型能力判断是否支持 text-to-video。如果模型不支持纯文本生成,又没有 image_path、first_clip_path 或 reference media,就会抛出错误,提示 API video models 需要 image_path、first_clip_path 或 reference media inputs。
这说明 Pixelle-Video 对视频 API 的处理不是盲目调用,而是先判断模型能力和输入条件。
十二、视频模型能力:VIDEO_MODEL_CAPABILITIES
Pixelle-Video 为视频模型维护了一套能力表:VIDEO_MODEL_CAPABILITIES。
例如 DashScope 的 wan2.7-t2v 标记了:
text
ability_type = text_to_video
adapter_ability_types = text_to_video, native_audio
input_modalities = text
duration = 2 到 15 秒
resolutions = 720P / 1080P
ratios = 16:9 / 9:16 / 1:1 / 4:3 / 3:4
fps = 30
format = mp4
Kling 的部分模型支持 text-to-video 和 first-frame image-to-video;Seedance 的 doubao-seedance-2-0-260128 支持 text-to-video、first-frame image-to-video 和 native_audio 等适配能力。源码中还保存了每个模型的 duration、resolution、ratio、api_contract_verified 和 contract_issues 等信息。
这套能力表的意义很大。
因为视频模型不像图片模型那么统一。
有的模型可以纯文生视频。
有的模型必须有首帧图。
有的模型只支持 5 秒或 10 秒。
有的模型支持 9:16。
有的模型支持原生音频。
有的模型只是别名,官方契约还需要确认。
如果没有能力表,调用时就很容易出错。
十三、视频时长和分辨率如何适配?
视频 API 常见的一个问题是:用户想要的时长,不一定是模型支持的时长。
Pixelle-Video 在 _video_duration() 中做了归一化处理。
如果能力表里有 verified 的 duration contract,就按 allowed_values 或 min/max 范围修正;如果没有精确能力表,则根据 provider 做兜底处理。例如 DashScope 会在 5 秒和 10 秒之间选择,Kling v3 会限制在 3 到 15 秒,其他 Kling 模型会在 5 秒和 10 秒之间选择,Seedance 会限制在 5 到 10 秒之间。
分辨率也有类似处理:
text
width / height
↓
_ratio()
↓
_resolution()
↓
_video_resolution()
例如宽高相等会得到 1:1,高度大于宽度会得到 9:16,否则得到 16:9;Seedance 的分辨率会使用小写的 720p / 1080p,其他 provider 则使用 720P / 1080P。
这说明 Pixelle-Video 没有简单把 UI 参数原封不动传给 provider,而是做了一层 provider 适配。
十四、视频 provider 参数如何映射?
不同 provider 的视频参数也不一样。
Pixelle-Video 在 _video_options() 中把通用参数映射成 provider-specific options。
基础 options 包括:
text
resolution
negative_prompt
watermark
seed
如果 provider 是 dashscope,会额外传:
text
last_image_path
first_clip_path
reference_image_path
reference_image_paths
reference_video_paths
reference_audio_path
audio
audio_path
prompt_extend
shot_type
如果 provider 是 kling,会额外传:
text
sound
mode
cfg_scale
如果 provider 是 seedance,会额外传:
text
generate_audio
源码最后会过滤掉值为 None 的字段,只把有效参数传给 VideoClient。
这就是适配器的价值。
上层 pipeline 不需要知道 Kling 叫 cfg_scale,DashScope 支持 first_clip_path,Seedance 支持 generate_audio。
这些差异都在 _video_options() 中处理。
十五、VideoClient 的配置从哪里来?
_create_video_client() 同样从 config_manager.get_api_providers_config() 读取配置。
它会把这些配置传给 VideoClient:
text
dashscope_api_key
dashscope_base_url
dashscope_local_proxy
kling_access_key
kling_secret_key
kling_base_url
kling_local_proxy
ark_api_key
ark_base_url
ark_local_proxy
这说明 Wan 类模型主要走 DashScope 配置,Kling 使用自己的 access_key / secret_key,Seedance 则通过 Ark 相关配置接入。
所以,从配置到调用的关系可以整理成:
text
api/dashscope/wan...
↓
api_providers.dashscope
↓
VideoClient(dashscope_api_key, dashscope_base_url)
api/kling/kling...
↓
api_providers.kling
↓
VideoClient(kling_access_key, kling_secret_key, kling_base_url)
api/seedance/doubao-seedance...
↓
api_providers.ark
↓
VideoClient(ark_api_key, ark_base_url)
十六、视频生成的安全重试机制
视频模型还有一个常见问题:内容审核。
有时 prompt 可能被 provider 判定为不适合生成,返回 content inspection 相关错误。
Pixelle-Video 在 _generate_video() 中做了一个安全重试逻辑:如果生成失败,并且错误信息命中 datainspectionfailed、inappropriate content、green net check failed、content inspection、safety inspection、risk control 等标记,就会调用 _neutralize_video_prompt() 把 prompt 改写成更中性、安全、适合公开视频模型审核的画面描述,然后重试一次。
如果 LLM 改写失败,还会走 _fallback_neutralize_prompt(),用保守替换规则把一些高风险词改成更中性的表达。
这个机制说明 Pixelle-Video 在直连 API 视频模型时,考虑到了真实生产环境中的审核失败问题。
当然,这不是为了绕过安全规则,而是把可能过激、模糊或容易误伤的 prompt 改成更中性、更公开发布友好的画面描述。
十七、直连 API 的完整调用链路
把前面内容串起来,Pixelle-Video 的直连 API 媒体生成链路大概是:
text
【配置】
config.yaml
↓
api_providers.openai / dashscope / ark / kling
【模型注册】
APIProviderMediaService
↓
IMAGE_MODELS
VIDEO_MODELS
↓
list_workflows()
↓
api/provider/model
【MediaService 入口】
FrameProcessor
↓
self.core.media(
prompt=frame.image_prompt,
workflow="api/kling/kling-v3",
media_type="video",
width=1080,
height=1920,
duration=5
)
【路由分发】
MediaService.__call__()
↓
selected_workflow.startswith("api/")
↓
self.core.api_media(...)
【API 适配】
APIProviderMediaService.__call__()
↓
resolve_workflow()
↓
provider / model / media_type
【图片路线】
_generate_image()
↓
ImageClient.generate_image()
↓
MediaResult(media_type="image", url=result_path)
【视频路线】
_generate_video()
↓
检查模型能力和输入条件
↓
归一化 duration / resolution / ratio
↓
映射 provider-specific options
↓
VideoClient.generate_video()
↓
MediaResult(media_type="video", url=save_path)
这就是 OpenAI、Wan、Kling、Seedance 等模型如何进入 Pixelle-Video 媒体生成流程的核心逻辑。
十八、直连 API 和 ComfyUI / RunningHub 的对比
可以把三种路线放在一起看:
text
selfhost:
优点:最自由,可控性最高,适合深度定制
缺点:需要本地 ComfyUI、模型、节点和显卡
runninghub:
优点:不需要本地显卡,仍然保留 workflow 灵活性
缺点:依赖 RunningHub API Key 和云端 workflow
api:
优点:不需要 ComfyUI,不需要 workflow,直接调用模型服务
缺点:强依赖 provider API,模型能力和参数差异较大
如果你是普通用户,只想尽快跑通,直连 API 可能更简单。
如果你是重度 ComfyUI 用户,本地 workflow 更自由。
如果你没有显卡但想用 workflow,RunningHub 更合适。
Pixelle-Video 的好处在于,它没有强迫用户只能选一种,而是通过 MediaService 把三种路线统一起来。
十九、直连 API 的优点
Pixelle-Video 这套直连 API 设计有几个明显优点。
第一,不依赖 ComfyUI。
用户不需要安装 ComfyUI,也不需要维护节点和模型。
第二,接入简单。
只要配置 provider 的 key 和 base_url,再选择 api/provider/model,就可以进入生成流程。
第三,和 pipeline 解耦。
上层仍然调用 self.core.media(),不需要为 OpenAI、Wan、Kling、Seedance 分别写 pipeline。
第四,模型能力可描述。
视频模型通过 VIDEO_MODEL_CAPABILITIES 保存 duration、resolution、ratio、ability_type 等能力信息,方便 UI 和调用逻辑做适配。
第五,结果统一。
无论图片还是视频,最后都返回 MediaResult,后续 FrameProcessor 可以继续复用。
二十、直连 API 的局限
当然,直连 API 也有一些局限。
1. provider 差异比较大
OpenAI、DashScope、Kling、Ark / Seedance 的认证、参数、返回格式都不同。
Pixelle-Video 虽然做了适配,但每新增一个 provider,仍然要处理不少细节。
2. 视频模型能力不完全一致
有的模型支持文生视频,有的只支持图生视频。
有的支持 5 秒和 10 秒,有的支持 2 到 15 秒。
有的支持原生音频,有的不支持。
所以不能假设所有 api/... 视频模型都能用同一种方式调用。
3. 成本不可忽略
直连云端媒体模型通常会消耗 API 额度。
如果批量生成短视频,成本需要提前估算。
4. 审核和失败率需要处理
视频 prompt 可能被 provider 审核拒绝。
Pixelle-Video 做了中性化重试,但实际使用中仍需要人工控制内容方向。
5. 不如 ComfyUI 灵活
ComfyUI 可以自由组合节点、模型、LoRA、ControlNet、参考图、后处理。
直连 API 通常只能使用 provider 开放的参数。
二十一、二次开发:如何增加新的直连 API 模型?
如果要给 Pixelle-Video 增加新的直连 API 模型,可以按这个思路做。
第一,在配置系统中增加 provider 配置。
如果是普通 API Key,可以类似 APIKeyProviderConfig。
如果是 access_key / secret_key,可以类似 Kling 的 AccessSecretProviderConfig。
第二,在 config.example.yaml 中增加示例配置。
让用户知道应该填什么 key、base_url、是否支持 proxy。
第三,在 APIProviderMediaService 中增加模型列表。
图片模型加入 IMAGE_MODELS。
视频模型加入 VIDEO_MODELS。
第四,如果是视频模型,补充 VIDEO_MODEL_CAPABILITIES。
至少要说明:
text
ability_type
adapter_ability_types
input_modalities
duration
resolutions
ratios
api_contract_verified
contract_issues
第五,在 ImageClient 或 VideoClient 中实现具体调用。
因为 APIProviderMediaService 本身更像路由和适配层,真正请求 provider 的逻辑是在 client 中。
第六,在 _video_options() 中补充 provider 参数映射。
如果新 provider 有特殊参数,就在这里把 Pixelle-Video 通用参数转成 provider 所需参数。
第七,确保返回 MediaResult。
无论 provider 返回格式多复杂,最终都要统一成:
text
MediaResult(media_type="image", url=...)
MediaResult(media_type="video", url=..., duration=...)
这样后续 FrameProcessor 不需要改。
二十二、源码阅读建议
如果你想读 Pixelle-Video 的直连 API 媒体模型源码,建议按这个顺序:
text
1. config.example.yaml
看 api_providers 如何配置 OpenAI、DashScope、Ark、Kling。
2. pixelle_video/config/schema.py
看 APIProvidersConfig、APIKeyProviderConfig、AccessSecretProviderConfig。
3. pixelle_video/services/media.py
看 MediaService 如何识别 api/... 并转交 core.api_media。
4. pixelle_video/services/api_media.py
看 APIProviderMediaService 的 IMAGE_MODELS、VIDEO_MODELS、list_workflows 和 resolve_workflow。
5. pixelle_video/services/api_media.py
看 _generate_image() 如何调用 ImageClient。
6. pixelle_video/services/api_media.py
看 _generate_video() 如何检查能力、处理时长、映射参数和安全重试。
7. pixelle_video/services/api_services/image_client.py
看不同图像 provider 的真实 API 调用。
8. pixelle_video/services/api_services/video_client.py
看 Wan、Kling、Seedance 等视频 provider 的真实 API 调用。
这样读,就能完整理解:
text
配置 → API workflow → provider/model → ImageClient/VideoClient → MediaResult → FrameProcessor
二十三、总结
这一篇我们分析了 Pixelle-Video 的直连 API 媒体模型接入。
它的核心不是把 OpenAI、Wan、Kling、Seedance 写进 pipeline,而是做了一层统一适配:
text
api/provider/model
↓
MediaService 识别 api/ 前缀
↓
APIProviderMediaService.resolve_workflow()
↓
解析 provider、model、media_type
↓
图片走 ImageClient
↓
视频走 VideoClient
↓
返回统一 MediaResult
从设计上看,它有几个关键点:
text
api/... 被包装成 workflow-like 结构
图片模型和视频模型分开维护
视频模型有能力表 VIDEO_MODEL_CAPABILITIES
provider 配置统一放在 api_providers
图片和视频最终都返回 MediaResult
上层 pipeline 不需要关心底层 provider 差异
所以一句话总结:
Pixelle-Video 的直连 API 媒体模型接入,本质是把 OpenAI、Wan、Kling、Seedance 等不同 provider 的图像 / 视频能力包装成 api/provider/model 形式,再通过 APIProviderMediaService 统一解析、调用和返回 MediaResult,让它们像普通 workflow 一样进入视频生成流程。