Add inactivity safeguard and speaker diagnostics
PR and Push Build/Test / build-and-test (push) Failing after 8m31s

This commit is contained in:
2026-06-02 13:16:02 +02:00
parent c56ecb6ab3
commit 0e9d525b63
24 changed files with 1780 additions and 117 deletions
@@ -1,5 +1,6 @@
using MeetingAssistant.Recording;
using MeetingAssistant.Transcription;
using Microsoft.Extensions.Logging;
using NAudio.Wave;
namespace MeetingAssistant.Tests;
@@ -47,6 +48,27 @@ public sealed class SpeakerAudioSampleCollectorTests
Assert.DoesNotContain(collector.Snapshot(), sample => sample.Speaker == "Guest01");
}
[Fact]
public void CollectorLogsWhenSampleIsDiscardedBecauseSpeechIsTooShort()
{
var logger = new CapturingLogger();
var collector = new SpeakerAudioSampleCollector(
TimeSpan.FromMinutes(2),
maxSamplesPerSpeaker: 3,
minimumUninterruptedSpeechDuration: TimeSpan.FromSeconds(30),
maximumSegmentGap: TimeSpan.FromSeconds(1),
logger: logger);
collector.AppendAudio(CreateAudio(TimeSpan.FromSeconds(35)));
collector.TryAdd(Segment(0, 12, "Guest01", "one two three four five."));
var message = Assert.Single(
logger.Messages,
message => message.Contains("Discarding speaker identity sample for Guest01", StringComparison.Ordinal));
Assert.Contains("duration", message);
Assert.Contains("minimum duration", message);
}
private static TranscriptionSegment Segment(
double start,
double end,
@@ -73,4 +95,30 @@ public sealed class SpeakerAudioSampleCollectorTests
using var reader = new WaveFileReader(new MemoryStream(wavBytes));
return reader.TotalTime;
}
private sealed class CapturingLogger : ILogger
{
public List<string> Messages { get; } = [];
public IDisposable? BeginScope<TState>(TState state)
where TState : notnull
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return true;
}
public void Log<TState>(
LogLevel logLevel,
EventId eventId,
TState state,
Exception? exception,
Func<TState, Exception?, string> formatter)
{
Messages.Add(formatter(state, exception));
}
}
}