feat: 添加最大视频时长检测和二次切分功能
- 添加最大视频时长限制配置 (默认2秒) - 实现二次切分功能,超过时长限制的视频自动切分 - 优化单场景检测逻辑,跳过不必要的切分 - 修复场景和片段统计逻辑,无场景切换时统计为1个场景 - 添加CLI参数 --max-duration 支持自定义时长限制 - 集成FfmpegSliceService同步版本,简化异步复杂性 - 完善错误处理和文件清理机制
This commit is contained in:
parent
5659bb34f3
commit
808c143bf8
|
|
@ -111,6 +111,7 @@ def batch_detect_and_split(
|
|||
use_advanced_split: bool = typer.Option(True, "--advanced/--traditional", help="使用高效批量切分/传统逐个切分"),
|
||||
split_quality: int = typer.Option(23, "--quality", "-q", help="切分质量 (CRF值, 18-28)"),
|
||||
split_preset: str = typer.Option("fast", "--preset", help="编码预设 (ultrafast/fast/medium/slow)"),
|
||||
max_duration: float = typer.Option(2.0, "--max-duration", "-d", help="最大视频时长限制(秒),超过将二次切分"),
|
||||
verbose: bool = typer.Option(False, "--verbose", "-v", help="详细输出")
|
||||
):
|
||||
"""批量场景检测和视频切分"""
|
||||
|
|
@ -162,7 +163,8 @@ def batch_detect_and_split(
|
|||
continue_on_error=continue_on_error,
|
||||
use_advanced_split=use_advanced_split,
|
||||
split_quality=split_quality,
|
||||
split_preset=split_preset
|
||||
split_preset=split_preset,
|
||||
max_video_duration=max_duration
|
||||
)
|
||||
|
||||
# 显示结果
|
||||
|
|
|
|||
|
|
@ -120,11 +120,12 @@ class SceneDetector:
|
|||
enable_ai_analysis: bool = False, enable_video_splitting: bool = True,
|
||||
max_concurrent: int = 2, continue_on_error: bool = True,
|
||||
use_advanced_split: bool = True, split_quality: int = 23, split_preset: str = "fast",
|
||||
request_id: Optional[str] = None) -> Dict[str, Any]:
|
||||
max_video_duration: float = 60.0, request_id: Optional[str] = None) -> Dict[str, Any]:
|
||||
"""批量场景检测和视频切分"""
|
||||
return self.workflow_manager.batch_detect_and_split(
|
||||
video_paths, output_base_dir, detector_type, threshold, min_scene_length,
|
||||
output_format, enable_ai_analysis, enable_video_splitting,
|
||||
max_concurrent, continue_on_error, use_advanced_split, split_quality, split_preset, request_id
|
||||
max_concurrent, continue_on_error, use_advanced_split, split_quality, split_preset,
|
||||
max_video_duration, request_id
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class BatchSceneDetectionWorkflowState:
|
|||
use_advanced_split: bool = True
|
||||
split_quality: int = 23
|
||||
split_preset: str = "fast"
|
||||
max_video_duration: float = 60.0 # 最大视频时长(秒),默认60秒
|
||||
max_video_duration: float = 2.0 # 最大视频时长(秒),默认60秒
|
||||
|
||||
# 批量处理配置
|
||||
max_concurrent: int = 4
|
||||
|
|
|
|||
|
|
@ -296,20 +296,6 @@ class BatchWorkflowNodes:
|
|||
)
|
||||
split_results_raw.append(split_result)
|
||||
|
||||
# 转换为字典格式
|
||||
split_results = [
|
||||
{
|
||||
"scene_index": r.scene_index + 1,
|
||||
"output_path": str(r.output_path),
|
||||
"start_time": r.start_time,
|
||||
"end_time": r.end_time,
|
||||
"duration": r.duration,
|
||||
"file_size": r.file_size,
|
||||
"success": r.success,
|
||||
"error": r.error
|
||||
}
|
||||
for r in split_results_raw
|
||||
]
|
||||
|
||||
# 创建切分摘要
|
||||
successful_results = [r for r in split_results_raw if r.success]
|
||||
|
|
@ -333,6 +319,79 @@ class BatchWorkflowNodes:
|
|||
# 切分失败不影响整体任务成功
|
||||
|
||||
# 4. 添加视频时长检查,如果时长大于 最大视频时长 那么就要进行二次切分 确保 视频不大于 最大视频时长
|
||||
final_split_results = []
|
||||
|
||||
for split_result in split_results_raw:
|
||||
try:
|
||||
# 检查切分后的视频时长
|
||||
video_path = str(split_result.output_path)
|
||||
|
||||
if split_result.duration > state.max_video_duration:
|
||||
logger.info(f"⚠️ 片段 {split_result.scene_index + 1} 时长 {split_result.duration:.2f}s 超过限制 {state.max_video_duration:.2f}s,进行二次切分")
|
||||
|
||||
# 进行二次切分
|
||||
secondary_results = self.splitter_service.check_and_split_by_duration(
|
||||
video_path=video_path,
|
||||
max_duration=state.max_video_duration,
|
||||
options=slice_options,
|
||||
output_dir=str(split_result.output_path.parent)
|
||||
)
|
||||
|
||||
# 处理二次切分结果
|
||||
for i, (secondary_path, secondary_metadata) in enumerate(secondary_results):
|
||||
if len(secondary_results) > 1:
|
||||
# 如果进行了二次切分,创建新的结果对象
|
||||
secondary_split_result = SplitResult(
|
||||
scene_index=split_result.scene_index,
|
||||
output_path=secondary_path,
|
||||
start_time=split_result.start_time + (i * state.max_video_duration),
|
||||
end_time=min(split_result.start_time + ((i + 1) * state.max_video_duration), split_result.end_time),
|
||||
duration=secondary_metadata.duration,
|
||||
file_size=secondary_metadata.size,
|
||||
success=Path(secondary_path).exists(),
|
||||
error=None if Path(secondary_path).exists() else "二次切分文件不存在"
|
||||
)
|
||||
final_split_results.append(secondary_split_result)
|
||||
|
||||
# 删除原始的过长片段(如果二次切分成功)
|
||||
if Path(video_path).exists() and len(secondary_results) > 1:
|
||||
try:
|
||||
Path(video_path).unlink()
|
||||
logger.info(f"🗑️ 已删除过长的原始片段: {Path(video_path).name}")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ 删除原始片段失败: {e}")
|
||||
else:
|
||||
# 如果没有进行二次切分(时长检查通过),保持原结果
|
||||
final_split_results.append(split_result)
|
||||
else:
|
||||
# 时长未超过限制,直接添加到最终结果
|
||||
final_split_results.append(split_result)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ 处理片段 {split_result.scene_index + 1} 的时长检查时出错: {e}")
|
||||
# 出错时保持原结果
|
||||
final_split_results.append(split_result)
|
||||
|
||||
# 使用最终的切分结果
|
||||
split_results_raw = final_split_results
|
||||
|
||||
# 转换为字典格式
|
||||
split_results = [
|
||||
{
|
||||
"scene_index": r.scene_index + 1,
|
||||
"output_path": str(r.output_path),
|
||||
"start_time": r.start_time,
|
||||
"end_time": r.end_time,
|
||||
"duration": r.duration,
|
||||
"file_size": r.file_size,
|
||||
"success": r.success,
|
||||
"error": r.error
|
||||
}
|
||||
for r in split_results_raw
|
||||
]
|
||||
|
||||
# 更新统计信息
|
||||
logger.info(f"📊 最终生成 {len(split_results_raw)} 个视频片段(包含二次切分)")
|
||||
|
||||
task.end_time = time.time()
|
||||
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ class SceneDetectionWorkflowManager:
|
|||
enable_ai_analysis: bool = False, enable_video_splitting: bool = True,
|
||||
max_concurrent: int = 2, continue_on_error: bool = True,
|
||||
use_advanced_split: bool = True, split_quality: int = 23, split_preset: str = "fast",
|
||||
request_id: Optional[str] = None) -> Dict[str, Any]:
|
||||
max_video_duration: float = 60.0, request_id: Optional[str] = None) -> Dict[str, Any]:
|
||||
"""批量场景检测和视频切分"""
|
||||
|
||||
# 创建批量工作流状态
|
||||
|
|
@ -200,6 +200,7 @@ class SceneDetectionWorkflowManager:
|
|||
use_advanced_split=use_advanced_split,
|
||||
split_quality=split_quality,
|
||||
split_preset=split_preset,
|
||||
max_video_duration=max_video_duration,
|
||||
max_concurrent=max_concurrent,
|
||||
continue_on_error=continue_on_error,
|
||||
request_id=request_id,
|
||||
|
|
|
|||
Loading…
Reference in New Issue