Add generic thumbnails route

This commit is contained in:
Zoe Roux 2024-02-18 18:34:24 +01:00
parent ff5ecb474f
commit a8b0eeb973
4 changed files with 64 additions and 25 deletions

View File

@ -32,13 +32,14 @@ public abstract class TranscoderApi<T>(IRepository<T> repository, IThumbnailsMan
: CrudThumbsApi<T>(repository, thumbs)
where T : class, IResource, IThumbnails, IQuery
{
private Task _Proxy(string route, string path)
private Task _Proxy(string route, (string path, string route) info)
{
HttpProxyOptions proxyOptions = HttpProxyOptionsBuilder
.Instance.WithBeforeSend(
(ctx, req) =>
{
req.Headers.Add("X-Path", path);
req.Headers.Add("X-Path", info.path);
req.Headers.Add("X-Route", info.route);
return Task.CompletedTask;
}
)
@ -55,7 +56,7 @@ public abstract class TranscoderApi<T>(IRepository<T> repository, IThumbnailsMan
return this.HttpProxyAsync($"http://transcoder:7666/{route}", proxyOptions);
}
protected abstract Task<string> GetPath(Identifier identifier);
protected abstract Task<(string path, string route)> GetPath(Identifier identifier);
/// <summary>
/// Direct stream
@ -117,10 +118,52 @@ public abstract class TranscoderApi<T>(IRepository<T> repository, IThumbnailsMan
await _Proxy($"/audio/{audio}/{segment}", await GetPath(identifier));
}
/// <summary>
/// Get file info
/// </summary>
/// <remarks>
/// Identify metadata about a file.
/// </remarks>
/// <param name="identifier">The ID or slug of the <see cref="Episode"/>.</param>
/// <returns>The media infos of the file.</returns>
/// <response code="404">No episode with the given ID or slug could be found.</response>
[HttpGet("{identifier:id}/info")]
[PartialPermission(Kind.Play)]
[PartialPermission(Kind.Read)]
public async Task GetInfo(Identifier identifier)
{
await _Proxy("/info", await GetPath(identifier));
}
/// <summary>
/// Get thumbnail sprite
/// </summary>
/// <remarks>
/// Get a sprite file containing all the thumbnails of the show.
/// </remarks>
/// <param name="identifier">The ID or slug of the <see cref="Episode"/>.</param>
/// <returns>A sprite with an image for every X seconds of the video file.</returns>
/// <response code="404">No episode with the given ID or slug could be found.</response>
[HttpGet("{identifier:id}/thumbnails.png")]
[PartialPermission(Kind.Read)]
public async Task GetThumbnails(Identifier identifier)
{
await _Proxy("/thumbnails.png", await GetPath(identifier));
}
/// <summary>
/// Get thumbnail vtt
/// </summary>
/// <remarks>
/// Get a vtt file containing timing/position of thumbnails inside the sprite file.
/// https://developer.bitmovin.com/playback/docs/webvtt-based-thumbnails for more info.
/// </remarks>
/// <param name="identifier">The ID or slug of the <see cref="Episode"/>.</param>
/// <returns>A vtt file containing metadata about timing and x/y/width/height of the sprites of /thumbnails.png.</returns>
/// <response code="404">No episode with the given ID or slug could be found.</response>
[HttpGet("{identifier:id}/thumbnails.vtt")]
[PartialPermission(Kind.Read)]
public async Task GetThumbnailsVtt(Identifier identifier)
{
await _Proxy("/thumbnails.vtt", await GetPath(identifier));
}
}

View File

@ -187,12 +187,13 @@ namespace Kyoo.Core.Api
await libraryManager.WatchStatus.DeleteEpisodeStatus(id, User.GetIdOrThrow());
}
protected override async Task<string> GetPath(Identifier identifier)
protected override async Task<(string path, string route)> GetPath(Identifier identifier)
{
return await identifier.Match(
string path = await identifier.Match(
async id => (await Repository.Get(id)).Path,
async slug => (await Repository.Get(slug)).Path
);
return (path, $"/episodes/{identifier}");
}
}
}

View File

@ -233,12 +233,13 @@ namespace Kyoo.Core.Api
await libraryManager.WatchStatus.DeleteMovieStatus(id, User.GetIdOrThrow());
}
protected override Task<string> GetPath(Identifier identifier)
protected override async Task<(string path, string route)> GetPath(Identifier identifier)
{
return identifier.Match(
string path = await identifier.Match(
async id => (await Repository.Get(id)).Path,
async slug => (await Repository.Get(slug)).Path
);
return (path, $"/movies/{identifier}");
}
}
}

View File

@ -182,10 +182,10 @@ func (h *Handler) GetInfo(c echo.Context) error {
}
// Run extractors to have them in cache
h.extractor.RunExtractor(ret.Path, ret.Sha, &ret.Subtitles)
// go h.thumbnails.ExtractThumbnail(
// ret.Path,
// fmt.Sprintf("%s/%s/thumbnails.png", resource, slug),
// )
go h.thumbnails.ExtractThumbnail(
ret.Path,
fmt.Sprintf("%s/thumbnails.png", c.Request().Header.Get("X-Route")),
)
return c.JSON(http.StatusOK, ret)
}
@ -245,19 +245,16 @@ func (h *Handler) GetSubtitle(c echo.Context) error {
//
// Get a sprite file containing all the thumbnails of the show.
//
// Path: /:resource/:slug/thumbnails.png
// Path: /thumbnails.png
func (h *Handler) GetThumbnails(c echo.Context) error {
resource := c.Param("resource")
slug := c.Param("slug")
path, err := GetPath(resource, slug)
path, err := GetPath(c)
if err != nil {
return err
}
out, err := h.thumbnails.ExtractThumbnail(
path,
fmt.Sprintf("%s/%s/thumbnails.png", resource, slug),
fmt.Sprintf("%s/thumbnails.png", c.Request().Header.Get("X-Route")),
)
if err != nil {
return err
@ -273,17 +270,14 @@ func (h *Handler) GetThumbnails(c echo.Context) error {
//
// Path: /:resource/:slug/thumbnails.vtt
func (h *Handler) GetThumbnailsVtt(c echo.Context) error {
resource := c.Param("resource")
slug := c.Param("slug")
path, err := GetPath(resource, slug)
path, err := GetPath(c)
if err != nil {
return err
}
out, err := h.thumbnails.ExtractThumbnail(
path,
fmt.Sprintf("%s/%s/thumbnails.png", resource, slug),
fmt.Sprintf("%s/thumbnails.png", c.Request().Header.Get("X-Route")),
)
if err != nil {
return err
@ -321,8 +315,8 @@ func main() {
e.GET("/:quality/:chunk", h.GetVideoSegment)
e.GET("/audio/:audio/:chunk", h.GetAudioSegment)
e.GET("/info", h.GetInfo)
e.GET("/:resource/:slug/thumbnails.png", h.GetThumbnails)
e.GET("/:resource/:slug/thumbnails.vtt", h.GetThumbnailsVtt)
e.GET("/thumbnails.png", h.GetThumbnails)
e.GET("/thumbnails.vtt", h.GetThumbnailsVtt)
e.GET("/:sha/attachment/:name", h.GetAttachment)
e.GET("/:sha/subtitle/:name", h.GetSubtitle)