Files

283 lines
19 KiB
Markdown
Raw Permalink 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.
# AI 短剧本地生产平台
这是一个面向私有部署和商业团队的本地化 AI 短剧/漫剧生产平台 MVP,不是单剧集页面。平台把组织、工作区、成员、角色、项目访问、剧本、角色锁、场景锁、道具锁、分镜、台词、生成任务、质检门、成本、合规、审计和剪辑交付放进同一个生产系统。
当前已经具备:
- 三类产品入口:创作空间、管理员后台、系统设置控制面;分别服务创作者日常生产、组织治理和部署级配置。
- 多组织:一个用户可以属于多个组织,组织之间的项目、成员、模型和审计数据隔离。
- 多工作区:制作部、素材实验室、客户空间可以在同一组织下独立管理。
- 多用户与角色:组织所有者、组织管理员、制片、编剧、资产美术、配音/字幕、审片、项目编辑和项目查看者。
- 项目级访问控制:项目邀请使用受限 `project_guest` 工作区身份和 `project-only` 访问模式,只能看到显式授权项目,不会因加入工作区而继承全部项目或生成权限。
- 真实 scope API:所有项目、任务、模型、审片、导出请求都经过 user → organization → workspace → project 检查。
- 平台级系统治理:系统配置、功能开关、通知渠道、API 客户端、服务健康和队列运营;系统权限独立于组织管理员。
- 实时运营概览:管理概览直接读取服务健康探针、Worker 心跳/队列和部署生产就绪度,不使用前端静态状态冒充在线运行状态。
- 企业身份中心:TOTP MFA、登录策略、OIDC/SAML 提供商登记与发现探测、SCIM 目录令牌轮换和受令牌保护的用户同步接口。
- 用户通知中心:按用户、组织、工作区隔离的通知收件箱、未读计数、单条/全部已读、组织级通知偏好和服务端收件人过滤。
- 全局生产搜索:支持 `⌘/Ctrl + K` 命令入口,在当前工作区或当前项目内定位项目、剧本、分集、镜头、资产、任务、生成任务和交付记录;结果由后端按租户作用域过滤。
- 协作任务中心:项目内任务创建、负责人分派、优先级、截止时间、状态、本人任务更新、任务通知和审计记录。
- 资产版本台账:资产版本不可覆盖,支持当前版本切换、历史版本恢复、锁定状态和镜头绑定审计。
- 本地持久化:Node 24 内置 SQLite 自动初始化到 `/Users/xz/Documents/daima/ai短剧/ai-drama-platform/data/platform.sqlite`。
- 本地模型优先:自有模型平台是主适配器,OpenAI-compatible / 自定义 HTTP JSON 可接入,ComfyUI 只是 optional adapter。
- 本地执行器:API 启动时自动拉起 Worker,支持租约、并发限制、心跳、依赖阻塞、重试记录和管理员手动领取。
## 运行
```bash
cd /Users/xz/Documents/daima/ai短剧/ai-drama-platform
npm install
npm run dev
```
本地 API 服务:
```bash
cd /Users/xz/Documents/daima/ai短剧/ai-drama-platform
npm run api
```
需要保持两个进程:Vite 前端和本地 API。API 进程会自动启动本地 Worker;只有需要独立调试 Worker 时才单独使用 `npm run worker`。启动后访问:
```text
前端:http://127.0.0.1:5173/
API:http://127.0.0.1:8787/api/health
```
完整回归(必须串行执行,共 32 项,避免 SQLite 写入竞争):
```bash
npm run smoke:all
```
API 默认每个令牌或匿名来源每分钟允许 120 次请求,可在系统配置中修改 `api.rate_limit_per_minute`;设置为 `0` 表示关闭限流。超限响应为 `429 rate_limit_exceeded`,并返回 `Retry-After` 与 `X-RateLimit-*` 响应头。当前本地模式使用单 API 进程内固定窗口计数,多实例部署应切换到 Redis/共享限流存储。
该命令覆盖租户隔离、MFA、OIDC、系统用户、商业配额、邀请、模型/Runner、API 客户端密钥轮换、任务队列、媒体证据、合成证据和项目生命周期;每个临时 smoke 用户、邀请和任务都会在成功或失败后清理。
API 默认地址:
```text
http://127.0.0.1:8787/api/health
http://127.0.0.1:8787/api/project
http://127.0.0.1:8787/api/qa
POST http://127.0.0.1:8787/api/auth/login
GET http://127.0.0.1:8787/api/auth/session
POST http://127.0.0.1:8787/api/auth/logout
GET http://127.0.0.1:8787/api/auth/security-events
GET http://127.0.0.1:8787/api/system/security-events?userId=<userId>
POST http://127.0.0.1:8787/api/auth/login/mfa
GET http://127.0.0.1:8787/api/auth/mfa
POST http://127.0.0.1:8787/api/auth/mfa/setup
POST http://127.0.0.1:8787/api/auth/mfa/enable
POST http://127.0.0.1:8787/api/auth/mfa/disable
GET http://127.0.0.1:8787/api/auth/sso/providers
GET http://127.0.0.1:8787/api/auth/sso/start?providerId=:id&returnTo=/
GET http://127.0.0.1:8787/api/auth/sso/callback
GET http://127.0.0.1:8787/api/auth/sso/saml/metadata?providerId=:id
POST http://127.0.0.1:8787/api/auth/sso/saml/acs
POST http://127.0.0.1:8787/api/auth/sso/redeem
GET http://127.0.0.1:8787/api/auth/sessions
POST http://127.0.0.1:8787/api/auth/sessions/:sessionId/revoke
POST http://127.0.0.1:8787/api/auth/sessions/revoke-others
POST http://127.0.0.1:8787/api/auth/password
GET http://127.0.0.1:8787/api/context
GET http://127.0.0.1:8787/api/search?q=雷雨&scope=workspace&limit=40
GET http://127.0.0.1:8787/api/search?q=雷雨&scope=project&limit=40
GET http://127.0.0.1:8787/api/tasks?status=all&assignedTo=me&limit=100
POST http://127.0.0.1:8787/api/tasks
PATCH http://127.0.0.1:8787/api/tasks/:taskId
GET http://127.0.0.1:8787/api/notifications?limit=60&unreadOnly=1
PATCH http://127.0.0.1:8787/api/notifications/:notificationId
POST http://127.0.0.1:8787/api/notifications/read-all
GET http://127.0.0.1:8787/api/notification-preferences
PATCH http://127.0.0.1:8787/api/notification-preferences/:category
GET http://127.0.0.1:8787/api/organizations
GET http://127.0.0.1:8787/api/organizations/:orgId
POST http://127.0.0.1:8787/api/organizations/:orgId/invitations
GET http://127.0.0.1:8787/api/organizations/:orgId/members
PATCH http://127.0.0.1:8787/api/organizations/:orgId/members/:userId
GET http://127.0.0.1:8787/api/invitations
POST http://127.0.0.1:8787/api/invitations/:invitationId/accept
GET http://127.0.0.1:8787/api/workspaces
POST http://127.0.0.1:8787/api/workspaces
GET http://127.0.0.1:8787/api/workspaces/:workspaceId/members
PATCH http://127.0.0.1:8787/api/workspaces/:workspaceId/members/:userId
GET http://127.0.0.1:8787/api/projects
POST http://127.0.0.1:8787/api/projects
GET http://127.0.0.1:8787/api/projects/:projectId/members
PATCH http://127.0.0.1:8787/api/projects/:projectId/members/:userId
GET http://127.0.0.1:8787/api/usage
GET http://127.0.0.1:8787/api/billing
GET http://127.0.0.1:8787/api/audit
GET http://127.0.0.1:8787/api/audit/:auditId
GET http://127.0.0.1:8787/api/audit/export
GET http://127.0.0.1:8787/api/system/health
GET http://127.0.0.1:8787/api/system/worker
GET http://127.0.0.1:8787/api/system/readiness
GET http://127.0.0.1:8787/api/permissions
GET http://127.0.0.1:8787/api/assets?kind=voice
POST http://127.0.0.1:8787/api/assets/upload
GET http://127.0.0.1:8787/api/assets/:assetId/content
POST http://127.0.0.1:8787/api/assets/:assetId/versions
POST http://127.0.0.1:8787/api/assets/:assetId/versions/upload
POST http://127.0.0.1:8787/api/assets/:assetId/verify
POST http://127.0.0.1:8787/api/assets/:assetId/versions/:versionId/restore
POST http://127.0.0.1:8787/api/assets/:assetId/lock
POST http://127.0.0.1:8787/api/assets/:assetId/rights
POST http://127.0.0.1:8787/api/assets/:assetId/bindings
GET http://127.0.0.1:8787/api/production/graph
GET http://127.0.0.1:8787/api/production/catalog
POST http://127.0.0.1:8787/api/production/seasons
POST http://127.0.0.1:8787/api/production/episodes
PATCH http://127.0.0.1:8787/api/production/episodes/:episodeId
POST http://127.0.0.1:8787/api/production/script/import
POST http://127.0.0.1:8787/api/production/script/materialize
PATCH http://127.0.0.1:8787/api/production/bible
POST http://127.0.0.1:8787/api/production/shots
PATCH http://127.0.0.1:8787/api/production/shots/:shotId
POST http://127.0.0.1:8787/api/production/shots/:shotId/prompt-versions
GET http://127.0.0.1:8787/api/production/reviews
POST http://127.0.0.1:8787/api/production/qa/run
POST http://127.0.0.1:8787/api/production/reviews/:reviewId/decision
POST http://127.0.0.1:8787/api/production/reviews/:reviewId/comments
GET http://127.0.0.1:8787/api/production/deliveries
POST http://127.0.0.1:8787/api/production/deliveries
POST http://127.0.0.1:8787/api/production/deliveries/:deliveryId/approve
GET http://127.0.0.1:8787/api/admin/queue
GET http://127.0.0.1:8787/api/platform/models
POST http://127.0.0.1:8787/api/platform/models/register
PATCH http://127.0.0.1:8787/api/platform/models/:modelId
POST http://127.0.0.1:8787/api/platform/models/:modelId/probe
GET http://127.0.0.1:8787/api/system/config
POST http://127.0.0.1:8787/api/system/config
GET http://127.0.0.1:8787/api/system/health
GET http://127.0.0.1:8787/api/system/readiness
GET http://127.0.0.1:8787/api/system/backups
POST http://127.0.0.1:8787/api/system/backups
POST http://127.0.0.1:8787/api/system/health/:serviceKey/action
GET http://127.0.0.1:8787/api/system/feature-flags
POST http://127.0.0.1:8787/api/system/feature-flags
GET http://127.0.0.1:8787/api/system/notifications
POST http://127.0.0.1:8787/api/system/notifications
GET http://127.0.0.1:8787/api/system/api-clients
POST http://127.0.0.1:8787/api/system/api-clients
PATCH http://127.0.0.1:8787/api/system/api-clients/:clientId
POST http://127.0.0.1:8787/api/system/api-clients/:clientId/rotate
GET http://127.0.0.1:8787/api/jobs
GET http://127.0.0.1:8787/api/jobs/:jobId
POST http://127.0.0.1:8787/api/jobs
POST http://127.0.0.1:8787/api/jobs/:jobId/run
POST http://127.0.0.1:8787/api/jobs/:jobId/retry
POST http://127.0.0.1:8787/api/jobs/:jobId/cancel
POST http://127.0.0.1:8787/api/jobs/:jobId/priority
POST http://127.0.0.1:8787/api/adapters/dry-run
POST http://127.0.0.1:8787/api/exports/write
GET http://127.0.0.1:8787/api/system/worker
POST http://127.0.0.1:8787/api/system/worker/dispatch
```
前端模块支持 `#creator-home`、`#factory`、`#script`、`#casting`、`#director`、`#jobs`、`#bible`、`#qa`、`#export`、`#admin-*` 和 `#system-*` 深链接;移动端使用抽屉导航,不会把整套后台菜单堆在内容之前。
## 季 / 集主数据
系列 Bible 页面现在按商业剧集目录管理 `series → seasons → episodes → shots`:
- 一个项目可以创建多季、多集,每集创建时自动初始化一个镜头草稿,避免空集无法进入生产。
- 当前集选择会通过 `episodeId` 传给生产图谱;剧本版本、镜头、Prompt 和返回的图谱都按当前集隔离。
- 分集状态支持草稿、制作中、审片中、已通过和已归档;标题、时长、开场钩子和结尾悬念都写入 SQLite 并记录审计日志。
- 服务端创建季、创建集、修改集都经过 `script:edit` 权限检查,不能靠前端隐藏绕过。
- `npm run smoke:production-catalog` 会验证目录读取、创建季、创建集、首个镜头初始化、集级图谱切换和分集更新;该脚本会清理自己的临时数据。
## 用户鉴权与访问边界
平台默认使用真实的邮箱 + 密码登录和 Bearer session。会话默认有效 12 小时,失败 5 次会暂时锁定;所有业务 API 都先解析 session,再执行用户 → 组织 → 工作区 → 项目 → 权限检查。浏览器端不会因为知道组织 ID 就获得跨组织访问权。
仅在本地接口调试或冒烟测试时,显式设置 `AI_DRAMA_ALLOW_DEV_CONTEXT=1` 才会启用请求头上下文 bypass;默认值是 session-only,正式部署应保持 `AI_DRAMA_ALLOW_DEV_CONTEXT=0` 或不设置。
认证接口:
```text
POST http://127.0.0.1:8787/api/auth/login
GET http://127.0.0.1:8787/api/auth/session
POST http://127.0.0.1:8787/api/auth/logout
```
本地演示账号统一密码:`Demo@123456`。
```text
系统管理员:producer@local.test
组织管理员 / 制片:producer2@local.test
普通编剧:writer@local.test
```
访问范围:
- 普通创作者:我的工作台,以及被授予的剧本、资产、导演、生成、审片或交付页面;未授权的入口、按钮和敏感数据会隐藏,API 同时返回 403。
- 制片 / 组织管理员:本组织的组织、工作区、成员、项目、模型、队列、用量和审计能力,数据不会跨组织返回。
- 系统管理员:在组织权限之上,额外管理部署、存储、全局生成策略、通知、API 客户端、功能开关和系统健康。
系统级权限单独记录在 `system_admins` 表。组织管理员不会因为组织角色自动获得全局部署策略权限。
API 客户端密钥:完整密钥只在创建或轮换成功响应中返回一次;SQLite 仅保存 SHA-256 摘要、版本号和不可用的前缀预览,客户端目录不会再次返回完整密钥。轮换会立即撤销旧密钥,撤销或暂停状态的客户端不能调用业务 API。
API 客户端 scope 由后端白名单强制执行:`jobs:read` 只能读取任务,`jobs:write` 才能创建/执行/重试/取消任务,`models:read` 只能读取连接器,`models:write` 才能登记/修改/探测连接器,`audit:read` 才能读取和导出审计日志。普通 Bearer session 不受 API 客户端 scope 规则影响。
平台管理页顶部的组织、工作区和项目切换器会实际刷新 API scope;邀请成员、创建工作区、创建项目和生成任务都会写入 SQLite,并产生审计/用量记录。
通知中心按当前用户和组织保存消息,工作区/项目消息会继续经过服务端作用域过滤。用户可以按生成任务、审片、交付、协作任务、组织访问、用量配额和系统通知分别关闭站内提醒;关闭偏好后,服务端不会继续写入该用户的对应收件箱。
协作任务中心与“我的待办”互通:项目负责人可以创建和分派任务,普通成员只能更新自己负责任务的状态,任务状态会回写到项目审计和站内通知。
账号安全页支持修改密码、查看最近登录设备、撤销单个其他会话、撤销其他全部会话和接受组织邀请;会话撤销操作由后端执行并写入审计日志。独立的 `auth_security_events` 台账记录登录成功/失败、账号锁定、MFA 挑战与验证、MFA 开关、会话创建/撤销/退出和密码变更;普通用户只能读取自己的事件,系统管理员可按用户读取全局事件,API 客户端不能读取个人安全事件。
系统设置中的“企业身份”页面支持保存登录策略、登记 OIDC/SAML 提供商、用 OIDC discovery 或 SAML 环境配置探测提供商、创建和轮换 SCIM 令牌。SAML 使用 HTTP-Redirect AuthnRequest + HTTP-POST ACS:IdP 证书只从服务端环境变量引用读取,断言必须通过签名、Audience、时间窗口和 `InResponseTo` 校验,再进入组织/工作区入组、MFA 和一次性 Bearer ticket。ACS 不接受前端提交的用户身份。SCIM 接口为 `/scim/v2.0/:directoryId/Users`,支持用户列表、新增、部分更新和停用;目录令牌只在创建或轮换响应中返回一次,数据库只保存哈希。MFA 密钥使用 AES-GCM 加密存储,可通过 `AI_DRAMA_MFA_ENCRYPTION_KEY` 指定独立加密密钥。
登录后入口读取当前用户有权访问的组织、工作区和项目;新组织或空工作区会进入空项目工厂,不会自动复制其他项目的角色、资产、镜头或任务。仓库内的《雷雨口》只用于本地种子数据和回归测试。当前平台不会主动调用任何云端或付费节点;生成适配器配置在:
```text
/Users/xz/Documents/daima/ai短剧/ai-drama-platform/config/adapters.example.json
```
## 平台边界
- 主适配器是用户自有模型平台,支持 HTTP、自定义 JSON、OpenAI-compatible 形态。
- 已确认的音频生产链路走 NewAPI OpenAI-compatible 中转:`IndexTTS-2.5` 用于中文角色配音和情绪控制,`paraformer-zh-long` 用于中文 ASR、台词校验和字幕时间轴;密钥只从 `NEWAPI_API_KEY` 环境变量读取,不写入仓库。
- ComfyUI 只是 optional adapter,用来复用旧的 Qwen/QwenEdit/H3 首尾帧桥接经验。
- 一次生成只允许一张完整单画面;分镜图、接触表、边界表只能审核,不能喂回生成。
- 声音作为独立资产锁定,不把 MiniMax H3 随机原生声音作为最终角色声线。
- 当前平台底座已具备真实任务合同、队列、重试、取消、租约、并发控制和 HTTP Runner 执行接口;API 启动时自动运行本地 Worker,只会领取本地 `ready` 连接器任务。若未配置可用的自有图片/视频/TTS/ASR Runner,任务会明确显示 `not-connected`/`blocked`,不会伪称已经生成真实媒体成片。
- 手动执行接口对已完成任务是幂等的:如果本地 Worker 已先完成任务,重复调用 `POST /api/jobs/:jobId/run` 会返回现有完成结果并标记 `idempotent: true`,不会再次调用模型或生成第二份媒体。
- 流程模板已经是服务端版本化对象:全局内置模板可被组织 / 工作区新版本覆盖,生成队列支持“只生成计划”或“按步骤创建带依赖的 generation jobs”。
- 媒体证据支持按项目 scope 读取原始图片、视频、音频以及实际首帧 / 末帧;审片中心使用文件级预览、SHA-256、FFprobe 和 QA 证据共同验收,不把路径字符串当作已生成事实。
- 系统存储页支持保留周期和“仅清理无引用临时文件”的清理预览;回收动作只处理 `outputs/frames/tmp/cache` 中未被资产版本、媒体证据或合成清单引用的文件,并写入审计。
- 模型协议、Worker 环境变量、状态字段和接口返回约定见 `/Users/xz/Documents/daima/ai短剧/ai-drama-platform/docs/API_REFERENCE.md`。
- 本地验证脚本会修改 SQLite,因此多个 smoke 脚本应顺序执行;并行写入会触发 SQLite 的正常写锁保护。
## 私有商业部署
生产编排 profile 位于 `/Users/xz/Documents/daima/ai短剧/ai-drama-platform/deploy/`,包含 API、独立 Worker、Nginx 前端、PostgreSQL、Redis 和 MinIO/S3-compatible 对象存储。当前业务代码的数据库真源仍是 Node 24 SQLite;compose 会先把目标基础设施和连接契约部署起来,但不会伪称已经完成 PostgreSQL、Redis 或对象存储运行时切换。系统管理员可以在系统总览查看生产就绪度,并通过 `/api/system/backups` 创建可审计的 SQLite 快照。具体边界和启动命令见 `/Users/xz/Documents/daima/ai短剧/ai-drama-platform/deploy/README.md`。
NewAPI 音频请求格式见:
```text
/Users/xz/Documents/daima/ai短剧/ai-drama-platform/docs/NEWAPI_AUDIO_WORKFLOW.md
```
## 商业平台研究
功能研究与本地版能力映射见:
```text
/Users/xz/Documents/daima/ai短剧/ai-drama-platform/docs/MARKET_RESEARCH_2026.md
/Users/xz/Documents/daima/ai短剧/ai-drama-platform/docs/COMMERCIAL_PLATFORM_BLUEPRINT.md
/Users/xz/Documents/daima/ai短剧/ai-drama-platform/docs/MULTI_TENANT_DESIGN.md
/Users/xz/Documents/daima/ai短剧/ai-drama-platform/docs/superpowers/plans/2026-08-19-commercial-multitenant-platform.md
```
## 输出目录
```text
/Users/xz/Documents/daima/ai短剧/ai-drama-platform/exports/<project-id>
```
每个项目单独拥有一个子目录,子目录对应 series bible、角色、场景、道具、分镜、配音、QA、剪辑工程和最终视频交付;服务端不会把一个项目的导出写进另一个项目目录。