aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs24
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/KeyframeExtractor.cs25
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaKeyframeExtractor.cs8
3 files changed, 41 insertions, 16 deletions
diff --git a/src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs b/src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs
index 0395d7ea4..13204c757 100644
--- a/src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs
+++ b/src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs
@@ -26,6 +26,7 @@ namespace Jellyfin.MediaEncoding.Hls.Playlist
private readonly IMediaEncoder _mediaEncoder;
private readonly IApplicationPaths _applicationPaths;
private readonly KeyframeExtractor _keyframeExtractor;
+ private readonly ILogger<DynamicHlsPlaylistGenerator> _logger;
/// <summary>
/// Initializes a new instance of the <see cref="DynamicHlsPlaylistGenerator"/> class.
@@ -40,6 +41,7 @@ namespace Jellyfin.MediaEncoding.Hls.Playlist
_mediaEncoder = mediaEncoder;
_applicationPaths = applicationPaths;
_keyframeExtractor = new KeyframeExtractor(loggerFactory.CreateLogger<KeyframeExtractor>());
+ _logger = loggerFactory.CreateLogger<DynamicHlsPlaylistGenerator>();
}
private string KeyframeCachePath => Path.Combine(_applicationPaths.DataPath, "keyframes");
@@ -47,12 +49,13 @@ namespace Jellyfin.MediaEncoding.Hls.Playlist
/// <inheritdoc />
public string CreateMainPlaylist(CreateMainPlaylistRequest request)
{
- IReadOnlyList<double> segments;
- if (IsExtractionAllowed(request.FilePath))
+ IReadOnlyList<double> segments = Array.Empty<double>();
+ if (IsExtractionAllowedForFile(request.FilePath))
{
segments = ComputeSegments(request.FilePath, request.DesiredSegmentLengthMs);
}
- else
+
+ if (segments.Count == 0)
{
segments = ComputeEqualLengthSegments(request.DesiredSegmentLengthMs, request.TotalRuntimeTicks);
}
@@ -92,7 +95,7 @@ namespace Jellyfin.MediaEncoding.Hls.Playlist
foreach (var length in segments)
{
builder.Append("#EXTINF:")
- .Append(length.ToString("0.0000", CultureInfo.InvariantCulture))
+ .Append(length.ToString("0.000000", CultureInfo.InvariantCulture))
.AppendLine(", nodesc")
.Append(request.EndpointPrefix)
.Append(index++)
@@ -122,7 +125,16 @@ namespace Jellyfin.MediaEncoding.Hls.Playlist
}
else
{
- keyframeData = _keyframeExtractor.GetKeyframeData(filePath, _mediaEncoder.ProbePath, string.Empty);
+ try
+ {
+ keyframeData = _keyframeExtractor.GetKeyframeData(filePath, _mediaEncoder.ProbePath, string.Empty);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Keyframe extraction failed for path {FilePath}", filePath);
+ return Array.Empty<double>();
+ }
+
CacheResult(cachePath, keyframeData);
}
@@ -176,7 +188,7 @@ namespace Jellyfin.MediaEncoding.Hls.Playlist
return false;
}
- private bool IsExtractionAllowed(ReadOnlySpan<char> filePath)
+ private bool IsExtractionAllowedForFile(ReadOnlySpan<char> filePath)
{
// Remove the leading dot
var extension = Path.GetExtension(filePath)[1..];
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/KeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Keyframes/KeyframeExtractor.cs
index 641998273..5304a55f8 100644
--- a/src/Jellyfin.MediaEncoding.Keyframes/KeyframeExtractor.cs
+++ b/src/Jellyfin.MediaEncoding.Keyframes/KeyframeExtractor.cs
@@ -32,25 +32,38 @@ namespace Jellyfin.MediaEncoding.Keyframes
/// <returns>An instance of <see cref="KeyframeData"/>.</returns>
public KeyframeData GetKeyframeData(string filePath, string ffProbePath, string ffToolPath)
{
- var extension = Path.GetExtension(filePath);
- if (string.Equals(extension, ".mkv", StringComparison.OrdinalIgnoreCase))
+ var extension = Path.GetExtension(filePath.AsSpan());
+ if (extension.Equals(".mkv", StringComparison.OrdinalIgnoreCase))
{
try
{
return MatroskaKeyframeExtractor.GetKeyframeData(filePath);
}
- catch (InvalidOperationException ex)
+ catch (Exception ex)
{
- _logger.LogError(ex, "{MatroskaKeyframeExtractor} failed to extract keyframes", nameof(MatroskaKeyframeExtractor));
+ _logger.LogError(ex, "{ExtractorType} failed to extract keyframes", nameof(MatroskaKeyframeExtractor));
}
}
- if (!string.IsNullOrEmpty(ffToolPath))
+ try
{
return FfToolKeyframeExtractor.GetKeyframeData(ffToolPath, filePath);
}
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "{ExtractorType} failed to extract keyframes", nameof(FfToolKeyframeExtractor));
+ }
+
+ try
+ {
+ return FfProbeKeyframeExtractor.GetKeyframeData(ffProbePath, filePath);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "{ExtractorType} failed to extract keyframes", nameof(FfProbeKeyframeExtractor));
+ }
- return FfProbeKeyframeExtractor.GetKeyframeData(ffProbePath, filePath);
+ return new KeyframeData(0, Array.Empty<long>());
}
}
}
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaKeyframeExtractor.cs
index 10d017d2a..6a8a55643 100644
--- a/src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaKeyframeExtractor.cs
+++ b/src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaKeyframeExtractor.cs
@@ -49,7 +49,7 @@ namespace Jellyfin.MediaEncoding.Keyframes.Matroska
if (trackNumber == videoTrackNumber)
{
- keyframes.Add(ScaleToNanoseconds(cueTime, info.TimestampScale));
+ keyframes.Add(ScaleToTicks(cueTime, info.TimestampScale));
}
reader.LeaveContainer();
@@ -57,17 +57,17 @@ namespace Jellyfin.MediaEncoding.Keyframes.Matroska
reader.LeaveContainer();
- var result = new KeyframeData(ScaleToNanoseconds(info.Duration ?? 0, info.TimestampScale), keyframes);
+ var result = new KeyframeData(ScaleToTicks(info.Duration ?? 0, info.TimestampScale), keyframes);
return result;
}
- private static long ScaleToNanoseconds(ulong unscaledValue, long timestampScale)
+ private static long ScaleToTicks(ulong unscaledValue, long timestampScale)
{
// TimestampScale is in nanoseconds, scale it to get the value in ticks, 1 tick == 100 ns
return (long)unscaledValue * timestampScale / 100;
}
- private static long ScaleToNanoseconds(double unscaledValue, long timestampScale)
+ private static long ScaleToTicks(double unscaledValue, long timestampScale)
{
// TimestampScale is in nanoseconds, scale it to get the value in ticks, 1 tick == 100 ns
return Convert.ToInt64(unscaledValue * timestampScale / 100);