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.
9.0 KiB
9.0 KiB
Changelog: 为分镜资源添加命名和描述功能
日期: 2026-02-12
类型: Feature
影响范围: 后端 API、数据库结构
变更概述
为分镜图片(storyboard_images)和分镜视频(storyboard_videos)表添加 name 和 description 字段,支持用户自定义命名和描述资源,同时提供 AI 默认命名规则。
业务价值
- 资源命名:用户可以为生成的分镜图片和视频命名,便于在生成视频时通过 @ 引用特定资源
- 资源描述:用户可以添加描述信息,记录资源的用途、特点等
- 默认命名:AI 生成资源时自动使用规范化命名(镜号-分镜名称-方案编号)
- 灵活性:用户可以随时修改资源名称和描述
数据库变更
迁移文件
server/alembic/versions/20260212_1900_add_name_description_to_resources.py
新增字段
storyboard_images 表
| 字段 | 类型 | 约束 | 默认值 | 说明 |
|---|---|---|---|---|
name |
TEXT | nullable | NULL | 资源名称(用户可自定义,AI 生成时默认为:镜号-分镜名称-方案编号) |
description |
TEXT | nullable | NULL | 资源描述(用户自定义) |
storyboard_videos 表
| 字段 | 类型 | 约束 | 默认值 | 说明 |
|---|---|---|---|---|
name |
TEXT | nullable | NULL | 资源名称(默认为:镜号-分镜名称-方案编号) |
description |
TEXT | nullable | NULL | 资源描述(用户自定义,前期预留) |
字段注释
-- storyboard_images
COMMENT ON COLUMN storyboard_images.name IS '资源名称(用户可自定义,AI 生成时默认为:镜号-分镜名称-方案编号)';
COMMENT ON COLUMN storyboard_images.description IS '资源描述(用户自定义)';
-- storyboard_videos
COMMENT ON COLUMN storyboard_videos.name IS '资源名称(默认为:镜号-分镜名称-方案编号)';
COMMENT ON COLUMN storyboard_videos.description IS '资源描述(用户自定义,前期预留)';
代码变更
Model 层
文件: server/app/models/storyboard_resource.py
class StoryboardImage(SQLModel, table=True):
# ... 其他字段
# 资源命名
name: Optional[str] = Field(default=None, nullable=True)
description: Optional[str] = Field(default=None, nullable=True)
# ... 其他字段
class StoryboardVideo(SQLModel, table=True):
# ... 其他字段
# 资源命名
name: Optional[str] = Field(default=None, nullable=True)
description: Optional[str] = Field(default=None, nullable=True)
# ... 其他字段
Schema 层
文件: server/app/schemas/storyboard_resource.py
创建请求 Schema
class ImageCreate(BaseModel):
"""创建分镜图片请求"""
name: Optional[str] = Field(None, description="资源名称(可选,不提供则自动生成)")
description: Optional[str] = Field(None, description="资源描述")
# ... 其他字段
class VideoCreate(BaseModel):
"""创建分镜视频请求"""
name: Optional[str] = Field(None, description="资源名称(可选,不提供则自动生成)")
description: Optional[str] = Field(None, description="资源描述")
# ... 其他字段
响应 Schema
class ImageResponse(BaseModel):
"""分镜图片响应"""
image_id: str = Field(..., serialization_alias="imageId")
storyboard_id: str = Field(..., serialization_alias="storyboardId")
name: Optional[str] = Field(None, description="资源名称")
description: Optional[str] = Field(None, description="资源描述")
# ... 其他字段
class VideoResponse(BaseModel):
"""分镜视频响应"""
video_id: str = Field(..., serialization_alias="videoId")
storyboard_id: str = Field(..., serialization_alias="storyboardId")
name: Optional[str] = Field(None, description="资源名称")
description: Optional[str] = Field(None, description="资源描述")
# ... 其他字段
默认命名规则
命名格式
{镜号:03d}-{分镜名称}-方案{版本:02d}
示例
- 分镜 1,标题"开场镜头",版本 1:
001-开场镜头-方案01 - 分镜 5,标题"角色特写",版本 2:
005-角色特写-方案02 - 分镜 12,标题"场景切换",版本 1:
012-场景切换-方案01
实现位置
默认命名逻辑将在 Service 层实现:
def generate_default_resource_name(
order_index: int,
storyboard_title: str,
version: int
) -> str:
"""生成默认资源名称
Args:
order_index: 分镜序号(从 storyboards.order_index 获取)
storyboard_title: 分镜标题(从 storyboards.title 获取)
version: 资源版本号(从 storyboard_images/videos.version 获取)
Returns:
格式化的资源名称,如:001-开场镜头-方案01
"""
shot_number = f"{order_index:03d}"
version_label = f"方案{version:02d}"
return f"{shot_number}-{storyboard_title}-{version_label}"
API 变更
请求参数变更
创建分镜图片/视频
新增可选参数:
{
"name": "自定义名称", // 可选,不提供则自动生成
"description": "资源描述", // 可选
"url": "https://...",
"checksum": "...",
// ... 其他字段
}
响应数据变更
分镜图片/视频响应
新增字段:
{
"imageId": "uuid",
"storyboardId": "uuid",
"name": "001-开场镜头-方案01", // 新增
"description": "用户自定义描述", // 新增
"url": "https://...",
// ... 其他字段
}
使用场景
场景 1:AI 生成分镜图片
# Service 层自动生成名称
storyboard = await storyboard_repo.get_by_id(storyboard_id)
default_name = generate_default_resource_name(
order_index=storyboard.order_index,
storyboard_title=storyboard.title,
version=1
)
image = StoryboardImage(
storyboard_id=storyboard_id,
name=default_name, # 自动生成:001-开场镜头-方案01
url=generated_url,
# ... 其他字段
)
场景 2:用户自定义命名
# 用户在创建时提供自定义名称
image_data = ImageCreate(
name="我喜欢的版本",
description="这个版本的光线效果最好",
url=url,
# ... 其他字段
)
场景 3:生成视频时引用
# 用户在生成视频时可以通过名称引用特定图片
prompt = "使用 @001-开场镜头-方案01 作为视频的第一帧"
迁移指南
数据库迁移
# 在 Docker 容器内执行迁移
docker exec jointo-server-app alembic upgrade head
现有数据处理
- 现有的分镜图片和视频资源的
name和description字段将为 NULL - 可选:运行数据迁移脚本为现有资源生成默认名称
前端适配
-
创建资源时:
- 支持可选的
name和description参数 - 如果用户不提供,后端将自动生成
- 支持可选的
-
显示资源时:
- 在资源列表中显示
name字段 - 支持显示和编辑
description字段
- 在资源列表中显示
-
引用资源时:
- 支持通过 @ 符号引用资源名称
- 提供资源名称的自动补全功能
后续优化
短期(1-2 周)
- 在 Service 层实现默认命名生成逻辑
- 为现有资源生成默认名称(数据迁移脚本)
- 添加资源名称修改 API
中期(1 个月)
- 支持资源名称搜索
- 支持资源名称唯一性校验(可选)
- 添加资源描述的富文本支持
长期(3 个月)
- 支持资源标签系统
- 支持资源分组管理
- 支持资源版本历史
测试验证
数据库验证
-- 验证字段已添加
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'storyboard_images'
AND column_name IN ('name', 'description');
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'storyboard_videos'
AND column_name IN ('name', 'description');
API 测试
# 测试创建带名称的图片
curl -X POST http://localhost:8000/api/v1/storyboards/{id}/images \
-H "Content-Type: application/json" \
-d '{
"name": "测试图片",
"description": "这是一个测试",
"url": "https://example.com/image.jpg",
"checksum": "...",
"storagePath": "..."
}'
注意事项
- 向后兼容:现有 API 调用不受影响,
name和description为可选字段 - NULL 值处理:前端需要处理
name和description为 NULL 的情况 - 命名冲突:当前不强制名称唯一性,允许多个资源使用相同名称
- 性能影响:新增字段为 TEXT 类型,不影响查询性能(无索引)
相关文档
变更记录
- 2026-02-12: 初始版本,完成数据库迁移和 Model/Schema 更新