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 --- .../Extractors/FfProbeKeyframeExtractor.cs | 58 ++++++++++++++++++++++ .../Extractors/IKeyframeExtractor.cs | 24 +++++++++ .../Extractors/MatroskaKeyframeExtractor.cs | 48 ++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 src/Jellyfin.MediaEncoding.Hls/Extractors/FfProbeKeyframeExtractor.cs create mode 100644 src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs create mode 100644 src/Jellyfin.MediaEncoding.Hls/Extractors/MatroskaKeyframeExtractor.cs (limited to 'src/Jellyfin.MediaEncoding.Hls/Extractors') diff --git a/src/Jellyfin.MediaEncoding.Hls/Extractors/FfProbeKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Hls/Extractors/FfProbeKeyframeExtractor.cs new file mode 100644 index 0000000000..f86599a232 --- /dev/null +++ b/src/Jellyfin.MediaEncoding.Hls/Extractors/FfProbeKeyframeExtractor.cs @@ -0,0 +1,58 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using Emby.Naming.Common; +using Jellyfin.Extensions; +using Jellyfin.MediaEncoding.Keyframes; +using MediaBrowser.Controller.MediaEncoding; +using Microsoft.Extensions.Logging; +using Extractor = Jellyfin.MediaEncoding.Keyframes.FfProbe.FfProbeKeyframeExtractor; + +namespace Jellyfin.MediaEncoding.Hls.Extractors; + +/// +public class FfProbeKeyframeExtractor : IKeyframeExtractor +{ + private readonly IMediaEncoder _mediaEncoder; + private readonly NamingOptions _namingOptions; + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// An instance of the interface. + /// An instance of . + /// An instance of the interface. + public FfProbeKeyframeExtractor(IMediaEncoder mediaEncoder, NamingOptions namingOptions, ILogger logger) + { + _mediaEncoder = mediaEncoder; + _namingOptions = namingOptions; + _logger = logger; + } + + /// + public bool IsMetadataBased => false; + + /// + public bool TryExtractKeyframes(string filePath, [NotNullWhen(true)] out KeyframeData? keyframeData) + { + if (!_namingOptions.VideoFileExtensions.Contains(Path.GetExtension(filePath.AsSpan()), StringComparison.OrdinalIgnoreCase)) + { + keyframeData = null; + return false; + } + + try + { + keyframeData = Extractor.GetKeyframeData(_mediaEncoder.ProbePath, filePath); + return keyframeData.KeyframeTicks.Count > 0; + } + catch (Exception ex) + { + _logger.LogError(ex, "Extracting keyframes from {FilePath} using ffprobe failed", filePath); + } + + keyframeData = null; + return false; + } +} diff --git a/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs new file mode 100644 index 0000000000..497210f417 --- /dev/null +++ b/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs @@ -0,0 +1,24 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using Jellyfin.MediaEncoding.Keyframes; + +namespace Jellyfin.MediaEncoding.Hls.Extractors; + +/// +/// Keyframe extractor. +/// +public interface IKeyframeExtractor +{ + /// + /// Gets a value indicating whether the extractor is based on container metadata. + /// + bool IsMetadataBased { get; } + + /// + /// Attempt to extract keyframes. + /// + /// The path to the file. + /// The keyframes. + /// A value indicating whether the keyframe extraction was successful. + bool TryExtractKeyframes(string filePath, [NotNullWhen(true)] out KeyframeData? keyframeData); +} diff --git a/src/Jellyfin.MediaEncoding.Hls/Extractors/MatroskaKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Hls/Extractors/MatroskaKeyframeExtractor.cs new file mode 100644 index 0000000000..ee370fb01e --- /dev/null +++ b/src/Jellyfin.MediaEncoding.Hls/Extractors/MatroskaKeyframeExtractor.cs @@ -0,0 +1,48 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using Jellyfin.MediaEncoding.Keyframes; +using Microsoft.Extensions.Logging; +using Extractor = Jellyfin.MediaEncoding.Keyframes.Matroska.MatroskaKeyframeExtractor; + +namespace Jellyfin.MediaEncoding.Hls.Extractors; + +/// +public class MatroskaKeyframeExtractor : IKeyframeExtractor +{ + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// An instance of the interface. + public MatroskaKeyframeExtractor(ILogger logger) + { + _logger = logger; + } + + /// + public bool IsMetadataBased => true; + + /// + public bool TryExtractKeyframes(string filePath, [NotNullWhen(true)] out KeyframeData? keyframeData) + { + if (filePath.AsSpan().EndsWith(".mkv", StringComparison.OrdinalIgnoreCase)) + { + keyframeData = null; + return false; + } + + try + { + keyframeData = Extractor.GetKeyframeData(filePath); + return keyframeData.KeyframeTicks.Count > 0; + } + catch (Exception ex) + { + _logger.LogError(ex, "Extracting keyframes from {FilePath} using matroska metadata failed", filePath); + } + + keyframeData = null; + return false; + } +} -- cgit v1.2.3