Files
probably-rendering-one-more…/README.md
T
codex-bot 83e19d31ca
PROMPT Docker CI and deployment / verify-and-deploy (push) Successful in 15m54s
Publish photo-to-shadow-puppet skill with shared linked documentation
2026-10-23 17:26:46 +08:00

131 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PROMPT
仓库名:Probably Rendering One More Pixel Tonight。其余命名使用 PROMPT / `prompt`。
自己的素材与创作工作台:Next.js Pages Router、React、TypeScript、Tailwind CSS、Node.js 24。中文界面包含瀑布流、日期贡献热力图、素材导入、多媒体详情、分类管理、独立素材架与线条图形工具。没有创建作品的按钮;图文和动态作品由代码实现。
## 全 Docker 启动
本机只需 Docker Engine / Docker Desktop 和 Compose v2。Node、npm、FFmpeg、迁移程序、网站与后台处理都在镜像里。
```bash
cp .env.example .env
# 修改 .env 中的三个密码 / 密钥,不能使用示例值。
docker build --target runtime -t prompt:local .
docker compose --env-file .env up -d --wait postgres objects
docker compose --env-file .env run --rm migrate
docker compose --env-file .env up -d --wait web worker
```
访问 `http://localhost:18131`。图片与其他文件保存在 S3 对象卷,文字、分类、素材包引用和任务保存在 PostgreSQL 卷;停止、重建应用容器不会删除这些数据。
| 容器服务 | 职责 |
| --- | --- |
| `web` | Next.js 页面、API、素材上传/读取;宿主机 18131 → 容器 3000 |
| `worker` | FFmpeg 音画分离、封面与音轨处理;没有 HTTP 端口 |
| `postgres` | PostgreSQL 元数据和文字;兼容维护用回环端口 18132 |
| `objects` | RustFS 私有 S3 对象存储;兼容维护用回环端口 18133,控制台关闭 |
| `migrate` | 一次性数据库迁移与对象桶初始化,执行后退出 |
| `tests` | CI 的一次性集成测试执行器,执行后退出 |
四个常驻服务使用 `restart: unless-stopped`,Web 和 worker 以非 root 用户运行。worker 通过心跳检查存活;Web 健康检查同时验证当前版本、数据库和 S3。
## 页面与数据
- `/`:所有非空素材包与已注册代码作品,按创建时间倒序;顶部为过去一年的贡献汇总。
- `/images`、`/videos`、`/audio`:图片、视频、声音收藏。
- `/articles`、`/motion`:代码编写的图文与动态作品。
- 上述五类路径可以附加标签树路径,如 `/images/style/white-line`;父分类会包含后代分类的内容。
- `/p/<slug>`:素材包的稳定详情地址,不随标签改变。多图切换、多视频及其关联音轨、多声音均可展示。
- `/library/import`:导入同一类型的一组文件和说明,自动收为一份收藏。支持最多 16 个文件,单个 250 MB,总计 1 GB。
- `/tools/doodle`:手绘线条造型参考,可选色、复制和下载透明 SVG。不是 AI 图片编辑器。
素材库不插入演示或占位帖子。空分类显示简洁的空状态;空素材包不进入任何瀑布流。分页游标由时间与 UUID 组成,重复时间戳下仍稳定。
详细模型见 `docs/data-model.md`。应用容器通过 Docker 网络的 `postgres:5432` 和 `objects:9000` 访问存储,不使用宿主机回环地址。浏览器通过应用访问媒体,支持 Range 分段读取。
视频原件保持不变,后台生成无声 MP4、封面,以及存在声音时的 M4A 音轨。音轨记录在 `asset_variants`,始终属于原视频;不会生成独立声音资产。后台单任务处理,使用数据库锁领取任务,失败重试三次,支持超时任务恢复。FFmpeg 禁止输入网络协议。
## 编程加入素材包与作品
`POST /api/posts` 接收 `kind`、`title`、可选 `slug`、`assets: [{id, role?}]`、`tags: [tagId]`、`text`、`coverAssetId` 和 `pageKey`。`role` 为 `content` 或 `caption`。素材和说明文字都可以通过 ID 引用已有资产;`text` 是创建新文字资产的快捷方式。引用不会复制原文件。
`POST /api/tags` 接收 `name`、`slug` 和可选 `parentId`。
图文或动态作品需要先在 `src/content/registry.tsx` 注册 React 组件与类型,再通过 API 创建引用对应 `pageKey` 的素材包。封面引用普通图片资产。动态作品的 React 组件就是画面本身,不会被强制套入视频播放器。未注册的页面不会出现在瀑布流中,也不会执行数据库中的任意路径或脚本。
当前不内置作品模板或视频导出引擎;后续一起确定设计系统和制作方案。
## 贡献记录
`contribution_events` 保存细分的 `kind`、对象类型、对象 ID、数量、发生时间、元数据和可选幂等键。显示时按上海时区汇总所有类型。当前没有将上传、分类或保存动作自动算作贡献;触发规则留待确定。没有随机或伪造热力图数据。
## CI/CD 与生产部署
`.gitea/workflows/ci.yml` 使用 `runs-on: ces-control`。依赖安装、类型检查、单元测试、生产构建、启动检查都在 Docker 构建阶段运行。集成测试启动隔离的完整容器栈,并由测试容器请求真实的非 root Web / worker 容器,验证 PostgreSQL、RustFS、上传、共享引用和音画分离。
main 上的 push 或手动运行,在全部检查通过后才发布。测试环境使用独立 Compose 项目、随机端口和随机凭据;测试结束只删除它自己的容器和卷。
生产使用固定 Compose project `prompt`,复用原有 `prompt_postgres_data` 和 `prompt_objects` 卷,以及 `/etc/prompt.env` 的凭据。由旧部署升级时,发布脚本会停用 `prompt.service`、`prompt-worker.service`,由容器接管运行;宿主机无需项目专用的 Node/FFmpeg 进程。旧发布目录留作首次迁移失败时的回退依据。
| 项目 | 值 |
| --- | --- |
| 生产运行 | Docker Compose:web、worker、postgres、objects |
| 网站端口 | `18131`,映射到 Web 容器 3000 |
| 应用镜像 | `prompt:<commit>`;回退使用上一版镜像 |
| 发布清单 | `/opt/prompt/releases/<commit>/compose.yml` 和 `release.env` |
| 当前发布 | `/opt/prompt/current` 原子软链接 |
| 密钥 | `/etc/prompt.env`,保留既有凭据,新建时随机生成;不进代码和日志 |
| 持久数据 | Docker named volumes,不随应用发布删除 |
| 数据库备份 | `/var/lib/prompt/backups`,每次发布前备份,保留最近 10 份 |
发布使用宿主机文件锁串行执行,自动跳过已落后的提交。先备份、迁移,再切换 Web / worker;新版本失败时恢复上一版容器,首次迁移失败时可恢复原先的宿主机服务。生产发布从不执行 `down -v`。对象卷需要独立快照,数据库 dump 不能代替对象备份。
在服务器上维护当前版本:
```bash
cd /opt/prompt/current
sudo docker compose -p prompt --env-file /etc/prompt.env --env-file release.env ps
sudo docker compose -p prompt --env-file /etc/prompt.env --env-file release.env logs --tail 100 web worker
sudo docker compose -p prompt --env-file /etc/prompt.env --env-file release.env exec web node container-health.mjs
```
`GET /api/health` 返回应用版本;`GET /api/ready` 检查数据库与对象存储。
## 内网与公网访问
`172.31.212.211` 是服务器内网 IP,不能作为公网入口。Web 端口默认映射为 `0.0.0.0:18131:3000`;公网访问仍需要实例绑定公网 IP / EIP 或反向代理,并配置相应安全组和防火墙。Docker 化不会使内网 IP 自动变成公网 IP。本项目不会擅自修改云安全组或开放数据库/S3 的公网端口。
## 独立运行 CI 验证
```bash
docker build --target integration -t prompt:tests .
docker build --target runtime -t prompt:local .
PROMPT_IMAGE=prompt:local PROMPT_TEST_IMAGE=prompt:tests bash scripts/integration.sh
```
整个验证过程无需在宿主机安装 Node.js、PostgreSQL、S3 或 FFmpeg。runner 仅需 Docker Engine、Compose、Git、Bash、flock 和管理 Docker/旧服务所需的权限。
## 街头小人技能与 Agent 接口
导航「工具 → 技能」打开 `/tools/skills`,`/tools/skills/street-people` 包含风格约定、提示词、上传示例和两个独立图包入口。
把 `GET /api/skills/street-people` 的完整地址交给有绘图工具的 coding agent。GET 返回 JSON 规范,`?format=md` 返回 Markdown。agent 用自己的绘图能力生成单人透明 PNG,再向同一地址 POST multipart/form-data,字段 `files` 可重复,`title`、`description`、`tags` 和 `slug` 可选。网站不调用外部模型,也不需要模型密钥。PNG 必须有真实透明与接近不透明的像素(alpha ≥250),最多 4000 万像素,其余上传数量和大小限制与导入页一致。成功返回 post 地址和可复用素材 ID。
`seed/characters` 存放本次参考图提取 15 张、新生成测试 4 张及来源说明。部署健康检查后通过 `scripts/import-character-packs.mjs` 调用真实上传接口写入 PostgreSQL/S3,生成 `/p/street-people-reference` 与 `/p/street-people-original` 两个独立 post。已有同 slug 时跳过,重发版不重复导入。原图提取由 imagegen 执行,可能重建细节,并非逐像素无损裁剪。
## 网页原稿、截图与技能文档
图文笔记中的每张图片拥有独立网页:`/p/<slug>/pages/1` 至 `/pages/8`。笔记页展示真实服务器截图,可刷新一张或全部,并单独打开 HTML 原稿。截图由 Docker worker 内 Chromium 生成并存入私有 S3,发布会等待当版全部 24 张截图完成。数据与任务结构见 `db/002_page_snapshots.sql`,详细行为见 `docs/learning-series.md`。
工具栏首项为技能;素材库与分类管理页面已移除,已有素材、标签、导入和数据 API 保留。技能使用瀑布卡片,首页也混排展示。
交给 agent 的入口为 `/skills/street-people/SKILL.md`,后续子文档为 `style.md`、`upload.md`、`checks.md`;纯文本只通过链接引用图片、文档和 API。人类阅读入口 `/tools/skills/street-people` 和对应子页面使用相同文档数据。右侧资源面板分类收录全部文档、图片和 API,支持预览与打开;不会执行 POST,也不展示与技能流程无关的测试图包。旧 JSON API 和 `?format=md` 兼容保留,后者返回相同入口文档。
## 照片入皮影
技能目录和首页新增「照片入皮影」,入口网页 `/tools/skills/shadow-puppet`,Agent 入口纯文本 `/skills/shadow-puppet/SKILL.md`。网页与纯文本共用 `src/content/skills/shadow-puppet.ts` 的五份文档:入口、制作流程、画面语法、完整提示词、验收与上传。侧栏包含五份文档、用户提供的白鹭/舞者两张完成示例,以及通用图片上传和媒体读取两个 API。示例被明确标记为风格参考,不当作原始照片重新嵌套。
每张原片独立输出不透明 3:4 海报,上下高度严格 1:1:上半保真摄影,下半是一幕一偶的暖灯宣纸皮影。Agent 使用自己的图像工具逐张制作与验收,完成后调用 `POST /api/upload`;不使用街头小人的透明 PNG 接口。资源面板只展示 API 说明,不执行上传或直接请求未替换参数的媒体地址模板。阅读器和纯文本文档路由按技能注册表读取,后续可继续增加技能。