ソースを参照

Move GetHlsPlaylist to ITrickplayManager

Nick 1 年間 前
コミット
619d1d47f2

+ 9 - 77
Jellyfin.Api/Controllers/TrickplayController.cs

@@ -1,6 +1,5 @@
 using System;
 using System.ComponentModel.DataAnnotations;
-using System.Globalization;
 using System.Net.Mime;
 using System.Text;
 using Jellyfin.Api.Attributes;
@@ -54,7 +53,14 @@ public class TrickplayController : BaseJellyfinApiController
         [FromRoute, Required] int width,
         [FromQuery] Guid? mediaSourceId)
     {
-        return GetTrickplayPlaylistInternal(width, mediaSourceId ?? itemId);
+        string? playlist = _trickplayManager.GetHlsPlaylist(mediaSourceId ?? itemId, width, User.GetToken());
+
+        if (string.IsNullOrEmpty(playlist))
+        {
+            return NotFound();
+        }
+
+        return new FileContentResult(Encoding.UTF8.GetBytes(playlist), MimeTypes.GetMimeType("playlist.m3u8"));
     }
 
     /// <summary>
@@ -71,7 +77,7 @@ public class TrickplayController : BaseJellyfinApiController
     [ProducesResponseType(StatusCodes.Status200OK)]
     [ProducesResponseType(StatusCodes.Status404NotFound)]
     [ProducesImageFile]
-    public ActionResult GetTrickplayHlsPlaylist(
+    public ActionResult GetTrickplayGridImage(
         [FromRoute, Required] Guid itemId,
         [FromRoute, Required] int width,
         [FromRoute, Required] int index,
@@ -91,78 +97,4 @@ public class TrickplayController : BaseJellyfinApiController
 
         return NotFound();
     }
-
-    private ActionResult GetTrickplayPlaylistInternal(int width, Guid mediaSourceId)
-    {
-        var tilesResolutions = _trickplayManager.GetTilesResolutions(mediaSourceId);
-        if (tilesResolutions is not null && tilesResolutions.TryGetValue(width, out var tilesInfo))
-        {
-            var builder = new StringBuilder(128);
-
-            if (tilesInfo.TileCount > 0)
-            {
-                const string urlFormat = "Trickplay/{0}/{1}.jpg?MediaSourceId={2}&api_key={3}";
-                const string decimalFormat = "{0:0.###}";
-
-                var resolution = $"{tilesInfo.Width}x{tilesInfo.Height}";
-                var layout = $"{tilesInfo.TileWidth}x{tilesInfo.TileHeight}";
-                var tilesPerGrid = tilesInfo.TileWidth * tilesInfo.TileHeight;
-                var tileDuration = tilesInfo.Interval / 1000d;
-                var infDuration = tileDuration * tilesPerGrid;
-                var tileGridCount = (int)Math.Ceiling((decimal)tilesInfo.TileCount / tilesPerGrid);
-
-                builder
-                    .AppendLine("#EXTM3U")
-                    .Append("#EXT-X-TARGETDURATION:")
-                    .AppendLine(tileGridCount.ToString(CultureInfo.InvariantCulture))
-                    .AppendLine("#EXT-X-VERSION:7")
-                    .AppendLine("#EXT-X-MEDIA-SEQUENCE:1")
-                    .AppendLine("#EXT-X-PLAYLIST-TYPE:VOD")
-                    .AppendLine("#EXT-X-IMAGES-ONLY");
-
-                for (int i = 0; i < tileGridCount; i++)
-                {
-                    // All tile grids before the last one must contain full amount of tiles.
-                    // The final grid will be 0 < count <= maxTiles
-                    if (i == tileGridCount - 1)
-                    {
-                        tilesPerGrid = tilesInfo.TileCount - (i * tilesPerGrid);
-                        infDuration = tileDuration * tilesPerGrid;
-                    }
-
-                    // EXTINF
-                    builder
-                        .Append("#EXTINF:")
-                        .AppendFormat(CultureInfo.InvariantCulture, decimalFormat, infDuration)
-                        .AppendLine(",");
-
-                    // EXT-X-TILES
-                    builder
-                        .Append("#EXT-X-TILES:RESOLUTION=")
-                        .Append(resolution)
-                        .Append(",LAYOUT=")
-                        .Append(layout)
-                        .Append(",DURATION=")
-                        .AppendFormat(CultureInfo.InvariantCulture, decimalFormat, tileDuration)
-                        .AppendLine();
-
-                    // URL
-                    builder
-                        .AppendFormat(
-                            CultureInfo.InvariantCulture,
-                            urlFormat,
-                            width.ToString(CultureInfo.InvariantCulture),
-                            i.ToString(CultureInfo.InvariantCulture),
-                            mediaSourceId.ToString("N"),
-                            User.GetToken())
-                        .AppendLine();
-                }
-
-                builder.AppendLine("#EXT-X-ENDLIST");
-                return new FileContentResult(Encoding.UTF8.GetBytes(builder.ToString()), MimeTypes.GetMimeType("playlist.m3u8"));
-            }
-        }
-
-        return NotFound();
-    }
 }

+ 9 - 0
MediaBrowser.Controller/Trickplay/ITrickplayManager.cs

@@ -50,4 +50,13 @@ public interface ITrickplayManager
     /// <param name="index">The tile grid's index.</param>
     /// <returns>The absolute path.</returns>
     string GetTrickplayTilePath(BaseItem item, int width, int index);
+
+    /// <summary>
+    /// Gets the trickplay HLS playlist.
+    /// </summary>
+    /// <param name="itemId">The item.</param>
+    /// <param name="width">The width of a single tile.</param>
+    /// <param name="apiKey">Optional api key of the requesting user.</param>
+    /// <returns>The text content of the .m3u8 playlist.</returns>
+    string? GetHlsPlaylist(Guid itemId, int width, string? apiKey);
 }

+ 76 - 0
MediaBrowser.Providers/Trickplay/TrickplayManager.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using System.Linq;
+using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using MediaBrowser.Controller.Configuration;
@@ -321,6 +322,81 @@ public class TrickplayManager : ITrickplayManager
         return Path.Combine(GetTrickplayDirectory(item, width), index + ".jpg");
     }
 
+    /// <inheritdoc />
+    public string? GetHlsPlaylist(Guid itemId, int width, string? apiKey)
+    {
+        var tilesResolutions = GetTilesResolutions(itemId);
+        if (tilesResolutions is not null && tilesResolutions.TryGetValue(width, out var tilesInfo))
+        {
+            var builder = new StringBuilder(128);
+
+            if (tilesInfo.TileCount > 0)
+            {
+                const string urlFormat = "Trickplay/{0}/{1}.jpg?MediaSourceId={2}&api_key={3}";
+                const string decimalFormat = "{0:0.###}";
+
+                var resolution = $"{tilesInfo.Width}x{tilesInfo.Height}";
+                var layout = $"{tilesInfo.TileWidth}x{tilesInfo.TileHeight}";
+                var tilesPerGrid = tilesInfo.TileWidth * tilesInfo.TileHeight;
+                var tileDuration = tilesInfo.Interval / 1000d;
+                var infDuration = tileDuration * tilesPerGrid;
+                var tileGridCount = (int)Math.Ceiling((decimal)tilesInfo.TileCount / tilesPerGrid);
+
+                builder
+                    .AppendLine("#EXTM3U")
+                    .Append("#EXT-X-TARGETDURATION:")
+                    .AppendLine(tileGridCount.ToString(CultureInfo.InvariantCulture))
+                    .AppendLine("#EXT-X-VERSION:7")
+                    .AppendLine("#EXT-X-MEDIA-SEQUENCE:1")
+                    .AppendLine("#EXT-X-PLAYLIST-TYPE:VOD")
+                    .AppendLine("#EXT-X-IMAGES-ONLY");
+
+                for (int i = 0; i < tileGridCount; i++)
+                {
+                    // All tile grids before the last one must contain full amount of tiles.
+                    // The final grid will be 0 < count <= maxTiles
+                    if (i == tileGridCount - 1)
+                    {
+                        tilesPerGrid = tilesInfo.TileCount - (i * tilesPerGrid);
+                        infDuration = tileDuration * tilesPerGrid;
+                    }
+
+                    // EXTINF
+                    builder
+                        .Append("#EXTINF:")
+                        .AppendFormat(CultureInfo.InvariantCulture, decimalFormat, infDuration)
+                        .AppendLine(",");
+
+                    // EXT-X-TILES
+                    builder
+                        .Append("#EXT-X-TILES:RESOLUTION=")
+                        .Append(resolution)
+                        .Append(",LAYOUT=")
+                        .Append(layout)
+                        .Append(",DURATION=")
+                        .AppendFormat(CultureInfo.InvariantCulture, decimalFormat, tileDuration)
+                        .AppendLine();
+
+                    // URL
+                    builder
+                        .AppendFormat(
+                            CultureInfo.InvariantCulture,
+                            urlFormat,
+                            width.ToString(CultureInfo.InvariantCulture),
+                            i.ToString(CultureInfo.InvariantCulture),
+                            itemId.ToString("N"),
+                            apiKey)
+                        .AppendLine();
+                }
+
+                builder.AppendLine("#EXT-X-ENDLIST");
+                return builder.ToString();
+            }
+        }
+
+        return null;
+    }
+
     private string GetTrickplayDirectory(BaseItem item, int? width = null)
     {
         var path = Path.Combine(item.GetInternalMetadataPath(), "trickplay");