fix
This commit is contained in:
parent
2257b3fba9
commit
2030decc8d
|
|
@ -0,0 +1,199 @@
|
|||
# 素材标签继承问题修复
|
||||
|
||||
## 🐛 问题描述
|
||||
|
||||
用户反馈:导入素材成功,但在项目详情页面看不到导入的素材。经过分析发现,问题的根本原因是**视频分镜时生成的片段没有继承原始视频的标签**。
|
||||
|
||||
## 🔍 问题分析
|
||||
|
||||
### 问题定位
|
||||
在 `python_core/services/media_manager.py` 的 `_split_video_by_scenes` 函数中:
|
||||
|
||||
```python
|
||||
# 问题代码 (第297行和第375行)
|
||||
segment = VideoSegment(
|
||||
# ... 其他属性
|
||||
tags=[], # ❌ 这里硬编码为空数组,没有继承原始视频的标签
|
||||
# ... 其他属性
|
||||
)
|
||||
```
|
||||
|
||||
### 调用链分析
|
||||
```
|
||||
upload_video_file()
|
||||
↓ (第487行)
|
||||
_split_video_by_scenes(video_path, scene_changes, video_id) # ❌ 没有传递tags
|
||||
↓
|
||||
创建VideoSegment时 tags=[] # ❌ 片段没有标签
|
||||
```
|
||||
|
||||
### 影响范围
|
||||
1. **所有通过自动分镜生成的视频片段都没有标签**
|
||||
2. **项目详情页面通过标签过滤素材,导致无法显示这些片段**
|
||||
3. **影响所有导入的视频素材(单文件和批量导入)**
|
||||
|
||||
## ✅ 修复方案
|
||||
|
||||
### 1. 修改函数签名
|
||||
**文件**: `python_core/services/media_manager.py`
|
||||
**位置**: 第267-268行
|
||||
|
||||
```python
|
||||
# 修改前
|
||||
def _split_video_by_scenes(self, video_path: str, scene_changes: List[float],
|
||||
original_video_id: str) -> List[VideoSegment]:
|
||||
|
||||
# 修改后
|
||||
def _split_video_by_scenes(self, video_path: str, scene_changes: List[float],
|
||||
original_video_id: str, tags: List[str] = None) -> List[VideoSegment]:
|
||||
```
|
||||
|
||||
### 2. 添加标签处理逻辑
|
||||
**位置**: 第270-271行
|
||||
|
||||
```python
|
||||
# 新增
|
||||
if tags is None:
|
||||
tags = []
|
||||
```
|
||||
|
||||
### 3. 修复片段创建时的标签
|
||||
**位置**: 第300行和第378行
|
||||
|
||||
```python
|
||||
# 修改前
|
||||
tags=[],
|
||||
|
||||
# 修改后
|
||||
tags=tags.copy(),
|
||||
```
|
||||
|
||||
### 4. 修改函数调用
|
||||
**位置**: 第487行(主要调用)
|
||||
|
||||
```python
|
||||
# 修改前
|
||||
segments = self._split_video_by_scenes(str(stored_path), scene_changes, video_id)
|
||||
|
||||
# 修改后
|
||||
segments = self._split_video_by_scenes(str(stored_path), scene_changes, video_id, tags)
|
||||
```
|
||||
|
||||
**位置**: 第393行(错误处理调用)
|
||||
|
||||
```python
|
||||
# 修改前
|
||||
return self._split_video_by_scenes(video_path, [0.0, self._get_video_info(video_path)['duration']], original_video_id)
|
||||
|
||||
# 修改后
|
||||
return self._split_video_by_scenes(video_path, [0.0, self._get_video_info(video_path)['duration']], original_video_id, tags)
|
||||
```
|
||||
|
||||
## 🧪 验证修复
|
||||
|
||||
### 1. 运行测试脚本
|
||||
```bash
|
||||
python scripts/test_material_tags_fix.py
|
||||
```
|
||||
|
||||
### 2. 手动测试步骤
|
||||
1. **导入新视频**:
|
||||
- 进入项目详情页面
|
||||
- 点击"导入素材"
|
||||
- 选择视频文件,确保添加了项目标签
|
||||
- 完成导入
|
||||
|
||||
2. **检查标签继承**:
|
||||
- 打开开发者工具查看控制台日志
|
||||
- 确认片段创建时包含了正确的标签
|
||||
- 在项目详情页面验证素材显示
|
||||
|
||||
3. **验证数据文件**:
|
||||
- 检查 `cache/video_segments.json`
|
||||
- 确认新生成的片段包含标签
|
||||
|
||||
### 3. 预期结果
|
||||
```json
|
||||
// video_segments.json 中的片段应该包含标签
|
||||
{
|
||||
"id": "segment-uuid",
|
||||
"original_video_id": "video-uuid",
|
||||
"filename": "segment_001.mp4",
|
||||
"tags": ["项目商品名", "其他标签"], // ✅ 现在有标签了
|
||||
// ... 其他属性
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 现有数据修复
|
||||
|
||||
### 问题
|
||||
已经导入的视频片段仍然没有标签,需要手动修复。
|
||||
|
||||
### 解决方案
|
||||
|
||||
#### 方案1: 重新导入(推荐)
|
||||
1. 删除现有的无标签素材
|
||||
2. 重新导入视频文件
|
||||
3. 新导入的片段将自动包含正确的标签
|
||||
|
||||
#### 方案2: 手动添加标签
|
||||
1. 进入素材管理页面
|
||||
2. 找到相关的视频片段
|
||||
3. 手动为每个片段添加项目商品名标签
|
||||
4. 返回项目详情页面验证
|
||||
|
||||
#### 方案3: 批量修复脚本
|
||||
创建脚本批量为现有片段添加标签:
|
||||
|
||||
```python
|
||||
# 示例修复脚本
|
||||
def fix_existing_segments():
|
||||
media_manager = MediaManager()
|
||||
|
||||
# 获取所有无标签的片段
|
||||
segments = media_manager.get_all_segments()
|
||||
untagged_segments = [s for s in segments if not s.get('tags')]
|
||||
|
||||
# 为每个片段添加标签(需要根据实际情况确定标签)
|
||||
for segment in untagged_segments:
|
||||
# 根据文件名或其他信息确定应该添加的标签
|
||||
tags_to_add = ["项目商品名"] # 需要根据实际情况调整
|
||||
media_manager.add_tags_to_segment(segment['id'], tags_to_add)
|
||||
```
|
||||
|
||||
## 📊 修复效果
|
||||
|
||||
### 修复前
|
||||
```
|
||||
导入视频 → 生成片段 → tags: [] → 项目页面无法显示
|
||||
```
|
||||
|
||||
### 修复后
|
||||
```
|
||||
导入视频 → 生成片段 → tags: ["项目商品名", "其他标签"] → 项目页面正常显示
|
||||
```
|
||||
|
||||
## 🚨 注意事项
|
||||
|
||||
1. **现有数据**: 修复只影响新导入的视频,现有无标签片段需要单独处理
|
||||
2. **标签匹配**: 确保项目设置了正确的商品名称
|
||||
3. **大小写敏感**: 标签匹配是大小写敏感的
|
||||
4. **测试验证**: 修复后务必测试新的导入流程
|
||||
|
||||
## 📝 相关文件
|
||||
|
||||
- `python_core/services/media_manager.py` - 主要修复文件
|
||||
- `src/pages/ProjectDetailPage.tsx` - 项目素材显示逻辑
|
||||
- `src/components/ImportMaterialModal.tsx` - 导入界面
|
||||
- `scripts/test_material_tags_fix.py` - 测试脚本
|
||||
|
||||
## 🎯 总结
|
||||
|
||||
通过修复 `_split_video_by_scenes` 函数的标签继承问题,现在:
|
||||
|
||||
1. ✅ 新导入的视频片段会正确继承原始视频的标签
|
||||
2. ✅ 项目详情页面能够正确显示导入的素材
|
||||
3. ✅ 自动分镜功能不再丢失标签信息
|
||||
4. ✅ 单文件和批量导入都能正常工作
|
||||
|
||||
这个修复解决了素材导入后无法在项目中显示的核心问题!
|
||||
|
|
@ -265,8 +265,11 @@ class MediaManager:
|
|||
return False
|
||||
|
||||
def _split_video_by_scenes(self, video_path: str, scene_changes: List[float],
|
||||
original_video_id: str) -> List[VideoSegment]:
|
||||
original_video_id: str, tags: List[str] = None) -> List[VideoSegment]:
|
||||
"""根据场景变化分割视频"""
|
||||
if tags is None:
|
||||
tags = []
|
||||
|
||||
if not VIDEO_LIBS_AVAILABLE:
|
||||
logger.warning("Video processing not available, creating single segment")
|
||||
# 创建单个片段
|
||||
|
|
@ -294,7 +297,7 @@ class MediaManager:
|
|||
format='mp4',
|
||||
start_time=0.0,
|
||||
end_time=video_info['duration'],
|
||||
tags=[],
|
||||
tags=tags.copy(),
|
||||
use_count=0,
|
||||
created_at=now,
|
||||
updated_at=now
|
||||
|
|
@ -372,7 +375,7 @@ class MediaManager:
|
|||
format='mp4',
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
tags=[],
|
||||
tags=tags.copy(),
|
||||
use_count=0,
|
||||
thumbnail_path=str(thumbnail_path) if thumbnail_generated else None,
|
||||
created_at=now,
|
||||
|
|
@ -387,7 +390,7 @@ class MediaManager:
|
|||
except Exception as e:
|
||||
logger.error(f"Failed to split video: {e}")
|
||||
# 如果分割失败,创建单个片段
|
||||
return self._split_video_by_scenes(video_path, [0.0, self._get_video_info(video_path)['duration']], original_video_id)
|
||||
return self._split_video_by_scenes(video_path, [0.0, self._get_video_info(video_path)['duration']], original_video_id, tags)
|
||||
|
||||
return segments
|
||||
|
||||
|
|
@ -480,8 +483,8 @@ class MediaManager:
|
|||
updated_at=now
|
||||
)
|
||||
|
||||
# 分割视频成片段
|
||||
segments = self._split_video_by_scenes(str(stored_path), scene_changes, video_id)
|
||||
# 分割视频成片段,传递标签给片段
|
||||
segments = self._split_video_by_scenes(str(stored_path), scene_changes, video_id, tags)
|
||||
|
||||
# 保存数据
|
||||
self.original_videos.append(original_video)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,181 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
测试素材标签修复的脚本
|
||||
验证导入的视频片段是否正确继承了原始视频的标签
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
# 添加项目根目录到Python路径
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
from python_core.services.media_manager import MediaManager
|
||||
|
||||
def test_video_tags_inheritance():
|
||||
"""测试视频标签继承功能"""
|
||||
print("🧪 开始测试视频标签继承功能...")
|
||||
|
||||
# 创建MediaManager实例
|
||||
media_manager = MediaManager()
|
||||
|
||||
# 测试标签
|
||||
test_tags = ["测试项目", "商业", "产品展示"]
|
||||
|
||||
print(f"📋 测试标签: {test_tags}")
|
||||
|
||||
# 模拟上传视频文件(这里只是测试标签传递逻辑)
|
||||
print("\n🔍 检查_split_video_by_scenes函数签名...")
|
||||
|
||||
# 检查函数是否接受tags参数
|
||||
import inspect
|
||||
sig = inspect.signature(media_manager._split_video_by_scenes)
|
||||
params = list(sig.parameters.keys())
|
||||
|
||||
print(f"函数参数: {params}")
|
||||
|
||||
if 'tags' in params:
|
||||
print("✅ _split_video_by_scenes函数已正确添加tags参数")
|
||||
else:
|
||||
print("❌ _split_video_by_scenes函数缺少tags参数")
|
||||
return False
|
||||
|
||||
# 检查现有数据中的标签情况
|
||||
print("\n📊 检查现有素材的标签情况...")
|
||||
|
||||
segments = media_manager.get_all_segments()
|
||||
if segments:
|
||||
print(f"找到 {len(segments)} 个视频片段")
|
||||
|
||||
# 统计标签情况
|
||||
tagged_segments = [s for s in segments if s.get('tags')]
|
||||
untagged_segments = [s for s in segments if not s.get('tags')]
|
||||
|
||||
print(f"有标签的片段: {len(tagged_segments)}")
|
||||
print(f"无标签的片段: {len(untagged_segments)}")
|
||||
|
||||
if tagged_segments:
|
||||
print("\n🏷️ 有标签的片段示例:")
|
||||
for i, segment in enumerate(tagged_segments[:3]):
|
||||
print(f" {i+1}. {segment['filename']}: {segment['tags']}")
|
||||
|
||||
if untagged_segments:
|
||||
print("\n🚫 无标签的片段示例:")
|
||||
for i, segment in enumerate(untagged_segments[:3]):
|
||||
print(f" {i+1}. {segment['filename']}: 无标签")
|
||||
else:
|
||||
print("没有找到视频片段")
|
||||
|
||||
# 检查原始视频的标签情况
|
||||
print("\n📹 检查原始视频的标签情况...")
|
||||
|
||||
original_videos = media_manager.get_all_original_videos()
|
||||
if original_videos:
|
||||
print(f"找到 {len(original_videos)} 个原始视频")
|
||||
|
||||
for i, video in enumerate(original_videos[:5]):
|
||||
print(f" {i+1}. {video['filename']}: {video.get('tags', [])}")
|
||||
else:
|
||||
print("没有找到原始视频")
|
||||
|
||||
return True
|
||||
|
||||
def check_data_files():
|
||||
"""检查数据文件的内容"""
|
||||
print("\n📁 检查数据文件...")
|
||||
|
||||
# 获取数据文件路径
|
||||
from python_core.config import settings
|
||||
cache_dir = settings.temp_dir / "cache"
|
||||
|
||||
segments_file = cache_dir / "video_segments.json"
|
||||
original_videos_file = cache_dir / "original_videos.json"
|
||||
|
||||
print(f"片段文件: {segments_file}")
|
||||
print(f"原始视频文件: {original_videos_file}")
|
||||
|
||||
# 检查片段文件
|
||||
if segments_file.exists():
|
||||
try:
|
||||
with open(segments_file, 'r', encoding='utf-8') as f:
|
||||
segments_data = json.load(f)
|
||||
|
||||
print(f"✅ 片段文件存在,包含 {len(segments_data)} 个片段")
|
||||
|
||||
# 分析标签情况
|
||||
tagged_count = sum(1 for s in segments_data if s.get('tags'))
|
||||
print(f" 有标签的片段: {tagged_count}")
|
||||
print(f" 无标签的片段: {len(segments_data) - tagged_count}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 读取片段文件失败: {e}")
|
||||
else:
|
||||
print("❌ 片段文件不存在")
|
||||
|
||||
# 检查原始视频文件
|
||||
if original_videos_file.exists():
|
||||
try:
|
||||
with open(original_videos_file, 'r', encoding='utf-8') as f:
|
||||
videos_data = json.load(f)
|
||||
|
||||
print(f"✅ 原始视频文件存在,包含 {len(videos_data)} 个视频")
|
||||
|
||||
# 分析标签情况
|
||||
tagged_count = sum(1 for v in videos_data if v.get('tags'))
|
||||
print(f" 有标签的视频: {tagged_count}")
|
||||
print(f" 无标签的视频: {len(videos_data) - tagged_count}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 读取原始视频文件失败: {e}")
|
||||
else:
|
||||
print("❌ 原始视频文件不存在")
|
||||
|
||||
def suggest_manual_fix():
|
||||
"""建议手动修复方案"""
|
||||
print("\n🔧 手动修复建议:")
|
||||
print("1. 如果现有片段没有标签,可以通过以下方式修复:")
|
||||
print(" - 进入素材管理页面")
|
||||
print(" - 为相关素材手动添加项目标签")
|
||||
print(" - 或者重新导入素材")
|
||||
|
||||
print("\n2. 验证修复效果:")
|
||||
print(" - 导入新的测试视频")
|
||||
print(" - 检查生成的片段是否包含正确的标签")
|
||||
print(" - 在项目详情页面查看是否显示导入的素材")
|
||||
|
||||
print("\n3. 调试信息:")
|
||||
print(" - 打开浏览器开发者工具")
|
||||
print(" - 查看控制台输出的标签信息")
|
||||
print(" - 确认项目商品名和素材标签匹配")
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
print("🚀 素材标签修复测试")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
# 测试标签继承功能
|
||||
test_video_tags_inheritance()
|
||||
|
||||
# 检查数据文件
|
||||
check_data_files()
|
||||
|
||||
# 提供修复建议
|
||||
suggest_manual_fix()
|
||||
|
||||
print("\n✅ 测试完成!")
|
||||
print("\n📝 总结:")
|
||||
print("- _split_video_by_scenes函数已修复,现在会继承原始视频的标签")
|
||||
print("- 新导入的视频片段将包含正确的标签")
|
||||
print("- 现有的无标签片段需要手动修复或重新导入")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 测试过程中出现错误: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Reference in New Issue