Files
meeting-assistant/MeetingAssistant.Tests/FunAsrTranscriptFinalizerTests.cs
2026-05-20 02:06:16 +02:00

110 lines
4.0 KiB
C#

using MeetingAssistant;
using MeetingAssistant.Transcription;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
namespace MeetingAssistant.Tests;
public sealed class FunAsrTranscriptFinalizerTests
{
[Fact]
public async Task FinalizerRunsFunAsrAutoModelAndReturnsSentenceSpeakerSegments()
{
var audioPath = Path.Combine(Path.GetTempPath(), "meeting-assistant-tests", Guid.NewGuid().ToString("N"), "meeting.wav");
Directory.CreateDirectory(Path.GetDirectoryName(audioPath)!);
await File.WriteAllBytesAsync(audioPath, [1, 2, 3, 4]);
var commandRunner = new CapturingCommandRunner(
"""
setup noise
__MEETING_ASSISTANT_DIARIZATION_JSON_START__
[{"key":"input","sentence_info":[{"text":" hello","start":410,"end":4810,"spk":0},{"text":" yes","start":22550,"end":22770,"spk":1}]}]
__MEETING_ASSISTANT_DIARIZATION_JSON_END__
""");
var finalizer = new FunAsrTranscriptFinalizer(
commandRunner,
Options.Create(new MeetingAssistantOptions
{
FunAsr = new FunAsrOptions
{
Backend = new FunAsrBackendOptions
{
DockerCommand = "docker",
Image = "funasr:test",
ModelsFolder = "C:\\Models"
},
Diarization = new FunAsrDiarizationOptions
{
Enabled = true,
CommandTimeout = TimeSpan.FromMinutes(1)
}
}
}),
NullLogger<FunAsrTranscriptFinalizer>.Instance);
var segments = await finalizer.FinalizeAsync(audioPath, [], CancellationToken.None);
Assert.Contains("run", commandRunner.Arguments);
Assert.Contains("funasr:test", commandRunner.Arguments);
Assert.Contains($"{audioPath}:/workspace/input.wav:ro", commandRunner.Arguments);
Assert.Collection(
segments,
first =>
{
Assert.Equal(TimeSpan.FromMilliseconds(410), first.Start);
Assert.Equal(TimeSpan.FromMilliseconds(4810), first.End);
Assert.Equal("Speaker 0", first.Speaker);
Assert.Equal("hello", first.Text);
},
second =>
{
Assert.Equal(TimeSpan.FromMilliseconds(22550), second.Start);
Assert.Equal(TimeSpan.FromMilliseconds(22770), second.End);
Assert.Equal("Speaker 1", second.Speaker);
Assert.Equal("yes", second.Text);
});
}
[Fact]
public async Task FinalizerReturnsNoSegmentsWhenDiarizationIsDisabled()
{
var commandRunner = new CapturingCommandRunner("");
var finalizer = new FunAsrTranscriptFinalizer(
commandRunner,
Options.Create(new MeetingAssistantOptions
{
FunAsr = new FunAsrOptions
{
Diarization = new FunAsrDiarizationOptions { Enabled = false }
}
}),
NullLogger<FunAsrTranscriptFinalizer>.Instance);
var segments = await finalizer.FinalizeAsync("C:\\Recordings\\meeting.wav", [], CancellationToken.None);
Assert.Empty(segments);
Assert.Empty(commandRunner.Arguments);
}
private sealed class CapturingCommandRunner : ICommandRunner
{
private readonly string output;
public CapturingCommandRunner(string output)
{
this.output = output;
}
public IReadOnlyList<string> Arguments { get; private set; } = [];
public Task<CommandResult> RunAsync(
string fileName,
IReadOnlyList<string> arguments,
CancellationToken cancellationToken,
IReadOnlyDictionary<string, string>? environment = null)
{
Arguments = arguments;
return Task.FromResult(new CommandResult(0, output, ""));
}
}
}