Files
meeting-assistant/MeetingAssistant/Speakers/SpeakerSampleSpanSelector.cs
T
codex a72cda0c03
PR and Push Build/Test / build-and-test (push) Successful in 7m0s
Harden speaker identity samples
2026-05-28 12:02:44 +02:00

80 lines
2.3 KiB
C#

using MeetingAssistant.Transcription;
namespace MeetingAssistant.Speakers;
internal static class SpeakerSampleSpanSelector
{
public static bool CanExtend(
string currentSpeaker,
TimeSpan currentEnd,
TranscriptionSegment nextSegment,
TimeSpan maximumSegmentGap)
{
return string.Equals(currentSpeaker, nextSegment.Speaker, StringComparison.OrdinalIgnoreCase) &&
nextSegment.Start - currentEnd <= maximumSegmentGap;
}
public static IReadOnlyList<TranscriptionSegment> SelectBestContinuousSpan(
IReadOnlyList<TranscriptionSegment> segments,
string speaker,
TimeSpan maximumSegmentGap,
TimeSpan minimumDuration)
{
var best = new List<TranscriptionSegment>();
var current = new List<TranscriptionSegment>();
foreach (var segment in segments.OrderBy(segment => segment.Start))
{
if (current.Count == 0)
{
if (IsSpeaker(segment, speaker))
{
current.Add(segment);
best = LongerSpan(current, best);
}
continue;
}
if (!CanExtend(speaker, current[^1].End, segment, maximumSegmentGap))
{
current.Clear();
if (!IsSpeaker(segment, speaker))
{
continue;
}
}
current.Add(segment);
best = LongerSpan(current, best);
}
return SpanDuration(best) >= minimumDuration
? best
: [];
}
public static TimeSpan SpanDuration(IReadOnlyList<TranscriptionSegment> segments)
{
return segments.Count == 0
? TimeSpan.Zero
: segments[^1].End - segments[0].Start;
}
private static bool IsSpeaker(
TranscriptionSegment segment,
string speaker)
{
return string.Equals(segment.Speaker, speaker, StringComparison.OrdinalIgnoreCase);
}
private static List<TranscriptionSegment> LongerSpan(
List<TranscriptionSegment> current,
List<TranscriptionSegment> best)
{
return SpanDuration(current) > SpanDuration(best)
? current.ToList()
: best;
}
}