
Qiaomu Image Generator
- 12 installs
- 3 repo stars
- Updated May 24, 2026
- joeseesun/qiaomu-image-generator
Helps with ai & agent building tasks.
About
qiaomu-image-generator is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- qiaomu-image-generator
- AI & Agent Building
- AI-coding skill
Qiaomu Image Generator by the numbers
- 12 all-time installs (skills.sh)
- Ranked #11,618 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/joeseesun/qiaomu-image-generator --skill qiaomu-image-generatorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 12 |
|---|---|
| repo stars | ★ 3 |
| Last updated | May 24, 2026 |
| Repository | joeseesun/qiaomu-image-generator ↗ |
What it does
Helps with ai & agent building tasks.
Files
统一配图生成器
为文章、论文、小红书、公众号封面、X 封面等多场景生成配图。
核心设计
用户请求
↓
Claude(智能层)
├── 理解意图,选择场景模板
├── 处理覆盖指令(风格、比例等)
└── 生成 visual_config.json
↓
执行脚本(执行层)
├── 加载风格模板
├── 多线程调用 API
└── 保存图片并插入文章
↓
输出结果原则:Claude 做决策,脚本做执行。JSON 是唯一契约。
---
场景模板
| 场景 | 模板名 | 默认风格 | 比例 | 像素 |
|---|---|---|---|---|
| 文章配图 | article | minimalist | 16:9 | 1920×1080 |
| 公众号封面 | wechat_cover | paper-watercolor-cover | 2.35:1 | 900×383 |
| 小红书 | xiaohongshu | colorful_sketch | 3:4 | 1242×1660 |
| X 封面 | x_cover | paper-watercolor-cover | 5:2 | 1500×600 |
| 论文配图 | paper | newyorker | 16:9 | 1920×1080 |
| 海报设计 | poster | mondo-screenprint | 9:16 | 720×1280 |
| 书籍封面 | book_cover | literary-mondo-cover | 2:3 | 1024×1536 |
| 专辑封面 | album_cover | album-mondo-cover | 1:1 | 1024×1024 |
---
风格选择指南
共 66 种风格,每种风格都有 use_cases 字段标注适用场景。
按场景推荐
| 场景 | 推荐风格 |
|---|---|
| 知识科普 | minimalist, vintage-scientific, line-art, chalkboard |
| 技术解析 | vintage-scientific, isometric, low-poly, geometric-abstract |
| 产品设计 | flat-illustration, flat-simple, minimal-icon, soft-geometric |
| 文艺创作 | watercolor, ink-painting, morandi, soft-watercolor |
| 轻松趣味 | cartoon, children-book, paper-cut, newyorker |
| 传统文化 | ink-painting, woodcut, retro-poster, screen-print |
| 海报/封面 | mondo-screenprint, negative-space-poster, literary-mondo-cover, album-mondo-cover |
常用风格速查
| 风格ID | 中文名 | 特点 | 适用场景 |
|---|---|---|---|
minimalist | 极简线条 | 单色/双色,减法美学 | 知识分享、思考类文章 |
newyorker | 纽约客 | 黑白钢笔+朱红点缀 | 观点评论、文化分析 |
pen-sketch | 钢笔速写 | 手绘松弛质感 | 叙事文章、旅行笔记 |
flat-illustration | 平面插画 | 纯色填充,无阴影 | 产品推介、科技新闻 |
vintage-scientific | 复古科学插图 | 老式教科书质感 | 科学原理、技术解析 |
morandi | 莫兰迪色系 | 极低饱和度灰调 | 文艺评论、设计分享 |
children-book | 儿童绘本 | 温暖柔和色彩 | 儿童科普、亲子教育 |
isometric | 等距视图 | 30度角斜视,立体感 | 技术架构、产品设计 |
mondo-screenprint | Mondo 丝网海报 | 有限色板、半调网点、符号化 | 海报、封面、活动图 |
negative-space-poster | 负空间概念海报 | 单一焦点、图底反转、隐藏意象 | 高级封面、电影感海报 |
literary-mondo-cover | 文学书封 | 克制、象征、强缩略图辨识度 | 书籍封面、读书笔记 |
album-mondo-cover | 专辑封面 | 1:1、音乐情绪、强视觉记忆点 | 音乐封面、歌单封面 |
完整风格列表:见 config/styles.json,每种风格包含:
name: 中文名description: 简短描述prompt: 风格前缀suffix: 风格后缀use_cases: 适用场景数组(供 AI 参考选择)
---
封面生成(标准化流程)
所有内容创作都应生成封面图,工作流程:
读取文章
↓
提炼核心关键词(1-3个关键词概括主题)
↓
提炼一个可视化符号(物件/轮廓/空间关系/隐喻)
↓
选择封面风格(默认 paper-watercolor-cover)
↓
生成 visual_config.json(cover 节点)
↓
调用生图脚本
↓
插入文章开头(作为 cover image)封面配置格式
{
"cover": {
"enabled": true,
"filename": "cover.png",
"style": "paper-watercolor-cover",
"aspect_ratio": "16:9",
"description": "关键词1 关键词2 关键词3",
"retry_count": 2
}
}关键词提炼原则
- 从文章主题中提取 1-3 个核心概念
- 避免过长,控制在 20 字以内
- 示例:
Qwen3-TTS 语音合成 3秒克隆
Mondo 式视觉提炼法
从 qiaomu-mondo-poster-design 整合来的封面/海报判断流程:
1. 不要复述内容,先找符号:把文章、歌词、书籍或活动压缩成一个最有记忆点的视觉符号,例如裂纹、门、眼睛、船、椅子、城市剪影、一本发光的书。 2. 优先单一焦点:封面通常只放一个主视觉,最多加入一个次级隐喻。宁可留白,也不要把所有概念都塞进去。 3. 用构图讲故事:从居中对称、负空间、几何框景、前中后景分层、剪影主导、尺度反差中选 1-2 个,不要全用。 4. 有限色板:海报/封面默认 2-5 色,明确冷暖或主辅色关系。避免泛泛写“色彩丰富”。 5. 符号优于脸:当主题涉及人物、歌手、作者或角色时,优先用剪影、背影、局部轮廓、物件和空间隐喻,避免让模型生成不稳定的人脸。 6. 文字默认禁止:除非用户明确要封面文字,否则 description 和负面词都应强调 no text/no letters/no logos。中文/英文标题后期排版更可靠。
常用构图词可写进 description:
中心单一焦点,周围大面积留白负空间形成隐藏图像,图底反转几何圆形/拱门/三角形框景前景剪影、中景主体、远景光源三层空间渺小人物面对巨大物体的尺度反差单一象征物承载全部叙事
封面风格推荐
| 场景 | 推荐风格 |
|---|---|
| 公众号/X 封面 | paper-watercolor-cover(默认) |
| 论文解读封面 | paper-watercolor-cover |
| 技术文章封面 | vintage-scientific |
| 轻松话题封面 | newyorker |
---
工作流程
Step 1: 分析文章/需求
读取文章,识别:
- 场景类型(文章配图/封面/小红书等)
- H2 章节数量
- 用户的覆盖指令(如"用水彩风格")
- 是否属于海报/书封/专辑封面/音乐封面;如果是,必须先提炼视觉符号、构图模式和有限色板
Step 2: 创建输出目录
# 文章配图
mkdir -p "{文章目录}/{文章名}.assets"
# 封面类
mkdir -p "{输出目录}"Step 3: 生成 visual_config.json
配置格式:
{
"task_id": "article_20260120_143052",
"template": "article",
"source": "/path/to/article.md",
"output_dir": "/path/to/article.assets/",
"cover": {
"enabled": false,
"style": "colorful_sketch",
"aspect_ratio": "2.35:1",
"description": "视觉描述...",
"retry_count": 2
},
"illustrations": [
{
"index": 1,
"h2_title": "章节标题",
"style": "minimalist",
"aspect_ratio": "16:9",
"description": "视觉描述..."
}
],
"defaults": {
"style": "minimalist",
"aspect_ratio": "16:9",
"provider": "jimeng",
"retry_count": 2
}
}Step 4: 调用生成脚本
python ~/.claude/skills/qiaomu-image-generator/scripts/generate.py \
/path/to/visual_config.json \
--workers 3参数说明:
--workers 3: 并发线程数(默认 3)--dry-run: 只打印不执行--no-insert: 不自动插入到 Markdown--output result.json: 输出结果到文件
---
风格模板编写规范
核心原则:风格模板只定义如何渲染,不定义渲染什么。
设计哲学
用户输入 = 主体内容(description)
风格模板 = 渲染方式(prompt + suffix)
最终提示词 = prompt + description + suffix职责分离:
- description(主体词):描述具体内容(人物、场景、物体、动作)
- prompt/suffix(风格词):定义风格特征(材质、色彩、笔触、构图)
✅ 风格模板应该包含
1. 材质质感
- 磨砂玻璃、纸张、胶片颗粒、水彩晕染
- 丝网印刷、木刻纹理、半调网点
2. 色彩处理
- 红橙渐变、莫兰迪灰调、高饱和度纯色
- 冷暖对比、单色调、有限色板
3. 笔触技法
- 精致线条、交叉线纹理、素描笔触
- 色块拼接、剪影轮廓、模糊颗粒
4. 构图方式
- 极简留白、拼贴层次、对称/非对称
- 中心/边缘、动态/静态、前景/背景关系
5. 光影处理
- 边缘光、通透光、柔和光影
- 高对比、渐变过渡、明暗表现方式
6. 艺术风格
- Moebius、Matisse、波普艺术、野兽派
- 工笔重彩、丝网印刷、数字艺术
❌ 风格模板不应包含
1. 具体人物
- ❌ "重金属摇滚电吉他手"
- ❌ "飘逸长发、戴墨镜"
- ❌ "人物轮廓"
2. 具体场景
- ❌ "上海外滩场景"
- ❌ "山水意境"
- ❌ "热带森林"
3. 具体物体
- ❌ "植物花朵"、"每片叶子"
- ❌ "家具、小物件"
- ❌ "街景路牌和建筑碎片"
4. 具体元素
- ❌ "英文字母和单词"
- ❌ "蘑菇"、"松树"
示例对比
❌ 错误示例(混入具体内容)
{
"prompt": "工笔重彩绘画风格,植物花朵的纹理细腻,热带植物和蘑菇森林...",
"suffix": "每片叶子每朵花都有独特纹理,奇幻森林秘境..."
}问题:指定了"植物"、"蘑菇"、"森林"等具体内容,限制了风格的通用性。
✅ 正确示例(只有风格特征)
{
"prompt": "工笔重彩绘画风格,每一根线条都极其精致入微,纹理细腻到极致...",
"suffix": "极繁主义的细节密度,每个元素都有独特纹理,奇幻秘境的浪漫感..."
}优点:只定义渲染方式,可以应用到任何主体(人物、建筑、动物、抽象概念)。
测试方法
创建风格后,用不同的 description 测试:
同一个风格 + 不同主体 = 都应该合理
例如 "minimalist-dreamy-blur" 风格:
- description: "一只猫" → 应该生成朦胧模糊的猫
- description: "城市建筑" → 应该生成朦胧模糊的建筑
- description: "抽象情绪" → 应该生成朦胧模糊的抽象形态如果某个 description 搭配风格后感觉奇怪,说明风格模板可能混入了具体内容。
常见错误
1. 从用户描述中提取具体元素加入风格
- 用户说:"电吉他手" → 不要把"电吉他"写进风格
- 只提取风格特征:"半调网点"、"剪影"、"高对比"
2. 用场景来定义风格
- ❌ "上海外滩场景的磨砂玻璃风"
- ✅ "磨砂玻璃材质 + 红橙渐变 + 极简构图"
3. 混淆风格与内容
- 风格:"工笔重彩、精致线条"(可以画任何东西)
- 内容:"植物、蘑菇、森林"(具体画什么)
---
visual_description 写作规范
🎬 像导演拍默片一样思考:
- 演员不能说话、没有字幕
- 用纯视觉语言传递信息
🌏 必须使用中文:
- 即梦 API 对中文理解更准确
❌ 绝对禁止: 1. 风格指令:极简、水墨、油画、素描(风格由 style 字段控制) 2. 产品名/公司名:OpenAI、Claude、DeepSeek 3. 版本号/型号:2.0、3.5、V3 4. 数字参数:78%、152层、200美元 5. 日期时间:2025年、12月 6. 文字/符号:不要有任何文字
✅ 应该用: 1. 空间关系:中心 vs 边缘、顶部 vs 底部 2. 大小对比:高塔 vs 低建筑、巨大 vs 渺小 3. 动态趋势:向上攀登、向外扩散 4. 视觉隐喻:塔楼(地位)、攀登(追赶) 5. 负空间:空白处形成另一层图像或暗示未出现的主体 6. 有限色板:用 2-5 个明确色彩建立海报识别度
示例:
| ❌ 错误 | ✅ 正确 |
|---|---|
| "OpenAI 的 logo 在中心" | "中心矗立一座最高的塔楼,四周快速升起多座新塔" |
| "极简线条风格的猫" | "一只橘色短毛猫坐在窗台上,阳光洒落" |
---
覆盖指令识别
Claude 应识别用户的自然语言指令并写入 JSON:
| 用户说 | 覆盖字段 |
|---|---|
| "用水彩风格" | style: "watercolor" |
| "竖版" / "3:4" | aspect_ratio: "3:4" |
| "用 Z-Image" / "用通义生图" | provider: "z-image" |
| "用即梦" | provider: "jimeng" |
| "封面要活泼一点" | cover.style: "colorful_sketch" |
| "Mondo/海报感/电影海报" | style: "mondo-screenprint" |
| "高级一点/极简概念/留白" | style: "negative-space-poster" |
| "书籍封面/读书封面" | template: "book_cover" |
| "专辑封面/音乐封面/歌单封面" | template: "album_cover" |
可用 Provider:
| Provider | 说明 |
|---|---|
jimeng | 即梦 4.5(默认),高质量生图 |
z-image | 阿里通义 Z-Image-Turbo,支持 LoRA |
---
完整示例
示例 1: 文章配图
用户:「为这篇文章配图 /path/to/article.md」
Step 1: 读取文章,发现 5 个 H2 章节
Step 2: 创建目录
mkdir -p /path/to/article.assetsStep 3: 生成配置
{
"task_id": "article_20260120_150000",
"template": "article",
"source": "/path/to/article.md",
"output_dir": "/path/to/article.assets/",
"illustrations": [
{
"index": 1,
"h2_title": "用Claude写战略文档",
"description": "一个人坐在书桌前,与一面大镜子对话,镜子里是不断演变的文档轮廓"
},
{
"index": 2,
"h2_title": "用Google AI Studio做原型",
"description": "左边陶工快速塑形已完成,右边雕刻家还在缓慢雕琢"
}
],
"defaults": {
"style": "minimalist",
"aspect_ratio": "16:9",
"retry_count": 2
}
}Step 4: 执行
python ~/.claude/skills/qiaomu-image-generator/scripts/generate.py \
/path/to/article.assets/visual_config.json示例 2: 小红书配图(覆盖风格)
用户:「为这篇文章生成小红书配图,用彩色简笔画风格」
配置:
{
"template": "xiaohongshu",
"defaults": {
"style": "colorful_sketch",
"aspect_ratio": "3:4"
}
}示例 3: 公众号封面
用户:「生成公众号封面」
配置:
{
"template": "wechat_cover",
"cover": {
"enabled": true,
"style": "colorful_sketch",
"aspect_ratio": "2.35:1",
"description": "一只猫站在书架顶端,俯瞰书房"
}
}---
完成后必须输出
每次配图任务完成后,必须输出以下信息:
✅ 配图完成!
📄 文章:/完整/路径/文章名.md
📁 资源:/完整/路径/文章名.assets/
🖼️ 配图:X 张
⏱️ 耗时:约 X 秒
生成的图片:
1. 01-章节名-极简.png
2. 02-章节名-极简.png
...关键:必须输出完整绝对路径。
---
配置文件位置
~/.claude/skills/qiaomu-image-generator/
├── SKILL.md # 本文档
├── config/
│ ├── styles.json # 风格模板(可编辑)
│ ├── templates.json # 场景模板(可编辑)
│ └── providers.json # API 配置
└── scripts/
└── generate.py # 执行脚本自定义风格:编辑 config/styles.json 添加新风格 自定义场景:编辑 config/templates.json 添加新场景
---
故障排查
问题 1: 风格不对
原因:visual_description 中包含了风格词
解决:检查 description 是否有"极简"、"水墨"等词,删除
问题 2: 生成失败
原因:API 超时或配额用尽
解决:
- 检查
~/.claude/skills/shared-lib/config.json中的凭据 - 尝试减少
--workers数量 - 使用
--dry-run检查配置
问题 3: 图片没插入文章
原因:h2_title 与文章中的 H2 不匹配
解决:确保 h2_title 完全匹配文章中的 H2 标题文本
{
"default": "jimeng",
"providers": {
"jimeng": {
"name": "即梦",
"model": "jimeng-2.1",
"enabled": true,
"description": "即梦 4.5,高质量生图"
},
"z-image": {
"name": "通义 Z-Image",
"model": "Tongyi-MAI/Z-Image-Turbo",
"enabled": true,
"description": "阿里通义 Z-Image-Turbo,支持 LoRA"
},
"gemini": {
"name": "Gemini",
"model": "gemini-2.0-flash-exp-image-generation",
"enabled": false,
"description": "Google Gemini,当前不可用"
}
}
}
{
"minimalist": {
"name": "极简线条",
"description": "现代极简,单色或双色,减法美学",
"prompt": "优雅简约,单色或双色线条,精准流畅的笔触,纯白背景,极度克制的细节,现代高级感。",
"suffix": "超宽横向构图,画面宽度是高度的约两倍,电影级宽屏比例,连续流畅的细线条,一笔成形的优雅感,大量留白和呼吸感,减法美学,只保留最必要的线条,精准而克制,留白即是画面的一部分。画面中不要任何文字、数字、标注、符号",
"use_cases": [
"知识分享",
"思考类文章",
"教程文档",
"产品介绍"
]
},
"newyorker": {
"name": "纽约客",
"description": "经典黑白钢笔速写,朱红色点缀",
"prompt": "Black ink drawing on white paper, fine pen strokes, minimalist, sophisticated, single scene, clean background, vermilion red accent. NO BOTTOM TEXT BAR, NO CAPTION, NO TITLE AREA.",
"suffix": "Pure ink illustration only. NO TEXT, NO WORDS, NO LETTERS anywhere. No bottom text bar. No caption area. Just the scene. VERMILION RED ACCENT ONLY.",
"use_cases": [
"观点评论",
"文化分析",
"幽默故事",
"社评杂感"
]
},
"pen-sketch": {
"name": "钢笔速写",
"description": "黑白线条为主,朱红色点缀",
"prompt": "钢笔速写,黑白线条为主,朱红色点缀重点,简约留白。",
"suffix": "宽幅横向构图,画面铺满整个画布,手绘松弛质感。画面中不要任何文字、数字、标注、符号。NO BLACK BARS, NO LETTERBOX, NO BORDER.",
"use_cases": [
"叙事文章",
"旅行笔记",
"人物采访",
"生活随笔"
]
},
"minimalist-lines": {
"name": "极简线条画",
"description": "大量留白,减法美学",
"prompt": "极简线条风格,大量留白,减法美学,黑色细线勾勒轮廓。",
"suffix": "简洁构图,元素精简到最少,负空间占主导,几何化处理。画面不要文字、装饰、多余细节。",
"use_cases": [
"极简风格文章",
"创意概念",
"建筑设计",
"品牌视觉"
]
},
"morandi": {
"name": "莫兰迪色系",
"description": "极低饱和度,灰调柔和",
"prompt": "莫兰迪色系,极低饱和度,灰调柔和,淡雅克制的配色。",
"suffix": "平衡构图,色块简洁,雾蒙蒙的质感,静谧氛围。避免高饱和度色彩、强烈对比、鲜艳元素。",
"use_cases": [
"文艺评论",
"设计分享",
"美学讨论",
"人文科普"
]
},
"negative-space": {
"name": "负空间设计",
"description": "巧用留白形成隐藏图案",
"prompt": "负空间设计,巧用留白形成隐藏图案,双重视觉效果。",
"suffix": "聪明的正负形关系,空白区域与实体图形互为图底,简洁有力的视觉冲击。不要填满画面、不要复杂细节。",
"use_cases": [
"创意文章",
"设计思维",
"视觉拆解",
"概念诠释"
]
},
"geometric-abstract": {
"name": "几何抽象",
"description": "规则图形组合,现代主义美学",
"prompt": "几何抽象风格,规则图形组合,色块拼接,现代主义美学。",
"suffix": "理性构图,直线与曲线的平衡,色彩对比,数学般的精确。不要有机形态、自然元素、随机笔触。",
"use_cases": [
"现代艺术",
"设计理论",
"技术概念",
"抽象思维"
]
},
"watercolor": {
"name": "水彩渲染",
"description": "颜色自然晕染,透明叠加",
"prompt": "水彩渲染,颜色自然晕染,边缘模糊,透明叠加,湿画法质感。",
"suffix": "松弛构图,色彩流动感,留白呼吸空间,手工痕迹。避免锐利边缘、数字感、过度饱和。",
"use_cases": [
"感悟文章",
"艺术欣赏",
"创作过程",
"美的分享"
]
},
"ink-painting": {
"name": "水墨风格",
"description": "中国水墨,墨色浓淡变化",
"prompt": "中国水墨风格,墨色浓淡变化,写意手法,留白为画。",
"suffix": "意境构图,虚实相生,笔断意连,东方美学。不要西式透视、写实细节、鲜艳色彩。",
"use_cases": [
"中国文化",
"哲学思考",
"传统艺术",
"意境表达"
]
},
"isometric": {
"name": "等距视图",
"description": "30度角斜视,扁平色块",
"prompt": "等距视图设计,30度角斜视,扁平色块,立体感但无透视。",
"suffix": "整齐构图,建筑感,模块化元素,清晰的空间关系。不要自然透视、有机形态、真实光影。",
"use_cases": [
"技术架构",
"产品设计",
"空间关系",
"复杂系统"
]
},
"pixel-art": {
"name": "像素艺术",
"description": "8-bit复古游戏质感",
"prompt": "像素艺术风格,8-bit/16-bit复古游戏质感,有限色板,方块像素点,锯齿边缘。",
"suffix": "简洁构图,平面化处理,怀旧游戏机美学。避免渐变色彩、平滑边缘、高细节渲染。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"复古技术",
"游戏分析",
"怀旧话题",
"复古风尚"
]
},
"low-poly": {
"name": "低多边形",
"description": "三角形面片构成,现代3D风",
"prompt": "低多边形设计,三角形和四边形面片构成,低面数模型,平面着色,几何化抽象形状。",
"suffix": "简洁构图,块状几何结构,现代3D风格,清晰的光影分割。避免有机曲线、高细节纹理、真实材质。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"3D设计",
"技术美学",
"现代艺术",
"几何创意"
]
},
"paper-cut": {
"name": "剪纸风格",
"description": "多层彩色纸张叠加,手工剪裁质感",
"prompt": "剪纸艺术风格,多层彩色纸张叠加,手工剪裁质感,阴影层次分明,儿童画般的纯真感。",
"suffix": "平面构图,装饰性图案,对称或重复元素,手工制作痕迹。避免透视深度、写实光影、数字感。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"儿童内容",
"手工艺",
"传统文化",
"温馨故事"
]
},
"chalkboard": {
"name": "粉笔画",
"description": "黑板背景,粉笔质感",
"prompt": "粉笔画风格,黑板背景,粉笔质感,手写字体效果,教育课堂氛围。",
"suffix": "简洁构图,黑板纹理,粉笔颗粒感,教学图解风格。避免彩色背景、平滑线条、数字渲染。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"教学内容",
"知识讲解",
"学习笔记",
"教室氛围"
]
},
"flat-illustration": {
"name": "平面插画",
"description": "纯色填充,无渐变无阴影",
"prompt": "平面插画风格,简洁的纯色填充,无渐变无阴影,几何化造型,现代简约美学。",
"suffix": "平衡构图,色彩区块分明,负空间运用得当,视觉层次清晰。避免复杂纹理、写实光影、过度细节。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"产品推介",
"科技新闻",
"界面设计",
"现代商业"
]
},
"line-art": {
"name": "线描艺术",
"description": "精细流畅的黑色线条",
"prompt": "线描艺术风格,精细流畅的黑色线条,单色勾勒轮廓,类似钢笔素描但更简洁。",
"suffix": "简洁构图,线条为主,少量阴影暗示体积,注重轮廓表达。避免大面积填色、复杂纹理、色彩混杂。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"极简教程",
"技能分享",
"简洁讲解",
"精致表达"
]
},
"hand-drawn": {
"name": "手绘草图",
"description": "铅笔或炭笔质感,自然随性",
"prompt": "手绘草图风格,铅笔或炭笔质感,保留草稿线条和轻微涂抹痕迹,自然随性。",
"suffix": "自然构图,略带不对称,手工绘制感觉,纸张纹理背景。避免完美对称、数字感、过度修饰。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"个人笔记",
"随笔思考",
"创意过程",
"自然风格"
]
},
"cartoon": {
"name": "卡通风格",
"description": "夸张表情,明亮饱和色彩",
"prompt": "卡通插画风格,夸张的表情和动作,明亮饱和的色彩,简洁的造型,生动有趣。",
"suffix": "动态构图,角色表达清晰,色彩对比鲜明,轻松愉快氛围。避免写实比例、灰暗色调、复杂背景。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"幽默段子",
"趣味科普",
"儿童教育",
"轻松话题"
]
},
"minimal-icon": {
"name": "简约图标",
"description": "极简几何形状,符号化表达",
"prompt": "简约图标风格,极简几何形状,单色或双色设计,高度抽象化,符号化表达。",
"suffix": "中心构图,元素精简到极致,负空间巧妙利用,清晰易识别。避免复杂细节、渐变色彩、写实表现。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"品牌设计",
"图标文化",
"符号美学",
"简约表达"
]
},
"collage": {
"name": "拼贴画",
"description": "纸质素材剪切拼接,层次叠加",
"prompt": "拼贴艺术风格,纸质或数字素材剪切拼接,层次叠加,不同纹理和图案组合。",
"suffix": "自由构图,元素看似随意但有意安排,手工制作质感,创意混搭。避免完美对齐、统一风格、数字平滑感。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"创意混搭",
"艺术拼贴",
"多元观点",
"视觉碰撞"
]
},
"screen-print": {
"name": "丝网印刷",
"description": "有限色板,轻微错版质感",
"prompt": "丝网印刷效果,有限色板(通常2-3色),色彩重叠产生新色调,轻微错版质感。",
"suffix": "平面构图,色块分明,手工印刷痕迹,复古设计感。避免渐变色彩、照片质感、过多颜色。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"复古风格",
"平面设计",
"艺术作品",
"印刷美学"
]
},
"woodcut": {
"name": "木刻版画",
"description": "黑白强烈对比,木纹质感",
"prompt": "木刻版画风格,黑白强烈对比,木纹质感,雕刻线条粗犷有力,传统印刷美感。",
"suffix": "高对比构图,黑白分明,纹理表现木材特性,手工雕刻痕迹。避免灰色调、平滑渐变、数字精度。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"传统艺术",
"文化遗产",
"高对比表达",
"经典审美"
]
},
"pointillism": {
"name": "点彩派",
"description": "无数小色点构成图像",
"prompt": "点彩派绘画风格,无数小色点构成图像,色彩光学混合,印象派光影效果。",
"suffix": "细腻构图,点状笔触均匀分布,距离观看时图像融合,柔和过渡。避免大笔触、清晰轮廓、平板色块。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"艺术分析",
"细节美学",
"光影表达",
"印象派风格"
]
},
"abstract-expressionist": {
"name": "抽象表现主义",
"description": "色彩泼洒、滴流、挥洒",
"prompt": "抽象表现主义风格,色彩泼洒、滴流、挥洒,情感强烈表达,非具象形式。",
"suffix": "动态构图,笔触自由奔放,色彩碰撞,情感张力。避免写实形象、规则图案、冷静克制。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"艺术创作",
"情感表达",
"抽象思维",
"激情话题"
]
},
"surrealist": {
"name": "超现实主义",
"description": "梦幻不合逻辑的场景",
"prompt": "超现实主义风格,梦幻不合逻辑的场景,日常元素非常规组合,潜意识意象。",
"suffix": "奇异构图,元素比例反常,空间关系扭曲,神秘氛围。避免现实逻辑、常规透视、平凡场景。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"梦幻创意",
"想象力",
"非理性思维",
"超现实场景"
]
},
"manga": {
"name": "日本漫画",
"description": "黑白线条,速度线效果",
"prompt": "日本漫画风格,黑白线条为主,速度线效果,夸张表情符号,动态分镜感。",
"suffix": "动态构图,焦点突出,漫画格效果,戏剧性表达。避免写实色彩、静态姿势、西方漫画风格。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"动漫文化",
"故事叙述",
"戏剧表现",
"日本风格"
]
},
"children-book": {
"name": "儿童绘本",
"description": "温暖柔和色彩,可爱造型",
"prompt": "儿童绘本风格,温暖柔和色彩,简单可爱造型,友好角色设计,故事书质感。",
"suffix": "亲切构图,元素圆润安全,色彩和谐,充满童趣。避免锐利边缘、暗黑色调、成人主题。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"儿童科普",
"亲子教育",
"温馨故事",
"柔和叙事"
]
},
"vintage-scientific": {
"name": "复古科学插图",
"description": "老式教科书质感,剖面图效果",
"prompt": "复古科学插图风格,老式教科书质感,手写标签,剖面图效果,褪色纸张色调。",
"suffix": "教育构图,图解风格,标注线示意,知识性呈现。避免现代UI、鲜艳色彩、随意艺术感。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"科学原理",
"技术解析",
"知识讲解",
"复古学术"
]
},
"simple-outline": {
"name": "简单线描",
"description": "极简线条,2-3笔完成",
"prompt": "简单线描风格,极简线条,清晰轮廓,2-3笔完成。",
"suffix": "大量留白,线条轻盈,构图简洁。避免复杂细节、过多元素、密集线条。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"极简表达",
"清晰讲解",
"快速草稿",
"核心概念"
]
},
"soft-shape": {
"name": "柔和形状",
"description": "圆润柔和的色块,无锐角",
"prompt": "柔和形状风格,圆润柔和的色块,无锐角,温馨感。",
"suffix": "色块层次清晰,柔和过渡,构图平衡。避免尖锐边缘、强对比色、复杂形状。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"温馨内容",
"柔和叙述",
"儿童友好",
"温暖氛围"
]
},
"minimal-geo": {
"name": "极简几何",
"description": "简单几何图形组合,3-5个元素",
"prompt": "极简几何风格,简单几何图形组合,3-5个元素,网格对齐。",
"suffix": "几何排列有序,留白充足,构图严谨。避免有机形态、复杂组合、不规则图形。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"现代设计",
"几何表达",
"简洁构图",
"秩序之美"
]
},
"gentle-tint": {
"name": "柔和色调",
"description": "低饱和度单色调,宁静感",
"prompt": "柔和色调风格,低饱和度单色调,灰调为主,宁静感。",
"suffix": "色彩渐变,温和过渡,构图和谐。避免高饱和度、强对比色、鲜艳色彩。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"宁静思考",
"文艺表达",
"冥想主题",
"柔和氛围"
]
},
"clean-sketch": {
"name": "清洁草图",
"description": "轻盈的手绘线条,干净整洁",
"prompt": "清洁草图风格,轻盈的手绘线条,干净整洁,纸张质感。",
"suffix": "线条稀疏,构图简洁,留白合理。避免污渍、复杂纹理、过度涂抹。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"快速笔记",
"初期想法",
"草稿阶段",
"清晰表达"
]
},
"flat-simple": {
"name": "扁平简约",
"description": "纯色扁平化设计,无渐变无阴影",
"prompt": "扁平简约风格,纯色扁平化设计,无渐变无阴影。",
"suffix": "色块明确,边界清晰,构图几何。避免立体感、阴影效果、渐变色彩。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"商业展示",
"产品介绍",
"现代应用",
"简洁美学"
]
},
"airy-illustration": {
"name": "空灵插画",
"description": "轻盈留白,梦幻感,半透明",
"prompt": "空灵插画风格,轻盈留白,梦幻感,半透明效果。",
"suffix": "大量负空间,元素悬浮,构图空灵。避免拥挤、厚重感、强烈色彩。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"梦幻表达",
"诗意文章",
"空灵氛围",
"想象力"
]
},
"soft-watercolor": {
"name": "柔和水彩",
"description": "水彩质感但简化,朦胧感",
"prompt": "柔和水彩风格,水彩质感但简化,色彩轻薄,朦胧感。",
"suffix": "色彩流动,留白呼吸,构图柔和。避免厚重色彩、锐利边缘、过度饱和。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"柔和叙事",
"感悟分享",
"艺术欣赏",
"朦胧美感"
]
},
"delicate-line": {
"name": "精致线条",
"description": "精细但不复杂的线条画",
"prompt": "精致线条风格,精细但不复杂的线条画,点线面结合。",
"suffix": "线条疏密有致,构图平衡,留白得当。避免密集线条、复杂图案、过度装饰。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"精致表达",
"细节讨论",
"优雅风格",
"精工作品"
]
},
"gentle-abstract": {
"name": "温和抽象",
"description": "抽象但柔和,有机形态",
"prompt": "温和抽象风格,抽象但柔和,形状圆润,有机形态。",
"suffix": "非对称但平衡,构图温和,留白合理。避免尖锐形状、强对比、几何硬朗感。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"温和概念",
"抽象但友好",
"有机思维",
"流动创意"
]
},
"simple-pattern": {
"name": "简单图案",
"description": "重复但和谐的简单图案",
"prompt": "简单图案风格,重复但和谐的简单图案,节奏感强。",
"suffix": "图案规律,构图重复,元素统一。避免复杂图案、不规律组合、过多变化。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"规律讨论",
"重复美学",
"节奏感",
"模式分析"
]
},
"light-sketch": {
"name": "轻盈素描",
"description": "轻快的铅笔素描,明暗简洁",
"prompt": "轻盈素描风格,轻快的铅笔素描,明暗简洁。",
"suffix": "阴影最少,线条流畅,构图轻盈。避免厚重阴影、复杂明暗、粗糙质感。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"快速构思",
"轻量级表达",
"初稿风格",
"灵活思维"
]
},
"soft-collage": {
"name": "柔和拼贴",
"description": "柔和的纸片拼贴,色彩统一",
"prompt": "柔和拼贴风格,柔和的纸片拼贴,色彩统一。",
"suffix": "层次分明但不杂乱,构图和谐,留白得当。避免强对比、复杂层次、杂乱无章。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"柔和混搭",
"温馨混合",
"和谐组合",
"温暖碰撞"
]
},
"minimal-face": {
"name": "简约人像",
"description": "简化的人脸特征,符号化表达",
"prompt": "简约人像风格,简化的人脸特征,符号化表达。",
"suffix": "面部留白,表情温和,构图简洁。避免细节过多、表情夸张、复杂特征。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"人物表达",
"人像讨论",
"角色定义",
"简约风格"
]
},
"gentle-botanical": {
"name": "温和植物",
"description": "简单的植物插画,叶子花朵",
"prompt": "温和植物风格,简单的植物插画,叶子花朵,优雅姿态。",
"suffix": "植物姿态优雅,留白合理,构图自然。避免复杂枝叶、密集细节、野生感。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"自然话题",
"植物分享",
"生态讨论",
"生命美学"
]
},
"simple-iconic": {
"name": "简约符号",
"description": "图标化的简单图形,符号性强",
"prompt": "简约图标风格,图标化的简单图形,符号性强。",
"suffix": "图形居中,对称或非对称,识别度高。避免复杂细节、装饰元素、模糊边界。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"符号设计",
"图标文化",
"品牌表达",
"视觉识别"
]
},
"airy-landscape": {
"name": "空景插画",
"description": "简约的风景轮廓,山水天际线",
"prompt": "空景插画风格,简约的风景轮廓,山水天际线。",
"suffix": "地平线构图,层次简单,留白开阔。避免复杂细节、密集元素、拥挤构图。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"风景欣赏",
"地理分享",
"开阔意境",
"自然美学"
]
},
"soft-geometric": {
"name": "柔和几何",
"description": "圆角几何图形,柔和线条",
"prompt": "柔和几何风格,圆角几何图形,柔和线条。",
"suffix": "几何排列有序,留白平衡,构图温和。避免尖锐角度、硬朗线条、强烈对比。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"柔和设计",
"舒适视感",
"几何但温暖",
"优雅结构"
]
},
"delicate-doodle": {
"name": "精致涂鸦",
"description": "精致的手绘涂鸦,线条活泼",
"prompt": "精致涂鸦风格,精致的手绘涂鸦,线条活泼。",
"suffix": "元素分布自然,有机生长,构图活泼。避免规整排列、僵硬线条、过度控制。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"创意涂鸦",
"自由表达",
"有机生长",
"活泼氛围"
]
},
"gentle-story": {
"name": "温和叙事",
"description": "叙事性插画,场景简洁",
"prompt": "温和叙事风格,叙事性插画,场景简洁,人物温和。",
"suffix": "人物与场景和谐,留白叙事,构图温暖。避免戏剧冲突、强烈情绪、复杂场景。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"温馨故事",
"人文叙事",
"情感表达",
"亲切氛围"
]
},
"retro-poster": {
"name": "复古海报",
"description": "限定色板(3-4色),vintage质感",
"prompt": "复古海报风格,限定色板(3-4色),网点效果,vintage质感。",
"suffix": "对称或中心构图,强烈视觉层次,字体与图形结合,怀旧氛围。避免现代梯度、照片质感、复杂细节。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"怀旧设计",
"复古风格",
"视觉冲击",
"经典美感"
]
},
"glam-rock-psychedelic": {
"name": "华丽摇滚迷幻",
"description": "70年代华丽摇滚美学,迷幻色彩爆炸",
"prompt": "1970s glam rock psychedelic art, kaleidoscope patterns, prismatic light explosions, metallic shimmer, liquid chrome effects, starburst radiations, cosmic spirals, electric neon against deep space black, geometric fractals, glitter and sequin texture, Art Nouveau curves meeting Op Art illusions, David Bowie Ziggy Stardust era aesthetics, theatrical spotlights, mirror ball reflections.",
"suffix": "Dynamic asymmetric composition, explosive energy radiating from center, bold contrasting colors (electric purple, hot pink, acid yellow, metallic silver, deep black), layered transparency effects, motion blur and light trails, vintage screen print texture with modern intensity. NO TEXT, NO WORDS, NO LETTERS. Pure visual ecstasy.",
"use_cases": [
"摇滚音乐",
"迷幻艺术",
"70年代复古",
"华丽视觉",
"音乐视频",
"演出海报"
]
},
"paper-watercolor-cover": {
"name": "纸雕水彩封面",
"description": "纸雕风格融合水彩层次美学,专为公众号和X封面设计",
"prompt": "根据内容主题自动匹配关键词和设计风格。关键词符合纸雕风格融合水彩层次美学,字体结构立体精致如水彩纸雕工艺,边缘细腻带水彩渐变与阴影效果,柔和红色与淡蓝水彩背景中营造纸艺空间,点缀立体几何图形与水彩装饰元素,文字表面呈现高级纸张与水彩光泽质感,字形排列层次分明如精美纸雕作品,整体营造出精致工艺与艺术学习的优雅层次,温和而富有艺术感的教学氛围中透出水彩的精致美感,高级水彩工艺视觉。主题内容:\"",
"suffix": "\"",
"use_cases": [
"公众号封面",
"X封面",
"论文解读封面",
"知识分享封面"
]
},
"moebius": {
"name": "Moebius 极繁线条",
"description": "Jean Giraud大师风格,极致细腻的交叉线条,浪漫忧郁诗意",
"prompt": "每一根线条都极其细腻精致,密集的交叉线纹理覆盖所有表面,层次极其丰富的明暗渐变,每个细节都清晰可见,大师级的构图和空间关系,浪漫而深沉的诗意氛围,法式漫画美学的精致表现力。",
"suffix": "极致的细节密度,交叉线条形成细腻的纹理和体积感,光影渐变通过线条疏密实现,空间透视准确但充满梦幻感,整体氛围忧郁浪漫但不失精致优雅,大师级手工笔触。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"忧郁主题",
"诗意表达",
"极致细节",
"大师美学",
"浪漫氛围",
"音乐视频"
]
},
"photorealistic-collage": {
"name": "写实拼贴碎片",
"description": "写实摄影碎片化重组,素描笔触穿插,明艳色块点缀,报纸剪贴风",
"prompt": "写实摄影质感的主体被切割成不规则碎片重新拼贴,穿插手绘素描笔触线条,局部叠加鲜明艳丽的纯色块(红、黄、蓝),保留写实质感但打破完整性,报纸剪贴美学的碎片化构成。",
"suffix": "混合媒介拼贴构图,写实摄影碎片与手绘素描交织,明艳色块(vermilion red, electric yellow, cobalt blue)局部覆盖强调重点,不规则切割边缘,报纸印刷质感,层次丰富的拼贴叠加,既有写实细节又有抽象碎片感,街头艺术与摄影的混搭美学。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"现代拼贴",
"碎片化主题",
"街头艺术",
"混合媒介",
"朋克美学",
"音乐视频"
]
},
"fantasy-botanical-masters": {
"name": "奇幻工笔重彩大师",
"description": "Moebius+鸟山明融合,极繁细腻工笔,明亮鲜艳童话氛围",
"prompt": "工笔重彩绘画风格,每一根线条都极其精致入微,纹理细腻到极致,明亮鲜艳的色彩(亮黄、翠绿、粉红、橙色)层次丰富交织,自然野趣与奇幻童话般的浪漫氛围,大师级的构图和细节表现力,画面干净清晰但细节极其丰富,温馨可爱又充满艺术感。",
"suffix": "极繁主义的细节密度,Moebius式的精致线条工艺融合鸟山明的明快色彩和可爱造型,每个元素都有独特纹理,色彩明艳但和谐统一,奇幻秘境的浪漫感,大师级的视角和表现力,层次分明的工笔重彩技法,童话般温馨又不失艺术深度,视觉冲击力强。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"奇幻主题",
"细腻插画",
"童话氛围",
"温馨浪漫",
"极致细节",
"大师美学"
]
},
"paper-collage-lifestyle": {
"name": "纸艺拼贴生活美学",
"description": "艺术插画杂志封面风,不同材质纸张拼贴,清新蓝绿与暖棕色调",
"prompt": "纸艺拼贴插画风格,使用不同材质的彩色卡纸、印刷品、旧杂志页面拼贴组合,清新的蓝绿色调与温暖的棕色搭配,前景细节丰富,背景用简化的色块和几何形拼贴,材质肌理清晰可见,层次分明的纸张叠加,悠闲的生活美学氛围。",
"suffix": "艺术插画杂志封面级构图,不同纸张材质的拼贴感(光滑卡纸、印刷品纹理、手工剪裁边缘),清新配色(海洋蓝、薄荷绿、暖棕、奶白),前景细节精致呈现,背景简化但层次清晰,纸张边缘自然、叠加阴影分明,手工制作的温暖质感,悠闲度假般的生活美学,既精致又放松的视觉氛围。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"生活美学",
"杂志封面",
"度假氛围",
"手工艺术",
"温馨悠闲",
"纸艺拼贴"
]
},
"minimalist-dreamy-blur": {
"name": "极简朦胧梦幻",
"description": "虚实结合,模糊颗粒肌理,冷暖对比,动态模糊,高级氛围感",
"prompt": "极简插画风格,单一纯色背景,主体形态隐约朦胧,模糊的泛红颗粒肌理覆盖画面,虚实结合的梦幻感,清新淡雅的治愈配色,色彩冷暖对比强烈(冷色背景配暖色主体光晕),微光从主体散发,动态模糊效果,非传统构图角度。",
"suffix": "高级的艺术氛围感,模糊感+颗粒感+肌理感+朦胧感多重叠加,虚实结合的梦幻温暖氛围,主体轮廓隐约可见但充满诗意,动态模糊传递流动感,非对称构图,色彩层次丰富但统一(冷蓝+暖橙、薄荷+粉红等对比),泛红颗粒质感如老电影胶片,微光营造希望感,整体朦胧治愈,既清新又温暖,高级艺术插画质感。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"梦幻主题",
"治愈氛围",
"诗意表达",
"情绪化艺术",
"高级插画",
"音乐视频"
]
},
"matisse-fauvism": {
"name": "Matisse 野兽派色彩",
"description": "浓烈色块组合,红黄为主调,光影通过色彩交织表现,强烈视觉冲击",
"prompt": "Matisse野兽派风格绘画,充满活力的纯色色块组合,浓烈鲜艳的红色、黄色、绿色、蓝色大胆碰撞,形态简化但富有表现力,色彩本身传递光影和情绪,平面化处理但层次丰富,强调形状和色彩的和谐组合,艺术性装饰感。",
"suffix": "野兽派大师级色彩构图,浓烈饱和的纯色块(朱红、柠檬黄、翠绿、钴蓝)大胆并置,色彩边界清晰锐利,形态简化为几何化轮廓,光影效果通过色彩深浅和冷暖对比实现而非明暗渐变,平面装饰性强但不失空间感,强烈的视觉冲击力,色彩即是主题,注重形状与色块的平衡,Matisse式的优雅与激情并存。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"色彩主题",
"艺术表现",
"视觉冲击",
"装饰性强",
"大师风格",
"情绪激烈"
]
},
"frosted-glass-tech": {
"name": "磨砂玻璃科技风",
"description": "透明磨砂材质,红橙炫彩渐变,C4D数字艺术,极简科技美学",
"prompt": "矢量风格数字插画,透明磨砂玻璃材质(frosted glass translucent effect),红橙色炫彩渐变光影(red-orange iridescent gradient),C4D高级渲染质感,极简构图留白与层次,现代科技感造型,数字艺术(digital art)精致表现,光线通透柔和。",
"suffix": "浅色干净背景(light clean background),画面纯净简洁,极致的透明光线效果(premium lighting),磨砂玻璃质感细腻,红橙渐变流动自然,C4D级别的材质渲染,8k超高清细节,留白与层次分明,线条简洁现代,数字艺术的精准与优雅,光影柔和通透,整体氛围高级而宁静。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"科技产品",
"现代设计",
"建筑视觉",
"高端品牌",
"数字艺术",
"城市美学"
]
},
"halftone-rock-poster": {
"name": "半调网点摇滚海报",
"description": "渐变网点半调插画,剪影高对比,边缘光,放射背景",
"prompt": "半调渐变网点数字插画(halftone gradient dots digital illustration),通过渐变网点密度表现体积、明暗、高光和质感,剪影式轮廓(silhouette),边缘光勾勒(rim light edge),极简主义构图但艺术气质强烈,动态特写视角,色彩饱满浓烈。",
"suffix": "爆炸放射状渐变网点深色背景(radial burst gradient halftone dots on dark background),高对比度色彩(高饱和度纯色与深色对比),网点从细密到粗大形成渐变过渡,剪影边缘清晰锐利,边缘光勾勒出立体感,摇滚海报美学,波普艺术(Pop Art)风格,丝网印刷质感,意境强烈充满张力,动态构图爆发力十足。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"摇滚音乐",
"演出海报",
"高对比风格",
"波普艺术",
"动态视觉",
"剪影设计"
]
},
"mondo-screenprint": {
"name": "Mondo 丝网海报",
"description": "有限色板、平面色块、半调网点、复古电影海报构图",
"prompt": "Mondo alternative poster aesthetic, silkscreen print design, limited edition poster art, flat graphic color blocks, strong symbolic reinterpretation rather than literal scene, bold simplified shapes, iconic single focal point, vintage mid-century poster language.",
"suffix": "Use a limited 2-5 color palette with explicit high contrast, halftone dot texture, risograph or screen print grain, slight ink misregistration, clean geometric composition, strong negative space, poster-like visual hierarchy, no photorealism, no glossy gradients, no clutter. No text, no words, no letters, no logos, no watermarks.",
"use_cases": [
"海报设计",
"电影海报",
"活动海报",
"公众号封面",
"X封面",
"小红书封面",
"概念视觉",
"复古设计"
]
},
"negative-space-poster": {
"name": "负空间概念海报",
"description": "Olly Moss 式图底反转,单一焦点,隐藏意象与大量留白",
"prompt": "Minimal conceptual poster design, clever figure-ground inversion, negative space storytelling, one iconic symbol carries the whole idea, ultra-clean silhouette language, restrained graphic abstraction, high-concept visual metaphor.",
"suffix": "One central focal element only, vast empty space, hidden secondary image formed by blank areas, 2-3 color screen print palette, crisp silhouette edges, strong thumbnail readability, sophisticated quiet tension, no facial details unless necessary, no decorative clutter. No text, no words, no letters, no logos, no watermarks.",
"use_cases": [
"高级封面",
"概念海报",
"电影感海报",
"书籍封面",
"专辑封面",
"悬疑主题",
"极简视觉",
"留白构图"
]
},
"literary-mondo-cover": {
"name": "文学 Mondo 书封",
"description": "克制文学封面,单一象征物,纸张颗粒,强缩略图识别度",
"prompt": "Literary book cover design with Mondo screen print influence, sophisticated minimal symbolism, restrained editorial composition, one memorable object or spatial metaphor, vintage paperback cover sensibility, refined graphic restraint.",
"suffix": "Muted 2-4 color palette such as cream, charcoal, rust, sage, burgundy, or aged gold; paper grain, screen print texture, clean vertical hierarchy, strong shelf presence and thumbnail readability, conceptual rather than literal, elegant negative space. No text, no title, no author name, no letters, no logos, no watermarks.",
"use_cases": [
"书籍封面",
"读书笔记",
"文学主题",
"电子书封面",
"播客封面",
"知识封面",
"克制设计"
]
},
"album-mondo-cover": {
"name": "Mondo 专辑封面",
"description": "1:1 音乐封面,情绪符号、复古印刷、强记忆点",
"prompt": "Square album cover design with Mondo-inspired screen print aesthetics, symbolic music mood distilled into one iconic image, bold graphic silhouette or object, alternative record sleeve design, emotional visual metaphor, vintage print craft.",
"suffix": "Square 1:1 composition, strong center or geometric framing, limited 2-5 color palette, halftone texture, paper grain, subtle ink misalignment, clear visual hook at small size, cinematic but not literal, no typography unless explicitly requested. No text, no words, no letters, no logos, no watermarks.",
"use_cases": [
"专辑封面",
"音乐封面",
"歌曲封面",
"歌单封面",
"Suno封面",
"播客封面",
"音乐视觉",
"复古唱片"
]
},
"ethereal-ink-fantasy": {
"name": "空灵水墨奇幻",
"description": "蓝白水墨晕染,云雾飘渺半透明,东方奇幻意境,空气透视",
"prompt": "东方水墨意境数字绘画,蓝白色调为主(天蓝、白色、浅蓝渐变),高明度低饱和度有限色板,水墨晕染质感,云雾飘渺半透明叠加效果,流畅曲线与飘逸线条,细腻细节刻画与大块留白结合,奇幻美学氛围,数字绘画精细度。",
"suffix": "中心放射构图,上下呼应对称感,大量留白营造空灵感,柔和自然光处理,逆光轮廓效果,空气透视层次分明,水墨烟雾般的边缘柔化处理,半透明材质叠加,东方奇幻意境,数字绘画的精细度与水墨写意结合,清新空灵高级感,仙侠美学气质。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"东方奇幻",
"仙侠主题",
"水墨意境",
"空灵氛围",
"中国风",
"奇幻插画"
]
},
"impasto-impressionist": {
"name": "厚涂印象派",
"description": "厚重油画刀触感,蓝金互补色对比,粗犷笔触,浪漫印象派",
"prompt": "厚涂印象派油画风格(impasto impressionist oil painting),厚重的油画刀触感(thick impasto texture),颜料堆叠的立体质感,粗糙纹理可见笔触痕迹,粗犷有力的刀刮效果,色彩饱满浓烈但层次丰富,印象派光影处理,浪漫主义氛围。",
"suffix": "蓝色与金黄色互补色强烈对比,暖黄、白色、蓝色为主的有限色板,厚涂法笔触方向性明显,颜料堆叠立体凸起效果,碎片化飘散构图,中心聚焦周围元素飘浮,非写实空间感,超现实组合,柔和温暖光线,色彩本身传递光感而非明暗渐变,后印象派粗犷表现力,浪漫诗意氛围。画面中不要任何文字、数字、标注、符号。",
"use_cases": [
"浪漫主题",
"情感表达",
"印象派风格",
"油画质感",
"温暖氛围",
"怀旧情绪"
]
},
"black-metal": {
"name": "黑金属",
"description": "哥特暗黑美学,高对比黑白,残暴雕刻质感,冰冷月光氛围",
"prompt": "Brutal gothic aesthetic, harsh carved aggressive lines like extreme woodcut, pure black and stark white extreme high contrast, cold blue-gray mist and fog, sharp jagged edges, rough scratched textures, corpse paint makeup aesthetic influence, Norwegian black metal album art style, ominous freezing atmosphere, cold metallic surfaces. NO BOTTOM TEXT BAR.",
"suffix": "Gothic darkness rendering only. Stark harsh shadows, cold moonlight quality, freezing blue-gray tones, no soft gradients, no warm colors, no gentle smooth lines. Brutal aggressive marks, razor-sharp edges, rough carved surface texture. Pure black metal aesthetic. NO TEXT, NO WORDS, NO LETTERS anywhere.",
"use_cases": [
"黑金属音乐",
"哥特风格",
"暗黑主题",
"极端音乐",
"音乐MTV",
"摇滚海报",
"残暴美学",
"冷峻氛围"
]
}
}
{
"article": {
"name": "文章配图",
"description": "公众号/博客文章的 H2 章节配图",
"triggers": ["文章配图", "为文章配图", "article illustration"],
"defaults": {
"style": "minimalist",
"aspect_ratio": "16:9",
"width": 1920,
"height": 1080,
"provider": "jimeng-4.1",
"retry_count": 2
},
"cover": {
"enabled": false,
"style": "colorful_sketch",
"aspect_ratio": "2.35:1",
"width": 900,
"height": 383
}
},
"wechat_cover": {
"name": "公众号封面",
"description": "微信公众号文章封面图",
"triggers": ["公众号封面", "微信封面", "wechat cover"],
"defaults": {
"style": "colorful_sketch",
"aspect_ratio": "2.35:1",
"width": 900,
"height": 383,
"provider": "jimeng-4.1",
"retry_count": 2
}
},
"xiaohongshu": {
"name": "小红书配图",
"description": "小红书帖子配图,竖版",
"triggers": ["小红书", "小红书配图", "xiaohongshu"],
"defaults": {
"style": "colorful_sketch",
"aspect_ratio": "3:4",
"width": 1242,
"height": 1660,
"provider": "jimeng-4.1",
"retry_count": 2
}
},
"xiaohongshu_cover": {
"name": "小红书封面",
"description": "小红书帖子封面,正方形或竖版",
"triggers": ["小红书封面"],
"defaults": {
"style": "colorful_sketch",
"aspect_ratio": "1:1",
"width": 1080,
"height": 1080,
"provider": "jimeng-4.1",
"retry_count": 2
}
},
"x_cover": {
"name": "X文章封面",
"description": "X (Twitter) Articles 封面图",
"triggers": ["X封面", "Twitter封面", "x cover"],
"defaults": {
"style": "minimalist",
"aspect_ratio": "5:2",
"width": 1500,
"height": 600,
"provider": "jimeng-4.1",
"retry_count": 2
}
},
"paper": {
"name": "论文配图",
"description": "学术论文解读文章配图",
"triggers": ["论文配图", "paper illustration"],
"defaults": {
"style": "newyorker",
"aspect_ratio": "16:9",
"width": 1920,
"height": 1080,
"provider": "jimeng-4.1",
"retry_count": 2
},
"cover": {
"enabled": true,
"style": "newyorker",
"aspect_ratio": "16:9",
"width": 1920,
"height": 1080
}
},
"poster": {
"name": "海报设计",
"description": "电影感、活动、概念海报,强调符号化与有限色板",
"triggers": ["海报", "电影海报", "活动海报", "poster"],
"defaults": {
"style": "mondo-screenprint",
"aspect_ratio": "9:16",
"width": 720,
"height": 1280,
"provider": "jimeng",
"retry_count": 2
}
},
"book_cover": {
"name": "书籍封面",
"description": "书籍、读书笔记、电子书封面,强调缩略图可识别的单一象征",
"triggers": ["书籍封面", "图书封面", "读书封面", "book cover"],
"defaults": {
"style": "literary-mondo-cover",
"aspect_ratio": "2:3",
"width": 1024,
"height": 1536,
"provider": "jimeng",
"retry_count": 2
}
},
"album_cover": {
"name": "专辑封面",
"description": "歌曲、专辑、歌单封面,1:1 方形音乐封面",
"triggers": ["专辑封面", "音乐封面", "歌曲封面", "歌单封面", "album cover"],
"defaults": {
"style": "album-mondo-cover",
"aspect_ratio": "1:1",
"width": 1024,
"height": 1024,
"provider": "jimeng",
"retry_count": 2
}
}
}
MIT License
Copyright (c) 2026 joeseesun
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
qiaomu-image-generator
Use when user requests image generation for articles, papers, covers, or social media.
安装
npx skills add joeseesun/qiaomu-image-generator前置要求
<!-- TODO: 填写该 Skill 所需的前置条件(工具、账号、配置等) -->
- Claude Code 已安装
- (在此补充其他依赖)
使用方式
安装后,在 Claude Code 中用自然语言描述你的需求即可,例如:
<!-- TODO: 填写 2-3 个典型的自然语言触发示例 -->
"..."
"..."统一配图生成器
为文章、论文、小红书、公众号封面、X 封面等多场景生成配图。
核心设计
用户请求
↓
Claude(智能层)
├── 理解意图,选择场景模板
├── 处理覆盖指令(风格、比例等)
└── 生成 visual_config.json
↓
执行脚本(执行层)
├── 加载风格模板
├── 多线程调用 API
└── 保存图片并插入文章
↓
输出结果原则:Claude 做决策,脚本做执行。JSON 是唯一契约。
---
场景模板
| 场景 | 模板名 | 默认风格 | 比例 | 像素 |
|---|---|---|---|---|
| 文章配图 | article | minimalist | 16:9 | 1920×1080 |
| 公众号封面 | wechat_cover | paper-watercolor-cover | 2.35:1 | 900×383 |
| 小红书 | xiaohongshu | colorful_sketch | 3:4 | 1242×1660 |
| X 封面 | x_cover | paper-watercolor-cover | 5:2 | 1500×600 |
| 论文配图 | paper | newyorker | 16:9 | 1920×1080 |
---
风格选择指南
共 49 种风格,每种风格都有 use_cases 字段标注适用场景。
按场景推荐
| 场景 | 推荐风格 |
|---|---|
| 知识科普 | minimalist, vintage-scientific, line-art, chalkboard |
| 技术解析 | vintage-scientific, isometric, low-poly, geometric-abstract |
| 产品设计 | flat-illustration, flat-simple, minimal-icon, soft-geometric |
| 文艺创作 | watercolor, ink-painting, morandi, soft-watercolor |
| 轻松趣味 | cartoon, children-book, paper-cut, newyorker |
| 传统文化 | ink-painting, woodcut, retro-poster, screen-print |
常用风格速查
| 风格ID | 中文名 | 特点 | 适用场景 |
|---|---|---|---|
minimalist | 极简线条 | 单色/双色,减法美学 | 知识分享、思考类文章 |
newyorker | 纽约客 | 黑白钢笔+朱红点缀 | 观点评论、文化分析 |
pen-sketch | 钢笔速写 | 手绘松弛质感 | 叙事文章、旅行笔记 |
flat-illustration | 平面插画 | 纯色填充,无阴影 | 产品推介、科技新闻 |
vintage-scientific | 复古科学插图 | 老式教科书质感 | 科学原理、技术解析 |
morandi | 莫兰迪色系 | 极低饱和度灰调 | 文艺评论、设计分享 |
children-book | 儿童绘本 | 温暖柔和色彩 | 儿童科普、亲子教育 |
isometric | 等距视图 | 30度角斜视,立体感 | 技术架构、产品设计 |
完整风格列表:见 config/styles.json,每种风格包含:
name: 中文名description: 简短描述prompt: 风格前缀suffix: 风格后缀use_cases: 适用场景数组(供 AI 参考选择)
---
封面生成(标准化流程)
所有内容创作都应生成封面图,工作流程:
读取文章
↓
提炼核心关键词(1-3个关键词概括主题)
↓
选择封面风格(默认 paper-watercolor-cover)
↓
生成 visual_config.json(cover 节点)
↓
调用生图脚本
↓
插入文章开头(作为 cover image)封面配置格式
{
"cover": {
"enabled": true,
"filename": "cover.png",
"style": "paper-watercolor-cover",
"aspect_ratio": "16:9",
"description": "关键词1 关键词2 关键词3",
"retry_count": 2
}
}关键词提炼原则
- 从文章主题中提取 1-3 个核心概念
- 避免过长,控制在 20 字以内
- 示例:
Qwen3-TTS 语音合成 3秒克隆
封面风格推荐
| 场景 | 推荐风格 |
|---|---|
| 公众号/X 封面 | paper-watercolor-cover(默认) |
| 论文解读封面 | paper-watercolor-cover |
| 技术文章封面 | vintage-scientific |
| 轻松话题封面 | newyorker |
---
工作流程
Step 1: 分析文章/需求
读取文章,识别:
- 场景类型(文章配图/封面/小红书等)
- H2 章节数量
- 用户的覆盖指令(如"用水彩风格")
Step 2: 创建输出目录
# 文章配图
mkdir -p "{文章目录}/{文章名}.assets"
# 封面类
mkdir -p "{输出目录}"Step 3: 生成 visual_config.json
配置格式:
{
"task_id": "article_20260120_143052",
"template": "article",
"source": "/path/to/article.md",
"output_dir": "/path/to/article.assets/",
"cover": {
"enabled": false,
"style": "colorful_sketch",
"aspect_ratio": "2.35:1",
"description": "视觉描述...",
"retry_count": 2
},
"illustrations": [
{
"index": 1,
"h2_title": "章节标题",
"style": "minimalist",
"aspect_ratio": "16:9",
"description": "视觉描述..."
}
],
"defaults": {
"style": "minimalist",
"aspect_ratio": "16:9",
"provider": "jimeng",
"retry_count": 2
}
}Step 4: 调用生成脚本
python ~/.claude/skills/qiaomu-image-generator/scripts/generate.py \
/path/to/visual_config.json \
--workers 3参数说明:
--workers 3: 并发线程数(默认 3)--dry-run: 只打印不执行--no-insert: 不自动插入到 Markdown--output result.json: 输出结果到文件
---
风格模板编写规范
核心原则:风格模板只定义如何渲染,不定义渲染什么。
设计哲学
用户输入 = 主体内容(description)
风格模板 = 渲染方式(prompt + suffix)
最终提示词 = prompt + description + suffix职责分离:
- description(主体词):描述具体内容(人物、场景、物体、动作)
- prompt/suffix(风格词):定义风格特征(材质、色彩、笔触、构图)
✅ 风格模板应该包含
1. 材质质感
- 磨砂玻璃、纸张、胶片颗粒、水彩晕染
- 丝网印刷、木刻纹理、半调网点
2. 色彩处理
- 红橙渐变、莫兰迪灰调、高饱和度纯色
- 冷暖对比、单色调、有限色板
3. 笔触技法
- 精致线条、交叉线纹理、素描笔触
- 色块拼接、剪影轮廓、模糊颗粒
4. 构图方式
- 极简留白、拼贴层次、对称/非对称
- 中心/边缘、动态/静态、前景/背景关系
5. 光影处理
- 边缘光、通透光、柔和光影
- 高对比、渐变过渡、明暗表现方式
6. 艺术风格
- Moebius、Matisse、波普艺术、野兽派
- 工笔重彩、丝网印刷、数字艺术
❌ 风格模板不应包含
1. 具体人物
- ❌ "重金属摇滚电吉他手"
- ❌ "飘逸长发、戴墨镜"
- ❌ "人物轮廓"
2. 具体场景
- ❌ "上海外滩场景"
- ❌ "山水意境"
- ❌ "热带森林"
3. 具体物体
- ❌ "植物花朵"、"每片叶子"
- ❌ "家具、小物件"
- ❌ "街景路牌和建筑碎片"
4. 具体元素
- ❌ "英文字母和单词"
- ❌ "蘑菇"、"松树"
示例对比
❌ 错误示例(混入具体内容)
{
"prompt": "工笔重彩绘画风格,植物花朵的纹理细腻,热带植物和蘑菇森林...",
"suffix": "每片叶子每朵花都有独特纹理,奇幻森林秘境..."
}问题:指定了"植物"、"蘑菇"、"森林"等具体内容,限制了风格的通用性。
✅ 正确示例(只有风格特征)
{
"prompt": "工笔重彩绘画风格,每一根线条都极其精致入微,纹理细腻到极致...",
"suffix": "极繁主义的细节密度,每个元素都有独特纹理,奇幻秘境的浪漫感..."
}优点:只定义渲染方式,可以应用到任何主体(人物、建筑、动物、抽象概念)。
测试方法
创建风格后,用不同的 description 测试:
同一个风格 + 不同主体 = 都应该合理
例如 "minimalist-dreamy-blur" 风格:
- description: "一只猫" → 应该生成朦胧模糊的猫
- description: "城市建筑" → 应该生成朦胧模糊的建筑
- description: "抽象情绪" → 应该生成朦胧模糊的抽象形态如果某个 description 搭配风格后感觉奇怪,说明风格模板可能混入了具体内容。
常见错误
1. 从用户描述中提取具体元素加入风格
- 用户说:"电吉他手" → 不要把"电吉他"写进风格
- 只提取风格特征:"半调网点"、"剪影"、"高对比"
2. 用场景来定义风格
- ❌ "上海外滩场景的磨砂玻璃风"
- ✅ "磨砂玻璃材质 + 红橙渐变 + 极简构图"
3. 混淆风格与内容
- 风格:"工笔重彩、精致线条"(可以画任何东西)
- 内容:"植物、蘑菇、森林"(具体画什么)
---
visual_description 写作规范
🎬 像导演拍默片一样思考:
- 演员不能说话、没有字幕
- 用纯视觉语言传递信息
🌏 必须使用中文:
- 即梦 API 对中文理解更准确
❌ 绝对禁止: 1. 风格指令:极简、水墨、油画、素描(风格由 style 字段控制) 2. 产品名/公司名:OpenAI、Claude、DeepSeek 3. 版本号/型号:2.0、3.5、V3 4. 数字参数:78%、152层、200美元 5. 日期时间:2025年、12月 6. 文字/符号:不要有任何文字
✅ 应该用: 1. 空间关系:中心 vs 边缘、顶部 vs 底部 2. 大小对比:高塔 vs 低建筑、巨大 vs 渺小 3. 动态趋势:向上攀登、向外扩散 4. 视觉隐喻:塔楼(地位)、攀登(追赶)
示例:
| ❌ 错误 | ✅ 正确 |
|---|---|
| "OpenAI 的 logo 在中心" | "中心矗立一座最高的塔楼,四周快速升起多座新塔" |
| "极简线条风格的猫" | "一只橘色短毛猫坐在窗台上,阳光洒落" |
---
覆盖指令识别
Claude 应识别用户的自然语言指令并写入 JSON:
| 用户说 | 覆盖字段 |
|---|---|
| "用水彩风格" | style: "watercolor" |
| "竖版" / "3:4" | aspect_ratio: "3:4" |
| "用 Z-Image" / "用通义生图" | provider: "z-image" |
| "用即梦" | provider: "jimeng" |
| "封面要活泼一点" | cover.style: "colorful_sketch" |
可用 Provider:
| Provider | 说明 |
|---|---|
jimeng | 即梦 4.5(默认),高质量生图 |
z-image | 阿里通义 Z-Image-Turbo,支持 LoRA |
---
完整示例
示例 1: 文章配图
用户:「为这篇文章配图 /path/to/article.md」
Step 1: 读取文章,发现 5 个 H2 章节
Step 2: 创建目录
mkdir -p /path/to/article.assetsStep 3: 生成配置
{
"task_id": "article_20260120_150000",
"template": "article",
"source": "/path/to/article.md",
"output_dir": "/path/to/article.assets/",
"illustrations": [
{
"index": 1,
"h2_title": "用Claude写战略文档",
"description": "一个人坐在书桌前,与一面大镜子对话,镜子里是不断演变的文档轮廓"
},
{
"index": 2,
"h2_title": "用Google AI Studio做原型",
"description": "左边陶工快速塑形已完成,右边雕刻家还在缓慢雕琢"
}
],
"defaults": {
"style": "minimalist",
"aspect_ratio": "16:9",
"retry_count": 2
}
}Step 4: 执行
python ~/.claude/skills/qiaomu-image-generator/scripts/generate.py \
/path/to/article.assets/visual_config.json示例 2: 小红书配图(覆盖风格)
用户:「为这篇文章生成小红书配图,用彩色简笔画风格」
配置:
{
"template": "xiaohongshu",
"defaults": {
"style": "colorful_sketch",
"aspect_ratio": "3:4"
}
}示例 3: 公众号封面
用户:「生成公众号封面」
配置:
{
"template": "wechat_cover",
"cover": {
"enabled": true,
"style": "colorful_sketch",
"aspect_ratio": "2.35:1",
"description": "一只猫站在书架顶端,俯瞰书房"
}
}---
完成后必须输出
每次配图任务完成后,必须输出以下信息:
✅ 配图完成!
📄 文章:/完整/路径/文章名.md
📁 资源:/完整/路径/文章名.assets/
🖼️ 配图:X 张
⏱️ 耗时:约 X 秒
生成的图片:
1. 01-章节名-极简.png
2. 02-章节名-极简.png
...关键:必须输出完整绝对路径。
---
配置文件位置
~/.claude/skills/qiaomu-image-generator/
├── SKILL.md # 本文档
├── config/
│ ├── styles.json # 风格模板(可编辑)
│ ├── templates.json # 场景模板(可编辑)
│ └── providers.json # API 配置
└── scripts/
└── generate.py # 执行脚本自定义风格:编辑 config/styles.json 添加新风格 自定义场景:编辑 config/templates.json 添加新场景
---
故障排查
问题 1: 风格不对
原因:visual_description 中包含了风格词
解决:检查 description 是否有"极简"、"水墨"等词,删除
问题 2: 生成失败
原因:API 超时或配额用尽
解决:
- 检查
~/.claude/skills/shared-lib/config.json中的凭据 - 尝试减少
--workers数量 - 使用
--dry-run检查配置
问题 3: 图片没插入文章
原因:h2_title 与文章中的 H2 不匹配
解决:确保 h2_title 完全匹配文章中的 H2 标题文本
License
MIT
📱 关注作者
如果这个项目对你有帮助,欢迎关注我获取更多 AI 工具分享:
- X (Twitter): @vista8
- 微信公众号「向阳乔木推荐看」:
<p align="center"> <img src="https://github.com/joeseesun/terminal-boost/raw/main/assets/wechat-qr.jpg?raw=true" alt="向阳乔木推荐看公众号二维码" width="300"> </p>
#!/usr/bin/env python3
"""
统一配图生成器(独立版)
用法:
python generate.py <visual_config.json>
python generate.py <visual_config.json> --workers 3
python generate.py <visual_config.json> --dry-run
功能:
- 读取 visual_config.json 配置
- 使用本地 styles.json 风格模板(不依赖 shared-lib)
- 多线程并发生成图片
- 自动重试失败的任务
"""
import argparse
import json
import os
import sys
import time
import threading
import requests
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime
from typing import Dict, List, Optional, Tuple
# 配置目录
CONFIG_DIR = Path(__file__).parent.parent / 'config'
# 线程锁(用于打印)
print_lock = threading.Lock()
def safe_print(*args, **kwargs):
"""线程安全的打印"""
with print_lock:
print(*args, **kwargs)
def load_styles() -> Dict:
"""加载风格模板"""
styles_file = CONFIG_DIR / 'styles.json'
if not styles_file.exists():
raise FileNotFoundError(f"风格配置文件不存在: {styles_file}")
return json.loads(styles_file.read_text(encoding='utf-8'))
def load_templates() -> Dict:
"""加载场景模板"""
templates_file = CONFIG_DIR / 'templates.json'
if not templates_file.exists():
raise FileNotFoundError(f"场景模板文件不存在: {templates_file}")
return json.loads(templates_file.read_text(encoding='utf-8'))
def load_providers() -> Dict:
"""加载 API 配置"""
providers_file = CONFIG_DIR / 'providers.json'
if not providers_file.exists():
raise FileNotFoundError(f"API 配置文件不存在: {providers_file}")
return json.loads(providers_file.read_text(encoding='utf-8'))
def load_config(config_path: str) -> Dict:
"""加载任务配置"""
config_file = Path(config_path)
if not config_file.exists():
raise FileNotFoundError(f"配置文件不存在: {config_path}")
return json.loads(config_file.read_text(encoding='utf-8'))
def get_api_credentials() -> Dict:
"""获取 API 凭据"""
# 从 shared-lib 的 config.json 读取
config_path = Path.home() / '.claude' / 'skills' / 'shared-lib' / 'config.json'
if config_path.exists():
config = json.loads(config_path.read_text(encoding='utf-8'))
return {
'jimeng_session_id': config.get('jimeng_session_id', ''),
'jimeng_api_key': config.get('jimeng_api_key', os.environ.get('JIMENG_API_KEY', 'jimeng@42')),
'jimeng_api_url': config.get('jimeng_api_url', 'https://api.qiaomu.ai/jimeng-auth'),
'jimeng_model': config.get('jimeng_model', 'jimeng-4.5'),
'modelscope_api_key': config.get('modelscope_api_key', '')
}
# 回退到环境变量
return {
'jimeng_session_id': os.environ.get('JIMENG_SESSION_ID', ''),
'jimeng_api_key': os.environ.get('JIMENG_API_KEY', 'jimeng@42'),
'jimeng_api_url': os.environ.get('JIMENG_API_URL', 'https://api.qiaomu.ai/jimeng-auth'),
'jimeng_model': os.environ.get('JIMENG_MODEL', 'jimeng-4.5'),
'modelscope_api_key': os.environ.get('MODELSCOPE_API_KEY', '')
}
def extract_cover_keywords(article_path: str) -> str:
"""
从文章内容中提取封面关键词(4-6字)
简单策略:读取文章标题所在行,提取核心概念词
"""
try:
with open(article_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
# 找第一段有意义的文字(通常包含核心主题)
for line in lines:
if len(line.strip()) > 20:
text = line.strip()
# 匹配常见主题词
import re
words = re.findall(r'[\u4e00-\u9fff]{2,4}', text)
# 核心主题词库
topic_words = [
# AI/技术
'AI', '人工智能', '大模型', 'LLM', 'ChatGPT', 'Transformer', '注意力',
'智能', '硬件', '机器人', '芯片', '算力', '模型', '算法', '数据',
# 应用
'教育', '儿童', '玩具', '学习', '医疗', '办公', '创作', '设计',
# 行业
'深圳', '创业', '产品', '市场', '商业', '产业', '供应链', '出海',
# 概念
'趋势', '洞察', '思考', '复盘', '总结', '分享', '经验', '方法论',
]
matched = []
for tw in topic_words:
if tw in text:
matched.append(tw)
if matched:
# 返回第一个匹配的主题词
kw = matched[0]
# 如果是英文,尝试加中文
if len(kw) <= 3 and 'AI' in kw or 'LLM' in kw:
return kw
return kw[:6] if len(kw) > 6 else kw
# 如果没匹配,返回第一个2-4字词
if words:
return words[0][:6]
break
return "科技"
except Exception as e:
return "科技"
def build_prompt(style_name: str, description: str, styles: Dict, aspect_ratio: str = '16:9') -> str:
"""
构建完整的生图提示词
最终提示词 = 前缀(prompt) + 画面描述(description) + 后缀(suffix) + 比例说明
"""
if style_name not in styles:
available_list = list(styles.keys())[:10] # 只显示前10个
raise ValueError(
f"未找到匹配的风格: '{style_name}'\n\n"
f"可用风格(共 {len(styles)} 种):\n"
+ '\n'.join(f" {i+1}. {styles[s]['name']} ({s})" for i, s in enumerate(available_list))
+ f"\n ... 等 {len(styles)} 种风格"
)
style = styles[style_name]
# 根据比例生成构图说明
aspect_instructions = {
"16:9": "超宽横向构图,画面宽度是高度的约两倍,电影级宽屏比例。",
"9:16": "竖版构图,画面高度是宽度的约两倍,适合手机屏幕。",
"1:1": "正方形构图,宽高相等。",
"4:3": "横向构图,经典4:3比例。",
"3:4": "竖版构图,3:4比例。",
"2.35:1": "超宽横幅,电影宽银幕比例。",
"5:2": "超宽横幅,5:2比例,适合Banner。",
}
aspect_hint = aspect_instructions.get(aspect_ratio, "")
return f"{style['prompt']}\n\n{description}\n\n{style['suffix']}\n\n{aspect_hint}"
def merge_defaults(item: Dict, config_defaults: Dict, template_defaults: Dict) -> Dict:
"""
合并默认值
优先级: 单项配置 > config.defaults > template.defaults
"""
merged = {}
# 先应用 template 默认值
merged.update(template_defaults)
# 再应用 config 默认值
merged.update(config_defaults)
# 最后应用单项配置
merged.update(item)
return merged
def get_aspect_ratio_size(aspect_ratio: str) -> Tuple[int, int]:
"""
根据比例获取尺寸
即梦 API 支持的标准比例:
- 1:1 (1024x1024) - 方形
- 16:9 (1280x720) - 横版
- 9:16 (720x1280) - 竖版
- 4:3 (1024x768) - 横向
- 3:4 (768x1024) - 竖向
- 2:3 (1024x1536) - 书封竖向
- 2.35:1 (1280x544) - 超宽横版
不支持的比例会自动 fallback 到 16:9
"""
# 标准尺寸映射(即梦 API 支持的尺寸)
standard_sizes = {
"1:1": (1024, 1024),
"16:9": (1280, 720),
"9:16": (720, 1280),
"4:3": (1024, 768),
"3:4": (768, 1024),
"2:3": (1024, 1536),
"2.35:1": (1280, 544),
}
if aspect_ratio not in standard_sizes:
# 不支持的比例,fallback 到 16:9
import warnings
warnings.warn(f"即梦 API 不支持比例 '{aspect_ratio}',已自动使用 16:9")
return (1280, 720)
return standard_sizes[aspect_ratio]
def get_jimeng_ratio(aspect_ratio: str) -> str:
"""Map local aspect ratio names to the ratio values accepted by Jimeng."""
supported = {"1:1", "16:9", "9:16", "4:3", "3:4", "2:3", "2.35:1"}
if aspect_ratio in supported:
return aspect_ratio
import warnings
warnings.warn(f"即梦 API 不支持比例 '{aspect_ratio}',已自动使用 16:9")
return "16:9"
def call_jimeng_api(
prompt: str,
aspect_ratio: str = '16:9',
max_retries: int = 3
) -> str:
"""
直接调用即梦 API 生成图片(通过本地 Docker 代理)
Args:
prompt: 完整的提示词
aspect_ratio: 图片比例
max_retries: 最大重试次数
Returns:
图片 URL
"""
credentials = get_api_credentials()
session_id = credentials['jimeng_session_id']
api_key = credentials.get('jimeng_api_key', '')
api_url = credentials['jimeng_api_url'].rstrip('/')
model = credentials['jimeng_model']
if not api_key and not session_id:
raise ValueError("未设置 jimeng_api_key 或 jimeng_session_id,请检查 ~/.claude/skills/shared-lib/config.json")
url = f"{api_url}/v1/images/generations"
headers = {'Content-Type': 'application/json'}
if api_key:
headers['X-API-Key'] = api_key
else:
headers['Authorization'] = f'Bearer {session_id}'
data = {
'model': model,
'prompt': prompt,
'negative_prompt': '低质量,模糊,变形,多余的文字,水印,杂乱,中文字符,中文标签,中文标注,中文标语,字母,数字,符号,文本框,标签,云文字,混合文字,乱码文字,彩色文字,文字覆盖层,字幕,说明文字,标题文字,any text, any words, any letters, any numbers, any Chinese characters, any symbols, watermarks, logos, labels',
'ratio': get_jimeng_ratio(aspect_ratio),
'resolution': '1k',
'sample_strength': 0.7,
'n': 1
}
for attempt in range(max_retries):
try:
response = requests.post(url, headers=headers, json=data, timeout=120)
response.raise_for_status()
result = response.json()
if 'data' not in result or not result['data']:
raise Exception(f"API返回格式错误: {json.dumps(result, ensure_ascii=False)[:200]}")
return result['data'][0]['url']
except Exception as e:
if attempt < max_retries - 1:
time.sleep(2)
continue
else:
raise Exception(f"即梦API失败: {str(e)}")
def call_zimage_api(
prompt: str,
aspect_ratio: str = '16:9',
max_retries: int = 3
) -> str:
"""
调用通义 Z-Image API 生成图片
Args:
prompt: 完整的提示词
aspect_ratio: 图片比例
max_retries: 最大重试次数
Returns:
图片 URL
"""
credentials = get_api_credentials()
api_key = credentials['modelscope_api_key']
if not api_key:
raise ValueError("未设置 modelscope_api_key,请检查 ~/.claude/skills/shared-lib/config.json")
width, height = get_aspect_ratio_size(aspect_ratio)
size = f"{width}x{height}"
base_url = 'https://api-inference.modelscope.cn/'
model = 'Tongyi-MAI/Z-Image-Turbo'
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
"X-ModelScope-Async-Mode": "true"
}
payload = {
"model": model,
"prompt": prompt,
"size": size,
"negative_prompt": "低质量,模糊,变形,多余的文字,水印,杂乱,中文字符,中文标签,中文标注,中文标语,字母,数字,符号,文本框,标签,云文字,混合文字,乱码文字,彩色文字,文字覆盖层,字幕,说明文字,标题文字,any text, any words, any letters, any numbers, any Chinese characters, any symbols, watermarks, logos, labels"
}
for attempt in range(max_retries):
try:
# 提交任务
response = requests.post(
f"{base_url}v1/images/generations",
headers=headers,
data=json.dumps(payload, ensure_ascii=False).encode('utf-8'),
timeout=60
)
if response.status_code == 429:
wait_time = 2 ** attempt * 10
safe_print(f" ⚠️ Z-Image 限流,等待 {wait_time} 秒...")
time.sleep(wait_time)
continue
response.raise_for_status()
task_id = response.json().get("task_id")
if not task_id:
raise Exception("Z-Image API 返回缺少 task_id")
# 轮询任务状态
poll_headers = {
"Authorization": f"Bearer {api_key}",
"X-ModelScope-Task-Type": "image_generation"
}
while True:
result = requests.get(
f"{base_url}v1/tasks/{task_id}",
headers=poll_headers,
timeout=30
)
result.raise_for_status()
data = result.json()
status = data.get("task_status")
if status == "SUCCEED":
return data["output_images"][0]
elif status == "FAILED":
raise Exception(f"Z-Image 生成失败: {data.get('error', '未知错误')}")
else:
time.sleep(5)
except Exception as e:
if attempt < max_retries - 1:
time.sleep(2)
continue
else:
raise Exception(f"Z-Image API 失败: {str(e)}")
def save_image(url: str, output_path: str):
"""下载并保存图片"""
response = requests.get(url, timeout=60)
response.raise_for_status()
with open(output_path, 'wb') as f:
f.write(response.content)
def generate_single_image(
item: Dict,
styles: Dict,
output_dir: Path,
index: int,
is_cover: bool = False,
provider: str = 'jimeng'
) -> Dict:
"""
生成单张图片
Args:
item: 图片配置(包含 description, style, aspect_ratio 等)
styles: 风格模板(本地 styles.json)
output_dir: 输出目录
index: 序号(用于文件名)
is_cover: 是否是封面
provider: API 提供商(jimeng 或 z-image)
Returns:
结果字典 {status, path, error?}
"""
retry_count = item.get('retry_count', 2)
style_name = item.get('style', 'minimalist')
description = item.get('description', item.get('visual_description', ''))
aspect_ratio = item.get('aspect_ratio', '16:9')
section_title = item.get('section', item.get('h2_title', '')) # 兼容两种字段名
# 构建提示词(使用本地 styles.json + 比例说明)
try:
prompt = build_prompt(style_name, description, styles, aspect_ratio)
except ValueError as e:
return {
"status": "error",
"index": index,
"error": str(e)
}
# 生成文件名:优先使用配置文件中定义的 filename
if 'filename' in item:
filename = item['filename']
elif is_cover:
filename = item.get('filename', f"{index:02d}--{style_name}.png")
else:
# 后备方案:自动生成文件名
filename = f"{index:02d}--{style_name}.png"
output_path = output_dir / filename
# 带重试的生成
last_error = None
for attempt in range(retry_count + 1):
try:
provider_label = "即梦" if provider == 'jimeng' else "Z-Image"
safe_print(f" 🎨 [{index:02d}] {provider_label} 生成中... (尝试 {attempt + 1}/{retry_count + 1})")
# 根据 provider 调用不同的 API
if provider == 'z-image':
image_url = call_zimage_api(
prompt=prompt,
aspect_ratio=aspect_ratio,
max_retries=1
)
else:
# 默认使用即梦
image_url = call_jimeng_api(
prompt=prompt,
aspect_ratio=aspect_ratio,
max_retries=1
)
# 保存图片
output_dir.mkdir(parents=True, exist_ok=True)
save_image(image_url, str(output_path))
safe_print(f" ✅ [{index:02d}] 完成: {filename}")
return {
"status": "success",
"index": index,
"path": str(output_path),
"filename": filename,
"provider": provider
}
except Exception as e:
last_error = str(e)
if attempt < retry_count:
safe_print(f" ⚠️ [{index:02d}] 失败,等待重试: {str(e)[:50]}")
time.sleep(2)
else:
safe_print(f" ❌ [{index:02d}] 最终失败: {str(e)[:50]}")
return {
"status": "error",
"index": index,
"error": last_error
}
def generate_images(config: Dict, styles: Dict, templates: Dict, providers: Dict, workers: int = 3, dry_run: bool = False) -> Dict:
"""
批量生成图片
Args:
config: 任务配置(visual_config.json 内容)
styles: 风格模板
templates: 场景模板
providers: API 配置
workers: 并发线程数
dry_run: 是否只打印不执行
Returns:
生成结果
"""
start_time = time.time()
# 获取模板默认值
template_name = config.get('template', 'article')
template = templates.get(template_name, {})
template_defaults = template.get('defaults', {})
# 获取 config 级别默认值
config_defaults = config.get('defaults', {})
# 输出目录
output_dir = Path(config.get('output_dir', '.'))
# 获取 provider
provider_name = config_defaults.get('provider', providers.get('default', 'jimeng'))
# 获取风格
default_style = config_defaults.get('style', 'minimalist')
print(f"\n📋 任务配置:")
print(f" 模板: {template_name}")
print(f" 风格: {default_style} ({styles.get(default_style, {}).get('name', '未知')})")
print(f" 输出: {output_dir}")
print(f" API: {provider_name}")
print(f" 并发: {workers} 线程")
print(f" 可用风格: {len(styles)} 种")
if dry_run:
print(f"\n🔍 Dry Run 模式,不会实际生成图片\n")
results = {
"cover": None,
"illustrations": [],
"summary": {
"total": 0,
"success": 0,
"failed": 0,
"duration": 0
}
}
tasks = []
# 封面任务
cover_config = config.get('cover', {})
if cover_config.get('enabled', False):
merged_cover = merge_defaults(cover_config, config_defaults, template_defaults)
# 只有当 description 完全为空时才自动提取关键词
article_path = config.get('source', '')
current_desc = merged_cover.get('description', '')
if not current_desc or current_desc.strip() == '':
# 从文章提取关键词(仅作为后备方案)
keywords = extract_cover_keywords(article_path)
# 生成简洁的封面描述
merged_cover['description'] = f"{keywords},科技感场景,简约大气"
safe_print(f" 📝 自动提取封面关键词: {keywords}")
tasks.append(('cover', 0, merged_cover))
# 配图任务
for item in config.get('illustrations', []):
index = item.get('index', len(tasks))
merged_item = merge_defaults(item, config_defaults, template_defaults)
tasks.append(('illustration', index, merged_item))
results["summary"]["total"] = len(tasks)
if dry_run:
print(f"📝 待生成任务: {len(tasks)} 张图片")
for task_type, index, item in tasks:
style = item.get('style', default_style)
style_info = styles.get(style, {})
print(f" [{index:02d}] {task_type}: {item.get('h2_title', '封面')[:30]}")
print(f" 风格: {style} ({style_info.get('name', '未知')}), 比例: {item.get('aspect_ratio')}")
return results
print(f"\n🚀 开始生成 {len(tasks)} 张图片...\n")
# 多线程执行
with ThreadPoolExecutor(max_workers=workers) as executor:
futures = {}
for task_type, index, item in tasks:
is_cover = (task_type == 'cover')
future = executor.submit(
generate_single_image,
item,
styles,
output_dir,
index,
is_cover,
provider_name
)
futures[future] = (task_type, index)
# 收集结果
for future in as_completed(futures):
task_type, index = futures[future]
result = future.result()
if task_type == 'cover':
results["cover"] = result
else:
results["illustrations"].append(result)
if result["status"] == "success":
results["summary"]["success"] += 1
else:
results["summary"]["failed"] += 1
# 按 index 排序
results["illustrations"].sort(key=lambda x: x.get("index", 0))
# 计算耗时
duration = time.time() - start_time
results["summary"]["duration"] = round(duration, 1)
# 打印总结
print(f"\n{'='*50}")
print(f"✅ 生成完成!")
print(f" 成功: {results['summary']['success']}/{results['summary']['total']}")
print(f" 失败: {results['summary']['failed']}")
print(f" 耗时: {results['summary']['duration']}秒")
print(f" 输出: {output_dir}")
print(f"{'='*50}\n")
return results
def insert_images_to_markdown(
markdown_path: Path,
results: Dict,
config: Dict
) -> bool:
"""
将生成的图片插入到 Markdown 文件
Args:
markdown_path: Markdown 文件路径
results: 生成结果
config: 任务配置
Returns:
是否成功
"""
if not markdown_path.exists():
print(f"⚠️ Markdown 文件不存在: {markdown_path}")
return False
# 读取文件
content = markdown_path.read_text(encoding='utf-8')
lines = content.split('\n')
# 获取输出目录的相对路径
output_dir = Path(config.get('output_dir', '.'))
# 计算相对路径
try:
relative_dir = output_dir.relative_to(markdown_path.parent)
except ValueError:
# 如果不在同一目录树下,使用绝对路径
relative_dir = output_dir
# 创建 h2_title 到结果的映射
title_to_result = {}
for result in results.get('illustrations', []):
if result.get('status') == 'success':
# 从配置中找到对应的 h2_title
for item in config.get('illustrations', []):
if item.get('index') == result.get('index'):
title = item.get('h2_title', '')
title_to_result[title] = result
break
# 在每个 H2 标题下插入图片
new_lines = []
i = 0
inserted_count = 0
while i < len(lines):
line = lines[i]
new_lines.append(line)
# 用于匹配的标题文本
h2_title = None
# 检查是否是 H2 标题
if line.startswith('## '):
# 提取标题文本
h2_title = line[3:].strip()
# 检查是否是加粗文本作为标题(如 **新的瓶颈正在形成**)
elif line.strip().startswith('**') and line.strip().endswith('**') and len(line.strip()) > 4:
# 完整的加粗行,包括星号
h2_title = line.strip()
# 查找匹配的结果
if h2_title:
result = title_to_result.get(h2_title)
if result:
filename = result.get('filename', '')
# Obsidian 会自动搜索 vault,只需文件名即可
img_path = filename
# 提取纯文本标题(去掉星号)用于图片说明
clean_title = h2_title.strip('*').strip() if h2_title.startswith('**') else h2_title
# 插入空行和图片
new_lines.append('')
new_lines.append(f'')
new_lines.append('')
inserted_count += 1
i += 1
# 写回文件
markdown_path.write_text('\n'.join(new_lines), encoding='utf-8')
print(f"✅ 已插入 {inserted_count} 张图片到 {markdown_path.name}")
return True
def main():
parser = argparse.ArgumentParser(description='统一配图生成器')
parser.add_argument('config', help='visual_config.json 配置文件路径')
parser.add_argument('--workers', '-w', type=int, default=3, help='并发线程数(默认 3)')
parser.add_argument('--dry-run', '-n', action='store_true', help='只打印不执行')
parser.add_argument('--no-insert', action='store_true', help='不自动插入到 Markdown')
parser.add_argument('--output', '-o', help='输出结果到 JSON 文件')
args = parser.parse_args()
try:
# 加载配置
print("📂 加载配置...")
config = load_config(args.config)
styles = load_styles()
templates = load_templates()
providers = load_providers()
print(f" ✅ 已加载 {len(styles)} 种风格")
# 生成图片
results = generate_images(
config=config,
styles=styles,
templates=templates,
providers=providers,
workers=args.workers,
dry_run=args.dry_run
)
# 插入到 Markdown
if not args.dry_run and not args.no_insert:
source = config.get('source')
if source:
markdown_path = Path(source)
insert_images_to_markdown(markdown_path, results, config)
# 输出结果
if args.output:
output_path = Path(args.output)
output_path.write_text(
json.dumps(results, ensure_ascii=False, indent=2),
encoding='utf-8'
)
print(f"📄 结果已保存到: {args.output}")
# 返回结果
if results["summary"]["failed"] > 0:
sys.exit(1)
except Exception as e:
print(f"❌ 错误: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == '__main__':
main()
#!/usr/bin/env python3
"""
即梦 Token Auto Refresh - 连接到已运行的 Chrome
Connect to existing Chrome via CDP (Chrome DevTools Protocol)
使用方法:
1. 先启动 Chrome(开启远程调试):
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--remote-debugging-port=9222 \
--user-data-dir="/tmp/chrome-debug-profile"
注意:必须使用临时数据目录(/tmp/chrome-debug-profile),
使用默认数据目录会导致 Chrome 拒绝开启远程调试端口。
2. 在 Chrome 中手动登录即梦(只需要做一次):https://ai.jimeng.ai
3. 运行此脚本:
python refresh_jimeng_token_cdp.py
"""
import os
import sys
import time
import json
from pathlib import Path
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeout
# 配置路径
SCRIPT_DIR = Path(__file__).parent
CONFIG_FILE = Path.home() / ".claude/skills/shared-lib/config.json"
# Chrome CDP 地址
CDP_URL = "http://localhost:9222"
# 即梦网站
JIMENG_URL = "https://ai.jimeng.ai"
class JimengTokenRefresher:
def __init__(self):
self.captured_token = None
def extract_token_from_request(self, request):
"""从网络请求中提取 JWT Token"""
try:
# 监控即梦 API 域名
if "jimeng.ai" in request.url or "ai.jimeng.ai" in request.url:
headers = request.headers
auth_header = headers.get("authorization", "")
if auth_header.startswith("Bearer "):
token = auth_header.replace("Bearer ", "").strip()
if len(token) > 100: # JWT Token 很长
print(f"🎯 Captured JWT Token from: {request.url[:80]}...")
self.captured_token = token
return token
except Exception as e:
pass
return None
def update_config_file(self, token):
"""更新 config.json 文件中的 jimeng_session_id"""
if not CONFIG_FILE.exists():
print(f"❌ Config file not found: {CONFIG_FILE}")
# 创建默认配置
CONFIG_FILE.parent.mkdir(parents=True, exist_ok=True)
config = {
"jimeng_session_id": token,
"jimeng_api_url": "http://localhost:8000",
"jimeng_model": "jimeng-image-4.5"
}
with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
json.dump(config, f, indent=2, ensure_ascii=False)
print(f"✅ Created new config: {CONFIG_FILE}")
return True
try:
# 读取现有配置
with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
config = json.load(f)
# 更新 jimeng_session_id
config['jimeng_session_id'] = token
# 写回文件
with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
json.dump(config, f, indent=2, ensure_ascii=False)
print(f"✅ Updated {CONFIG_FILE}")
return True
except Exception as e:
print(f"❌ Failed to update config: {e}")
return False
def verify_token(self, token):
"""验证 Token 是否有效(可选,通过调用即梦 API)"""
print("🔍 Verifying token...")
try:
import requests
# 读取配置获取 API URL
with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
config = json.load(f)
api_url = config.get('jimeng_api_url', 'http://localhost:8000')
# 发送测试请求(小图片)
response = requests.post(
f"{api_url}/v1/images/generations",
headers={
'Content-Type': 'application/json',
'Authorization': f'Bearer {token}'
},
json={
'model': 'jimeng-image-4.5',
'prompt': 'test',
'width': 512,
'height': 512,
'n': 1
},
timeout=10
)
if response.status_code == 200:
print("✅ Token is valid!")
return True
else:
print(f"⚠️ Token validation returned: {response.status_code}")
print(f" Response: {response.text[:200]}")
return False
except Exception as e:
print(f"❌ Verification failed: {e}")
return False
def check_chrome_running(self):
"""检查 Chrome 是否在运行并开启了远程调试"""
print("🔍 Checking Chrome remote debugging...")
try:
import requests
response = requests.get(f"{CDP_URL}/json/version", timeout=2)
if response.status_code == 200:
data = response.json()
print(f"✅ Chrome connected: {data.get('Browser', 'Unknown')}")
return True
except Exception as e:
print(f"❌ Cannot connect to Chrome at {CDP_URL}")
print(f" Error: {e}")
return False
def run(self):
"""主运行流程"""
print("🚀 即梦 Token Auto Refresh (CDP Mode)\n")
# 检查 Chrome 是否运行
if not self.check_chrome_running():
print("\n💡 请先启动 Chrome(开启远程调试):\n")
print('"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --remote-debugging-port=9222 --user-data-dir="/tmp/chrome-debug-profile"\n')
print("然后重新运行此脚本。")
return
try:
with sync_playwright() as p:
print("🌐 Connecting to Chrome via CDP...")
browser = p.chromium.connect_over_cdp(CDP_URL)
# 获取所有已打开的上下文
contexts = browser.contexts
if not contexts:
print("❌ No browser context found")
print("💡 请先在 Chrome 中打开一个窗口")
return
context = contexts[0]
pages = context.pages
# 如果没有页面,创建新页面
if not pages:
page = context.new_page()
else:
# 使用第一个页面
page = pages[0]
# 设置请求监听
page.on("request", self.extract_token_from_request)
print(f"📍 Current URL: {page.url}")
# 如果不在即梦,则导航到即梦
if "jimeng.ai" not in page.url:
print(f"📍 Navigating to {JIMENG_URL}...")
try:
page.goto(JIMENG_URL, wait_until="domcontentloaded", timeout=60000)
except Exception as e:
print(f"⚠️ Navigation warning: {e}")
print("\n" + "="*60)
print("👉 请检查 Chrome 窗口:")
print(" 1. 确保已登录即梦")
print(" 2. 如果未登录,请现在登录")
print(" 3. 脚本将在 60 秒后自动继续")
print("="*60)
print("\n⏳ 等待 60 秒...")
wait_time = 60
for i in range(wait_time):
time.sleep(1)
if i > 0 and i % 15 == 0:
remaining = wait_time - i
print(f" 还剩 {remaining} 秒...")
print("\n✅ 继续执行...\n")
# 尝试触发 API 请求
if "jimeng.ai" not in page.url:
print(f"📍 Navigating to {JIMENG_URL}...")
try:
page.goto(JIMENG_URL, wait_until="domcontentloaded", timeout=60000)
except Exception as e:
print(f"⚠️ Navigation warning: {e}")
# 等待 API 请求
print("⏳ Waiting for API requests (15 seconds)...")
time.sleep(15)
# 如果还没捕获到,尝试交互触发
if not self.captured_token:
print("🔄 Trying to trigger more API requests...")
try:
# 滚动页面
page.mouse.wheel(0, 500)
time.sleep(3)
# 刷新页面
print("🔄 Refreshing page...")
page.reload(wait_until="domcontentloaded", timeout=60000)
time.sleep(10)
except Exception as e:
print(f"⚠️ Interaction error: {e}")
token = self.captured_token
if token:
print(f"\n✅ Token captured! (Length: {len(token)})")
print(f" Token preview: {token[:50]}...{token[-50:]}\n")
# 更新 config.json 文件
if self.update_config_file(token):
# 验证 Token(可选)
self.verify_token(token)
print("\n" + "="*60)
print("✅ Token refresh completed successfully!")
print("="*60)
else:
print("\n❌ Failed to update configuration")
else:
print("\n❌ Failed to capture token")
print("💡 Possible reasons:")
print(" 1. Not logged in to 即梦")
print(" 2. Network issue")
print(" 3. Try manually triggering requests (click around the page)")
browser.close()
except Exception as e:
print(f"\n❌ Error: {e}")
import traceback
traceback.print_exc()
def main():
refresher = JimengTokenRefresher()
refresher.run()
if __name__ == "__main__":
main()