专为电商卖家和美工打造的无限画布 AI 工具。生图、改图、抠图、换视角、做视频、AI Skills / An infinite canvas AI tool built for e-commerce sellers and designers — generate, edit, cut out, change perspectives, create videos, and use AI Skills.
TypeScript
24
277 commits
updated Sep 14, 2026
语言:English
image-prompt-sop 把模糊需求改写成高质量单图提示词、amazon-listing-pack-sop 一键生成协调的 7 张亚马逊套图)。在侧栏「技能库」可以装自己的skill:拖一个 SKILL.md 进去(或者直接在浏览器里写),下一条消息 agent 就能使用,不需要重启应用。flowchart LR
subgraph FE["前端 — React + Excalidraw"]
Chat["聊天框"]
Bar["AI 工具栏"]
end
subgraph BE["后端 — Django + DRF"]
Agent["deepagents agent<br/>(skills + tools)"]
API["job 端点"]
end
Q[["Celery 队列<br/>canvas · canvas_cpu"]]
Prov["图像 / 视频 / fal.ai 供应商"]
Chat -->|"POST /chat/ (SSE)"| Agent
Agent -->|"generate_image · generate_video"| Q
Bar -->|"编辑 · 抠图 · 拆分 · 换视角 · 视频"| API --> Q
Q --> Prov --> Q
Q -->|"轮询 job → 落到画布"| FE
create_deep_agent),带两个工具(generate_image、generate_video)、一份按场景隔离的 memory 文件、以及按需展开的 SKILL.md 技能。每轮对话历史从数据库回放(不需要独立的记忆存储)。QUEUED 记录、提交后入 Celery 队列;前端轮询 job 直到结果就绪再落到画布。抠图是两段链(LLM 出白底 → CPU rembg 出 alpha)。git clone https://github.com/Orieileen/Canvex.git
cd Canvex
cp .env.example .env
cp .env.example .env后默认值直接可用,不需要更改.env里的任何一行这里不填任何 API key —— api key在应用内配置(第 4 步)。.env 只管基础设施:端口、数据库,以及 PUBLIC_MEDIA_BASE(见下表)。
前置:Docker + Docker Compose。
docker compose up -d --build
由于各家供应商的请求参数各不相同,Canvex 预设了一套 API 供应商格式(不是广告):
fal-ai/qwen-image-edit-2511-multiple-angles。快捷配置 —— 打开 http://localhost:5173,点左侧栏的「通道配置」。在「快捷配置」中填入对应供应商的key即可。下面列出Canvex可用预设:
1.聊天/llm agent用兔子、生图和视频用 API Mart,变换视角使用fal.ai是这个项目经过测试得出跑的最稳最便宜的供应商 —— 这里每个功能都是对着它们做出来、验过来的,所以想最快跑通就配这两家。其余几条聊天/llm agent官方供应商通道也可以使用,不过openai等国外供应商一方面比较贵,一方面api并不好买,除了tu-zi也可以使用国内llm厂商,而图片apimart则是便宜+稳定。换视角只有一个选项,因为视角 LoRA 只在 fal.ai 上。
2.从一段 curl 开始配置供应商 —— 如果要使用不在Canvex列表的供应商走这条:把你需要的api供应商文档里的示例 curl 粘进去,Canvex向导会替你自动把通道拼出来,不用写 JSON。(这个功能可能不适配所有供应商)
3.新建自定义供应商配置 —— 完全自己写请求模板。你需要知道供应商所有的请求参数以及值怎么写,并手动拼成json填入自定义供应商
模型行右边的 ⚡ 会真发一次最小生成。它只出现在生图和换视角通道上:聊天通道要验的是它认不认 tools 参数,直接在聊天框里说「生成一张图」最快;视频则太慢,撑不过一次同步测试 —— 对视频来说,画布上第一条真片子就是那次测试。
每条通道名字左边有一个状态点:绿 = 上次调用通了,橙 = 上次失败,空心 = 还没调用过。真实生成也会更新它,不只是 ⚡ —— 一条通道哪天悄悄坏了(key 过期、额度打光、供应商换端点),在这里一眼能看见,而不是变成又一次莫名其妙的生成失败。展开失败的卡片,能看到供应商返回的原文,上面还有一句说这属于哪类问题、该改哪儿:key 过期、余额打光、模型名供应商不认、以及人家自己挂了,在原始报错里长得都差不多,而其中只有一部分是靠改配置能解决的。
每个模型行下面还能挂自己的覆盖项 —— 一条通道底下挂着四十个在时长、比例、键名上互相不一致的模型,而不是建四十条通道,靠的就是它。如果你是手写通道:这些旋钮填错大多不会报错,只是静默失效 —— 比例发到一个供应商不读的键上不是错误,只是那个设置永远不起作用。
最少需要这些就能跑起来(完整列表 + 调优旋钮见 .env.example)(Canvex已经配置好了环境变量,所以以下只做展示说明,不需要任何更改):
| 变量 | 必填 | 说明 |
|---|---|---|
PUBLIC_MEDIA_BASE | – | 你的浏览器访问这个后端的地址(默认 http://localhost:28000)。只用在「发到聊天」附件那几个绝对 URL 上;从别的机器/域名打开这个应用时才需要改。供应商永远不会来拉它 —— 源图要么内联成 base64、要么由我们主动推给供应商,所以自托管不需要任何隧道、CDN 或公网地址。 |
CANVAS_AGENT_STORE_BACKEND | – | memory(默认,进程内)或 postgres(持久化 agent 记忆;同时要设 CANVAS_AGENT_STORE_DSN,并装上 langgraph-checkpoint-postgres)。 |
POSTGRES_DB / _USER / _PASSWORD | – | 默认都是 canvex。 |
BACKEND_PORT / FRONTEND_PORT | – | 宿主端口,默认 28000 / 5173。 |
VITE_API_URL | – | 前端调用的后端地址。Docker Compose 会传 http://localhost:28000;不走 Compose 直接跑 dev server 又不设它的话,代码回落到 :8000,连不上。 |
所有路由在 /api/v1/canvas/ 下。
| 用途 | 端点 |
|---|---|
| 场景(CRUD) | GET/POST /scenes/、GET/PATCH/DELETE /scenes/{id}/ |
| 聊天(SSE 流) | POST /scenes/{id}/chat/ |
| 图像编辑 / 生成 | POST /scenes/{id}/image-edit/ → GET /image-edit-jobs/{job_id}/ |
| 拆分(主体 + 背景) | POST /scenes/{id}/split/ → 返回两个 job,都在 /image-edit-jobs/{job_id}/ 轮询 |
| 视频 | POST /scenes/{id}/video/ → GET /video-jobs/{job_id}/ |
| 换视角(fal.ai) | POST /scenes/{id}/angle/ → GET /angle-jobs/{job_id}/ |
| 进行中的 job(恢复轮询) | GET /scenes/{id}/active-jobs/ |
| 每个场景的 job 历史 | GET /scenes/{id}/image-edit-jobs/、/video-jobs/、/angle-jobs/ |
| 发到聊天的上传 | POST /scenes/{id}/upload-attachment/ |
| 素材库 | GET /media-library/folders/、GET /media-library/folders/{scene_id}/items/ |
| Agent 当前看得见的技能 | GET /skills/ |
| 装 / 卸技能 | GET / POST /skill-library/、PATCH / DELETE /skill-library/{id}/ |
| 通道(CRUD + 嵌套的模型) | GET/POST /image-providers/、GET/PATCH/PUT/DELETE /image-providers/{id}/ |
| ⚡ 测一条通道 | POST /image-providers/{id}/test/ —— 失败也返 200,带原始报文 + 诊断码 |
| 表单字段表 + 一键预设 | GET /image-providers/schema/ |
| curl 向导 | POST /image-providers/wizard/parse/(只解析不发送)、POST /image-providers/wizard/probe/(拿还没保存的通道真发一次生成) |
| 工具栏选择器读的模型列表 | GET /image-models/(回包里不含 base URL / key) |
聊天端点走 SSE(text/event-stream,每个事件的帧格式是 data: <json>\n\n)。事件类型:user_created、assistant_delta(逐 token 的文字流,实际量最大的就是它)、tool_call、tool_result、canvas_asset({url},agent 本轮产出、客户端要落到画布的图)、assistant_final、assistant、error、done。
技术栈:Django + DRF + Celery + Redis + PostgreSQL + deepagents(底层是 LangChain / LangGraph)。
backend/
├── config/ # Django 工程 (settings, celery, urls, wsgi/asgi)
└── studio/ # 主 app,挂在 /api/v1/canvas/
├── models.py # Scene, ChatMessage, ImageEditJob/Result, VideoJob,
│ # AngleJob/Result, DataFolder/DataAsset,
│ # ImageProvider/ImageModel (通道), Skill
├── views.py serializers.py urls.py
├── tasks.py # Celery: canvas.image_edit_job / image_edit_cutout_job
│ # / video_job / angle_job / cutout_llm_step
├── tests/ # 预设与端点的契约、curl 导入、比例、通道诊断、
│ # 聊天协议、请求模板
└── services/
├── image.py video.py # **只**建 job —— 真正调供应商的在
│ # agent/tools/ 里, 见下
├── angle.py # 建 job + 调 fal.ai
├── image_client.py # OpenAI 兼容图像客户端, 由一个 ImageChannel
│ # 构造 (库是唯一配置来源)
├── image_channels.py # 库里那两级行 → 每个调用点消费的那一个
│ # ImageChannel; 通道类型规则、预设、表单
├── template_client.py # 真正跑一条用户写的请求模板: 发送、轮询、
│ # 从回包里把结果挖出来
├── request_template.py # 模板格式本身 (占位符放哪儿)
├── curl_import.py # 供应商的示例 curl → 那份模板
├── channel_health.py # 每次真实往返之后写那个状态点
├── channel_diagnosis.py # 供应商报错 → 「这属于哪类问题」
├── attachments.py scenes.py billing.py (空操作) http_retry.py listings_utils.py
└── agent/
├── builder.py # create_deep_agent (model, tools, skills, memory, store)
├── skills.py context.py
├── skill_md.py # 解析 + 准入检查上传的 SKILL.md
├── tools/ # **不只是 agent 的工具** —— 全产品每一个图/视频 job
# 都在这儿真正执行, 包括工具栏发起的
# (common.py, image.py, video.py)
└── skills/ # 只是出厂种子 —— 迁移 0018 把它导进库, 运行时以库为准
# (改这些文件不生效)
一个生成请求会在事务里建 QUEUED job、提交后入 Celery 队列(返回 202 + {job_id, status} —— 拆分返回两个,两条 leg 各一个)。任务跑在专用队列上:
| 队列(worker) | 池 | 任务 |
|---|---|---|
canvas(worker_canvas) | gevent | image_edit_job、video_job、angle_job、cutout_llm_step |
canvas_cpu(worker_canvas_cpu) | prefork | image_edit_cutout_job(rembg alpha,CPU 密集) |
excalidraw(worker) | prefork | 默认队列 |
抠图/拆分是两段链:第一段(LLM,跑 canvas)出白底图,第二段(rembg,跑 canvas_cpu)把白底转透明 alpha。前端轮询 job 端点(或 /active-jobs/),就绪后落到画布。聊天 agent 调用的图像/视频工具建的是同样的 job —— agent 返回一句"已入队",不阻塞等渲染。
查日志(某个 job 失败时)—— 要带上三个 worker:
docker compose logs -f backend worker worker_canvas worker_canvas_cpu
图像结果不对或报错 —— 在侧栏「通道配置」里核对 base URL、key 和模型名,用 ⚡ 测一下。视频通道也在同一个面板里配,但没有 ⚡(见第 4 步):对它来说,画布上第一条真片子就是那次测试。
视频好像卡住了 —— 多半没有。视频供应商本来就要几分钟;模板通道的轮询预算给到了约 50 分钟,那个数是照 APIMart 一次真实出片实测定的。整个等待期间画布上都留着那个占位框,刷新页面也还在。
某次生成栽在源图上 —— 它会直说:job 翻成 FAILED,带着供应商自己的报错原文,画布会把它显示在占位卡片上。这不是 PUBLIC_MEDIA_BASE 的问题 —— Canvex 要么把源图内联成 base64,要么主动推给供应商,从不指望谁来访问你的机器。唯一还需要「公网可达」的,是你自己粘进来的外部 URL。图生视频那一类:有些视频供应商既不收 base64、又要求图片地址公网可达,对这种,通道上的 upload_path 指向供应商自己的上传端点,Canvex 在生成之前先把字节推过去。API Mart 的视频预设自带这一项;手写的视频通道要自己填。
前端请求被 CORS 拦 —— 保持 CORS_ALLOW_ALL_ORIGINS=true(默认),或把你的来源加进 CORS_ALLOWED_ORIGINS。
277 commits
TypeScript
55.9%
Python
42.6%
专为电商卖家和美工打造的无限画布 AI 工具。生图、改图、抠图、换视角、做视频、AI Skills / An infinite canvas AI tool built for e-commerce sellers and designers — generate, edit, cut out, change perspectives, create videos, and use AI Skills.
TypeScript
24
277 commits
updated Sep 14, 2026
语言:English
image-prompt-sop 把模糊需求改写成高质量单图提示词、amazon-listing-pack-sop 一键生成协调的 7 张亚马逊套图)。在侧栏「技能库」可以装自己的skill:拖一个 SKILL.md 进去(或者直接在浏览器里写),下一条消息 agent 就能使用,不需要重启应用。flowchart LR
subgraph FE["前端 — React + Excalidraw"]
Chat["聊天框"]
Bar["AI 工具栏"]
end
subgraph BE["后端 — Django + DRF"]
Agent["deepagents agent<br/>(skills + tools)"]
API["job 端点"]
end
Q[["Celery 队列<br/>canvas · canvas_cpu"]]
Prov["图像 / 视频 / fal.ai 供应商"]
Chat -->|"POST /chat/ (SSE)"| Agent
Agent -->|"generate_image · generate_video"| Q
Bar -->|"编辑 · 抠图 · 拆分 · 换视角 · 视频"| API --> Q
Q --> Prov --> Q
Q -->|"轮询 job → 落到画布"| FE
create_deep_agent),带两个工具(generate_image、generate_video)、一份按场景隔离的 memory 文件、以及按需展开的 SKILL.md 技能。每轮对话历史从数据库回放(不需要独立的记忆存储)。QUEUED 记录、提交后入 Celery 队列;前端轮询 job 直到结果就绪再落到画布。抠图是两段链(LLM 出白底 → CPU rembg 出 alpha)。git clone https://github.com/Orieileen/Canvex.git
cd Canvex
cp .env.example .env
cp .env.example .env后默认值直接可用,不需要更改.env里的任何一行这里不填任何 API key —— api key在应用内配置(第 4 步)。.env 只管基础设施:端口、数据库,以及 PUBLIC_MEDIA_BASE(见下表)。
前置:Docker + Docker Compose。
docker compose up -d --build
由于各家供应商的请求参数各不相同,Canvex 预设了一套 API 供应商格式(不是广告):
fal-ai/qwen-image-edit-2511-multiple-angles。快捷配置 —— 打开 http://localhost:5173,点左侧栏的「通道配置」。在「快捷配置」中填入对应供应商的key即可。下面列出Canvex可用预设:
1.聊天/llm agent用兔子、生图和视频用 API Mart,变换视角使用fal.ai是这个项目经过测试得出跑的最稳最便宜的供应商 —— 这里每个功能都是对着它们做出来、验过来的,所以想最快跑通就配这两家。其余几条聊天/llm agent官方供应商通道也可以使用,不过openai等国外供应商一方面比较贵,一方面api并不好买,除了tu-zi也可以使用国内llm厂商,而图片apimart则是便宜+稳定。换视角只有一个选项,因为视角 LoRA 只在 fal.ai 上。
2.从一段 curl 开始配置供应商 —— 如果要使用不在Canvex列表的供应商走这条:把你需要的api供应商文档里的示例 curl 粘进去,Canvex向导会替你自动把通道拼出来,不用写 JSON。(这个功能可能不适配所有供应商)
3.新建自定义供应商配置 —— 完全自己写请求模板。你需要知道供应商所有的请求参数以及值怎么写,并手动拼成json填入自定义供应商
模型行右边的 ⚡ 会真发一次最小生成。它只出现在生图和换视角通道上:聊天通道要验的是它认不认 tools 参数,直接在聊天框里说「生成一张图」最快;视频则太慢,撑不过一次同步测试 —— 对视频来说,画布上第一条真片子就是那次测试。
每条通道名字左边有一个状态点:绿 = 上次调用通了,橙 = 上次失败,空心 = 还没调用过。真实生成也会更新它,不只是 ⚡ —— 一条通道哪天悄悄坏了(key 过期、额度打光、供应商换端点),在这里一眼能看见,而不是变成又一次莫名其妙的生成失败。展开失败的卡片,能看到供应商返回的原文,上面还有一句说这属于哪类问题、该改哪儿:key 过期、余额打光、模型名供应商不认、以及人家自己挂了,在原始报错里长得都差不多,而其中只有一部分是靠改配置能解决的。
每个模型行下面还能挂自己的覆盖项 —— 一条通道底下挂着四十个在时长、比例、键名上互相不一致的模型,而不是建四十条通道,靠的就是它。如果你是手写通道:这些旋钮填错大多不会报错,只是静默失效 —— 比例发到一个供应商不读的键上不是错误,只是那个设置永远不起作用。
最少需要这些就能跑起来(完整列表 + 调优旋钮见 .env.example)(Canvex已经配置好了环境变量,所以以下只做展示说明,不需要任何更改):
| 变量 | 必填 | 说明 |
|---|---|---|
PUBLIC_MEDIA_BASE | – | 你的浏览器访问这个后端的地址(默认 http://localhost:28000)。只用在「发到聊天」附件那几个绝对 URL 上;从别的机器/域名打开这个应用时才需要改。供应商永远不会来拉它 —— 源图要么内联成 base64、要么由我们主动推给供应商,所以自托管不需要任何隧道、CDN 或公网地址。 |
CANVAS_AGENT_STORE_BACKEND | – | memory(默认,进程内)或 postgres(持久化 agent 记忆;同时要设 CANVAS_AGENT_STORE_DSN,并装上 langgraph-checkpoint-postgres)。 |
POSTGRES_DB / _USER / _PASSWORD | – | 默认都是 canvex。 |
BACKEND_PORT / FRONTEND_PORT | – | 宿主端口,默认 28000 / 5173。 |
VITE_API_URL | – | 前端调用的后端地址。Docker Compose 会传 http://localhost:28000;不走 Compose 直接跑 dev server 又不设它的话,代码回落到 :8000,连不上。 |
所有路由在 /api/v1/canvas/ 下。
| 用途 | 端点 |
|---|---|
| 场景(CRUD) | GET/POST /scenes/、GET/PATCH/DELETE /scenes/{id}/ |
| 聊天(SSE 流) | POST /scenes/{id}/chat/ |
| 图像编辑 / 生成 | POST /scenes/{id}/image-edit/ → GET /image-edit-jobs/{job_id}/ |
| 拆分(主体 + 背景) | POST /scenes/{id}/split/ → 返回两个 job,都在 /image-edit-jobs/{job_id}/ 轮询 |
| 视频 | POST /scenes/{id}/video/ → GET /video-jobs/{job_id}/ |
| 换视角(fal.ai) | POST /scenes/{id}/angle/ → GET /angle-jobs/{job_id}/ |
| 进行中的 job(恢复轮询) | GET /scenes/{id}/active-jobs/ |
| 每个场景的 job 历史 | GET /scenes/{id}/image-edit-jobs/、/video-jobs/、/angle-jobs/ |
| 发到聊天的上传 | POST /scenes/{id}/upload-attachment/ |
| 素材库 | GET /media-library/folders/、GET /media-library/folders/{scene_id}/items/ |
| Agent 当前看得见的技能 | GET /skills/ |
| 装 / 卸技能 | GET / POST /skill-library/、PATCH / DELETE /skill-library/{id}/ |
| 通道(CRUD + 嵌套的模型) | GET/POST /image-providers/、GET/PATCH/PUT/DELETE /image-providers/{id}/ |
| ⚡ 测一条通道 | POST /image-providers/{id}/test/ —— 失败也返 200,带原始报文 + 诊断码 |
| 表单字段表 + 一键预设 | GET /image-providers/schema/ |
| curl 向导 | POST /image-providers/wizard/parse/(只解析不发送)、POST /image-providers/wizard/probe/(拿还没保存的通道真发一次生成) |
| 工具栏选择器读的模型列表 | GET /image-models/(回包里不含 base URL / key) |
聊天端点走 SSE(text/event-stream,每个事件的帧格式是 data: <json>\n\n)。事件类型:user_created、assistant_delta(逐 token 的文字流,实际量最大的就是它)、tool_call、tool_result、canvas_asset({url},agent 本轮产出、客户端要落到画布的图)、assistant_final、assistant、error、done。
技术栈:Django + DRF + Celery + Redis + PostgreSQL + deepagents(底层是 LangChain / LangGraph)。
backend/
├── config/ # Django 工程 (settings, celery, urls, wsgi/asgi)
└── studio/ # 主 app,挂在 /api/v1/canvas/
├── models.py # Scene, ChatMessage, ImageEditJob/Result, VideoJob,
│ # AngleJob/Result, DataFolder/DataAsset,
│ # ImageProvider/ImageModel (通道), Skill
├── views.py serializers.py urls.py
├── tasks.py # Celery: canvas.image_edit_job / image_edit_cutout_job
│ # / video_job / angle_job / cutout_llm_step
├── tests/ # 预设与端点的契约、curl 导入、比例、通道诊断、
│ # 聊天协议、请求模板
└── services/
├── image.py video.py # **只**建 job —— 真正调供应商的在
│ # agent/tools/ 里, 见下
├── angle.py # 建 job + 调 fal.ai
├── image_client.py # OpenAI 兼容图像客户端, 由一个 ImageChannel
│ # 构造 (库是唯一配置来源)
├── image_channels.py # 库里那两级行 → 每个调用点消费的那一个
│ # ImageChannel; 通道类型规则、预设、表单
├── template_client.py # 真正跑一条用户写的请求模板: 发送、轮询、
│ # 从回包里把结果挖出来
├── request_template.py # 模板格式本身 (占位符放哪儿)
├── curl_import.py # 供应商的示例 curl → 那份模板
├── channel_health.py # 每次真实往返之后写那个状态点
├── channel_diagnosis.py # 供应商报错 → 「这属于哪类问题」
├── attachments.py scenes.py billing.py (空操作) http_retry.py listings_utils.py
└── agent/
├── builder.py # create_deep_agent (model, tools, skills, memory, store)
├── skills.py context.py
├── skill_md.py # 解析 + 准入检查上传的 SKILL.md
├── tools/ # **不只是 agent 的工具** —— 全产品每一个图/视频 job
# 都在这儿真正执行, 包括工具栏发起的
# (common.py, image.py, video.py)
└── skills/ # 只是出厂种子 —— 迁移 0018 把它导进库, 运行时以库为准
# (改这些文件不生效)
一个生成请求会在事务里建 QUEUED job、提交后入 Celery 队列(返回 202 + {job_id, status} —— 拆分返回两个,两条 leg 各一个)。任务跑在专用队列上:
| 队列(worker) | 池 | 任务 |
|---|---|---|
canvas(worker_canvas) | gevent | image_edit_job、video_job、angle_job、cutout_llm_step |
canvas_cpu(worker_canvas_cpu) | prefork | image_edit_cutout_job(rembg alpha,CPU 密集) |
excalidraw(worker) | prefork | 默认队列 |
抠图/拆分是两段链:第一段(LLM,跑 canvas)出白底图,第二段(rembg,跑 canvas_cpu)把白底转透明 alpha。前端轮询 job 端点(或 /active-jobs/),就绪后落到画布。聊天 agent 调用的图像/视频工具建的是同样的 job —— agent 返回一句"已入队",不阻塞等渲染。
查日志(某个 job 失败时)—— 要带上三个 worker:
docker compose logs -f backend worker worker_canvas worker_canvas_cpu
图像结果不对或报错 —— 在侧栏「通道配置」里核对 base URL、key 和模型名,用 ⚡ 测一下。视频通道也在同一个面板里配,但没有 ⚡(见第 4 步):对它来说,画布上第一条真片子就是那次测试。
视频好像卡住了 —— 多半没有。视频供应商本来就要几分钟;模板通道的轮询预算给到了约 50 分钟,那个数是照 APIMart 一次真实出片实测定的。整个等待期间画布上都留着那个占位框,刷新页面也还在。
某次生成栽在源图上 —— 它会直说:job 翻成 FAILED,带着供应商自己的报错原文,画布会把它显示在占位卡片上。这不是 PUBLIC_MEDIA_BASE 的问题 —— Canvex 要么把源图内联成 base64,要么主动推给供应商,从不指望谁来访问你的机器。唯一还需要「公网可达」的,是你自己粘进来的外部 URL。图生视频那一类:有些视频供应商既不收 base64、又要求图片地址公网可达,对这种,通道上的 upload_path 指向供应商自己的上传端点,Canvex 在生成之前先把字节推过去。API Mart 的视频预设自带这一项;手写的视频通道要自己填。
前端请求被 CORS 拦 —— 保持 CORS_ALLOW_ALL_ORIGINS=true(默认),或把你的来源加进 CORS_ALLOWED_ORIGINS。
277 commits
TypeScript
55.9%
Python
42.6%