OpenAI Whisper ile .NET'te Ses Transkripsiyon ve Text-to-Speech
OpenAI'ın Whisper modeli, 99 dili destekleyen ve gürültülü ortamlarda bile yüksek doğrulukla çalışan bir ses tanıma modelidir. .NET'in resmi OpenAI kütüphanesi ile Whisper'ı ve TTS (Text-to-Speech) özelliğini uygulamalarınıza entegre edebilirsiniz.
Kurulum
dotnet add package OpenAI
Ses Dosyasından Metin Transkripsiyon
using OpenAI.Audio;
public class TranscriptionService
{
private readonly AudioClient _client;
public TranscriptionService(IConfiguration config)
{
var openAiClient = new OpenAI.OpenAIClient(config["OpenAI:ApiKey"]!);
_client = openAiClient.GetAudioClient("whisper-1");
}
public async Task<string> TranscribeAsync(Stream audioStream, string filename)
{
var result = await _client.TranscribeAudioAsync(
audioStream,
filename,
new AudioTranscriptionOptions
{
Language = "tr",
ResponseFormat = AudioTranscriptionFormat.Verbose,
TimestampGranularities = AudioTimestampGranularityFlags.Word
});
return result.Value.Text;
}
public async Task<IReadOnlyList<TranscribedSegment>> TranscribeWithTimestampsAsync(
Stream audioStream, string filename)
{
var result = await _client.TranscribeAudioAsync(
audioStream,
filename,
new AudioTranscriptionOptions
{
ResponseFormat = AudioTranscriptionFormat.Verbose,
TimestampGranularities = AudioTimestampGranularityFlags.Segment
});
return result.Value.Segments;
}
}
Zaman Damgalı Altyazı Üretimi
Segment bazlı zaman damgaları ile SRT formatında altyazı dosyası oluşturmak:
public async Task<string> GenerateSrtAsync(Stream audioStream, string filename)
{
var segments = await TranscribeWithTimestampsAsync(audioStream, filename);
var sb = new StringBuilder();
int index = 1;
foreach (var segment in segments)
{
sb.AppendLine(index.ToString());
sb.AppendLine($"{FormatTime(segment.StartTime)} --> {FormatTime(segment.EndTime)}");
sb.AppendLine(segment.Text.Trim());
sb.AppendLine();
index++;
}
return sb.ToString();
}
private static string FormatTime(TimeSpan time) =>
$"{(int)time.TotalHours:D2}:{time.Minutes:D2}:{time.Seconds:D2},{time.Milliseconds:D3}";
Büyük Ses Dosyalarını Parçalara Bölme
Whisper API 25 MB ile sınırlıdır; uzun dosyalar için parçalama gerekir:
public class AudioChunker
{
private const int MaxFileSizeBytes = 24 * 1024 * 1024; // 24 MB güvenli sınır
public async Task<string> TranscribeLargeFileAsync(string filePath)
{
var fileInfo = new FileInfo(filePath);
if (fileInfo.Length <= MaxFileSizeBytes)
{
await using var stream = File.OpenRead(filePath);
return await _transcription.TranscribeAsync(stream, fileInfo.Name);
}
// NAudio veya FFmpeg ile parçalara böl
var chunks = await SplitAudioAsync(filePath, TimeSpan.FromMinutes(10));
var transcriptions = new List<string>();
foreach (var chunk in chunks)
{
await using var stream = File.OpenRead(chunk);
transcriptions.Add(await _transcription.TranscribeAsync(stream, Path.GetFileName(chunk)));
}
return string.Join(" ", transcriptions);
}
}
Text-to-Speech ile Sesli Yanıt Üretimi
public class TtsService
{
private readonly AudioClient _client;
public TtsService(IConfiguration config)
{
var openAiClient = new OpenAI.OpenAIClient(config["OpenAI:ApiKey"]!);
_client = openAiClient.GetAudioClient("tts-1");
}
public async Task<byte[]> SynthesizeSpeechAsync(
string text,
GeneratedSpeechVoice voice = GeneratedSpeechVoice.Alloy,
GeneratedSpeechFormat format = GeneratedSpeechFormat.Mp3)
{
var result = await _client.GenerateSpeechAsync(text, voice,
new SpeechGenerationOptions
{
ResponseFormat = format,
SpeedRatio = 1.0f
});
return result.Value.ToArray();
}
// Sesli asistan için akış
public async IAsyncEnumerable<byte[]> StreamSpeechAsync(string text)
{
var result = await _client.GenerateSpeechAsync(text, GeneratedSpeechVoice.Nova);
// Streaming TTS SDK desteğiyle buffer'lara bölerek gönder
var data = result.Value.ToArray();
const int chunkSize = 4096;
for (int i = 0; i < data.Length; i += chunkSize)
yield return data[i..Math.Min(i + chunkSize, data.Length)];
}
}
Gerçek Zamanlı Ses Altyazısı (SignalR ile)
[ApiController]
[Route("api/[controller]")]
public class TranscriptionController : ControllerBase
{
private readonly TranscriptionService _transcription;
private readonly IHubContext<TranscriptionHub> _hub;
[HttpPost("upload")]
public async Task<IActionResult> UploadAndTranscribe(IFormFile audio)
{
await using var stream = audio.OpenReadStream();
var text = await _transcription.TranscribeAsync(stream, audio.FileName);
// Diğer bağlı kullanıcılara bildir
await _hub.Clients.All.SendAsync("TranscriptionComplete", text);
return Ok(new { transcript = text });
}
}
Çeviri Özelliği
Whisper, başka dillerdeki sesi doğrudan İngilizceye çevirebilir:
public async Task<string> TranslateToEnglishAsync(Stream audioStream, string filename)
{
var result = await _client.TranslateAudioAsync(
audioStream,
filename,
new AudioTranslationOptions
{
ResponseFormat = AudioTranslationFormat.Text
});
return result.Value.Text;
}
Production Önerileri
- Model Seçimi:
whisper-1API modeli; yerel çalışma içinfaster-whisperNuGet paketi düşünülebilir. - Dosya Formatı: mp3 ve webm, mp4'ten daha küçük boyutludur; transkripsiyon maliyetini düşürür.
- TTS Kalitesi:
tts-1-hdmodeli daha yavaş ama daha doğal ses üretir. - Önbellek: Aynı metin için TTS çıktısını Redis'te önbelleğe alarak maliyeti azaltın.
Sonuç
OpenAI Whisper ve TTS, .NET uygulamalarınıza güçlü ses yetenekleri ekler. Müşteri hizmetleri botlarından video altyazısına, erişilebilirlik araçlarından sesli asistanlara kadar geniş bir kullanım alanı sunar. API maliyetini kontrol altında tutmak için büyük dosyaları önceden parçalamayı ve TTS çıktılarını önbelleğe almayı unutmayın.