Files
xiaoxia-saas/scripts/backfill_generated_videos.py
T
xiaoxia 62a974a836
CI/CD Pipeline / Frontend Unit Tests (push) Failing after 3m19s
CI/CD Pipeline / Validate Code Quality And Tests (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI Build & Deploy Pipeline / Build Staging Web Image (push) Failing after 3m43s
CI Build & Deploy Pipeline / Staging API Integration Tests (push) Failing after 1432h20m15s
CI Build & Deploy Pipeline / Staging E2E Tests (push) Failing after 1432h20m15s
CI Build & Deploy Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Failing after 1432h20m15s
CI Build & Deploy Pipeline / Production Browser E2E (push) Failing after 1432h27m55s
CI Build & Deploy Pipeline / Deploy Production (push) Failing after 1432h27m56s
CI Build & Deploy Pipeline / Build Production Web Image (push) Failing after 1432h27m56s
CI Build & Deploy Pipeline / Build Production API Image (push) Failing after 1432h27m56s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 1432h27m58s
CI Build & Deploy Pipeline / Build Staging API Image (push) Has been skipped
CI Build & Deploy Pipeline / Build Staging Worker Image (push) Has been skipped
CI Build & Deploy Pipeline / Build Production Worker Image (push) Failing after 1433h0m0s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
fix(P0): 修复一键生成视频成片库不显示 - project_id为空时跳过写表 (#541)
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-07-18 23:01:36 +08:00

146 lines
4.8 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""补写 generated_videos 记录 — 修复一键生成场景下 project_id 为空导致未写表的问题.
背景:#535 之前的一键生成场景,由于 edit_plan.project_id 为空,
_finalize_render_success 中 `if generation_task_id and project_id:` 判断不通过,
导致渲染成功的视频没有写入 generated_videos 表,成片库看不到。
本脚本扫描所有 status=completed 的 generation_task
如果没有对应的 generated_videos 记录,则从 plan.config.rendered_url 补写。
用法:
PYTHONPATH="apps/worker:apps/api:packages" python scripts/backfill_generated_videos.py
安全说明:
- 只读事务扫描,补写前检查是否已存在,不会重复写入
- 失败不中断,继续处理下一个
"""
from __future__ import annotations
import logging
import sys
from datetime import datetime, timezone
from uuid import uuid4
# 配置日志
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
)
logger = logging.getLogger(__name__)
def main() -> int:
from sqlalchemy import exists
from sqlalchemy.orm import Session
from packages.adapters.sqlalchemy_impl.models import (
EditPlanModel,
GeneratedVideoModel,
GenerationTaskModel,
)
from packages.adapters.sqlalchemy_impl.session import get_db_session
db: Session = next(get_db_session())
try:
# 1. 查询所有 status=completed 的 generation_task
completed_tasks = (
db.query(GenerationTaskModel)
.filter(
GenerationTaskModel.status == "completed",
)
.all()
)
logger.info("找到 %d 个已完成的生成任务", len(completed_tasks))
fixed_count = 0
skipped_count = 0
failed_count = 0
for task in completed_tasks:
task_id = task.id
# 2. 检查是否已有 generated_videos 记录
exists_video = db.query(exists().where(GeneratedVideoModel.generation_task_id == task_id)).scalar()
if exists_video:
skipped_count += 1
continue
# 3. 从 source_edit_plan_id 找到对应的 edit_plan,取 rendered_url
if not task.source_edit_plan_id:
logger.warning("任务 %s 无 source_edit_plan_id,跳过", task_id)
skipped_count += 1
continue
plan = (
db.query(EditPlanModel)
.filter(
EditPlanModel.id == task.source_edit_plan_id,
)
.first()
)
if not plan:
logger.warning("任务 %s 对应的剪辑计划不存在,跳过", task_id)
skipped_count += 1
continue
# 从 config 中取 rendered_url
config = plan.config or {}
rendered_url = config.get("rendered_url", "")
rendered_storage_key = config.get("rendered_storage_key", "")
if not rendered_url:
logger.warning("任务 %s 的剪辑计划无 rendered_url,跳过", task_id)
skipped_count += 1
continue
# 4. 补写 generated_videos 记录
try:
video_id = uuid4().hex
video = GeneratedVideoModel(
id=video_id,
project_id=task.project_id or "",
generation_task_id=task_id,
name=f"generated-{task_id[:8]}.mp4",
file_url=rendered_url,
storage_key=rendered_storage_key,
file_size=0,
duration=0.0,
width=0,
height=0,
fps=0.0,
status="completed",
generation_params={"mode": "backfill", "plan_id": plan.id},
review_status="pending",
created_at=task.completed_at or datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc),
)
db.add(video)
db.commit()
fixed_count += 1
logger.info("已补写视频记录: task_id=%s video_id=%s url=%s", task_id, video_id, rendered_url[:80])
except Exception as e:
db.rollback()
failed_count += 1
logger.error("补写视频记录失败: task_id=%s error=%s", task_id, e)
logger.info(
"补写完成:共 %d 个已完成任务,补写 %d 条,跳过 %d 条,失败 %d 条",
len(completed_tasks),
fixed_count,
skipped_count,
failed_count,
)
return 0 if failed_count == 0 else 1
finally:
db.close()
if __name__ == "__main__":
sys.exit(main())