fix: 修正文件名序号001全局限制逻辑

修复问题:
- 将序号001限制从仅针对FilenameSequence规则改为全局限制
- 现在所有匹配规则(AiClassification、RandomMatch、FilenameSequence)都会遵守序号001限制
- 在单个模板匹配过程中,最多只能使用一个文件名以001结尾的视频文件

实现细节:
1. 在match_single_segment方法开始时检查模板是否已使用序号001视频
2. 将此状态传递给所有匹配方法
3. 在每个匹配方法的过滤逻辑中应用序号001限制
4. 统一的过滤逻辑确保一致性

这确保了无论使用哪种匹配规则,都不会在同一个模板中使用多个序号001的视频文件。
This commit is contained in:
imeepos 2025-07-21 19:24:58 +08:00
parent 856d0b1055
commit 5ae7874792
1 changed files with 57 additions and 20 deletions

View File

@ -496,6 +496,18 @@ impl MaterialMatchingService {
project_materials: &[Material],
used_segment_ids: &mut HashSet<String>,
) -> Result<SegmentMatch, String> {
// 全局限制检查当前模板匹配过程中是否已经使用了以001结尾的文件
let mut template_already_used_sequence_001 = false;
for used_id in used_segment_ids.iter() {
if let Some((used_segment, _)) = available_segments.iter().find(|(seg, _)| seg.id == *used_id) {
if FilenameUtils::has_sequence_001(&used_segment.file_path) && FilenameUtils::is_video_file(&used_segment.file_path) {
template_already_used_sequence_001 = true;
println!("⚠️ 当前模板已使用序号001视频: {}", FilenameUtils::extract_filename(&used_segment.file_path));
break;
}
}
}
// 检查匹配规则
match &track_segment.matching_rule {
SegmentMatchingRule::FixedMaterial => {
@ -509,6 +521,7 @@ impl MaterialMatchingService {
category_name,
project_materials,
used_segment_ids,
template_already_used_sequence_001,
).await
}
SegmentMatchingRule::RandomMatch => {
@ -517,6 +530,7 @@ impl MaterialMatchingService {
available_segments,
project_materials,
used_segment_ids,
template_already_used_sequence_001,
).await
}
SegmentMatchingRule::FilenameSequence { target_sequence } => {
@ -526,6 +540,7 @@ impl MaterialMatchingService {
target_sequence,
project_materials,
used_segment_ids,
template_already_used_sequence_001,
).await
}
}
@ -539,6 +554,7 @@ impl MaterialMatchingService {
target_category: &str,
project_materials: &[Material],
used_segment_ids: &mut HashSet<String>,
template_already_used_sequence_001: bool,
) -> Result<SegmentMatch, String> {
// 计算目标时长(微秒转秒)- 修复单位转换
let target_duration = track_segment.duration as f64 / 1_000_000.0;
@ -550,11 +566,25 @@ impl MaterialMatchingService {
println!(" 转换后时长(秒): {:.3}", target_duration);
println!(" 目标分类: {}", target_category);
// 过滤出匹配分类的片段
// 过滤出匹配分类的片段同时应用序号001限制
let category_segments: Vec<_> = available_segments
.iter()
.filter(|(segment, category)| {
category == target_category && !used_segment_ids.contains(&segment.id)
// 基本条件:分类匹配且未被使用
if category != target_category || used_segment_ids.contains(&segment.id) {
return false;
}
// 全局限制如果模板已经使用了序号001的视频则跳过所有序号001的视频
if template_already_used_sequence_001
&& FilenameUtils::has_sequence_001(&segment.file_path)
&& FilenameUtils::is_video_file(&segment.file_path) {
println!(" ⏭️ 跳过序号001片段模板已使用序号001: {}",
FilenameUtils::extract_filename(&segment.file_path));
return false;
}
true
})
.collect();
@ -616,6 +646,7 @@ impl MaterialMatchingService {
available_segments: &[(MaterialSegment, String)],
project_materials: &[Material],
used_segment_ids: &mut HashSet<String>,
template_already_used_sequence_001: bool,
) -> Result<SegmentMatch, String> {
// 计算目标时长(微秒转秒)- 修复单位转换
let target_duration = track_segment.duration as f64 / 1_000_000.0;
@ -626,10 +657,26 @@ impl MaterialMatchingService {
println!(" 原始时长(微秒): {}", track_segment.duration);
println!(" 转换后时长(秒): {:.3}", target_duration);
// 过滤出未使用的片段
// 过滤出未使用的片段同时应用序号001限制
let unused_segments: Vec<_> = available_segments
.iter()
.filter(|(segment, _)| !used_segment_ids.contains(&segment.id))
.filter(|(segment, _)| {
// 基本条件:未被使用
if used_segment_ids.contains(&segment.id) {
return false;
}
// 全局限制如果模板已经使用了序号001的视频则跳过所有序号001的视频
if template_already_used_sequence_001
&& FilenameUtils::has_sequence_001(&segment.file_path)
&& FilenameUtils::is_video_file(&segment.file_path) {
println!(" ⏭️ 跳过序号001片段模板已使用序号001: {}",
FilenameUtils::extract_filename(&segment.file_path));
return false;
}
true
})
.collect();
if unused_segments.is_empty() {
@ -728,6 +775,7 @@ impl MaterialMatchingService {
target_sequence: &str,
project_materials: &[Material],
used_segment_ids: &mut HashSet<String>,
template_already_used_sequence_001: bool,
) -> Result<SegmentMatch, String> {
println!("🔢 开始文件名序号匹配:");
println!(" 目标序号: {}", target_sequence);
@ -736,20 +784,7 @@ impl MaterialMatchingService {
let target_duration = track_segment.duration as f64 / 1_000_000.0; // 转换为秒
println!(" 目标时长(秒): {:.3}", target_duration);
// 特殊处理如果目标序号是001检查当前模板匹配过程中是否已经使用了序号001的视频
let mut template_already_used_sequence_001 = false;
if target_sequence == "001" {
// 检查当前模板匹配过程中已使用的片段中是否有序号001的视频
for used_id in used_segment_ids.iter() {
if let Some((used_segment, _)) = available_segments.iter().find(|(seg, _)| seg.id == *used_id) {
if FilenameUtils::has_sequence_001(&used_segment.file_path) && FilenameUtils::is_video_file(&used_segment.file_path) {
template_already_used_sequence_001 = true;
println!("⚠️ 当前模板已使用序号001视频: {}", FilenameUtils::extract_filename(&used_segment.file_path));
break;
}
}
}
}
// 序号001限制检查已在上层完成这里直接使用传递的参数
// 筛选出包含目标序号的视频文件片段
let mut matching_segments = Vec::new();
@ -762,8 +797,10 @@ impl MaterialMatchingService {
// 检查文件名是否包含目标序号
if FilenameUtils::has_sequence_number(&segment.file_path, target_sequence) {
// 特殊处理如果目标序号是001且当前模板已经使用了序号001的视频则跳过这个片段
if target_sequence == "001" && template_already_used_sequence_001 {
// 全局限制如果模板已经使用了序号001的视频则跳过所有序号001的视频
if template_already_used_sequence_001
&& FilenameUtils::has_sequence_001(&segment.file_path)
&& FilenameUtils::is_video_file(&segment.file_path) {
println!(" ⏭️ 跳过序号001片段模板已使用序号001: {}",
FilenameUtils::extract_filename(&segment.file_path));
continue;