Warm up pyannote and FunASR runtimes
PR and Push Build/Test / build-and-test (push) Successful in 6m48s

This commit is contained in:
2026-05-28 13:05:27 +02:00
parent 7ff93b73b3
commit c46c587e65
14 changed files with 696 additions and 20 deletions
@@ -1,3 +1,5 @@
using MeetingAssistant;
using MeetingAssistant.LaunchProfiles;
using MeetingAssistant.Transcription;
using Microsoft.Extensions.Logging.Abstractions;
@@ -27,18 +29,118 @@ public sealed class SpeechRecognitionPipelineHostedServiceTests
Assert.True(pipeline.Disposed);
}
[Fact]
public async Task HostedServiceWarmsConfiguredLaunchProfilePipelinesWithoutBlockingStartup()
{
var defaultPipeline = new CapturingSpeechRecognitionPipeline();
var funAsrPipeline = new CapturingSpeechRecognitionPipeline { BlockReadinessUntilCancelled = true };
var englishPipeline = new CapturingSpeechRecognitionPipeline();
var service = new SpeechRecognitionPipelineHostedService(
new CapturingSpeechRecognitionPipelineFactory(new Dictionary<string, ISpeechRecognitionPipeline>
{
[ConfigurationLaunchProfileOptionsProvider.DefaultProfileName] = defaultPipeline,
["funasr"] = funAsrPipeline,
["english"] = englishPipeline
}),
new FakeLaunchProfileOptionsProvider(
[
new LaunchProfile(
ConfigurationLaunchProfileOptionsProvider.DefaultProfileName,
new MeetingAssistantOptions
{
Recording = { TranscriptionProvider = "azure-speech" }
}),
new LaunchProfile(
"funasr",
new MeetingAssistantOptions
{
Recording = { TranscriptionProvider = "funasr" }
}),
new LaunchProfile(
"english",
new MeetingAssistantOptions
{
Recording = { TranscriptionProvider = "azure-speech" }
})
]),
NullLogger<SpeechRecognitionPipelineHostedService>.Instance);
var startTask = service.StartAsync(CancellationToken.None);
await startTask.WaitAsync(TimeSpan.FromSeconds(1));
await defaultPipeline.WaitForInitializeAsync();
await defaultPipeline.WaitForReadinessAsync();
await funAsrPipeline.WaitForInitializeAsync();
await funAsrPipeline.WaitForReadinessAsync();
await service.StopAsync(CancellationToken.None);
Assert.Equal(1, defaultPipeline.InitializeCount);
Assert.Equal(1, funAsrPipeline.InitializeCount);
Assert.True(defaultPipeline.Disposed);
Assert.True(funAsrPipeline.Disposed);
Assert.True(funAsrPipeline.ReadinessCancellationWasObserved);
Assert.Equal(0, englishPipeline.InitializeCount);
Assert.False(englishPipeline.Disposed);
}
private sealed class CapturingSpeechRecognitionPipelineFactory : ISpeechRecognitionPipelineFactory
{
private readonly ISpeechRecognitionPipeline pipeline;
private readonly IReadOnlyDictionary<string, ISpeechRecognitionPipeline> pipelines;
public CapturingSpeechRecognitionPipelineFactory(ISpeechRecognitionPipeline pipeline)
: this(new Dictionary<string, ISpeechRecognitionPipeline>
{
[ConfigurationLaunchProfileOptionsProvider.DefaultProfileName] = pipeline
})
{
this.pipeline = pipeline;
}
public CapturingSpeechRecognitionPipelineFactory(
IReadOnlyDictionary<string, ISpeechRecognitionPipeline> pipelines)
{
this.pipelines = pipelines;
}
public ISpeechRecognitionPipeline Create()
{
return pipeline;
return Create(ConfigurationLaunchProfileOptionsProvider.DefaultProfileName);
}
public ISpeechRecognitionPipeline Create(string? launchProfileName)
{
var profileName = string.IsNullOrWhiteSpace(launchProfileName)
? ConfigurationLaunchProfileOptionsProvider.DefaultProfileName
: launchProfileName;
return pipelines[profileName];
}
}
private sealed class FakeLaunchProfileOptionsProvider : ILaunchProfileOptionsProvider
{
private readonly IReadOnlyList<LaunchProfile> profiles;
public FakeLaunchProfileOptionsProvider(IReadOnlyList<LaunchProfile> profiles)
{
this.profiles = profiles;
}
public LaunchProfile GetRequiredProfile(string? name)
{
var profileName = string.IsNullOrWhiteSpace(name)
? ConfigurationLaunchProfileOptionsProvider.DefaultProfileName
: name;
return profiles.Single(profile => profile.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));
}
public IReadOnlyList<LaunchProfile> GetProfiles()
{
return profiles;
}
public IReadOnlyList<LaunchProfileHotkey> GetHotkeys()
{
return [];
}
}