Convert-it/Services/AudioTranscriptionService.cs
Ricardo Carneiro 724e03176e
All checks were successful
Deploy ASP.NET MVC to OCI / build-and-deploy (push) Successful in 21m10s
feat: conversor de audio
2026-01-25 14:47:46 -03:00

98 lines
3.5 KiB
C#

using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Whisper.net;
using Whisper.net.Ggml;
using Xabe.FFmpeg;
using Microsoft.Extensions.Logging;
namespace Convert_It_Online.Services
{
public class AudioTranscriptionService : IAudioTranscriptionService
{
private readonly string _modelPath;
private readonly ILogger<AudioTranscriptionService> _logger;
private readonly HttpClient _httpClient;
public AudioTranscriptionService(ILogger<AudioTranscriptionService> logger)
{
_logger = logger;
_httpClient = new HttpClient();
_modelPath = Path.Combine(AppContext.BaseDirectory, "Models", "ggml-base.bin");
// Garantir que a pasta Models existe
var modelsDir = Path.GetDirectoryName(_modelPath);
if (!Directory.Exists(modelsDir))
{
Directory.CreateDirectory(modelsDir!);
}
}
private async Task EnsureModelExistsAsync()
{
if (!System.IO.File.Exists(_modelPath))
{
_logger.LogInformation("Baixando modelo Whisper Base...");
var downloader = new WhisperGgmlDownloader(_httpClient);
using var modelStream = await downloader.GetGgmlModelAsync(GgmlType.Base);
using var fileStream = System.IO.File.Create(_modelPath);
await modelStream.CopyToAsync(fileStream);
_logger.LogInformation("Modelo Whisper baixado com sucesso.");
}
}
public async Task<string> TranscribeAsync(string inputPath, string culture = "pt-BR")
{
await EnsureModelExistsAsync();
string tempWavPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.wav");
try
{
_logger.LogInformation("Convertendo áudio para WAV 16kHz Mono...");
// Configurar FFmpeg (assume que está no PATH em Linux)
// Se estiver no Windows, pode precisar de FFmpeg.SetExecutablesPath
var conversion = await FFmpeg.Conversions.New()
.AddParameter($"-i \"{inputPath}\"")
.AddParameter("-ar 16000")
.AddParameter("-ac 1")
.AddParameter("-c:a pcm_s16le")
.SetOutput(tempWavPath)
.Start();
_logger.LogInformation("Iniciando transcrição com Whisper...");
using var factory = WhisperFactory.FromPath(_modelPath);
using var processor = factory.CreateBuilder()
.WithLanguage(culture.Split('-')[0]) // Usa "pt", "es", etc
.Build();
using var wavStream = System.IO.File.OpenRead(tempWavPath);
var result = "";
await foreach (var segment in processor.ProcessAsync(wavStream))
{
result += segment.Text + " ";
}
return result.Trim();
}
catch (Exception ex)
{
_logger.LogError(ex, "Erro durante a transcrição de áudio.");
throw;
}
finally
{
if (System.IO.File.Exists(tempWavPath))
{
System.IO.File.Delete(tempWavPath);
}
}
}
}
}