using System; using System.ComponentModel.DataAnnotations; using System.Net.Mime; using System.Text; using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Trickplay; using MediaBrowser.Model; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Api.Controllers; /// /// Trickplay controller. /// [Route("")] [Authorize] public class TrickplayController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; private readonly ITrickplayManager _trickplayManager; /// /// Initializes a new instance of the class. /// /// Instance of . /// Instance of . public TrickplayController( ILibraryManager libraryManager, ITrickplayManager trickplayManager) { _libraryManager = libraryManager; _trickplayManager = trickplayManager; } /// /// Gets an image tiles playlist for trickplay. /// /// The item id. /// The width of a single tile. /// The media version id, if using an alternate version. /// Tiles playlist returned. /// A containing the trickplay playlist file. [HttpGet("Videos/{itemId}/Trickplay/{width}/tiles.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesPlaylistFile] public async Task GetTrickplayHlsPlaylist( [FromRoute, Required] Guid itemId, [FromRoute, Required] int width, [FromQuery] Guid? mediaSourceId) { string? playlist = await _trickplayManager.GetHlsPlaylist(mediaSourceId ?? itemId, width, User.GetToken()).ConfigureAwait(false); if (string.IsNullOrEmpty(playlist)) { return NotFound(); } return Content(playlist, MimeTypes.GetMimeType("playlist.m3u8"), Encoding.UTF8); } /// /// Gets a trickplay tile image. /// /// The item id. /// The width of a single tile. /// The index of the desired tile. /// The media version id, if using an alternate version. /// Tile image returned. /// Tile image not found at specified index. /// A containing the trickplay tiles image. [HttpGet("Videos/{itemId}/Trickplay/{width}/{index}.jpg")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesImageFile] public async Task GetTrickplayTileImageAsync( [FromRoute, Required] Guid itemId, [FromRoute, Required] int width, [FromRoute, Required] int index, [FromQuery] Guid? mediaSourceId) { var item = _libraryManager.GetItemById(itemId, User.GetUserId()); if (item is null) { return NotFound(); } var saveWithMedia = _libraryManager.GetLibraryOptions(item).SaveTrickplayWithMedia; var path = await _trickplayManager.GetTrickplayTilePathAsync(item, width, index, saveWithMedia).ConfigureAwait(false); if (!string.IsNullOrEmpty(path) && System.IO.File.Exists(path)) { Response.Headers.ContentDisposition = "attachment"; return PhysicalFile(path, MediaTypeNames.Image.Jpeg); } return NotFound(); } }