Files
seanime-docker/seanime-2.9.10/internal/handlers/mediastream.go
2025-09-20 14:08:38 +01:00

180 lines
5.5 KiB
Go

package handlers
import (
"errors"
"fmt"
"seanime/internal/database/models"
"seanime/internal/mediastream"
"github.com/labstack/echo/v4"
)
// HandleGetMediastreamSettings
//
// @summary get mediastream settings.
// @desc This returns the mediastream settings.
// @returns models.MediastreamSettings
// @route /api/v1/mediastream/settings [GET]
func (h *Handler) HandleGetMediastreamSettings(c echo.Context) error {
mediastreamSettings, found := h.App.Database.GetMediastreamSettings()
if !found {
return h.RespondWithError(c, errors.New("media streaming settings not found"))
}
return h.RespondWithData(c, mediastreamSettings)
}
// HandleSaveMediastreamSettings
//
// @summary save mediastream settings.
// @desc This saves the mediastream settings.
// @returns models.MediastreamSettings
// @route /api/v1/mediastream/settings [PATCH]
func (h *Handler) HandleSaveMediastreamSettings(c echo.Context) error {
type body struct {
Settings models.MediastreamSettings `json:"settings"`
}
var b body
if err := c.Bind(&b); err != nil {
return h.RespondWithError(c, err)
}
settings, err := h.App.Database.UpsertMediastreamSettings(&b.Settings)
if err != nil {
return h.RespondWithError(c, err)
}
h.App.InitOrRefreshMediastreamSettings()
return h.RespondWithData(c, settings)
}
// HandleRequestMediastreamMediaContainer
//
// @summary request media stream.
// @desc This requests a media stream and returns the media container to start the playback.
// @returns mediastream.MediaContainer
// @route /api/v1/mediastream/request [POST]
func (h *Handler) HandleRequestMediastreamMediaContainer(c echo.Context) error {
type body struct {
Path string `json:"path"` // The path of the file.
StreamType mediastream.StreamType `json:"streamType"` // The type of stream to request.
AudioStreamIndex int `json:"audioStreamIndex"` // The audio stream index to use. (unused)
ClientId string `json:"clientId"` // The session id
}
var b body
if err := c.Bind(&b); err != nil {
return h.RespondWithError(c, err)
}
var mediaContainer *mediastream.MediaContainer
var err error
switch b.StreamType {
case mediastream.StreamTypeDirect:
mediaContainer, err = h.App.MediastreamRepository.RequestDirectPlay(b.Path, b.ClientId)
case mediastream.StreamTypeTranscode:
mediaContainer, err = h.App.MediastreamRepository.RequestTranscodeStream(b.Path, b.ClientId)
case mediastream.StreamTypeOptimized:
err = fmt.Errorf("stream type %s not implemented", b.StreamType)
//mediaContainer, err = h.App.MediastreamRepository.RequestOptimizedStream(b.Path)
default:
err = fmt.Errorf("stream type %s not implemented", b.StreamType)
}
if err != nil {
return h.RespondWithError(c, err)
}
return h.RespondWithData(c, mediaContainer)
}
// HandlePreloadMediastreamMediaContainer
//
// @summary preloads media stream for playback.
// @desc This preloads a media stream by extracting the media information and attachments.
// @returns bool
// @route /api/v1/mediastream/preload [POST]
func (h *Handler) HandlePreloadMediastreamMediaContainer(c echo.Context) error {
type body struct {
Path string `json:"path"` // The path of the file.
StreamType mediastream.StreamType `json:"streamType"` // The type of stream to request.
AudioStreamIndex int `json:"audioStreamIndex"` // The audio stream index to use.
}
var b body
if err := c.Bind(&b); err != nil {
return h.RespondWithError(c, err)
}
var err error
switch b.StreamType {
case mediastream.StreamTypeTranscode:
err = h.App.MediastreamRepository.RequestPreloadTranscodeStream(b.Path)
case mediastream.StreamTypeDirect:
err = h.App.MediastreamRepository.RequestPreloadDirectPlay(b.Path)
default:
err = fmt.Errorf("stream type %s not implemented", b.StreamType)
}
if err != nil {
return h.RespondWithError(c, err)
}
return h.RespondWithData(c, true)
}
func (h *Handler) HandleMediastreamGetSubtitles(c echo.Context) error {
return h.App.MediastreamRepository.ServeEchoExtractedSubtitles(c)
}
func (h *Handler) HandleMediastreamGetAttachments(c echo.Context) error {
return h.App.MediastreamRepository.ServeEchoExtractedAttachments(c)
}
//
// Direct
//
func (h *Handler) HandleMediastreamDirectPlay(c echo.Context) error {
client := "1"
return h.App.MediastreamRepository.ServeEchoDirectPlay(c, client)
}
//
// Transcode
//
func (h *Handler) HandleMediastreamTranscode(c echo.Context) error {
client := "1"
return h.App.MediastreamRepository.ServeEchoTranscodeStream(c, client)
}
// HandleMediastreamShutdownTranscodeStream
//
// @summary shuts down the transcode stream
// @desc This requests the transcoder to shut down. It should be called when unmounting the player (playback is no longer needed).
// @desc This will also send an events.MediastreamShutdownStream event.
// @desc It will not return any error and is safe to call multiple times.
// @returns bool
// @route /api/v1/mediastream/shutdown-transcode [POST]
func (h *Handler) HandleMediastreamShutdownTranscodeStream(c echo.Context) error {
client := "1"
h.App.MediastreamRepository.ShutdownTranscodeStream(client)
return h.RespondWithData(c, true)
}
//
// Serve file
//
func (h *Handler) HandleMediastreamFile(c echo.Context) error {
client := "1"
fp := c.QueryParam("path")
libraryPaths := h.App.Settings.GetLibrary().GetLibraryPaths()
return h.App.MediastreamRepository.ServeEchoFile(c, fp, client, libraryPaths)
}