4328854f58
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 1m7s
CI/CD Pipeline / Frontend Lint (push) Successful in 2m31s
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Successful in 2m57s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 5m5s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 5m29s
127 lines
3.9 KiB
Python
127 lines
3.9 KiB
Python
"""查重辅助函数 — 从 generation.py 提取的 GeneratedVideo 记录 + 查重逻辑.
|
|
|
|
供 render_edit_plan 和 generate_video 共同复用,
|
|
创建 GeneratedVideo 记录后计算指纹并执行项目级 + 批次内查重。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from uuid import uuid4
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def create_video_record_and_dedup(
|
|
*,
|
|
generation_task_id: str,
|
|
project_id: str,
|
|
batch_id: str,
|
|
file_url: str,
|
|
file_size: int,
|
|
duration: float,
|
|
video_path: str,
|
|
mode: str,
|
|
session: Session,
|
|
width: int = 1280,
|
|
height: int = 720,
|
|
fps: float = 25.0,
|
|
) -> int:
|
|
"""创建 GeneratedVideo 记录,计算指纹并执行查重(历史 + 批次)。
|
|
|
|
Args:
|
|
generation_task_id: 生成任务 ID
|
|
project_id: 项目 ID
|
|
batch_id: 批次 ID(可为空字符串)
|
|
file_url: 视频文件 URL
|
|
file_size: 文件大小(字节)
|
|
duration: 视频时长(秒)
|
|
video_path: 视频本地路径(用于计算指纹)
|
|
mode: 剪辑模式名称
|
|
session: 数据库会话
|
|
width: 视频宽度
|
|
height: 视频高度
|
|
fps: 视频帧率
|
|
|
|
Returns:
|
|
创建的视频记录数量(1 表示成功,0 表示失败)
|
|
"""
|
|
from video_processing.dedup import VideoDeduplicator
|
|
|
|
from packages.adapters.sqlalchemy_impl.generated_video_repository import (
|
|
SQLAlchemyGeneratedVideoRepository,
|
|
)
|
|
from packages.domain import GeneratedVideo
|
|
|
|
try:
|
|
video_id = uuid4().hex
|
|
generated_video = GeneratedVideo(
|
|
id=video_id,
|
|
project_id=project_id,
|
|
generation_task_id=generation_task_id,
|
|
name=f"generated-{generation_task_id[:8]}.mp4",
|
|
file_url=file_url,
|
|
file_size=file_size,
|
|
duration=duration,
|
|
width=width,
|
|
height=height,
|
|
fps=fps,
|
|
status="completed",
|
|
generation_params={"mode": mode},
|
|
)
|
|
|
|
video_repo = SQLAlchemyGeneratedVideoRepository(session)
|
|
video_repo.create(generated_video)
|
|
|
|
# 计算视频指纹
|
|
deduplicator = VideoDeduplicator()
|
|
try:
|
|
fingerprint = deduplicator.compute_fingerprint(video_path)
|
|
except Exception as fp_err:
|
|
logger.warning("Fingerprint computation failed for %s: %s", video_id, fp_err)
|
|
session.commit()
|
|
return 1
|
|
|
|
generated_video.video_fingerprint = fingerprint.to_dict()
|
|
|
|
# (a) 历史成片查重
|
|
duplicate_result = deduplicator.check_duplicate(fingerprint, project_id, session)
|
|
|
|
# (b) 批次内查重(仅当有 batch_id 时)
|
|
if not duplicate_result and batch_id:
|
|
duplicate_result = deduplicator.check_batch_duplicate(fingerprint, batch_id, video_id, session)
|
|
|
|
if duplicate_result:
|
|
generated_video.is_duplicate = True
|
|
generated_video.duplicate_of = duplicate_result["duplicate_of"]
|
|
logger.info(
|
|
"Duplicate detected: %s -> %s (reason=%s, similarity=%.3f)",
|
|
video_id,
|
|
duplicate_result["duplicate_of"],
|
|
duplicate_result["reason"],
|
|
duplicate_result["similarity"],
|
|
)
|
|
else:
|
|
generated_video.is_duplicate = False
|
|
generated_video.duplicate_of = None
|
|
|
|
video_repo.update(generated_video)
|
|
session.commit()
|
|
logger.info(
|
|
"GeneratedVideo record created: %s (task=%s, dup=%s)",
|
|
video_id,
|
|
generation_task_id,
|
|
generated_video.is_duplicate,
|
|
)
|
|
return 1
|
|
except Exception as e:
|
|
logger.error(
|
|
"Failed to create video record / dedup for task %s: %s",
|
|
generation_task_id,
|
|
e,
|
|
)
|
|
session.rollback()
|
|
return 0
|