using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using log4net; namespace MovieBarcodeGenerator { public class SharpFF { public static string ffmpegPath { get; set; } private static log4net.ILog log = log4net.LogManager.GetLogger("SharpFF"); public static void ExecuteCommand(string parameters) { if (String.IsNullOrEmpty(ffmpegPath) || !File.Exists(Path.Combine(ffmpegPath, "ffmpeg.exe"))) { log.FatalFormat("FFmpeg was not found at '{0}'.", ffmpegPath); throw new Exception("Path to ffmpeg not specified. Set ffmpeg path (excluding exe) before attempting to use SharpFF."); } log.DebugFormat("Calling ffmpeg at {0} with parameters {1}", ffmpegPath, parameters); Process p = new Process(); p.StartInfo.FileName = Path.Combine(ffmpegPath, "ffmpeg"); p.StartInfo.Arguments = parameters; p.StartInfo.UseShellExecute = false; p.Start(); // this could potentially be speeded up by not waiting, but then we end up trying to delete files before ffmpeg // is actually finished p.WaitForExit(); } public static decimal GetDuration(string videoPath) { string parameters = String.Format("-hide_banner -i \"{0}\"", videoPath); if (String.IsNullOrEmpty(ffmpegPath) || !File.Exists(Path.Combine(ffmpegPath, "ffmpeg.exe"))) { log.FatalFormat("FFmpeg was not found at '{0}'.", ffmpegPath); throw new Exception("Path to ffmpeg not specified. Set ffmpeg path (excluding exe) before attempting to use SharpFF."); } log.DebugFormat("Calling ffmpeg at {0} with parameters {1}", ffmpegPath, parameters); Process p = new Process(); p.StartInfo.FileName = Path.Combine(ffmpegPath, "ffmpeg"); p.StartInfo.Arguments = parameters; p.StartInfo.RedirectStandardError = true; p.StartInfo.UseShellExecute = false; p.Start(); string stderr = p.StandardError.ReadToEnd(); List outLines = stderr.Split(System.Environment.NewLine[0]) .Where(line => string.IsNullOrWhiteSpace(line) == false && string.IsNullOrEmpty(line.Trim()) == false) .Select(s => s.Trim()).ToList(); foreach (var line in outLines) { if (line.StartsWith("Duration")) { string timecode = line.Split(' ')[1].Trim(); return TimecodeToSeconds(timecode); } } p.WaitForExit(); return 0.0M; } public static decimal TimecodeToSeconds(string timecode) { timecode = timecode.Replace(",", String.Empty); decimal totalSeconds = 0; string[] timeElements = timecode.Split(':'); totalSeconds += Int32.Parse(timeElements[0]) * 3600; totalSeconds += Int32.Parse(timeElements[1]) * 60; totalSeconds += Math.Floor(decimal.Parse(timeElements[2]) * 100) / 100; return totalSeconds; } public static string SecondsToTimecode(object seconds) { decimal betterSeconds = System.Convert.ToDecimal(seconds); decimal hours = Math.Floor(betterSeconds / 3600); if (hours >= 1) { betterSeconds -= hours * 3600; } decimal minutes = Math.Floor(betterSeconds / 60); if (minutes >= 1) { betterSeconds -= minutes * 60; } return String.Format("{0:00}:{1:00}:{2:00.00}", hours, minutes, Math.Floor(betterSeconds * 100) / 100); } } }