generated from fahricansecer/boilerplate-be
@@ -128,8 +128,9 @@ public class FFmpegService
|
||||
var concatenatedPath = Path.Combine(outputDirectory, "concatenated.mp4");
|
||||
var concatArgs = new StringBuilder();
|
||||
concatArgs.Append($"-y -f concat -safe 0 -i \"{concatListPath}\" ");
|
||||
concatArgs.Append("-c:v libx264 -preset fast -crf 22 ");
|
||||
concatArgs.Append("-c:a aac -b:a 128k ");
|
||||
// OPTIMIZASYON: libx264 yerine Stream Copy (Hardware Acceleration'a gerek kalmadan saniyeler sürer)
|
||||
concatArgs.Append("-c:v copy ");
|
||||
concatArgs.Append("-c:a copy ");
|
||||
concatArgs.Append("-movflags +faststart ");
|
||||
concatArgs.Append($"\"{concatenatedPath}\"");
|
||||
|
||||
|
||||
@@ -93,21 +93,25 @@ public class VideoRenderPipeline
|
||||
_logger.LogInformation("🎙️ Adım 2/5: TTS narration üretimi");
|
||||
|
||||
var voiceStyle = job.ScriptJson?.VoiceStyle ?? "Deep authoritative male voice";
|
||||
var ttsTasks = new List<Task<GeneratedMediaFile>>();
|
||||
var ttsResults = new List<GeneratedMediaFile>();
|
||||
|
||||
foreach (var scene in scenes)
|
||||
{
|
||||
ttsTasks.Add(GenerateTtsWithProgress(
|
||||
var result = await GenerateTtsWithProgress(
|
||||
scene, projectDir, voiceStyle,
|
||||
() =>
|
||||
{
|
||||
completedSteps++;
|
||||
var progress = (int)(completedSteps / (double)totalSteps * 40); // TTS %0-40
|
||||
return progressCallback(progress, "TTS_GENERATION");
|
||||
}, ct));
|
||||
}, ct);
|
||||
|
||||
ttsResults.Add(result);
|
||||
|
||||
// Rate limit (429 Too Many Requests) yememek için sahneler arası 1 saniye bekle
|
||||
await Task.Delay(1000, ct);
|
||||
}
|
||||
|
||||
var ttsResults = await Task.WhenAll(ttsTasks);
|
||||
allMediaFiles.AddRange(ttsResults);
|
||||
|
||||
// ═══════════════════════════════════════
|
||||
@@ -272,9 +276,17 @@ public class VideoRenderPipeline
|
||||
GeneratedMediaFile result;
|
||||
|
||||
if (!string.IsNullOrEmpty(scene.TtsProvider) && scene.TtsProvider.Equals("openai", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
try
|
||||
{
|
||||
result = await _openAiTts.GenerateNarrationAsync(scene, outputDir, voiceStyle, ct);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "OpenAI TTS başarısız (Muhtemelen 429 Rate Limit/Quota). Voicebox'a fallback yapılıyor.");
|
||||
result = await _voiceboxTts.GenerateNarrationAsync(scene, outputDir, voiceStyle, ct);
|
||||
}
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(scene.TtsProvider) && scene.TtsProvider.Equals("minimax", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result = await _minimaxTts.GenerateNarrationAsync(scene, outputDir, voiceStyle, ct);
|
||||
|
||||
@@ -46,15 +46,52 @@ public class VoiceboxTtsService
|
||||
scene.Order,
|
||||
scene.NarrationText[..Math.Min(60, scene.NarrationText.Length)]);
|
||||
|
||||
// VoiceBox'ta varsayılan bir profil (Örn: Kokoro default)
|
||||
var profileId = string.IsNullOrWhiteSpace(voiceStyle) ? "b6a8a474-0fc0-4a8f-b9f1-a1e4c84a8649" : voiceStyle;
|
||||
// 1. Voicebox profillerini çek ve uygun bir profil ID bul
|
||||
string profileId = string.Empty;
|
||||
try
|
||||
{
|
||||
var profilesResponse = await _httpClient.GetAsync("profiles", ct);
|
||||
if (profilesResponse.IsSuccessStatusCode)
|
||||
{
|
||||
var profilesStr = await profilesResponse.Content.ReadAsStringAsync(ct);
|
||||
using var profilesDoc = JsonDocument.Parse(profilesStr);
|
||||
if (profilesDoc.RootElement.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
foreach (var profile in profilesDoc.RootElement.EnumerateArray())
|
||||
{
|
||||
var lang = profile.GetProperty("language").GetString();
|
||||
var id = profile.GetProperty("id").GetString();
|
||||
// Türkçe profil öncelikli
|
||||
if (lang != null && lang.StartsWith("tr") && !string.IsNullOrEmpty(id))
|
||||
{
|
||||
profileId = id;
|
||||
break;
|
||||
}
|
||||
else if (string.IsNullOrEmpty(profileId) && !string.IsNullOrEmpty(id))
|
||||
{
|
||||
profileId = id; // İlk bulduğunu yedek olarak tut
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Voicebox profilleri çekilirken hata oluştu.");
|
||||
}
|
||||
|
||||
// Eğer hiçbir profil bulamazsak, hardcoded bir fallback (Voicebox'un ilk kurulumunda eklediği rastgele GUID değildir umarım)
|
||||
if (string.IsNullOrEmpty(profileId))
|
||||
{
|
||||
profileId = "b6a8a474-0fc0-4a8f-b9f1-a1e4c84a8649";
|
||||
}
|
||||
|
||||
var requestBody = new
|
||||
{
|
||||
text = scene.NarrationText,
|
||||
profile_id = profileId,
|
||||
language = "tr",
|
||||
engine = "kokoro"
|
||||
engine = "edge_tts" // Türkçe için en stabil olan edge_tts
|
||||
};
|
||||
|
||||
var content = new StringContent(
|
||||
|
||||
Reference in New Issue
Block a user