using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; using Flowframes.Data; using Flowframes.IO; using Flowframes.OS; namespace Flowframes.Media { class GetVideoInfoCached { enum InfoType { Ffmpeg, Ffprobe }; static Dictionary ffmpegCache = new Dictionary(); static Dictionary ffprobeCache = new Dictionary(); public static async Task GetFfmpegInfoAsync(string path, string lineFilter = "") { return await GetInfoAsync(path, InfoType.Ffmpeg, lineFilter); } public static async Task GetFfprobeInfoAsync(string path, string lineFilter = "") { return await GetInfoAsync(path, InfoType.Ffprobe, lineFilter); } static async Task GetInfoAsync(string path, InfoType type, string lineFilter) { Logger.Log($"Get{type}InfoAsync({path})", true); Dictionary cacheDict = new Dictionary(type == InfoType.Ffmpeg ? ffmpegCache : ffprobeCache); long filesize = IOUtils.GetFilesize(path); PseudoUniqueFile hash = new PseudoUniqueFile(path, filesize); if (filesize > 0 && CacheContains(hash, ref cacheDict)) { Logger.Log($"Returning cached {type} info.", true); return GetFromCache(hash, ref cacheDict); } Process process = OSUtils.NewProcess(true); string avPath = Path.Combine(Paths.GetPkgPath(), Paths.audioVideoDir); if(type == InfoType.Ffmpeg) process.StartInfo.Arguments = $"/C cd /D {avPath.Wrap()} & ffmpeg.exe -hide_banner -y -stats -i {path.Wrap()}"; if (type == InfoType.Ffprobe) process.StartInfo.Arguments = $"/C cd /D {avPath.Wrap()} & ffprobe -v quiet -show_format -show_streams {path.Wrap()}"; string output = await OSUtils.GetOutputAsync(process); if (type == InfoType.Ffmpeg) ffmpegCache.Add(hash, output); if (type == InfoType.Ffprobe) ffprobeCache.Add(hash, output); if (!string.IsNullOrWhiteSpace(lineFilter.Trim())) output = string.Join("\n", output.SplitIntoLines().Where(x => x.Contains(lineFilter)).ToArray()); return output; } private static bool CacheContains(PseudoUniqueFile hash, ref Dictionary cacheDict) { foreach (KeyValuePair entry in cacheDict) if (entry.Key.path == hash.path && entry.Key.filesize == hash.filesize) return true; return false; } private static string GetFromCache(PseudoUniqueFile hash, ref Dictionary cacheDict) { foreach (KeyValuePair entry in cacheDict) if (entry.Key.path == hash.path && entry.Key.filesize == hash.filesize) return entry.Value; return ""; } } }