using System.Diagnostics; using System.Text.Json; using Microsoft.Extensions.Logging; using SaasMediaWorker.Models; namespace SaasMediaWorker.Services; public class RemotionService { private readonly ILogger _logger; public RemotionService(ILogger logger) { _logger = logger; } public async Task RenderVideoAsync( string projectId, string projectDir, List scenes, List generatedMedia, string? musicPath, int targetDurationSeconds, string visualEffect, CancellationToken ct) { _logger.LogInformation("🎬 Remotion render başlatılıyor — Project: {Id}", projectId); // Remotion projesinin kök dizini (media-worker içindeki remotion klasörü) var remotionDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "remotion"); // Props JSON dosyasını hazırla var props = new { musicPath = musicPath, visualEffect = visualEffect, scenes = scenes.Select(s => new { imagePath = s.ImagePath, audioPath = generatedMedia.FirstOrDefault(m => m.SceneOrder == s.Order && m.Type == MediaFileType.AudioNarration)?.LocalPath, ambientPath = generatedMedia.FirstOrDefault(m => m.SceneOrder == s.Order && m.Type == MediaFileType.AudioAmbient)?.LocalPath, subtitle = s.SubtitleText, durationInFrames = (int)(s.Duration * 30) // 30 FPS varsayımı }).ToList() }; var propsPath = Path.Combine(projectDir, "remotion-props.json"); await File.WriteAllTextAsync(propsPath, JsonSerializer.Serialize(props), ct); // Final çıktı yolu var outputPath = Path.Combine(projectDir, $"final_{projectId}.mp4"); // npx remotion render src/index.ts MainVideo output.mp4 --props props.json var arguments = $"remotion render src/index.ts MainVideo \"{outputPath}\" --props=\"{propsPath}\""; _logger.LogInformation("Çalıştırılıyor: npx {Args} (Dizin: {Dir})", arguments, remotionDir); var processInfo = new ProcessStartInfo { FileName = "npx", Arguments = arguments, WorkingDirectory = remotionDir, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using var process = Process.Start(processInfo); if (process == null) throw new InvalidOperationException("Remotion process başlatılamadı."); var outputTask = process.StandardOutput.ReadToEndAsync(); var errorTask = process.StandardError.ReadToEndAsync(); await process.WaitForExitAsync(ct); var output = await outputTask; var error = await errorTask; if (process.ExitCode != 0) { _logger.LogError("Remotion render hatası. ExitCode: {Code}\nOutput: {Output}\nError: {Error}", process.ExitCode, output, error); throw new Exception($"Remotion render başarısız oldu. Hata: {error}"); } _logger.LogInformation("✅ Remotion render tamamlandı: {Path}", outputPath); return outputPath; } }