mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Add video and audio index/segment routes
This commit is contained in:
parent
d3a1c57111
commit
80d1b1af0f
@ -54,6 +54,132 @@ func (h *Handler) GetMaster(c echo.Context) error {
|
||||
return c.String(http.StatusOK, ret)
|
||||
}
|
||||
|
||||
// Transcode video
|
||||
//
|
||||
// Transcode the video to the selected quality.
|
||||
// This route can take a few seconds to respond since it will way for at least one segment to be
|
||||
// available.
|
||||
//
|
||||
// Path: /:resource/:slug/:quality/index.m3u8
|
||||
func (h *Handler) GetVideoIndex(c echo.Context) error {
|
||||
resource := c.Param("resource")
|
||||
slug := c.Param("slug")
|
||||
quality, err := src.QualityFromString(c.Param("quality"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := GetClientId(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path, err := GetPath(resource, slug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret, err := h.transcoder.GetVideoIndex(path, quality, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.String(http.StatusOK, ret)
|
||||
}
|
||||
|
||||
// Transcode audio
|
||||
//
|
||||
// Get the selected audio
|
||||
// This route can take a few seconds to respond since it will way for at least one segment to be
|
||||
// available.
|
||||
//
|
||||
// Path: /:resource/:slug/audio/:audio/index.m3u8
|
||||
func (h *Handler) GetAudioIndex(c echo.Context) error {
|
||||
resource := c.Param("resource")
|
||||
slug := c.Param("slug")
|
||||
audio := c.Param("audio")
|
||||
|
||||
client, err := GetClientId(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path, err := GetPath(resource, slug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret, err := h.transcoder.GetAudioIndex(path, audio, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.String(http.StatusOK, ret)
|
||||
}
|
||||
|
||||
// Get transmuxed chunk
|
||||
//
|
||||
// Retrieve a chunk of a transmuxed video.
|
||||
//
|
||||
// Path: /:resource/:slug/:quality/segments-:chunk.ts
|
||||
func (h *Handler) GetVideoSegment(c echo.Context) error {
|
||||
resource := c.Param("resource")
|
||||
slug := c.Param("slug")
|
||||
quality, err := src.QualityFromString(c.Param("quality"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
segment, err := ParseSegment(c.Param("chunk"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := GetClientId(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path, err := GetPath(resource, slug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret, err := h.transcoder.GetVideoSegment(path, quality, segment, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.File(ret)
|
||||
}
|
||||
|
||||
// Get audio chunk
|
||||
//
|
||||
// Retrieve a chunk of a transcoded audio.
|
||||
//
|
||||
// Path: /:resource/:slug/audio/:audio/segments-:chunk.ts
|
||||
func (h *Handler) GetAudioSegment(c echo.Context) error {
|
||||
resource := c.Param("resource")
|
||||
slug := c.Param("slug")
|
||||
audio := c.Param("audio")
|
||||
segment, err := ParseSegment(c.Param("chunk"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := GetClientId(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path, err := GetPath(resource, slug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret, err := h.transcoder.GetAudioSegment(path, audio, segment, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.File(ret)
|
||||
}
|
||||
|
||||
// Identify
|
||||
//
|
||||
// # Identify metadata about a file
|
||||
@ -88,6 +214,10 @@ func main() {
|
||||
|
||||
e.GET("/:resource/:slug/direct", DirectStream)
|
||||
e.GET("/:resource/:slug/master.m3u8", h.GetMaster)
|
||||
e.GET("/:resource/:slug/:quality/index.m3u8", h.GetVideoIndex)
|
||||
e.GET("/:resource/:slug/audio/:audio/index.m3u8", h.GetAudioIndex)
|
||||
e.GET("/:resource/:slug/:quality/:chunk", h.GetVideoSegment)
|
||||
e.GET("/:resource/:slug/audio/:audio/:chunk", h.GetAudioSegment)
|
||||
e.GET("/:resource/:slug/info", GetInfo)
|
||||
|
||||
e.Logger.Fatal(e.Start(":7666"))
|
||||
|
@ -1,5 +1,11 @@
|
||||
package src
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type Quality string
|
||||
|
||||
const (
|
||||
@ -17,6 +23,20 @@ const (
|
||||
// Purposfully removing Original from this list (since it require special treatments anyways)
|
||||
var Qualities = []Quality{P240, P360, P480, P720, P1080, P1440, P4k, P8k}
|
||||
|
||||
func QualityFromString(str string) (Quality, error) {
|
||||
if str == string(Original) {
|
||||
return Original, nil
|
||||
}
|
||||
|
||||
qualities := Qualities
|
||||
for _, quality := range qualities {
|
||||
if string(quality) == str {
|
||||
return quality, nil
|
||||
}
|
||||
}
|
||||
return Original, echo.NewHTTPError(http.StatusBadRequest, "Invalid quality")
|
||||
}
|
||||
|
||||
// I'm not entierly sure about the values for bitrates. Double checking would be nice.
|
||||
func (v Quality) AverageBitrate() uint32 {
|
||||
switch v {
|
||||
|
@ -73,3 +73,29 @@ func (t *Transcoder) cleanUnused() {
|
||||
delete(t.streams, path)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Transcoder) GetVideoIndex(path string, quality Quality, client string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (t *Transcoder) GetAudioIndex(path string, audio string, client string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (t *Transcoder) GetVideoSegment(
|
||||
path string,
|
||||
quality Quality,
|
||||
segment int32,
|
||||
client string,
|
||||
) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (t *Transcoder) GetAudioSegment(
|
||||
path string,
|
||||
audio string,
|
||||
segment int32,
|
||||
client string,
|
||||
) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
@ -64,15 +64,26 @@ func GetClientId(c echo.Context) (string, error) {
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func ParseSegment(segment string) (int32, error) {
|
||||
var ret int32
|
||||
_, err := fmt.Sscanf(segment, "segment-%d.ts", &ret)
|
||||
if err != nil {
|
||||
return 0, echo.NewHTTPError(http.StatusBadRequest, "Could not parse segment.")
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func ErrorHandler(err error, c echo.Context) {
|
||||
code := http.StatusInternalServerError
|
||||
var message string
|
||||
if he, ok := err.(*echo.HTTPError); ok {
|
||||
code = he.Code
|
||||
message = fmt.Sprint(he.Message)
|
||||
} else {
|
||||
c.Logger().Error(err)
|
||||
message = "Internal server error"
|
||||
}
|
||||
c.JSON(code, struct {
|
||||
Errors []string `json:"errors"`
|
||||
}{Errors: []string{fmt.Sprint(err)}})
|
||||
}{Errors: []string{message}})
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user