FFmpeg 경로를 확인하고, 없으면 다운로드한 후 최종 경로를 반환합니다.
69 {
70
71 if (File.Exists(configuredPath))
72 return configuredPath;
73
74
75 var localPath = Path.Combine(AppContext.BaseDirectory, "ffmpeg", "ffmpeg.exe");
76 if (File.Exists(localPath))
77 return localPath;
78
79
80 foreach (var dir in (Environment.GetEnvironmentVariable("PATH") ?? "").Split(Path.PathSeparator))
81 {
82 var candidate = Path.Combine(dir.Trim(), "ffmpeg.exe");
83 if (File.Exists(candidate))
84 return candidate;
85 }
86
87
88 progress?.Report("FFmpeg를 찾을 수 없습니다. GitHub에서 자동 다운로드를 시작합니다...");
89
90 var ffmpegDir = Path.Combine(AppContext.BaseDirectory, "ffmpeg");
91 Directory.CreateDirectory(ffmpegDir);
92 var zipPath = Path.Combine(ffmpegDir, "ffmpeg_download.zip");
93
94 try
95 {
96 using var http = new HttpClient();
97 http.Timeout = TimeSpan.FromMinutes(10);
98 http.DefaultRequestHeaders.UserAgent.ParseAdd("DreamineVMS/1.0");
99
100 progress?.Report("다운로드 중... (약 100 MB, 잠시 기다려 주세요)");
101
102 using var response = await http.GetAsync(ReleaseUrl, HttpCompletionOption.ResponseHeadersRead);
103 response.EnsureSuccessStatusCode();
104
105 await using (var src = await response.Content.ReadAsStreamAsync())
106 await using (var dst = File.Create(zipPath))
107 {
108 await src.CopyToAsync(dst);
109 }
110
111 progress?.Report("압축 해제 중...");
112
113 using var zip = ZipFile.OpenRead(zipPath);
114 var entry = zip.Entries.FirstOrDefault(e =>
115 e.FullName.EndsWith("/bin/ffmpeg.exe", StringComparison.OrdinalIgnoreCase));
116
117 if (entry is null)
118 throw new FileNotFoundException("zip 파일 안에서 ffmpeg.exe를 찾지 못했습니다.");
119
120 entry.ExtractToFile(localPath, overwrite: true);
121 progress?.Report("FFmpeg 설치 완료.");
122 return localPath;
123 }
124 finally
125 {
126 try { File.Delete(zipPath); } catch { }
127 }
128 }