68 public static async Task<string>
EnsureAsync(
string configuredPath, IProgress<string>? progress =
null)
71 if (File.Exists(configuredPath))
72 return configuredPath;
75 var localPath = Path.Combine(AppContext.BaseDirectory,
"ffmpeg",
"ffmpeg.exe");
76 if (File.Exists(localPath))
80 foreach (var dir
in (Environment.GetEnvironmentVariable(
"PATH") ??
"").Split(Path.PathSeparator))
82 var candidate = Path.Combine(dir.Trim(),
"ffmpeg.exe");
83 if (File.Exists(candidate))
88 progress?.Report(
"FFmpeg를 찾을 수 없습니다. GitHub에서 자동 다운로드를 시작합니다...");
90 var ffmpegDir = Path.Combine(AppContext.BaseDirectory,
"ffmpeg");
91 Directory.CreateDirectory(ffmpegDir);
92 var zipPath = Path.Combine(ffmpegDir,
"ffmpeg_download.zip");
96 using var http =
new HttpClient();
97 http.Timeout = TimeSpan.FromMinutes(10);
98 http.DefaultRequestHeaders.UserAgent.ParseAdd(
"DreamineVMS/1.0");
100 progress?.Report(
"다운로드 중... (약 100 MB, 잠시 기다려 주세요)");
102 using var response = await http.GetAsync(
ReleaseUrl, HttpCompletionOption.ResponseHeadersRead);
103 response.EnsureSuccessStatusCode();
105 await
using (var src = await response.Content.ReadAsStreamAsync())
106 await
using (var dst = File.Create(zipPath))
108 await src.CopyToAsync(dst);
111 progress?.Report(
"압축 해제 중...");
113 using var zip = ZipFile.OpenRead(zipPath);
114 var entry = zip.Entries.FirstOrDefault(e =>
115 e.FullName.EndsWith(
"/bin/ffmpeg.exe", StringComparison.OrdinalIgnoreCase));
118 throw new FileNotFoundException(
"zip 파일 안에서 ffmpeg.exe를 찾지 못했습니다.");
120 entry.ExtractToFile(localPath, overwrite:
true);
121 progress?.Report(
"FFmpeg 설치 완료.");
126 try { File.Delete(zipPath); }
catch { }