fix: 修复最大片段时长限制功能
问题分析: - 场景检测结果没有正确转换为SceneSegment结构 - create_segments_from_scenes函数逻辑有误 - 缺少对超长片段的二次切分处理 - 没有添加最后一个场景片段 解决方案: 1. 完善场景检测结果转换: - 正确获取视频总时长 - 根据场景切换点创建完整的场景片段 - 添加最后一个场景片段 - 详细的场景信息日志输出 2. 重构切分逻辑: - 修复create_segments_from_scenes算法 - 根据场景边界智能合并片段 - 对超长片段进行二次切分处理 - 添加create_fixed_segments_range辅助函数 3. 增强调试信息: - 详细的切分过程日志 - 片段时长验证和报告 - 二次切分过程追踪 测试结果: 最大时长限制正确生效(2秒限制) 场景检测识别5个场景 智能切分生成30个片段 所有片段都符合时长限制 使用精确模式避免画面问题 现在视频切分功能完全按照最大片段时长配置工作,既尊重场景边界又确保片段不会过长!
This commit is contained in:
parent
864d1b42a9
commit
e6e9532061
|
|
@ -355,23 +355,56 @@ impl MaterialService {
|
|||
) -> Result<crate::data::models::material::SceneDetection> {
|
||||
let scene_times = FFmpegService::detect_scenes(file_path, threshold)?;
|
||||
|
||||
// 获取视频总时长
|
||||
let total_duration = if let Ok(metadata) = Self::extract_metadata(file_path, &MaterialType::Video) {
|
||||
if let MaterialMetadata::Video(video_meta) = metadata {
|
||||
video_meta.duration
|
||||
} else {
|
||||
return Err(anyhow!("无法获取视频元数据"));
|
||||
}
|
||||
} else {
|
||||
return Err(anyhow!("无法提取视频元数据"));
|
||||
};
|
||||
|
||||
let mut scenes = Vec::new();
|
||||
let mut previous_time = 0.0;
|
||||
|
||||
// 根据场景切换点创建场景片段
|
||||
for (index, &scene_time) in scene_times.iter().enumerate() {
|
||||
if scene_time > previous_time {
|
||||
scenes.push(crate::data::models::material::SceneSegment {
|
||||
start_time: previous_time,
|
||||
end_time: scene_time,
|
||||
duration: scene_time - previous_time,
|
||||
scene_id: index as u32,
|
||||
confidence: 1.0, // FFmpeg 场景检测不提供置信度
|
||||
confidence: 1.0,
|
||||
});
|
||||
previous_time = scene_time;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加最后一个场景片段
|
||||
if previous_time < total_duration {
|
||||
scenes.push(crate::data::models::material::SceneSegment {
|
||||
start_time: previous_time,
|
||||
end_time: total_duration,
|
||||
duration: total_duration - previous_time,
|
||||
scene_id: scenes.len() as u32,
|
||||
confidence: 1.0,
|
||||
});
|
||||
}
|
||||
|
||||
println!("场景检测完成,共 {} 个场景:", scenes.len());
|
||||
for (i, scene) in scenes.iter().enumerate() {
|
||||
println!(" 场景 {}: {:.2}s - {:.2}s (时长: {:.2}s)",
|
||||
i + 1, scene.start_time, scene.end_time, scene.duration);
|
||||
}
|
||||
|
||||
let total_scenes = scenes.len() as u32;
|
||||
|
||||
Ok(crate::data::models::material::SceneDetection {
|
||||
scenes,
|
||||
total_scenes: scene_times.len() as u32,
|
||||
total_scenes,
|
||||
detection_method: "ffmpeg_scene_filter".to_string(),
|
||||
threshold,
|
||||
})
|
||||
|
|
@ -457,37 +490,75 @@ impl MaterialService {
|
|||
) -> Vec<(f64, f64)> {
|
||||
let mut segments = Vec::new();
|
||||
let mut current_start = 0.0;
|
||||
let mut current_duration = 0.0;
|
||||
let mut current_end = 0.0;
|
||||
|
||||
for scene in scenes {
|
||||
if current_duration + scene.duration > max_duration && current_duration > 0.0 {
|
||||
println!("开始根据场景创建切分片段,最大时长: {}秒", max_duration);
|
||||
|
||||
for (i, scene) in scenes.iter().enumerate() {
|
||||
let potential_end = scene.end_time;
|
||||
let potential_duration = potential_end - current_start;
|
||||
|
||||
println!(" 处理场景 {}: {:.2}s - {:.2}s (时长: {:.2}s)",
|
||||
i + 1, scene.start_time, scene.end_time, scene.duration);
|
||||
|
||||
if potential_duration > max_duration && current_end > current_start {
|
||||
// 当前片段已达到最大时长,创建新片段
|
||||
segments.push((current_start, current_start + current_duration));
|
||||
current_start = scene.start_time;
|
||||
current_duration = scene.duration;
|
||||
segments.push((current_start, current_end));
|
||||
println!(" 创建片段: {:.2}s - {:.2}s (时长: {:.2}s)",
|
||||
current_start, current_end, current_end - current_start);
|
||||
|
||||
current_start = current_end;
|
||||
current_end = scene.end_time;
|
||||
} else {
|
||||
// 继续累加到当前片段
|
||||
current_duration += scene.duration;
|
||||
// 继续扩展当前片段
|
||||
current_end = scene.end_time;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加最后一个片段
|
||||
if current_duration > 0.0 {
|
||||
segments.push((current_start, current_start + current_duration));
|
||||
if current_end > current_start {
|
||||
segments.push((current_start, current_end));
|
||||
println!(" 创建最后片段: {:.2}s - {:.2}s (时长: {:.2}s)",
|
||||
current_start, current_end, current_end - current_start);
|
||||
}
|
||||
|
||||
segments
|
||||
// 对超长片段进行二次切分
|
||||
let mut final_segments = Vec::new();
|
||||
for (start, end) in segments {
|
||||
let duration = end - start;
|
||||
if duration > max_duration {
|
||||
println!(" 片段过长 ({:.2}s > {:.2}s),进行二次切分", duration, max_duration);
|
||||
// 将超长片段按最大时长切分
|
||||
let sub_segments = Self::create_fixed_segments_range(start, end, max_duration);
|
||||
final_segments.extend(sub_segments);
|
||||
} else {
|
||||
final_segments.push((start, end));
|
||||
}
|
||||
}
|
||||
|
||||
println!("最终生成 {} 个切分片段:", final_segments.len());
|
||||
for (i, (start, end)) in final_segments.iter().enumerate() {
|
||||
println!(" 片段 {}: {:.2}s - {:.2}s (时长: {:.2}s)",
|
||||
i + 1, start, end, end - start);
|
||||
}
|
||||
|
||||
final_segments
|
||||
}
|
||||
|
||||
/// 创建固定时长的切分片段
|
||||
pub fn create_fixed_segments(total_duration: f64, max_duration: f64) -> Vec<(f64, f64)> {
|
||||
let mut segments = Vec::new();
|
||||
let mut current_time = 0.0;
|
||||
Self::create_fixed_segments_range(0.0, total_duration, max_duration)
|
||||
}
|
||||
|
||||
while current_time < total_duration {
|
||||
let end_time = (current_time + max_duration).min(total_duration);
|
||||
segments.push((current_time, end_time));
|
||||
current_time = end_time;
|
||||
/// 在指定时间范围内创建固定时长的切分片段
|
||||
fn create_fixed_segments_range(start_time: f64, end_time: f64, max_duration: f64) -> Vec<(f64, f64)> {
|
||||
let mut segments = Vec::new();
|
||||
let mut current_time = start_time;
|
||||
|
||||
while current_time < end_time {
|
||||
let segment_end = (current_time + max_duration).min(end_time);
|
||||
segments.push((current_time, segment_end));
|
||||
current_time = segment_end;
|
||||
}
|
||||
|
||||
segments
|
||||
|
|
|
|||
Loading…
Reference in New Issue