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.
 

7.6 KiB

分镜看板服务实现

日期:2026-02-04
类型:功能实现
影响范围:后端服务层、API 层


变更概述

实现分镜看板服务(StoryboardBoardService),提供多轨道视图展示分镜及其关联资源的可视化看板功能。


变更详情

1. 创建 Schema 定义

文件server/app/schemas/storyboard_board.py

创建了 4 个 Schema 类:

  • StoryboardBoardItem - 分镜看板项
  • StoryboardBoardTrack - 分镜看板轨道
  • StoryboardBoardData - 完整分镜看板数据
  • StoryboardReorder - 分镜重新排序请求

2. 创建 Service 层

文件server/app/services/storyboard_board_service.py

实现了 StoryboardBoardService 类,提供以下功能:

核心方法

  1. get_storyboard_board_data() - 获取项目的完整分镜看板数据

    • 实时从分镜表计算,无独立数据存储
    • 支持按轨道类型筛选
    • 计算每个项的 start_time 和 end_time
    • 计算项目总时长
  2. reorder_storyboards() - 调整分镜顺序

    • 直接更新分镜表的 order_index 字段
    • 使用事务批量更新
    • 应用层验证分镜存在性
    • 返回更新后的看板数据
  3. get_track_items() - 获取指定轨道的所有项

    • 支持 6 种轨道类型:storyboard/resource/video/sound/subtitle/voice
    • 验证轨道类型有效性
  4. get_items_by_time_range() - 查询时间范围内的所有项

    • 支持时间范围筛选
    • 支持按轨道类型筛选

私有方法

  • _calculate_storyboard_board_tracks() - 实时计算分镜看板轨道数据
  • _get_track_name() - 获取轨道显示名称

3. 创建 API 路由

文件server/app/api/v1/storyboard_board.py

实现了 4 个 API 端点:

  1. GET /projects/{project_id}/storyboard-board

    • 获取项目分镜看板数据
    • 查询参数:track_types(可选,逗号分隔)
  2. POST /projects/{project_id}/storyboard-board/reorder

    • 调整分镜顺序
    • 请求体:storyboard_orders(分镜 ID 到新排序的映射)
  3. GET /projects/{project_id}/storyboard-board/tracks/{track_type}

    • 获取指定轨道的所有项
    • 路径参数:track_type
  4. GET /projects/{project_id}/storyboard-board/items/time-range

    • 查询时间范围内的所有项
    • 查询参数:start_time、end_time、track_types(可选)

4. 注册路由

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

  • 导入 storyboard_board 模块
  • 注册路由:api_router.include_router(storyboard_board.router, tags=["分镜看板"])

技术栈符合性

完全符合 jointo-tech-stack 规范

  1. 日志系统

    • 使用标准库 logging
    • 使用 %-formatting 格式化
    • 异常日志使用 exc_info=True
  2. 异步编程

    • 所有数据库操作使用 async/await
    • 使用 AsyncSession
  3. 无物理外键

    • 应用层验证引用完整性
    • 使用 batch_exists() 批量检查分镜存在性
  4. 事务管理

    • 批量更新使用 async with self.db.begin()
  5. 统一响应格式

    • 所有 API 使用 ApiResponse 格式
  6. 权限检查

    • 使用 ProjectRepository.check_user_permission()
    • 区分 viewer 和 editor 权限

设计特点

1. 无独立数据存储

分镜看板服务不创建独立的数据表,所有数据实时从分镜表计算:

  • 优点

    • 避免数据冗余
    • 自动同步(分镜变化立即反映到看板)
    • 简化维护(无需维护同步逻辑)
  • 实现

    • 按 order_index 排序分镜
    • 累积计算每个分镜的时间位置
    • 实时组装轨道数据

2. 六种轨道类型

轨道类型 数据来源 说明
storyboard storyboards 表 分镜元素块
resource storyboard_items 表 项目素材(角色、场景、道具)
video 待实现 分镜生成的视频
sound 待实现 分镜搭配的音效
subtitle 待实现 对白台词文本
voice 待实现 对白生成的配音音频

注意:当前实现仅包含 storyboard 轨道,其他轨道需要在后续实现中添加 Relationship 查询。

3. 时间计算逻辑

current_time = 0.0
for storyboard in storyboards:
    start_time = current_time
    duration = float(storyboard.actual_duration or storyboard.estimated_duration or 0)
    end_time = current_time + duration
    current_time = end_time

API 示例

1. 获取分镜看板数据

请求

GET /api/v1/projects/019c0361-ea8e-7d43-bbcc-edd8eea06bb6/storyboard-board?track_types=storyboard,video

响应

{
  "success": true,
  "code": 200,
  "message": "分镜看板数据获取成功",
  "data": {
    "project_id": "019c0361-ea8e-7d43-bbcc-edd8eea06bb6",
    "total_duration": 120.5,
    "storyboard_count": 15,
    "tracks": [
      {
        "type": "storyboard",
        "name": "分镜轨道",
        "items": [
          {
            "id": "019c0361-ea8e-7d43-bbcc-edd8eea06bb7",
            "type": "storyboard",
            "start_time": 0,
            "end_time": 5.5,
            "data": {
              "id": "019c0361-ea8e-7d43-bbcc-edd8eea06bb7",
              "title": "开场镜头",
              "shot_size": 3,
              "camera_movement": 1
            }
          }
        ]
      }
    ]
  },
  "timestamp": "2026-02-04T10:00:00Z"
}

2. 调整分镜顺序

请求

POST /api/v1/projects/019c0361-ea8e-7d43-bbcc-edd8eea06bb6/storyboard-board/reorder
Content-Type: application/json

{
  "storyboard_orders": {
    "019c0361-ea8e-7d43-bbcc-edd8eea06bb7": 0,
    "019c0361-ea8e-7d43-bbcc-edd8eea06bb8": 1,
    "019c0361-ea8e-7d43-bbcc-edd8eea06bb9": 2
  }
}

响应

{
  "success": true,
  "code": 200,
  "message": "分镜顺序调整成功",
  "data": {
    "project_id": "019c0361-ea8e-7d43-bbcc-edd8eea06bb6",
    "total_duration": 120.5,
    "storyboard_count": 15,
    "tracks": [...]
  },
  "timestamp": "2026-02-04T10:00:00Z"
}

后续优化建议

1. 性能优化

  • 缓存策略:使用 Redis 缓存分镜看板数据(5 分钟)
  • 分页加载:对于大型项目(100+ 分镜)实现分页
  • 前端虚拟滚动:只渲染可见区域的轨道项

2. 功能扩展

  • 实现其他轨道:resource、video、sound、subtitle、voice
  • 添加 Relationship:在 Storyboard 模型中配置关联关系
  • 预加载关联数据:使用 selectinload() 减少 N+1 查询

3. 数据完整性

  • 引用计数维护:在 StoryboardService 中维护 project_resources.usage_count
  • 删除保护:usage_count > 0 的素材禁止删除

相关文档


测试建议

单元测试

  • test_get_storyboard_board_data() - 测试获取看板数据
  • test_reorder_storyboards() - 测试调整分镜顺序
  • test_get_track_items() - 测试获取轨道数据
  • test_get_items_by_time_range() - 测试时间范围查询
  • test_calculate_storyboard_board_tracks() - 测试轨道计算逻辑

集成测试

  • test_storyboard_board_api_get() - 测试 GET 端点
  • test_storyboard_board_api_reorder() - 测试 POST 端点
  • test_storyboard_board_api_tracks() - 测试轨道端点
  • test_storyboard_board_api_time_range() - 测试时间范围端点

变更作者:Kiro AI
审核状态:待审核
部署状态:待部署