Make meeting lifecycle stateful

This commit is contained in:
2026-05-27 12:55:17 +02:00
parent d607b957bb
commit e85274829a
91 changed files with 4076 additions and 479 deletions
@@ -52,7 +52,15 @@ public sealed class AzureSpeechSpeakerIdentityMatcher : ISpeakerIdentityMatcher
return null;
}
var segments = await diarizationClient.DiarizeAsync(tempPath, cancellationToken);
var segments = await DiarizeWithTimeoutAsync(tempPath, cancellationToken);
if (segments.Count == 0)
{
logger.LogInformation(
"Speaker identity matching {DiarizedSpeaker} skipped because diarization returned no segments",
request.DiarizedSpeaker);
return null;
}
logger.LogInformation(
"Speaker identity matching {DiarizedSpeaker} received {SegmentCount} diarized segment(s)",
request.DiarizedSpeaker,
@@ -95,6 +103,31 @@ public sealed class AzureSpeechSpeakerIdentityMatcher : ISpeakerIdentityMatcher
}
}
private async Task<IReadOnlyList<TranscriptionSegment>> DiarizeWithTimeoutAsync(
string wavPath,
CancellationToken cancellationToken)
{
var matchTimeout = options.MatchTimeout;
if (matchTimeout <= TimeSpan.Zero)
{
return await diarizationClient.DiarizeAsync(wavPath, cancellationToken);
}
using var timeout = new CancellationTokenSource(matchTimeout);
using var linked = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeout.Token);
try
{
return await diarizationClient.DiarizeAsync(wavPath, linked.Token);
}
catch (OperationCanceledException) when (timeout.IsCancellationRequested && !cancellationToken.IsCancellationRequested)
{
logger.LogWarning(
"Speaker identity diarization timed out after {Timeout}",
matchTimeout);
return [];
}
}
private CompositeLayout WriteCompositeWav(string path, SpeakerIdentityMatchRequest request)
{
using var firstReader = OpenFirstReadableWave(request);