public Status EncodeVideo(EncodeObject eo) { Status Result = Status.Done; if (!File.Exists(eo.MO.FileInfo.FullName)) { if (Completed != null) { CompletedEventArgs e = new CompletedEventArgs(); e.Result = Status.ErrorFileNotFound; eo.Status = Status.ErrorFileNotFound; e.EO = eo; Completed(this, e); } } string filename = Path.GetFileNameWithoutExtension(eo.MO.FileInfo.FullName); string ext = eo.MO.FileInfo.Extension; // -i 101S102_CT01V01.mp4 -c:v libx265 -vf scale=-1:720 -preset medium -crf 23 -acodec copy 101S102_CT01V01-x265.mp4 // nvenc_hevc hevc_qsv // \"'-1':'if(gt(a,720),720,-1)'\" if (eo.outdir == string.Empty) { eo.outdir = eo.MO.FileInfo.DirectoryName; } string outfilename = Path.Combine(eo.outdir, filename) + eo.suffix + ".mp4"; if (File.Exists(outfilename)) { if (Completed != null) { CompletedEventArgs e = new CompletedEventArgs(); e.Result = Status.ErrorFileAlreadyExists; eo.Status = Status.ErrorFileAlreadyExists; e.EO = eo; Completed(this, e); } return(Status.ErrorFileAlreadyExists); } int exitcode = -1; try { if (eo.QType == EncodeObject.QualityEnum.CRF) { StringBuilder arguments = new StringBuilder(); arguments.Append(" -i \"").Append(eo.MO.FileInfo.FullName).Append("\""); arguments.Append(" -c:v ").Append(eo.codec); if (eo.scale > 0) { arguments.Append(" -vf scale=\"'-1':'if(gt(ih," + eo.scale.ToString() + ")," + eo.scale.ToString() + ",-1)':flags=lanczos\""); } arguments.Append(" -preset medium"); arguments.Append(" -crf ").Append(eo.Q); if (eo.MO.Audio.StartsWith("aac")) { arguments.Append(" -acodec copy "); } arguments.Append(" \"").Append(outfilename).Append("\""); exitcode = executeFFmpeg(arguments.ToString(), eo); } else if (eo.QType == EncodeObject.QualityEnum.AvgBitrate) { StringBuilder arguments = new StringBuilder(); if (eo.codec == "libx264" || eo.codec == "libx265") { // first pass arguments.Append(" -y -i \"").Append(eo.MO.FileInfo.FullName).Append("\""); arguments.Append(" -c:v ").Append(eo.codec); if (eo.scale > 0) { arguments.Append(" -vf scale=\"'-1':'if(gt(ih," + eo.scale.ToString() + ")," + eo.scale.ToString() + ",-1)':flags=lanczos\""); } arguments.Append(" -preset medium"); arguments.Append(" -b:v ").Append(eo.Q).Append("k"); arguments.Append(" -an"); if (eo.codec == "libx265") { arguments.Append(" -x265-params no-slow-firstpass=1:pass=1"); } else if (eo.codec == "libx264") { arguments.Append(" -pass 1 -fastfirstpass 1 "); } arguments.Append(" -f mp4"); arguments.Append(" NUL"); exitcode = executeFFmpeg(arguments.ToString(), eo); } else { exitcode = 0; } if (exitcode == 0) { arguments.Clear(); arguments.Append(" -i \"").Append(eo.MO.FileInfo.FullName).Append("\""); arguments.Append(" -c:v ").Append(eo.codec); if (eo.scale > 0) { arguments.Append(" -vf scale=\"'-1':'if(gt(ih," + eo.scale.ToString() + ")," + eo.scale.ToString() + ",-1)':flags=lanczos\""); } arguments.Append(" -preset medium"); arguments.Append(" -b:v ").Append(eo.Q).Append("k"); if (eo.codec == "libx265") { arguments.Append(" -x265-params pass=2"); } else { arguments.Append(" -pass 2"); } if (eo.MO.Audio.StartsWith("aac")) { arguments.Append(" -acodec copy "); } arguments.Append(" \"").Append(outfilename).Append("\""); exitcode = executeFFmpeg(arguments.ToString(), eo); } } } catch (Exception e) { eo.Status = Status.ErrorUnknown; } if (eo.Status != Status.New) { // Set by event handler Result = eo.Status; } else if (exitcode == 0 && Result == Status.Done) { eo.NewSize = (new FileInfo(outfilename)).Length; } else if (exitcode != 0 && Result != Status.Done) { Result = Status.ErrorUnknown; } if (Completed != null) { CompletedEventArgs e = new CompletedEventArgs(); e.Result = Result; eo.Status = Result; e.EO = eo; Completed(this, e); } return(Result); }
private int executeFFmpeg(string args, EncodeObject eo) { ffmpeg_process = new Process { StartInfo = { FileName = ffmpeg_exe, RedirectStandardError = true, RedirectStandardOutput = true, UseShellExecute = false, Arguments = args, CreateNoWindow = true }, }; ffmpeg_process.Start(); ffmpeg_process.PriorityClass = ProcessPriorityClass.BelowNormal; try { Regex progressRegex = new Regex(@"(?<KEY>[a-z]+)=\s*(?<VALUE>[^ ]+)\s*", RegexOptions.Compiled); Regex digRegex = new Regex(@"\d+"); Regex fltRegex = new Regex(@"\d+(\.\d+)?"); while (true) { var line = ffmpeg_process.StandardError.ReadLine(); if (line == null || line == string.Empty) { break; } MatchCollection mc = progressRegex.Matches(line); if (mc.Count == 0) { continue; } string[] groups = new string[] { "frame", "fps", "size", "time", "bitrate", "speed" }; Dictionary <string, string> info = new Dictionary <string, string>(); foreach (Match m in mc) { info[m.Groups["KEY"].Value] = m.Groups["VALUE"].Value; } Debug.WriteLine(line); ProgressInfo pi = new ProgressInfo(); string v; info.TryGetValue("frame", out pi.frame); if (info.TryGetValue("fps", out v)) { Match m = fltRegex.Match(v); if (m.Success) { float.TryParse(m.Groups[0].Value, out pi.fps); } } if (info.TryGetValue("size", out v)) { Match m = digRegex.Match(v); if (m.Success) { int.TryParse(m.Groups[0].Value, out pi.size); } } if (info.TryGetValue("time", out v)) { TimeSpan.TryParse(v, out pi.time); } if (info.TryGetValue("bitrate", out v)) { Match m = fltRegex.Match(v); if (m.Success) { float.TryParse(m.Groups[0].Value, out pi.bitrate); eo.NewBitrate = (int)pi.bitrate; } } if (info.TryGetValue("speed", out v)) { Match m = fltRegex.Match(v); if (m.Success) { float.TryParse(m.Groups[0].Value, out pi.speed); } } if (ProgressUpdate != null) { ProgressInfoEventArgs e = new ProgressInfoEventArgs(); e.Info = pi; e.EO = eo; ProgressUpdate(this, e); } } } finally { } if (!ffmpeg_process.WaitForExit(500)) { ffmpeg_process.Kill(); ffmpeg_process.WaitForExit(); } int exitcode = ffmpeg_process.ExitCode; ffmpeg_process.Dispose(); return(exitcode); }