diff --git a/transcoder/go.mod b/transcoder/go.mod index 9a841abd..c3500bbf 100644 --- a/transcoder/go.mod +++ b/transcoder/go.mod @@ -1,3 +1,16 @@ module github.com/zoriya/kyoo/transcoder go 1.20 + +require ( + github.com/labstack/echo/v4 v4.11.4 // indirect + github.com/labstack/gommon v0.4.2 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect +) diff --git a/transcoder/go.sum b/transcoder/go.sum new file mode 100644 index 00000000..453ca6fa --- /dev/null +++ b/transcoder/go.sum @@ -0,0 +1,23 @@ +github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8= +github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8= +github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= +github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= diff --git a/transcoder/main.go b/transcoder/main.go index 6bd9f00d..7d15058b 100644 --- a/transcoder/main.go +++ b/transcoder/main.go @@ -1,5 +1,45 @@ package main -func main() { - print("") +import ( + "fmt" + "net/http" + + "github.com/labstack/echo/v4" +) + +// Direct video +// +// Retrieve the raw video stream, in the same container as the one on the server. No transcoding or +// transmuxing is done. +// Path: /:resource/:slug/direct +func DirectStream(c echo.Context) error { + resource := c.Param("resource") + slug := c.Param("slug") + + path, err := GetPath(resource, slug) + if err != nil { + return err + } + return c.File(*path) +} + +func ErrorHandler(err error, c echo.Context) { + code := http.StatusInternalServerError + if he, ok := err.(*echo.HTTPError); ok { + code = he.Code + } else { + c.Logger().Error(err) + } + c.JSON(code, struct { + Errors []string `json:"errors"` + }{Errors: []string{fmt.Sprint(err)}}) +} + +func main() { + e := echo.New() + e.HTTPErrorHandler = ErrorHandler + + e.GET("/:resource/:slug/direct", DirectStream) + + e.Logger.Fatal(e.Start(":7666")) } diff --git a/transcoder/utils.go b/transcoder/utils.go new file mode 100644 index 00000000..ab3cbdfa --- /dev/null +++ b/transcoder/utils.go @@ -0,0 +1,57 @@ +package main + +import ( + "encoding/json" + "errors" + "fmt" + "net/http" + "os" + "strings" + "time" + + "github.com/labstack/echo/v4" +) + +var client = &http.Client{Timeout: 10 * time.Second} + +type Item struct { + Path string `json:"path"` +} + +func GetPath(resource string, slug string) (*string, error) { + url := os.Getenv("API_URL") + if url == "" { + url = "http://back:5000" + } + key := os.Getenv("KYOO_APIKEYS") + if key == "" { + return nil, errors.New("missing api keys") + } + key = strings.Split(key, ",")[0] + + req, err := http.NewRequest("GET", strings.Join([]string{url, resource, slug}, "/"), nil) + if err != nil { + return nil, err + } + req.Header.Set("X-API-KEY", key) + res, err := client.Do(req) + if err != nil { + return nil, err + } + + if res.StatusCode != 200 { + return nil, echo.NewHTTPError( + http.StatusNotAcceptable, + fmt.Sprintf("No %s found with the slug %s.", resource, slug), + ) + } + + defer res.Body.Close() + ret := Item{} + err = json.NewDecoder(res.Body).Decode(&ret) + if err != nil { + return nil, err + } + + return &ret.Path, nil +}