You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

8.8 KiB

分镜服务完整实现

日期:2026-02-04
类型:Feature Implementation
影响范围:后端 - 分镜管理模块


概述

完整实现分镜管理服务(Storyboard Service),包括分镜 CRUD、排序管理、元素关联、筛选搜索等核心功能。

实现内容

1. 数据模型层

新建文件server/app/models/storyboard.py

  • Storyboard 模型:分镜主表
  • StoryboardItem 模型:分镜元素关联表
  • ShotSizeType 枚举:8种景别类型
  • CameraMovementType 枚举:9种运镜类型
  • ItemType 枚举:元素类型(剧本元素标签/项目素材)

技术栈符合度

  • UUID v7 应用层生成(generate_uuid_v7()
  • 枚举类型使用 SMALLINT + IntEnum
  • 时间戳使用 TIMESTAMPTZ
  • 无物理外键约束
  • CHECK 约束和 UNIQUE 约束

2. Schema 层

新建文件server/app/schemas/storyboard.py

  • StoryboardCreate:创建分镜请求
  • StoryboardUpdate:更新分镜请求
  • StoryboardResponse:分镜响应
  • StoryboardReorder:重新排序请求
  • StoryboardItemCreate:添加元素请求
  • StoryboardItemUpdate:更新元素请求
  • StoryboardItemResponse:元素响应
  • StoryboardListResponse:分镜列表响应
  • StoryboardDurationStats:时长统计响应

3. 仓储层

新建文件server/app/repositories/storyboard_repository.py

实现功能

  • 分镜 CRUD 操作
  • 排序管理(获取最大 order_index、批量更新顺序)
  • 筛选查询(按景别、运镜筛选)
  • 全文搜索(标题、描述、拍摄描述)
  • 时长统计(总时长、平均时长、方差)
  • 分镜元素关联 CRUD
  • 批量操作(批量检查存在性)

技术栈符合度

  • 使用 async/await 异步编程
  • 使用 flush() 而非 commit()(Repository 职责)
  • 日志使用 %-formatting 格式化

4. 服务层

新建文件server/app/services/storyboard_service.py

实现功能

  • 分镜 CRUD(创建、查询、更新、删除)
  • 排序管理(重新排序、删除后自动重排)
  • 元素关联管理(添加、移除、更新属性、批量调整顺序)
  • 筛选和搜索(按景别/运镜筛选、全文搜索)
  • 时长统计(项目总时长、平均时长、方差)
  • 权限检查(应用层验证项目权限)

技术栈符合度

  • 使用 commit() 提交事务(Service 职责)
  • 日志记录关键操作
  • 异常日志使用 exc_info=True
  • 应用层验证引用完整性

5. API 路由层

新建文件server/app/api/v1/storyboards.py

实现端点(13个):

  1. GET /storyboards - 获取分镜列表
  2. POST /storyboards - 创建分镜
  3. GET /storyboards/{id} - 获取分镜详情
  4. PUT /storyboards/{id} - 更新分镜
  5. DELETE /storyboards/{id} - 删除分镜
  6. POST /storyboards/reorder - 重新排序分镜
  7. POST /storyboards/{id}/items - 添加元素到分镜
  8. GET /storyboards/{id}/items - 获取分镜的所有关联元素
  9. PATCH /storyboards/items/{id} - 更新元素的关联属性
  10. DELETE /storyboards/items/{id} - 从分镜移除元素
  11. POST /storyboards/{id}/items/reorder - 批量调整元素顺序
  12. GET /storyboards/filter - 按景别和运镜筛选分镜
  13. GET /storyboards/search - 全文搜索分镜
  14. GET /storyboards/statistics/duration - 获取项目时长统计

技术栈符合度

  • 使用 ApiResponse 统一响应格式
  • 依赖注入模式
  • 日志记录 API 调用

6. 数据库迁移

新建文件server/alembic/versions/20260204_1600_create_storyboards_tables.py

迁移内容

  • 创建 storyboards
  • 创建 storyboard_items
  • 创建索引(B-tree、GIN、部分索引)
  • 创建全文搜索索引(pg_trgm)
  • 创建触发器(自动更新 updated_at)
  • 添加表和列注释

索引策略

  • B-tree 索引:project_id, order_index
  • 部分索引:shot_size, camera_movement(仅非空值)
  • GIN 索引:metadata, 全文搜索(title, description, shooting_description)

7. 路由注册

修改文件server/app/api/v1/__init__.py

  • 导入 storyboards 模块
  • 注册路由:/storyboards

核心设计

1. 镜号管理

  • 设计:使用 order_index 作为镜号(1, 2, 3...)
  • 创建时:自动分配下一个序号
  • 删除时:后续分镜的 order_index 自动 -1
  • 排序时:批量更新 order_index
  • 优势:极简设计,无需单独维护镜号字段

2. 影视专业字段

  • 景别(shot_size):SMALLINT 存储(1-8),代码层使用 IntEnum
    • 8种标准景别:大远景、远景、全景、中景、中近景、特写、大特写、过肩
  • 运镜(camera_movement):SMALLINT 存储(1-9),代码层使用 IntEnum
    • 9种标准运镜:固定、摇镜、俯仰、推拉、变焦、跟踪、环绕、升降、手持
  • 拍摄描述(shooting_description):TEXT 类型,支持全文搜索

3. 元素关联设计

统一关联表storyboard_items

  • 两种关联类型
    • item_type=1:剧本元素标签(角色/场景/道具的变体)
    • item_type=2:项目素材(实拍素材、音频、视频等)
  • 关联字段
    • element_tag_id:指向 screenplay_element_tags.tag_id
    • resource_id:指向 project_resources.project_resource_id
  • 冗余字段element_name, tag_label, cover_url 避免 JOIN
  • 关联属性action_description(动作)、spatial_position(位置)、is_visible(可见性)
  • 排序与层级display_order(显示顺序)、z_index(视觉层级)

4. 时间轴管理

  • start_time/end_time:用于视频编辑时间轴定位
  • estimated_duration/actual_duration:预估时长 vs 实际时长
  • 时间范围查询:支持 GiST 索引(未来扩展)

技术栈符合度检查

数据库设计

  • UUID v7 应用层生成(generate_uuid_v7()
  • 枚举类型使用 SMALLINT + IntEnum
  • 时间戳使用 TIMESTAMPTZ(ADR 006)
  • 无物理外键约束,应用层验证引用完整性
  • 索引策略完整(B-tree、GIN、部分索引)

后端代码

  • 异步编程(async/await)
  • Repository 使用 flush(),Service 使用 commit()
  • 日志使用 %-formatting 格式化
  • 异常日志使用 exc_info=True
  • API 响应使用 ApiResponse 统一格式
  • 依赖注入模式

文档规范

  • Changelog 文档创建
  • 文件路径符合规范:docs/server/changelogs/
  • 日期格式:YYYY-MM-DD

后续工作

阶段 3:分镜看板服务(未实现)

  • 创建 StoryboardBoardService
  • 实现六种轨道(分镜、资源、视频、音效、对白、配音)
  • 实时计算时间轴数据
  • 创建 API 路由

阶段 4:项目素材关联(未实现)

  • 扩展 ProjectResource 模型(添加 usage_count 字段)
  • 创建数据库迁移脚本
  • 扩展 ProjectResourceService(引用计数维护)
  • 实现删除保护逻辑

测试建议

单元测试

  • test_storyboard_repository.py:仓储层测试
  • test_storyboard_service.py:服务层测试

集成测试

  • test_storyboard_api.py:API 端点测试

测试场景

  1. 创建分镜并自动分配 order_index
  2. 删除分镜后自动重排序
  3. 批量调整分镜顺序
  4. 添加/移除元素到分镜
  5. 按景别/运镜筛选分镜
  6. 全文搜索分镜
  7. 获取项目时长统计

数据库迁移

执行迁移

# 在 Docker 容器内执行
docker exec jointo-server-app python scripts/db_migrate.py upgrade

验证迁移

# 检查当前迁移版本
docker exec jointo-server-app alembic current

# 查看表结构
docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "\d storyboards"
docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "\d storyboard_items"

相关文档


实现者:Kiro AI
审核状态:待审核
部署状态:待部署