fix
This commit is contained in:
@@ -26,6 +26,16 @@ except ImportError:
|
||||
logger.warning("Video processing libraries not available. Install opencv-python for full functionality.")
|
||||
VIDEO_LIBS_AVAILABLE = False
|
||||
|
||||
# PySceneDetect库
|
||||
try:
|
||||
from scenedetect import VideoManager, SceneManager
|
||||
from scenedetect.detectors import ContentDetector
|
||||
SCENEDETECT_AVAILABLE = True
|
||||
logger.info("PySceneDetect is available for advanced scene detection")
|
||||
except ImportError:
|
||||
logger.warning("PySceneDetect not available. Install scenedetect for better scene detection.")
|
||||
SCENEDETECT_AVAILABLE = False
|
||||
|
||||
|
||||
@dataclass
|
||||
class VideoSegment:
|
||||
@@ -210,54 +220,130 @@ class MediaManager:
|
||||
}
|
||||
|
||||
def _detect_scene_changes(self, file_path: str, threshold: float = 30.0) -> List[float]:
|
||||
"""检测场景变化点(转场镜头)"""
|
||||
"""使用PySceneDetect检测场景变化点(转场镜头)"""
|
||||
if SCENEDETECT_AVAILABLE:
|
||||
try:
|
||||
# 创建视频管理器
|
||||
video_manager = VideoManager([file_path])
|
||||
scene_manager = SceneManager()
|
||||
|
||||
# 添加内容检测器,threshold参数控制敏感度
|
||||
scene_manager.add_detector(ContentDetector(threshold=threshold))
|
||||
|
||||
# 开始检测
|
||||
video_manager.start()
|
||||
scene_manager.detect_scenes(frame_source=video_manager)
|
||||
|
||||
# 获取场景列表
|
||||
scene_list = scene_manager.get_scene_list()
|
||||
|
||||
# 转换为时间戳列表
|
||||
scene_changes = [0.0] # 开始时间
|
||||
|
||||
for scene in scene_list:
|
||||
start_time = scene[0].get_seconds()
|
||||
end_time = scene[1].get_seconds()
|
||||
|
||||
# 添加场景开始时间(跳过第一个,因为已经有0.0了)
|
||||
if start_time > 0 and start_time not in scene_changes:
|
||||
scene_changes.append(start_time)
|
||||
|
||||
# 添加场景结束时间
|
||||
if end_time not in scene_changes:
|
||||
scene_changes.append(end_time)
|
||||
|
||||
# 确保时间戳排序
|
||||
scene_changes = sorted(list(set(scene_changes)))
|
||||
|
||||
video_manager.release()
|
||||
|
||||
logger.info(f"PySceneDetect found {len(scene_changes)-1} scene changes in video")
|
||||
logger.debug(f"Scene change timestamps: {scene_changes}")
|
||||
|
||||
return scene_changes
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"PySceneDetect failed: {e}, falling back to OpenCV method")
|
||||
return self._detect_scene_changes_opencv(file_path, threshold)
|
||||
else:
|
||||
logger.warning("PySceneDetect not available, using OpenCV method")
|
||||
return self._detect_scene_changes_opencv(file_path, threshold)
|
||||
|
||||
def _detect_scene_changes_opencv(self, file_path: str, threshold: float = 30.0) -> List[float]:
|
||||
"""使用OpenCV检测场景变化点(备用方案)"""
|
||||
if not VIDEO_LIBS_AVAILABLE:
|
||||
logger.warning("Video processing not available, returning empty scene changes")
|
||||
return []
|
||||
|
||||
logger.warning("Video processing not available, returning basic scene changes")
|
||||
# 获取视频时长,返回开始和结束时间
|
||||
try:
|
||||
video_info = self._get_video_info(file_path)
|
||||
duration = video_info.get('duration', 0)
|
||||
return [0.0, duration] if duration > 0 else [0.0]
|
||||
except:
|
||||
return [0.0]
|
||||
|
||||
try:
|
||||
cap = cv2.VideoCapture(file_path)
|
||||
fps = cap.get(cv2.CAP_PROP_FPS)
|
||||
|
||||
|
||||
if fps <= 0:
|
||||
cap.release()
|
||||
logger.warning(f"Invalid fps ({fps}) for video {file_path}")
|
||||
return [0.0]
|
||||
|
||||
scene_changes = [0.0] # 开始时间
|
||||
prev_frame = None
|
||||
frame_count = 0
|
||||
|
||||
|
||||
# 每隔几帧检测一次,提高性能
|
||||
frame_skip = max(1, int(fps / 2)) # 每秒检测2次
|
||||
|
||||
while True:
|
||||
ret, frame = cap.read()
|
||||
if not ret:
|
||||
break
|
||||
|
||||
# 转换为灰度图
|
||||
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
if prev_frame is not None:
|
||||
# 计算帧间差异
|
||||
diff = cv2.absdiff(prev_frame, gray)
|
||||
mean_diff = np.mean(diff)
|
||||
|
||||
# 如果差异超过阈值,认为是场景变化
|
||||
if mean_diff > threshold:
|
||||
timestamp = frame_count / fps
|
||||
scene_changes.append(timestamp)
|
||||
logger.debug(f"Scene change detected at {timestamp:.2f}s (diff: {mean_diff:.2f})")
|
||||
|
||||
prev_frame = gray
|
||||
|
||||
# 跳帧处理
|
||||
if frame_count % frame_skip == 0:
|
||||
# 转换为灰度图并缩小尺寸以提高性能
|
||||
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||
gray = cv2.resize(gray, (320, 240))
|
||||
|
||||
if prev_frame is not None:
|
||||
# 计算帧间差异
|
||||
diff = cv2.absdiff(prev_frame, gray)
|
||||
mean_diff = np.mean(diff)
|
||||
|
||||
# 如果差异超过阈值,认为是场景变化
|
||||
if mean_diff > threshold:
|
||||
timestamp = frame_count / fps
|
||||
# 避免过于接近的场景变化点
|
||||
if not scene_changes or timestamp - scene_changes[-1] > 1.0:
|
||||
scene_changes.append(timestamp)
|
||||
logger.debug(f"Scene change detected at {timestamp:.2f}s (diff: {mean_diff:.2f})")
|
||||
|
||||
prev_frame = gray
|
||||
|
||||
frame_count += 1
|
||||
|
||||
|
||||
cap.release()
|
||||
|
||||
|
||||
# 添加结束时间
|
||||
duration = frame_count / fps if fps > 0 else 0
|
||||
if duration > 0:
|
||||
if duration > 0 and (not scene_changes or duration - scene_changes[-1] > 0.5):
|
||||
scene_changes.append(duration)
|
||||
|
||||
logger.info(f"Detected {len(scene_changes)-1} scene changes in video")
|
||||
|
||||
logger.info(f"OpenCV detected {len(scene_changes)-1} scene changes in video")
|
||||
return scene_changes
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to detect scene changes: {e}")
|
||||
return [0.0]
|
||||
logger.error(f"Failed to detect scene changes with OpenCV: {e}")
|
||||
# 返回基本的开始和结束时间
|
||||
try:
|
||||
video_info = self._get_video_info(file_path)
|
||||
duration = video_info.get('duration', 0)
|
||||
return [0.0, duration] if duration > 0 else [0.0]
|
||||
except:
|
||||
return [0.0]
|
||||
|
||||
def _generate_thumbnail(self, video_path: str, timestamp: float, output_path: str) -> bool:
|
||||
"""生成视频缩略图"""
|
||||
|
||||
Reference in New Issue
Block a user