generated from fahricansecer/boilerplate-be
@@ -0,0 +1,89 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SaasMediaWorker.Models;
|
||||
|
||||
namespace SaasMediaWorker.Services;
|
||||
|
||||
public class RemotionService
|
||||
{
|
||||
private readonly ILogger<RemotionService> _logger;
|
||||
|
||||
public RemotionService(ILogger<RemotionService> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<string> RenderVideoAsync(
|
||||
string projectId,
|
||||
string projectDir,
|
||||
List<ScenePayload> scenes,
|
||||
List<GeneratedMediaFile> generatedMedia,
|
||||
string? musicPath,
|
||||
int targetDurationSeconds,
|
||||
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,
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user