From 6ffa9539bbfbfb1090b02cebc8a28283a8c69041 Mon Sep 17 00:00:00 2001 From: cvium Date: Tue, 11 Jan 2022 23:30:30 +0100 Subject: Refactor and add scheduled task --- .../FfProbe/FfProbeKeyframeExtractor.cs | 127 ++++++++++----------- 1 file changed, 63 insertions(+), 64 deletions(-) (limited to 'src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs') diff --git a/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs index 351d880fe..320604e10 100644 --- a/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs +++ b/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs @@ -4,92 +4,91 @@ using System.Diagnostics; using System.Globalization; using System.IO; -namespace Jellyfin.MediaEncoding.Keyframes.FfProbe +namespace Jellyfin.MediaEncoding.Keyframes.FfProbe; + +/// +/// FfProbe based keyframe extractor. +/// +public static class FfProbeKeyframeExtractor { + private const string DefaultArguments = "-v error -skip_frame nokey -show_entries format=duration -show_entries stream=duration -show_entries packet=pts_time,flags -select_streams v -of csv \"{0}\""; + /// - /// FfProbe based keyframe extractor. + /// Extracts the keyframes using the ffprobe executable at the specified path. /// - public static class FfProbeKeyframeExtractor + /// The path to the ffprobe executable. + /// The file path. + /// An instance of . + public static KeyframeData GetKeyframeData(string ffProbePath, string filePath) { - private const string DefaultArguments = "-v error -skip_frame nokey -show_entries format=duration -show_entries stream=duration -show_entries packet=pts_time,flags -select_streams v -of csv \"{0}\""; - - /// - /// Extracts the keyframes using the ffprobe executable at the specified path. - /// - /// The path to the ffprobe executable. - /// The file path. - /// An instance of . - public static KeyframeData GetKeyframeData(string ffProbePath, string filePath) + using var process = new Process { - using var process = new Process + StartInfo = new ProcessStartInfo { - StartInfo = new ProcessStartInfo - { - FileName = ffProbePath, - Arguments = string.Format(CultureInfo.InvariantCulture, DefaultArguments, filePath), + FileName = ffProbePath, + Arguments = string.Format(CultureInfo.InvariantCulture, DefaultArguments, filePath), - CreateNoWindow = true, - UseShellExecute = false, - RedirectStandardOutput = true, + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardOutput = true, - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false, - }, - EnableRaisingEvents = true - }; + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false, + }, + EnableRaisingEvents = true + }; - process.Start(); + process.Start(); - return ParseStream(process.StandardOutput); - } + return ParseStream(process.StandardOutput); + } - internal static KeyframeData ParseStream(StreamReader reader) - { - var keyframes = new List(); - double streamDuration = 0; - double formatDuration = 0; + internal static KeyframeData ParseStream(StreamReader reader) + { + var keyframes = new List(); + double streamDuration = 0; + double formatDuration = 0; - while (!reader.EndOfStream) + while (!reader.EndOfStream) + { + var line = reader.ReadLine().AsSpan(); + if (line.IsEmpty) { - var line = reader.ReadLine().AsSpan(); - if (line.IsEmpty) - { - continue; - } + continue; + } - var firstComma = line.IndexOf(','); - var lineType = line[..firstComma]; - var rest = line[(firstComma + 1)..]; - if (lineType.Equals("packet", StringComparison.OrdinalIgnoreCase)) + var firstComma = line.IndexOf(','); + var lineType = line[..firstComma]; + var rest = line[(firstComma + 1)..]; + if (lineType.Equals("packet", StringComparison.OrdinalIgnoreCase)) + { + if (rest.EndsWith(",K_")) { - if (rest.EndsWith(",K_")) - { - // Trim the flags from the packet line. Example line: packet,7169.079000,K_ - var keyframe = double.Parse(rest[..^3], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture); - // Have to manually convert to ticks to avoid rounding errors as TimeSpan is only precise down to 1 ms when converting double. - keyframes.Add(Convert.ToInt64(keyframe * TimeSpan.TicksPerSecond)); - } + // Trim the flags from the packet line. Example line: packet,7169.079000,K_ + var keyframe = double.Parse(rest[..^3], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture); + // Have to manually convert to ticks to avoid rounding errors as TimeSpan is only precise down to 1 ms when converting double. + keyframes.Add(Convert.ToInt64(keyframe * TimeSpan.TicksPerSecond)); } - else if (lineType.Equals("stream", StringComparison.OrdinalIgnoreCase)) + } + else if (lineType.Equals("stream", StringComparison.OrdinalIgnoreCase)) + { + if (double.TryParse(rest, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var streamDurationResult)) { - if (double.TryParse(rest, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var streamDurationResult)) - { - streamDuration = streamDurationResult; - } + streamDuration = streamDurationResult; } - else if (lineType.Equals("format", StringComparison.OrdinalIgnoreCase)) + } + else if (lineType.Equals("format", StringComparison.OrdinalIgnoreCase)) + { + if (double.TryParse(rest, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var formatDurationResult)) { - if (double.TryParse(rest, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var formatDurationResult)) - { - formatDuration = formatDurationResult; - } + formatDuration = formatDurationResult; } } + } - // Prefer the stream duration as it should be more accurate - var duration = streamDuration > 0 ? streamDuration : formatDuration; + // Prefer the stream duration as it should be more accurate + var duration = streamDuration > 0 ? streamDuration : formatDuration; - return new KeyframeData(TimeSpan.FromSeconds(duration).Ticks, keyframes); - } + return new KeyframeData(TimeSpan.FromSeconds(duration).Ticks, keyframes); } } -- cgit v1.2.3