feat(storyboard): 故事板改分镜制(单场独立重跑/历史)+ 视频过审闸 + 审核前端如实化
三块改动在 services/views/pipeline/App/api 等文件按行交织、且过审闸后端依赖故事板新 模型,无法拆成各自独立可编译的提交,故合并为一次: · 故事板分镜制:新增 StoryboardShot/StoryboardShotVersion(对标 VideoSegment/Version) + 数据迁移(采用版每帧转一 shot+已采用版本)。每镜一个 shot,各自历史版本,可单场 重跑、逐场切换/采用,新增「开始生成故事板/单场重跑/采用某版」端点。重跑非阻塞(后台 静默轮询出图,不锁其它场按钮);历史「查看」与「采用」分离(切版本不丢在制重跑)。 视频取分镜图/删分镜清理/过审闸全部改读 storyboard_shots。 · 视频生成前过审闸:点生成校验含真人脸的人物立绘/故事板分镜是否过审,未过审弹窗列出 哪一镜/哪个,可一键送审,挡住不生成(collect_video_review_blockers + precheck 端点)。 · 审核前端如实化:不再 `|| "processing"` 伪造审核中;送审失败经 onNotify 如实提示; 审核轮询扩到视频阶段,送审后能看着盾变绿。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,8 @@ from .models import (
|
||||
ScriptSegment,
|
||||
ScriptVersion,
|
||||
StoryboardFrame,
|
||||
StoryboardShot,
|
||||
StoryboardShotVersion,
|
||||
StoryboardVersion,
|
||||
SubtitleTrack,
|
||||
Timeline,
|
||||
@@ -130,6 +132,54 @@ class StoryboardVersionSerializer(serializers.ModelSerializer):
|
||||
read_only_fields = fields
|
||||
|
||||
|
||||
# ── 故事板分镜制(对标 VideoSegment/Version):每镜一个 shot,采用版缩略图 + 各自历史版本 ──
|
||||
class StoryboardShotSerializer(serializers.ModelSerializer):
|
||||
adopted_asset = serializers.SerializerMethodField()
|
||||
adopted_asset_url = serializers.SerializerMethodField()
|
||||
# 分镜图含人脸,后端自动送火山人像审核;暴露采用版审核态让前端挂盾牌
|
||||
review_status = serializers.SerializerMethodField()
|
||||
review_error = serializers.SerializerMethodField()
|
||||
versions = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = StoryboardShot
|
||||
fields = ["id", "script_segment", "sort_order", "status", "error_message", "prompt",
|
||||
"adopted_version", "adopted_asset", "adopted_asset_url", "review_status", "review_error", "versions"]
|
||||
read_only_fields = fields
|
||||
|
||||
def get_adopted_asset(self, obj):
|
||||
v = obj.adopted_version
|
||||
return str(v.asset_id) if v and v.asset_id else None
|
||||
|
||||
def get_adopted_asset_url(self, obj) -> str:
|
||||
v = obj.adopted_version
|
||||
return _asset_preview_url(v.asset) if v is not None else ""
|
||||
|
||||
def get_review_status(self, obj) -> str:
|
||||
v = obj.adopted_version
|
||||
return (getattr(v.asset, "review_status", "") or "") if (v and v.asset_id) else ""
|
||||
|
||||
def get_review_error(self, obj) -> str:
|
||||
v = obj.adopted_version
|
||||
return (getattr(v.asset, "review_error", "") or "") if (v and v.asset_id) else ""
|
||||
|
||||
def get_versions(self, obj):
|
||||
versions = sorted(obj.versions.all(), key=lambda v: (v.created_at is None, v.created_at), reverse=True)
|
||||
return [
|
||||
{
|
||||
"id": str(v.id),
|
||||
"asset": str(v.asset_id) if v.asset_id else None,
|
||||
"asset_url": _asset_preview_url(v.asset) if v.asset_id else "",
|
||||
"prompt": v.prompt,
|
||||
"is_adopted": v.is_adopted,
|
||||
"review_status": (getattr(v.asset, "review_status", "") or "") if v.asset_id else "",
|
||||
"review_error": (getattr(v.asset, "review_error", "") or "") if v.asset_id else "",
|
||||
"created_at": v.created_at.isoformat() if v.created_at else "",
|
||||
}
|
||||
for v in versions
|
||||
]
|
||||
|
||||
|
||||
class VideoSegmentVersionSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = VideoSegmentVersion
|
||||
@@ -289,7 +339,8 @@ class ProjectSerializer(serializers.ModelSerializer):
|
||||
video_segments = VideoSegmentSerializer(many=True, read_only=True)
|
||||
script_versions = ScriptVersionSerializer(many=True, read_only=True)
|
||||
base_asset_groups = BaseAssetGroupSerializer(many=True, read_only=True)
|
||||
storyboard_versions = StoryboardVersionSerializer(many=True, read_only=True)
|
||||
storyboard_versions = StoryboardVersionSerializer(many=True, read_only=True) # 过渡期保留(旧整版,新生成不再写)
|
||||
storyboard_shots = StoryboardShotSerializer(many=True, read_only=True)
|
||||
timeline = TimelineSerializer(read_only=True)
|
||||
|
||||
class Meta:
|
||||
@@ -307,6 +358,7 @@ class ProjectSerializer(serializers.ModelSerializer):
|
||||
"script_versions",
|
||||
"base_asset_groups",
|
||||
"storyboard_versions",
|
||||
"storyboard_shots",
|
||||
"video_segments",
|
||||
"timeline",
|
||||
"created_at",
|
||||
|
||||
Reference in New Issue
Block a user