
Chanjing Ai Creation
- 41 installs
- 18 repo stars
- Updated March 28, 2026
- chanjing-ai/chan-skills
Submits and polls Chanjing AI creation image/video generation tasks via its Open API using local credentials.
About
A Python client for the Chanjing AI creation Open API that submits image and video generation tasks, polls status, and optionally downloads outputs. A developer uses it to generate media through Chanjing's cross-model text-to-image/video endpoints.
- Submit image/video tasks, poll status, list and get tasks via Chanjing Open API
- Reads/writes local credentials.json; optional output download
Chanjing Ai Creation by the numbers
- 41 all-time installs (skills.sh)
- Ranked #921 of 1,335 Generative Media skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
npx skills add https://github.com/chanjing-ai/chan-skills --skill chanjing-ai-creationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 41 |
|---|---|
| repo stars | ★ 18 |
| Last updated | March 28, 2026 |
| Repository | chanjing-ai/chan-skills ↗ |
What it does
Submits and polls Chanjing AI creation image/video generation tasks via its Open API using local credentials.
Files
Chanjing AI Creation
功能说明
调用蝉镜 AI 创作 Open API:提交任务、轮询状态、列表与单条查询;仅在用户明确要求时用 download_result.py 可选下载输出。需读写本地 credentials.json 并访问 Open API。跨模型文生图/视频等由 submit_task.py 参数与透传体决定。本 skill 脚本不依赖 ffmpeg/ffprobe。
运行依赖
- python3 与同仓库
scripts/*.py - 无 ffmpeg/ffprobe 门控
环境变量与机器可读声明
- 环境变量键名与说明:`manifest.yaml`(
environment段)及本文 - 变量、凭据、合规 `permissions`、`clientPermissions`、`agentPolicy`:`manifest.yaml`
使用命令
- ClawHub(slug 以注册表为准):
clawhub run chanjing-ai-creation - 本仓库示例:
python skills/chanjing-ai-creation/scripts/submit_task.py …(见正文 Standard Workflow)
---
登记与审稿(单一事实来源)
主凭据、可选 env、下载信任边界等:以 `manifest.yaml` 为准。本篇从 When to Use 起写业务能力。
When to Use This Skill
当用户要做这些事时使用本 Skill:
- 提交图片或视频 AI 创作任务(
submit_task.py) - 列表 / 单条查询任务(
list_tasks.py、get_task.py) - 轮询异步结果直至完成(
poll_task.py) - 仅在用户明确要求时下载输出(
download_result.py)
上述流程依赖读写本地 credentials.json 并调用 open-api.chanjing.cc。
如果需求更接近“文生数字人”,优先使用 chanjing-text-to-digital-person。 如果需求更接近“已有数字人视频合成”,优先使用 chanjing-video-compose。
Preconditions
执行本 Skill 前,必须先通过 chanjing-credentials-guard 完成 AK/SK 与 Token 校验。
本 Skill 与 guard 共用:
~/.chanjing/credentials.jsonhttps://open-api.chanjing.cc
无凭证时,脚本会自动打开蝉镜登录页,并提示配置命令。
审阅与安全(凭据)
与 Purpose / Credentials / Persistence、`download_result.py` 信任边界相关的逐项说明见 `manifest.yaml`。
运行时范围:本 Skill 的说明与脚本仅服务于已声明用途——读取本地 `credentials.json`、调用蝉镜 Open API 端点;不在轮询或查询成功时自动落盘生成物,仅在用户显式执行 `download_result.py` 时下载资源。
`_auth.py` 与仓库布局:鉴权辅助可能打开系统浏览器,或按相对路径调用同仓库下的 `chanjing-credentials-guard` 脚本(例如 open_login_page.py)。这假设当前工作区为 chan-skills 式多 Skill 目录结构,或已单独安装并具备等效路径的 guard skill;否则将回退为仅打开登录页 URL。
敏感数据与持久化:预期仅处理 `credentials.json` 中的 app_id、secret_key、access_token(及与 token 生命周期相关的字段,见 manifest.yaml)。将 `access_token` 写入磁盘 是有意设计且已文档化,对 API 客户端而言通常可接受;但在多人共用主机、全盘备份/同步到不可信存储等场景下,磁盘上的 token 会扩大泄露面,需按环境自行评估。
Standard Workflow
AI 创作的主接口是统一提交器:
1. 调用 submit_task.py 提交图片或视频生成任务,得到 unique_id 2. 调用 poll_task.py 轮询直到成功,得到 output_url 3. 如需回看任务参数或错误原因,调用 get_task.py 4. 如需看历史记录,调用 list_tasks.py 5. 只有在用户明确要求保存到本地时,才调用 download_result.py
这个 skill 默认做成“通用任务提交器”:
- 对常见图片/视频模型,优先使用脚本提供的通用参数
- 对特殊模型参数,使用
--body-file或--body-json透传完整请求体
Covered APIs
本 Skill 当前覆盖:
POST /open/v1/ai_creation/task/submitPOST /open/v1/ai_creation/task/pageGET /open/v1/ai_creation/task
Scripts
脚本目录:
skills/chanjing-ai-creation/scripts/
| 脚本 | 说明 |
|---|---|
_auth.py | 读写 credentials.json、获取或刷新 access_token |
submit_task.py | 提交 AI 创作任务,输出 unique_id |
get_task.py | 获取单个任务详情 |
list_tasks.py | 列出图片或视频任务 |
poll_task.py | 轮询任务直到完成,默认输出第一个结果地址 |
download_result.py | 下载图片或视频到 outputs/ai-creation/ |
Usage Examples
示例 1:Seedream 3.0 文生图
TASK_ID=$(python3 skills/chanjing-ai-creation/scripts/submit_task.py \
--creation-type 3 \
--model-code "doubao-seedream-3.0-t2i" \
--prompt "赛博朋克城市夜景,霓虹灯,雨夜,电影镜头" \
--aspect-ratio "16:9" \
--clarity 2048 \
--number-of-images 1)
python3 skills/chanjing-ai-creation/scripts/poll_task.py --unique-id "$TASK_ID"示例 2:腾讯 Kling v2.1 Master 图生视频
TASK_ID=$(python3 skills/chanjing-ai-creation/scripts/submit_task.py \
--creation-type 4 \
--model-code "tx_kling-v2-1-master" \
--ref-img-url "https://res.chanjing.cc/chanjing/res/aigc_creation/photo/start.jpg" \
--ref-img-url "https://res.chanjing.cc/chanjing/res/aigc_creation/photo/end.jpg" \
--prompt "角色从静止到转身,镜头平滑移动,叙事感强" \
--aspect-ratio "9:16" \
--clarity 1080 \
--quality-mode pro \
--video-duration 5)
python3 skills/chanjing-ai-creation/scripts/poll_task.py --unique-id "$TASK_ID"示例 3:直接透传完整 JSON
python3 skills/chanjing-ai-creation/scripts/submit_task.py \
--body-file ./payload.jsonDownload Rule
下载是显式动作,不是默认动作:
poll_task.py成功后应先返回远端output_url- 不要自动下载结果文件
- 只有当用户明确表达“下载到本地”“保存到 outputs”“帮我落盘”时,才执行
download_result.py
Output Convention
默认本地输出目录:
outputs/ai-creation/
Additional Resources
更多接口细节见:
skills/chanjing-ai-creation/reference.mdskills/chanjing-ai-creation/examples.md
Examples
Natural Language Triggers
这些说法通常应该触发本 skill:
- “用 Seedream 帮我生成一张海报图”
- “用 Kling 做一个图生视频”
- “帮我提交一个 AI 创作视频任务”
- “查一下这个 AI 创作任务现在到哪了”
- “把刚生成的图片下载到本地”
- “我有完整 payload.json,帮我直接提交”
Minimal CLI Flows
1. Seedream 3.0 文生图
TASK_ID=$(python3 skills/chanjing-ai-creation/scripts/submit_task.py \
--creation-type 3 \
--model-code "doubao-seedream-3.0-t2i" \
--prompt "赛博朋克城市夜景,霓虹灯,雨夜,电影镜头" \
--aspect-ratio "16:9" \
--clarity 2048 \
--number-of-images 1)
python3 skills/chanjing-ai-creation/scripts/poll_task.py \
--unique-id "$TASK_ID"2. 腾讯 Kling v2.1 Master 图生视频
TASK_ID=$(python3 skills/chanjing-ai-creation/scripts/submit_task.py \
--creation-type 4 \
--model-code "tx_kling-v2-1-master" \
--ref-img-url "https://res.chanjing.cc/chanjing/res/aigc_creation/photo/start.jpg" \
--ref-img-url "https://res.chanjing.cc/chanjing/res/aigc_creation/photo/end.jpg" \
--prompt "角色从静止到转身,镜头平滑移动,叙事感强" \
--aspect-ratio "9:16" \
--clarity 1080 \
--quality-mode pro \
--video-duration 5)
python3 skills/chanjing-ai-creation/scripts/poll_task.py \
--unique-id "$TASK_ID"3. 直接透传完整 JSON
python3 skills/chanjing-ai-creation/scripts/submit_task.py \
--body-file ./payload.json4. 查看历史任务
python3 skills/chanjing-ai-creation/scripts/list_tasks.py --type 3
python3 skills/chanjing-ai-creation/scripts/list_tasks.py --type 4 --success-only5. 显式下载
python3 skills/chanjing-ai-creation/scripts/download_result.py \
--url "https://example.com/output.png"Expected Outputs
submit_task.py输出任务unique_idpoll_task.py默认输出第一个结果 URLget_task.py默认输出任务详情 JSONlist_tasks.py默认输出摘要行download_result.py输出本地文件路径
# 合规:根目录 合规规则.md §1–§2(name/version/vendor/runtime/env/permissions)
name: chanjing-ai-creation
version: 0.1.0
vendor: chanjing
runtime:
interpreter: python3
dependencies: []
env:
required: []
optional:
- CHANJING_OPENAPI_CREDENTIALS_DIR
- CHANJING_OPENAPI_BASE_URL
permissions:
network_mode: allowlist
allowed_hosts:
- open-api.chanjing.cc
- www.chanjing.cc
filesystem:
read_roots:
- "${WORKSPACE_ROOT}"
- "${SKILL_DIR}"
- "${CHANJING_OPENAPI_CREDENTIALS_DIR}"
write_roots:
- "${WORKSPACE_ROOT}"
- "${CHANJING_OPENAPI_CREDENTIALS_DIR}"
allowed_commands:
- python3
# 扩展:蝉镜 Open API / Agent(与 SKILL.md、scripts 一致)
schemaVersion: 1
skill:
id: chanjing-ai-creation
author: chan-skills
category: 媒体处理
tags:
- AI创作
- 文生图
- 文生视频
- ChanjingAPI
- 蝉镜
summary: >-
Chanjing AI 创作 Open API:提交任务、轮询状态、列表/查询任务;可选下载输出;
读写本地 credentials.json 并访问 open-api.chanjing.cc。
skillDoc: SKILL.md
environment:
variables:
- name: CHANJING_OPENAPI_CREDENTIALS_DIR
required: false
description: 存放 credentials.json 的目录(兼容 CHANJING_CONFIG_DIR),默认 ~/.chanjing
- name: CHANJING_OPENAPI_BASE_URL
required: false
description: Open API 基址(兼容 CHANJING_API_BASE),默认 https://open-api.chanjing.cc
credentials:
model: credentials_json
defaultPath: "~/.chanjing/credentials.json"
directoryEnv: CHANJING_OPENAPI_CREDENTIALS_DIR
fileName: credentials.json
sensitiveFields:
- app_id
- secret_key
- access_token
- expire_in
persistAccessTokenOnDisk: true
primaryEnvIntentionallyOmitted: true
doNotCommitToVcs:
- credentials.json
clientPermissions:
network:
httpsOutbound: true
documentedHosts:
- open-api.chanjing.cc
filesystem:
read:
- "${CHANJING_OPENAPI_CREDENTIALS_DIR or CHANJING_CONFIG_DIR or ~/.chanjing}/credentials.json"
write:
- "${CHANJING_OPENAPI_CREDENTIALS_DIR or CHANJING_CONFIG_DIR or ~/.chanjing}/credentials.json"
browser:
mayOpenForAuth: true
documentedHosts:
- www.chanjing.cc
subprocess:
allowedPatterns:
- python3
userContent:
mayDownloadFromApiResponseUrls: true
metadata:
openclaw:
homepage: https://doc.chanjing.cc
agentPolicy:
alwaysSkill: false
modifiesOtherSkillsOrGlobalAgent: false
Reference
脚本职责与 SKILL.md 一致:submit_task.py 提交、poll_task.py 轮询、list_tasks.py / get_task.py 列表与详情、download_result.py 仅在显式需要时落盘;鉴权读写本地 credentials.json 并访问 Open API。
Covered APIs
本 skill 当前覆盖这些接口:
POST /open/v1/ai_creation/task/submitPOST /open/v1/ai_creation/task/pageGET /open/v1/ai_creation/task
Why A Generic Submitter
蝉镜 AI 创作有很多图片/视频模型,但它们大都复用同一个提交端点:
POST /open/v1/ai_creation/task/submit不同模型主要差在请求体字段和 model_code,因此本 skill 采用:
- 一个通用
submit_task.py - 一个通用
list_tasks.py - 一个通用
get_task.py - 一个通用
poll_task.py
对常见字段做 CLI 参数映射,对模型私有字段保留 --body-file / --body-json 透传能力。
Submit Task
接口:
POST /open/v1/ai_creation/task/submit这是异步任务接口,成功响应中的 data 即任务 unique_id。
Common request fields
creation_type:3=图片生成,4=视频生成model_code: 模型编码ref_prompt: 提示词ref_img_url: 参考图 URL 数组aspect_ratio: 比例,如1:1、3:4、4:3、9:16、16:9clarity: 图片常见1024/2048/4096,视频常见720/1080quality_mode: 常见std/pronumber_of_images: 图片生成数量,1-4video_duration: 视频时长(秒)style: 部分视频模型支持的视频风格
Typical image model example
以 doubao-seedream-3.0-t2i 为例:
{
"ref_prompt": "赛博朋克城市夜景,霓虹灯,雨夜,电影镜头",
"creation_type": 3,
"aspect_ratio": "16:9",
"clarity": 2048,
"number_of_images": 1,
"model_code": "doubao-seedream-3.0-t2i"
}注意:
- Seedream 3.0 不支持
ref_img_url
Typical video model example
以 tx_kling-v2-1-master 为例:
{
"ref_img_url": [
"https://res.chanjing.cc/chanjing/res/aigc_creation/photo/start.jpg",
"https://res.chanjing.cc/chanjing/res/aigc_creation/photo/end.jpg"
],
"ref_prompt": "角色从静止到转身,镜头平滑移动,叙事感强",
"creation_type": 4,
"aspect_ratio": "9:16",
"clarity": 1080,
"quality_mode": "pro",
"video_duration": 5,
"model_code": "tx_kling-v2-1-master"
}Other model notes
Doubao-Seedance-1.0-pro支持文生视频和图生视频kling-v2-1图片模型文档页虽然列了ref_img_url,但备注明确说不支持参考图
Get Task
接口:
GET /open/v1/ai_creation/task?unique_id=<unique_id>返回字段与任务列表里的单条对象一致。重点关注:
unique_idtype:3=图片,4=视频progress_desc:Queued / Ready / Generating / Success / Errorerr_msgoutput_urlphoto_infomotion_infomodel_codemodel_name
List Tasks
接口:
POST /open/v1/ai_creation/task/page请求体关键字段:
unique_ids: 任务 ID 列表,空数组表示不过滤type:3=图片,4=视频pagepage_size: 最大 50is_success: 是否只看成功任务
Poll Termination Rules
本 skill 按 progress_desc 判断:
Queued/Ready/Generating: 继续轮询Success: 成功,返回output_urlError/Fail: 失败,停止并报错
Output Fields
常见输出:
- 图片任务:
output_url为图片地址数组 - 视频任务:
output_url为视频地址数组
默认脚本行为:
poll_task.py默认输出第一条结果地址- 使用
--all-urls时输出完整output_url数组
Common Status Codes
任务提交、详情、列表文档里常见状态码基本一致:
0: 成功400: 参数格式错误10400: AccessToken 验证失败40000: 参数错误40001: 超出 QPS 限制50000: 系统内部错误
Script Mapping
| 脚本 | 对应接口 |
|---|---|
submit_task.py | POST /open/v1/ai_creation/task/submit |
get_task.py | GET /open/v1/ai_creation/task |
list_tasks.py | POST /open/v1/ai_creation/task/page |
poll_task.py | GET /open/v1/ai_creation/task |
download_result.py | 下载 output_url 到本地 |
Model Examples Referenced
本 skill 参考了这些模型页来整理通用字段:
doubao-seedream-3.0-t2ikling-v2-1tx_kling-v2-1-masterDoubao-Seedance-1.0-pro
#!/usr/bin/env python3
# 鉴权:与 chanjing-credentials-guard 使用同一配置文件(CONFIG_DIR/credentials.json)
# 无 AK/SK 时执行 open_login_page.py 打开注册/登录页
import json
import os
import subprocess
import sys
import time
import urllib.request
from pathlib import Path
_DEFAULT_OPENAPI_BASE = "https://open-api.chanjing.cc"
def credentials_config_dir() -> Path:
raw = os.environ.get("CHANJING_OPENAPI_CREDENTIALS_DIR") or os.environ.get("CHANJING_CONFIG_DIR")
return Path(raw).expanduser() if raw else Path.home() / ".chanjing"
def openapi_base_url() -> str:
return (
os.environ.get("CHANJING_OPENAPI_BASE_URL")
or os.environ.get("CHANJING_API_BASE")
or _DEFAULT_OPENAPI_BASE
).rstrip("/")
CONFIG_DIR = credentials_config_dir()
CONFIG_FILE = CONFIG_DIR / "credentials.json"
API_BASE = openapi_base_url()
BUFFER_SECONDS = 300
LOGIN_URL = "https://www.chanjing.cc/openapi/login"
NO_CREDENTIALS_MSG = """已在浏览器打开蝉镜登录/注册页。
获取秘钥后请执行:
python skills/chanjing-credentials-guard/scripts/chanjing_config.py --ak <你的app_id> --sk <你的secret_key>
设置完毕后请重新执行您之前的操作。"""
def _run_open_login_page():
"""执行 credentials-guard 的 open_login_page.py,在默认浏览器打开注册/登录页。"""
try:
skills_dir = Path(__file__).resolve().parent.parent.parent
script = skills_dir / "chanjing-credentials-guard" / "scripts" / "open_login_page.py"
if script.exists():
subprocess.run([sys.executable, str(script)], check=False, timeout=5)
else:
import webbrowser
webbrowser.open(LOGIN_URL)
except Exception:
try:
import webbrowser
webbrowser.open(LOGIN_URL)
except Exception:
pass
def read_config():
if CONFIG_FILE.exists():
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
return json.load(f)
return {}
def write_config(data):
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
def get_token():
"""返回 (token, None) 或 (None, error_msg)。"""
data = read_config()
app_id = (data.get("app_id") or "").strip()
secret_key = (data.get("secret_key") or "").strip()
if not app_id or not secret_key:
_run_open_login_page()
return None, NO_CREDENTIALS_MSG
now = int(time.time())
token = data.get("access_token")
expire_in = data.get("expire_in")
try:
expire_in = int(expire_in) if expire_in is not None else 0
except (ValueError, TypeError):
expire_in = 0
if token and expire_in > now + BUFFER_SECONDS:
return token, None
url = API_BASE + "/open/v1/access_token"
req = urllib.request.Request(
url,
data=json.dumps({"app_id": app_id, "secret_key": secret_key}).encode("utf-8"),
headers={"Content-Type": "application/json"},
method="POST",
)
try:
with urllib.request.urlopen(req, timeout=30) as resp:
body = json.loads(resp.read().decode("utf-8"))
except Exception as e:
return None, str(e)
if body.get("code") != 0:
return None, body.get("msg", "获取 Token 失败")
payload = body.get("data", {})
new_token = payload.get("access_token")
if not new_token:
return None, "API 返回无 access_token"
data["access_token"] = new_token
data["expire_in"] = payload.get("expire_in")
write_config(data)
return new_token, None
def main():
token, err = get_token()
if err:
raise SystemExit(err)
print(token)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
import json
import urllib.parse
import urllib.request
API_BASE = (__import__("os").environ.get("CHANJING_OPENAPI_BASE_URL") or __import__("os").environ.get("CHANJING_API_BASE") or "https://open-api.chanjing.cc").rstrip("/")
RUNNING_STATUSES = {"Queued", "Ready", "Generating"}
SUCCESS_STATUSES = {"Success"}
FAILED_STATUSES = {"Error", "Fail"}
def api_get(token, path, query=None):
query = query or {}
suffix = ""
if query:
suffix = "?" + urllib.parse.urlencode(query, doseq=True)
req = urllib.request.Request(
f"{API_BASE}{path}{suffix}",
headers={"access_token": token},
method="GET",
)
with urllib.request.urlopen(req, timeout=30) as resp:
body = json.loads(resp.read().decode("utf-8"))
if body.get("code") != 0:
raise RuntimeError(body.get("msg", body))
return body.get("data")
def api_post(token, path, payload):
req = urllib.request.Request(
f"{API_BASE}{path}",
data=json.dumps(payload).encode("utf-8"),
headers={"access_token": token, "Content-Type": "application/json"},
method="POST",
)
with urllib.request.urlopen(req, timeout=30) as resp:
body = json.loads(resp.read().decode("utf-8"))
if body.get("code") != 0:
raise RuntimeError(body.get("msg", body))
return body.get("data")
def get_task(token, unique_id):
return api_get(token, "/open/v1/ai_creation/task", {"unique_id": unique_id})
def list_tasks(token, creation_type, page=1, page_size=50, unique_ids=None, is_success=None):
payload = {
"unique_ids": unique_ids or [],
"type": creation_type,
"page": page,
"page_size": page_size,
}
if is_success is not None:
payload["is_success"] = bool(is_success)
return api_post(token, "/open/v1/ai_creation/task/page", payload)
def first_output_url(data):
urls = (data or {}).get("output_url") or []
if isinstance(urls, list) and urls:
return urls[0]
return None
#!/usr/bin/env python3
"""
下载 AI 创作生成结果到本地。
用法:
download_result --url https://example.com/output.png
download_result --url https://example.com/output.mp4 --output outputs/ai-creation/demo.mp4
输出: 本地文件路径
"""
from __future__ import annotations
import argparse
import os
import sys
import urllib.parse
import urllib.request
from pathlib import Path
def infer_filename(url: str) -> str:
parsed = urllib.parse.urlparse(url)
name = Path(parsed.path).name or "ai-creation.bin"
if "." not in name:
name += ".bin"
return name
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="下载蝉镜 AI 创作生成结果到本地目录")
parser.add_argument("--url", required=True, help="图片或视频输出地址")
parser.add_argument(
"--output",
help="输出文件路径;默认保存到 outputs/ai-creation/<文件名>",
)
return parser.parse_args()
def main() -> None:
args = parse_args()
default_dir = Path("outputs") / "ai-creation"
output_path = Path(args.output) if args.output else default_dir / infer_filename(args.url)
output_path.parent.mkdir(parents=True, exist_ok=True)
req = urllib.request.Request(
args.url,
headers={"User-Agent": "chanjing-ai-creation-downloader"},
method="GET",
)
try:
with urllib.request.urlopen(req, timeout=120) as resp, open(output_path, "wb") as handle:
handle.write(resp.read())
except Exception as exc:
print(f"下载失败: {exc}", file=sys.stderr)
raise SystemExit(1)
if not output_path.exists() or output_path.stat().st_size == 0:
print("下载失败: 输出文件为空", file=sys.stderr)
raise SystemExit(1)
print(os.fspath(output_path))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
获取 AI 创作任务详情。
用法: get_task.py --unique-id <id> [--field progress_desc] [--first-output]
默认输出完整 JSON。
"""
import argparse
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
from _auth import get_token
from _task_api import first_output_url, get_task
def main():
parser = argparse.ArgumentParser(description="获取 AI 创作任务详情")
parser.add_argument("--unique-id", required=True, help="创作任务 unique_id")
parser.add_argument("--field", help="只输出某个字段")
parser.add_argument("--first-output", action="store_true", help="只输出第一个 output_url")
args = parser.parse_args()
token, err = get_token()
if err:
print(err, file=sys.stderr)
sys.exit(1)
try:
data = get_task(token, args.unique_id)
except Exception as exc:
print(str(exc), file=sys.stderr)
sys.exit(1)
if args.first_output:
value = first_output_url(data)
if not value:
print("当前无 output_url", file=sys.stderr)
sys.exit(1)
print(value)
return
if args.field:
value = data.get(args.field)
if value is None:
print(f"字段不存在: {args.field}", file=sys.stderr)
sys.exit(1)
if isinstance(value, (dict, list)):
print(json.dumps(value, ensure_ascii=False))
else:
print(value)
return
print(json.dumps(data, ensure_ascii=False))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
列出 AI 创作任务列表。
用法: list_tasks.py --type 3 [--page 1] [--page-size 50] [--success-only] [--unique-id <id>] [--json]
"""
import argparse
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
from _auth import get_token
from _task_api import first_output_url, list_tasks
def main():
parser = argparse.ArgumentParser(description="列出 AI 创作任务列表")
parser.add_argument("--type", type=int, required=True, choices=[3, 4], help="3=图片,4=视频")
parser.add_argument("--page", type=int, default=1, help="页码,默认 1")
parser.add_argument("--page-size", type=int, default=50, help="每页数量,最大 50")
parser.add_argument("--success-only", action="store_true", help="仅查询成功任务")
parser.add_argument("--unique-id", action="append", help="按 unique_id 过滤,可重复传参")
parser.add_argument("--json", action="store_true", help="输出完整 JSON")
args = parser.parse_args()
token, err = get_token()
if err:
print(err, file=sys.stderr)
sys.exit(1)
try:
data = list_tasks(
token,
creation_type=args.type,
page=args.page,
page_size=args.page_size,
unique_ids=args.unique_id,
is_success=True if args.success_only else None,
)
except Exception as exc:
print(str(exc), file=sys.stderr)
sys.exit(1)
if args.json:
print(json.dumps(data, ensure_ascii=False))
return
for item in data.get("list", []):
row = [
item.get("unique_id", ""),
str(item.get("type", "")),
item.get("model_code", ""),
item.get("progress_desc", ""),
first_output_url(item) or "",
]
print("\t".join(row))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
轮询 AI 创作任务直到完成。
默认输出第一个结果地址;可用 --json 输出完整详情。
"""
import argparse
import json
import sys
import time
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
from _auth import get_token
from _task_api import FAILED_STATUSES, RUNNING_STATUSES, SUCCESS_STATUSES, first_output_url, get_task
def main():
parser = argparse.ArgumentParser(description="轮询 AI 创作任务直到完成")
parser.add_argument("--unique-id", required=True, help="创作任务 unique_id")
parser.add_argument("--interval", type=int, default=10, help="轮询间隔秒数,默认 10")
parser.add_argument("--timeout", type=int, default=1800, help="轮询超时秒数,默认 1800")
parser.add_argument("--json", action="store_true", help="成功时输出完整 JSON")
parser.add_argument("--all-urls", action="store_true", help="成功时输出全部 output_url JSON 数组")
args = parser.parse_args()
token, err = get_token()
if err:
print(err, file=sys.stderr)
sys.exit(1)
deadline = time.monotonic() + args.timeout
while time.monotonic() < deadline:
try:
data = get_task(token, args.unique_id)
except Exception as exc:
print(str(exc), file=sys.stderr)
sys.exit(1)
status = data.get("progress_desc")
if status in SUCCESS_STATUSES:
if args.json:
print(json.dumps(data, ensure_ascii=False))
return
urls = data.get("output_url") or []
if args.all_urls:
print(json.dumps(urls, ensure_ascii=False))
return
first_url = first_output_url(data)
if not first_url:
print("任务成功但无 output_url", file=sys.stderr)
sys.exit(1)
print(first_url)
return
if status in FAILED_STATUSES:
print(f"任务失败: {data.get('err_msg') or status}", file=sys.stderr)
sys.exit(1)
if status not in RUNNING_STATUSES:
print(f"未知任务状态: {status}", file=sys.stderr)
sys.exit(1)
time.sleep(args.interval)
print("轮询超时", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
提交 AI 创作任务。
推荐两种方式:
1. 通用参数模式:
submit_task --creation-type 3 --model-code doubao-seedream-3.0-t2i --prompt "..." --number-of-images 1
2. 原始 JSON 模式:
submit_task --body-file ./payload.json
submit_task --body-json '{"creation_type":3,...}'
"""
import argparse
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
from _auth import get_token
from _task_api import api_post
def load_body(args):
if args.body_file and args.body_json:
raise ValueError("--body-file 和 --body-json 只能二选一")
if args.body_file:
with open(args.body_file, "r", encoding="utf-8") as f:
return json.load(f)
if args.body_json:
return json.loads(args.body_json)
if not args.creation_type or not args.model_code:
raise ValueError("通用参数模式下必须提供 --creation-type 和 --model-code")
body = {
"creation_type": args.creation_type,
"model_code": args.model_code,
}
if args.prompt:
body["ref_prompt"] = args.prompt
if args.aspect_ratio:
body["aspect_ratio"] = args.aspect_ratio
if args.clarity is not None:
body["clarity"] = args.clarity
if args.quality_mode:
body["quality_mode"] = args.quality_mode
if args.number_of_images is not None:
body["number_of_images"] = args.number_of_images
if args.video_duration is not None:
body["video_duration"] = args.video_duration
if args.style:
body["style"] = args.style
if args.callback:
body["callback"] = args.callback
if args.ref_img_url:
body["ref_img_url"] = args.ref_img_url
return body
def main():
parser = argparse.ArgumentParser(description="提交蝉镜 AI 创作任务")
parser.add_argument("--body-file", help="完整请求体 JSON 文件路径")
parser.add_argument("--body-json", help="完整请求体 JSON 字符串")
parser.add_argument("--creation-type", type=int, choices=[3, 4], help="3=图片生成,4=视频生成")
parser.add_argument("--model-code", help="模型编码")
parser.add_argument("--prompt", help="提示词,对应 ref_prompt")
parser.add_argument("--ref-img-url", action="append", help="参考图 URL,可重复传参")
parser.add_argument("--aspect-ratio", help="比例,如 1:1 / 3:4 / 4:3 / 9:16 / 16:9")
parser.add_argument("--clarity", type=int, help="清晰度,如 1024/2048/4096 或 720/1080")
parser.add_argument("--quality-mode", help="质量模式,如 std / pro")
parser.add_argument("--number-of-images", type=int, help="图片生成数量,1-4")
parser.add_argument("--video-duration", type=int, help="视频时长(秒)")
parser.add_argument("--style", help="部分视频模型支持的视频风格")
parser.add_argument("--callback", help="任务完成回调 URL")
args = parser.parse_args()
try:
body = load_body(args)
except Exception as exc:
print(str(exc), file=sys.stderr)
sys.exit(1)
token, err = get_token()
if err:
print(err, file=sys.stderr)
sys.exit(1)
try:
unique_id = api_post(token, "/open/v1/ai_creation/task/submit", body)
except Exception as exc:
print(str(exc), file=sys.stderr)
sys.exit(1)
if not unique_id:
print("响应无任务 unique_id", file=sys.stderr)
sys.exit(1)
print(unique_id)
if __name__ == "__main__":
main()