// Copyright (c) Microsoft. All rights reserved. using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OpenAI.Audio; public class SpeechToTextService { private const float TranscriptionTemperature = 0f; // OpenAI transcription temperature for deterministic results private const string TranscriptionLanguage = "en"; // Language code for English transcription private const string TempAudioFileName = "audio.wav"; // Temporary filename for audio processing private readonly ILogger _logger; private readonly AudioClient _audioClient; private readonly AudioTranscriptionOptions _transcriptionOptions; public SpeechToTextService(ILogger logger, IOptions openAIOptions) { this._logger = logger; var options = openAIOptions.Value; this._audioClient = new AudioClient(options.TranscriptionModelId, options.ApiKey); // Initialize transcription options as a field this._transcriptionOptions = new AudioTranscriptionOptions { Temperature = TranscriptionTemperature, Language = TranscriptionLanguage, }; } public async Task TransformAsync(AudioEvent evt) => new(evt.TurnId, evt.CancellationToken, await this.TranscribeAsync(evt.Payload, evt.CancellationToken)); private async Task TranscribeAsync(AudioData audioData, CancellationToken cancellationToken = default) { return await Tools.ExecutePipelineOperationAsync( operation: async () => { var wavData = ConvertToWav(audioData); using var ms = new MemoryStream(wavData); AudioTranscription result = await this._audioClient.TranscribeAudioAsync(ms, TempAudioFileName, this._transcriptionOptions, cancellationToken); return result.Text; }, operationName: "STT", logger: this._logger, cancellationToken: cancellationToken, defaultValue: string.Empty, resultFormatter: text => text ?? "No text transcribed" ); } private static byte[] ConvertToWav(AudioData audioData) { using var ms = new MemoryStream(); var waveFormat = new NAudio.Wave.WaveFormat(audioData.SampleRate, audioData.BitsPerSample, audioData.Channels); using (var writer = new NAudio.Wave.WaveFileWriter(ms, waveFormat)) { writer.Write(audioData.Data, 0, audioData.Data.Length); } return ms.ToArray(); } }