修复拆镜复刻路由,修补API参数说明,版本迁移异常修复
This commit is contained in:
@@ -8,7 +8,16 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.dependencies import get_current_user, get_db
|
||||
from app.models.user import User
|
||||
from app.enums.shot_replicate import ModuleCodeEnum, ShotReplicateStepCodeEnum
|
||||
from app.enums.shot_replicate import (
|
||||
ModuleCodeEnum,
|
||||
ShotAnalysisStatusEnum,
|
||||
ShotReplicateStepCodeEnum,
|
||||
ShotSegmentAnalysisStatusEnum,
|
||||
ShotSegmentReplicateStatusEnum,
|
||||
ShotSegmentSourceModeEnum,
|
||||
ShotSplitStatusEnum,
|
||||
ShotTaskSetStatusEnum,
|
||||
)
|
||||
from app.schemas.shot_replicate import (
|
||||
ShotReplicateActionOut,
|
||||
ShotReplicateDeleteOut,
|
||||
@@ -222,6 +231,7 @@ async def _mark_dispatch_failed_and_raise(
|
||||
"/spec",
|
||||
response_model=ShotReplicateSpecOut,
|
||||
summary="查询拆镜复刻模块状态枚举和步骤 JSON 结构说明",
|
||||
description="保留给调试和前端兜底读取。原业务接口已经在 Path、Query、Body 和响应模型字段上直接展示参数说明与枚举值。",
|
||||
)
|
||||
async def get_spec():
|
||||
return ShotReplicateSpecOut()
|
||||
@@ -231,9 +241,14 @@ async def get_spec():
|
||||
"/task-sets",
|
||||
response_model=ShotTaskSetDetailOut,
|
||||
summary="创建拆镜总任务集并异步分析原视频",
|
||||
description=(
|
||||
"创建拆镜总任务集,保存原视频地址和时长,随后异步投递原视频 AI 分析任务。"
|
||||
"分析完成后会写入原视频内容、分类、受众和 AI 建议拆镜时间段。"
|
||||
"状态枚举直接见本接口响应字段:status、analysis_status、split_status。"
|
||||
),
|
||||
)
|
||||
async def create_shot_task_set(
|
||||
req: ShotTaskSetCreate = Body(...),
|
||||
req: ShotTaskSetCreate = Body(..., description="创建拆镜总任务集参数:原视频 URL、视频时长、标题和可选幂等键"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -275,21 +290,21 @@ async def create_shot_task_set(
|
||||
summary="查询拆镜总任务集列表",
|
||||
)
|
||||
async def list_shot_task_sets(
|
||||
status: str | None = Query(None, description="总任务状态,见 ShotTaskSetStatusEnum"),
|
||||
analysis_status: str | None = Query(None, description="分析状态,见 ShotAnalysisStatusEnum"),
|
||||
split_status: str | None = Query(None, description="拆镜状态,见 ShotSplitStatusEnum"),
|
||||
keyword: str | None = Query(None, description="标题/内容关键词"),
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(20, ge=1, le=100),
|
||||
status: ShotTaskSetStatusEnum | None = Query(None, description="总任务状态筛选:pending_analysis=等待分析,analyzing=分析中,analysis_completed=分析完成,analysis_failed=分析失败,splitting=拆镜中,split_completed=拆镜完成,partial_failed=部分失败,failed=失败,deleted=已软删"),
|
||||
analysis_status: ShotAnalysisStatusEnum | None = Query(None, description="原视频分析状态筛选:pending=待分析,processing=分析中,completed=分析完成,failed=分析失败"),
|
||||
split_status: ShotSplitStatusEnum | None = Query(None, description="拆镜状态筛选:none=尚未拆镜,pending=待拆镜,processing=拆镜中,completed=拆镜完成,failed=拆镜失败,retry_waiting=等待恢复重试"),
|
||||
keyword: str | None = Query(None, description="标题/原视频内容/分类/受众关键词,模糊搜索;为空不过滤"),
|
||||
page: int = Query(1, ge=1, description="分页页码,从1开始"),
|
||||
page_size: int = Query(20, ge=1, le=100, description="每页数量,范围1-100"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
return await list_task_sets(
|
||||
db,
|
||||
current_user=current_user,
|
||||
status=status,
|
||||
analysis_status=analysis_status,
|
||||
split_status=split_status,
|
||||
status=status.value if status else None,
|
||||
analysis_status=analysis_status.value if analysis_status else None,
|
||||
split_status=split_status.value if split_status else None,
|
||||
keyword=keyword,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
@@ -300,9 +315,10 @@ async def list_shot_task_sets(
|
||||
"/task-sets/{task_set_id}",
|
||||
response_model=ShotTaskSetDetailOut,
|
||||
summary="获取拆镜总任务集详情",
|
||||
description="根据拆镜总任务集ID查询详情,包含原视频分析结果、AI 建议拆镜列表和当前总任务状态。",
|
||||
)
|
||||
async def get_shot_task_set(
|
||||
task_set_id: str = Path(...),
|
||||
task_set_id: str = Path(..., description="拆镜总任务集ID,即 shot_replicate_task_sets.id"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -313,10 +329,14 @@ async def get_shot_task_set(
|
||||
"/task-sets/{task_set_id}/split-by-ai",
|
||||
response_model=ShotSplitByAIOut,
|
||||
summary="按 AI 建议方案异步拆镜",
|
||||
description=(
|
||||
"基于原视频 AI 分析生成的建议时间段创建拆镜片段,并异步投递 ffmpeg 切割任务。"
|
||||
"selected_indices 不传时默认按全部 AI 建议拆镜;replace_existing=true 时会软删旧 AI 建议片段后重新创建。"
|
||||
),
|
||||
)
|
||||
async def split_by_ai(
|
||||
task_set_id: str = Path(...),
|
||||
req: ShotSplitByAIRequest = Body(default_factory=ShotSplitByAIRequest),
|
||||
task_set_id: str = Path(..., description="拆镜总任务集ID,即 shot_replicate_task_sets.id"),
|
||||
req: ShotSplitByAIRequest = Body(default_factory=ShotSplitByAIRequest, description="AI 建议拆镜参数:可选择建议序号,也可选择是否覆盖旧 AI 片段"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -345,10 +365,11 @@ async def split_by_ai(
|
||||
"/task-sets/{task_set_id}/split-custom",
|
||||
response_model=ShotSplitCustomOut,
|
||||
summary="按用户自定义开始/结束秒异步拆单条片段",
|
||||
description="按用户传入的 start_second/end_second 创建 custom 来源片段,并异步投递 ffmpeg 切割任务;切割完成后可进入复刻项目。",
|
||||
)
|
||||
async def split_custom(
|
||||
task_set_id: str = Path(...),
|
||||
req: ShotSplitCustomRequest = Body(...),
|
||||
task_set_id: str = Path(..., description="拆镜总任务集ID,即 shot_replicate_task_sets.id"),
|
||||
req: ShotSplitCustomRequest = Body(..., description="自定义拆镜时间段参数,end_second 必须大于 start_second"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -376,15 +397,16 @@ async def split_custom(
|
||||
"/task-sets/{task_set_id}/segments",
|
||||
response_model=ShotSegmentListOut,
|
||||
summary="查询拆镜片段列表",
|
||||
description="分页查询指定拆镜总任务集下的片段列表,可按来源、切割状态、片段分析状态和复刻状态筛选。",
|
||||
)
|
||||
async def list_task_set_segments(
|
||||
task_set_id: str = Path(...),
|
||||
source_mode: str | None = Query(None, description="ai_suggestion/custom"),
|
||||
split_status: str | None = Query(None, description="拆镜状态"),
|
||||
analysis_status: str | None = Query(None, description="片段分析状态"),
|
||||
replicate_status: str | None = Query(None, description="复刻状态"),
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(20, ge=1, le=100),
|
||||
task_set_id: str = Path(..., description="拆镜总任务集ID,即 shot_replicate_task_sets.id"),
|
||||
source_mode: ShotSegmentSourceModeEnum | None = Query(None, description="片段来源:ai_suggestion=AI 建议拆镜,custom=用户自定义拆镜"),
|
||||
split_status: ShotSplitStatusEnum | None = Query(None, description="切割状态:none=尚未拆镜,pending=待拆镜,processing=拆镜中,completed=拆镜完成,failed=拆镜失败,retry_waiting=等待恢复重试"),
|
||||
analysis_status: ShotSegmentAnalysisStatusEnum | None = Query(None, description="片段分析状态:not_required=无需单独分析,pending=等待分析,processing=分析中,completed=分析完成,failed=分析失败"),
|
||||
replicate_status: ShotSegmentReplicateStatusEnum | None = Query(None, description="片段复刻状态:not_started=未复刻,project_created=已创建复刻项目,processing=复刻处理中,completed=复刻完成,failed=复刻失败"),
|
||||
page: int = Query(1, ge=1, description="分页页码,从1开始"),
|
||||
page_size: int = Query(20, ge=1, le=100, description="每页数量,范围1-100"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -392,10 +414,10 @@ async def list_task_set_segments(
|
||||
db,
|
||||
current_user=current_user,
|
||||
task_set_id=task_set_id,
|
||||
source_mode=source_mode,
|
||||
split_status=split_status,
|
||||
analysis_status=analysis_status,
|
||||
replicate_status=replicate_status,
|
||||
source_mode=source_mode.value if source_mode else None,
|
||||
split_status=split_status.value if split_status else None,
|
||||
analysis_status=analysis_status.value if analysis_status else None,
|
||||
replicate_status=replicate_status.value if replicate_status else None,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
)
|
||||
@@ -405,9 +427,10 @@ async def list_task_set_segments(
|
||||
"/segments/{segment_id}",
|
||||
response_model=ShotSegmentDetailOut,
|
||||
summary="获取拆镜片段详情",
|
||||
description="根据拆镜片段ID查询单个片段详情,包含切割结果、片段分析结果、复刻项目ID和状态。",
|
||||
)
|
||||
async def get_segment(
|
||||
segment_id: str = Path(...),
|
||||
segment_id: str = Path(..., description="拆镜片段ID,即 shot_replicate_segments.id"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -418,10 +441,15 @@ async def get_segment(
|
||||
"/segments/{segment_id}/replication-projects",
|
||||
response_model=ShotReplicateActionOut,
|
||||
summary="将拆镜片段创建为拆镜复刻项目",
|
||||
description=(
|
||||
"以拆镜片段作为锁定素材视频创建 ModuleGenerationProject 复刻项目。"
|
||||
"创建后只同步生成第1步 material_input,后续第2-5步需要调用 /projects/{project_id}/steps/{step_id}/... 系列接口手动推进。"
|
||||
"素材视频来自片段 segment_video_url,不允许前端传入或后续修改。"
|
||||
),
|
||||
)
|
||||
async def create_replication_project_from_segment(
|
||||
segment_id: str = Path(...),
|
||||
req: ShotSegmentReplicationCreateRequest = Body(...),
|
||||
segment_id: str = Path(..., description="拆镜片段ID,即 shot_replicate_segments.id"),
|
||||
req: ShotSegmentReplicationCreateRequest = Body(..., description="从拆镜片段创建复刻项目参数:生成项目名称、核心内容点、新产品图片和可选幂等键"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -450,9 +478,10 @@ async def create_replication_project_from_segment(
|
||||
"/projects/{project_id}",
|
||||
response_model=ShotReplicateTaskDetailOut,
|
||||
summary="获取拆镜复刻项目详情",
|
||||
description="获取拆镜复刻 ModuleGenerationProject 项目详情,聚合返回素材、图片提词、图片生成、视频提词、视频生成和当前有效步骤列表。",
|
||||
)
|
||||
async def get_project(
|
||||
project_id: str = Path(...),
|
||||
project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -463,10 +492,15 @@ async def get_project(
|
||||
"/projects/{project_id}/material",
|
||||
response_model=ShotReplicateActionOut,
|
||||
summary="修改拆镜复刻素材信息,素材视频不允许修改",
|
||||
description=(
|
||||
"修改拆镜复刻第1步素材输入,并重建第1步 material_input 新版本。"
|
||||
"素材视频 material_video_url 锁定为拆镜片段视频,不允许修改;可修改新产品图片、参考素材项目名、生成项目名和核心内容点。"
|
||||
"修改后会软删除第2、3、4、5步当前有效任务,并清空旧图片/视频结果。"
|
||||
),
|
||||
)
|
||||
async def update_material(
|
||||
project_id: str = Path(...),
|
||||
req: ShotReplicateMaterialUpdateRequest = Body(...),
|
||||
project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"),
|
||||
req: ShotReplicateMaterialUpdateRequest = Body(..., description="第1步素材输入修改参数;不接收 material_video_url,至少传一个允许修改字段"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -486,12 +520,13 @@ async def update_material(
|
||||
@router.put(
|
||||
"/projects/{project_id}/steps/{step_id}/image-prompt",
|
||||
response_model=ShotReplicateActionOut,
|
||||
summary="直接修改图片 AI 优化提词",
|
||||
summary="直接修改第2步图片 AI 优化提词",
|
||||
description="直接修改第2步 image_prompt_optimize 的图片提示词,不调用 AI、不扣积分;保存后软删除第3、4、5步当前有效任务。",
|
||||
)
|
||||
async def update_image_prompt(
|
||||
project_id: str = Path(...),
|
||||
step_id: str = Path(...),
|
||||
req: ShotReplicateImagePromptUpdateRequest = Body(...),
|
||||
project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"),
|
||||
step_id: str = Path(..., description="第2步图片 AI 提词子任务ID,即 module_generation_steps.id,step_code=image_prompt_optimize"),
|
||||
req: ShotReplicateImagePromptUpdateRequest = Body(..., description="图片 AI 优化提词修改参数"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -512,12 +547,16 @@ async def update_image_prompt(
|
||||
@router.put(
|
||||
"/projects/{project_id}/steps/{step_id}/video-prompt-schema",
|
||||
response_model=ShotReplicateActionOut,
|
||||
summary="修改视频 AI 提词 JSON schema",
|
||||
summary="修改第4步视频 AI 提词 JSON schema",
|
||||
description=(
|
||||
"修改第4步 video_prompt_optimize 的视频提词 JSON schema,不调用 AI、不扣积分。"
|
||||
"服务端会锁定视频时长、比例、分辨率、帧率、动态时间规划等关键结构;保存后软删除第5步视频生成任务。"
|
||||
),
|
||||
)
|
||||
async def update_video_prompt_schema(
|
||||
project_id: str = Path(...),
|
||||
step_id: str = Path(...),
|
||||
req: ShotReplicateVideoPromptSchemaUpdateRequest = Body(...),
|
||||
project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"),
|
||||
step_id: str = Path(..., description="第4步视频 AI 提词子任务ID,即 module_generation_steps.id,step_code=video_prompt_optimize"),
|
||||
req: ShotReplicateVideoPromptSchemaUpdateRequest = Body(..., description="视频 AI 提词 JSON schema 修改参数"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -536,19 +575,24 @@ async def update_video_prompt_schema(
|
||||
|
||||
|
||||
@router.post(
|
||||
"/projects/{project_id}/generate-image-prompt",
|
||||
"/projects/{project_id}/steps/{step_id}/generate-image-prompt",
|
||||
response_model=ShotReplicateActionOut,
|
||||
summary="生成图片 AI 提词",
|
||||
summary="基于第1步素材输入生成图片 AI 提词",
|
||||
description=(
|
||||
"基于第1步 material_input 子任务手动生成第2步 image_prompt_optimize。"
|
||||
"如果已存在旧的第2、3、4、5步,会先软删除旧步骤,再创建新的第2步并投递 Celery 文本提词任务。"
|
||||
),
|
||||
)
|
||||
async def generate_image_prompt(
|
||||
project_id: str = Path(...),
|
||||
req: ShotReplicateGenerateImagePromptRequest = Body(default_factory=ShotReplicateGenerateImagePromptRequest),
|
||||
project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"),
|
||||
step_id: str = Path(..., description="第1步素材输入子任务ID,即 module_generation_steps.id,step_code=material_input"),
|
||||
req: ShotReplicateGenerateImagePromptRequest = Body(default_factory=ShotReplicateGenerateImagePromptRequest, description="图片提词生成参数,当前无需传参,额外字段会忽略"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
_ensure_celery_enabled(current_user=current_user, project_id=locals().get("project_id") or locals().get("task_set_id"))
|
||||
_ensure_celery_enabled(current_user=current_user, project_id=project_id, step_id=step_id)
|
||||
try:
|
||||
project, step = await submit_image_prompt_optimize(db, current_user=current_user, project_id=project_id, req=req)
|
||||
project, step = await submit_image_prompt_optimize(db, current_user=current_user, project_id=project_id, material_step_id=step_id, req=req)
|
||||
project_id_value, step_id_value = project.id, step.id
|
||||
await db.commit()
|
||||
except HTTPException:
|
||||
@@ -577,19 +621,25 @@ async def generate_image_prompt(
|
||||
|
||||
|
||||
@router.post(
|
||||
"/projects/{project_id}/generate-image",
|
||||
"/projects/{project_id}/steps/{step_id}/generate-image",
|
||||
response_model=ShotReplicateActionOut,
|
||||
summary="根据图片 AI 提词生成图片",
|
||||
summary="基于第2步图片 AI 提词生成图片",
|
||||
description=(
|
||||
"基于第2步 image_prompt_optimize 子任务生成第3步 image_generate。"
|
||||
"请求体传入图片引擎和图片参数;ChatGenerationTask 幂等键由后端自动生成。"
|
||||
"如果已存在旧的第3、4、5步,会先软删除旧步骤,再创建新的第3步。"
|
||||
),
|
||||
)
|
||||
async def generate_image(
|
||||
project_id: str = Path(...),
|
||||
req: ShotReplicateGenerateImageRequest = Body(...),
|
||||
project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"),
|
||||
step_id: str = Path(..., description="第2步图片 AI 提词子任务ID,即 module_generation_steps.id,step_code=image_prompt_optimize"),
|
||||
req: ShotReplicateGenerateImageRequest = Body(..., description="图片生成引擎和参数;可选值来自图片引擎配置接口"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
_ensure_celery_enabled(current_user=current_user, project_id=locals().get("project_id") or locals().get("task_set_id"))
|
||||
_ensure_celery_enabled(current_user=current_user, project_id=project_id, step_id=step_id)
|
||||
try:
|
||||
project, step, chat_task = await generate_image_from_prompt(db, current_user=current_user, project_id=project_id, req=req)
|
||||
project, step, chat_task = await generate_image_from_prompt(db, current_user=current_user, project_id=project_id, prompt_step_id=step_id, req=req)
|
||||
project_id_value, step_id_value, chat_task_id_value = project.id, step.id, chat_task.id
|
||||
await db.commit()
|
||||
except HTTPException:
|
||||
@@ -611,19 +661,25 @@ async def generate_image(
|
||||
|
||||
|
||||
@router.post(
|
||||
"/projects/{project_id}/generate-video-prompt",
|
||||
"/projects/{project_id}/steps/{step_id}/generate-video-prompt",
|
||||
response_model=ShotReplicateActionOut,
|
||||
summary="生成视频 AI 提词 JSON schema",
|
||||
summary="基于第3步图片结果生成视频 AI 提词 JSON schema",
|
||||
description=(
|
||||
"基于第3步 image_generate 子任务生成第4步 video_prompt_optimize。"
|
||||
"视频时长、比例、分辨率在本步骤确定并写入第4步 output_json;第5步视频生成只选择视频引擎。"
|
||||
"如果已存在旧的第4、5步,会先软删除旧步骤,再创建新的第4步并投递 Celery 文本提词任务。"
|
||||
),
|
||||
)
|
||||
async def generate_video_prompt(
|
||||
project_id: str = Path(...),
|
||||
req: ShotReplicateGenerateVideoPromptRequest = Body(...),
|
||||
project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"),
|
||||
step_id: str = Path(..., description="第3步图片生成子任务ID,即 module_generation_steps.id,step_code=image_generate"),
|
||||
req: ShotReplicateGenerateVideoPromptRequest = Body(..., description="视频提词生成参数:视频引擎、时长、比例、分辨率和目标平台;可选值来自视频引擎配置接口"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
_ensure_celery_enabled(current_user=current_user, project_id=locals().get("project_id") or locals().get("task_set_id"))
|
||||
_ensure_celery_enabled(current_user=current_user, project_id=project_id, step_id=step_id)
|
||||
try:
|
||||
project, step = await submit_video_prompt_optimize(db, current_user=current_user, project_id=project_id, req=req)
|
||||
project, step = await submit_video_prompt_optimize(db, current_user=current_user, project_id=project_id, image_step_id=step_id, req=req)
|
||||
project_id_value, step_id_value = project.id, step.id
|
||||
await db.commit()
|
||||
except HTTPException:
|
||||
@@ -652,19 +708,25 @@ async def generate_video_prompt(
|
||||
|
||||
|
||||
@router.post(
|
||||
"/projects/{project_id}/generate-video",
|
||||
"/projects/{project_id}/steps/{step_id}/generate-video",
|
||||
response_model=ShotReplicateActionOut,
|
||||
summary="根据视频 AI 提词生成视频",
|
||||
summary="基于第4步视频 AI 提词生成最终视频",
|
||||
description=(
|
||||
"基于第4步 video_prompt_optimize 子任务生成第5步 video_generate。"
|
||||
"请求体只需要选择视频生成引擎 engine_id;duration、aspect_ratio、resolution 从第4步视频提词结果继承。"
|
||||
"如果已存在旧的第5步,会先软删除旧步骤,再创建新的第5步。"
|
||||
),
|
||||
)
|
||||
async def generate_video(
|
||||
project_id: str = Path(...),
|
||||
req: ShotReplicateGenerateVideoRequest = Body(...),
|
||||
project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"),
|
||||
step_id: str = Path(..., description="第4步视频 AI 提词子任务ID,即 module_generation_steps.id,step_code=video_prompt_optimize"),
|
||||
req: ShotReplicateGenerateVideoRequest = Body(..., description="视频生成参数:只传 engine_id,其它视频参数继承第4步视频提词结果"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
_ensure_celery_enabled(current_user=current_user, project_id=locals().get("project_id") or locals().get("task_set_id"))
|
||||
_ensure_celery_enabled(current_user=current_user, project_id=project_id, step_id=step_id)
|
||||
try:
|
||||
project, step, chat_task = await generate_video_from_prompt(db, current_user=current_user, project_id=project_id, req=req)
|
||||
project, step, chat_task = await generate_video_from_prompt(db, current_user=current_user, project_id=project_id, prompt_step_id=step_id, req=req)
|
||||
project_id_value, step_id_value, chat_task_id_value = project.id, step.id, chat_task.id
|
||||
await db.commit()
|
||||
except HTTPException:
|
||||
@@ -689,9 +751,10 @@ async def generate_video(
|
||||
"/projects/{project_id}",
|
||||
response_model=ShotReplicateDeleteOut,
|
||||
summary="软删除拆镜复刻项目",
|
||||
description="软删除拆镜复刻 ModuleGenerationProject,并联动软删除当前有效步骤和关联的 ChatGenerationTask。",
|
||||
)
|
||||
async def delete_project(
|
||||
project_id: str = Path(...),
|
||||
project_id: str = Path(..., description="拆镜复刻项目ID,即 module_generation_projects.id"),
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user