diff --git a/apps/worker/video_processing/dedup.py b/apps/worker/video_processing/dedup.py index 9e62e568a..817f9034b 100755 --- a/apps/worker/video_processing/dedup.py +++ b/apps/worker/video_processing/dedup.py @@ -1155,7 +1155,6 @@ def compute_structure_similarity(clips1: list[dict], clips2: list[dict]) -> floa # 三维度加权:数量 0.3 + 类型 0.4 + 时长 0.3 return count_sim * 0.3 + type_sim * 0.4 + duration_sim * 0.3 - def compute_duplicate_rate( self, fingerprint: VideoFingerprint, @@ -1205,12 +1204,16 @@ def compute_structure_similarity(clips1: list[dict], clips2: list[dict]) -> floa # Issue #P2-后端3: 加载当前视频的文案+结构数据 from packages.adapters.sqlalchemy_impl.models import EditPlanClipModel, GeneratedVideoModel - - current_video_obj = session.query(GeneratedVideoModel).filter(GeneratedVideoModel.id == current_video_id).first() if current_video_id else None + + current_video_obj = ( + session.query(GeneratedVideoModel).filter(GeneratedVideoModel.id == current_video_id).first() + if current_video_id + else None + ) current_plan_id = getattr(current_video_obj, "edit_plan_id", "") or "" current_clips_data = [] current_text_content = "" - + if current_plan_id: current_clips = ( session.query(EditPlanClipModel) @@ -1218,10 +1221,7 @@ def compute_structure_similarity(clips1: list[dict], clips2: list[dict]) -> floa .order_by(EditPlanClipModel.order) .all() ) - current_clips_data = [ - {"clip_type": c.clip_type, "duration": c.duration} - for c in current_clips - ] + current_clips_data = [{"clip_type": c.clip_type, "duration": c.duration} for c in current_clips] # 拼接所有片段的文本内容 current_text_content = " ".join(c.text_content for c in current_clips if c.text_content) @@ -1299,7 +1299,7 @@ def compute_structure_similarity(clips1: list[dict], clips2: list[dict]) -> floa existing_plan_id = getattr(existing, "edit_plan_id", "") or "" existing_clips_data = [] existing_text_content = "" - + if existing_plan_id: existing_clips = ( session.query(EditPlanClipModel) @@ -1307,22 +1307,29 @@ def compute_structure_similarity(clips1: list[dict], clips2: list[dict]) -> floa .order_by(EditPlanClipModel.order) .all() ) - existing_clips_data = [ - {"clip_type": c.clip_type, "duration": c.duration} - for c in existing_clips - ] + existing_clips_data = [{"clip_type": c.clip_type, "duration": c.duration} for c in existing_clips] existing_text_content = " ".join(c.text_content for c in existing_clips if c.text_content) # 计算文案相似度(有文案才算) - text_sim = compute_text_similarity(current_text_content, existing_text_content) if (current_text_content and existing_text_content) else 0.0 + text_sim = ( + compute_text_similarity(current_text_content, existing_text_content) + if (current_text_content and existing_text_content) + else 0.0 + ) # 计算结构相似度(有片段才算) - structure_sim = compute_structure_similarity(current_clips_data, existing_clips_data) if (current_clips_data and existing_clips_data) else 0.0 + structure_sim = ( + compute_structure_similarity(current_clips_data, existing_clips_data) + if (current_clips_data and existing_clips_data) + else 0.0 + ) # 多维度融合:visual*0.5 + text*0.25 + structure*0.25 # 如果文案/结构数据缺失,只用视觉维度(visual 权重提升到 1.0) if current_text_content and existing_text_content and current_clips_data and existing_clips_data: - dup_rate = (visual_sim * VISUAL_WEIGHT + text_sim * TEXT_WEIGHT + structure_sim * STRUCTURE_WEIGHT) * 100 + dup_rate = ( + visual_sim * VISUAL_WEIGHT + text_sim * TEXT_WEIGHT + structure_sim * STRUCTURE_WEIGHT + ) * 100 else: # 降级:只有视觉维度 dup_rate = visual_sim * 100 diff --git a/tests/unit/test_dedup_enhanced.py b/tests/unit/test_dedup_enhanced.py index bec63d84c..e23c603d6 100644 --- a/tests/unit/test_dedup_enhanced.py +++ b/tests/unit/test_dedup_enhanced.py @@ -31,6 +31,7 @@ _mock_if_absent("packages.shared.storage") # Mock cv2 and numpy if not available try: import cv2 as _cv2 + if not isinstance(_cv2, MagicMock): _HAS_CV2 = True else: @@ -154,11 +155,11 @@ class TestStructureSimilarity: """时长分布不同,时长相似度低。""" clips1 = [ {"clip_type": "video", "duration": 10.0}, # 占比 80% - {"clip_type": "title", "duration": 2.5}, # 占比 20% + {"clip_type": "title", "duration": 2.5}, # 占比 20% ] clips2 = [ - {"clip_type": "video", "duration": 2.0}, # 占比 20% - {"clip_type": "title", "duration": 8.0}, # 占比 80% + {"clip_type": "video", "duration": 2.0}, # 占比 20% + {"clip_type": "title", "duration": 8.0}, # 占比 80% ] sim = compute_structure_similarity(clips1, clips2) assert 0.7 < sim < 0.9 # 类型相同但时长分布不同,sim=0.82