Add srt to vvt converter in the backend

The HTML5 videos can only ready subtitles in the VVT format, let's
convert the srt files on the fly to make the browser happy
This commit is contained in:
Grégoire Delattre 2017-05-21 13:31:34 +02:00
parent a22c57e4e5
commit 1c7421b182
6 changed files with 112 additions and 0 deletions

View File

@ -14,6 +14,7 @@ import (
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/auth"
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/backend"
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/config"
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/subtitles"
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/users"
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/web"
)
@ -331,3 +332,30 @@ func RefreshMovieSubtitlesHandler(env *web.Env, w http.ResponseWriter, r *http.R
return env.RenderOK(w, "Subtitles refreshed")
}
// DownloadVVTSubtitle returns a vvt subtitle for the movie
func DownloadVVTSubtitle(env *web.Env, w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
id := vars["id"]
lang := vars["lang"]
// Get the user
v := auth.GetCurrentUser(r, env.Log)
user, ok := v.(*users.User)
if !ok {
return fmt.Errorf("invalid user type")
}
// Create a new papi client
client, err := user.NewPapiClient()
if err != nil {
return env.RenderError(w, err)
}
url, err := client.SubtitleURL(&papi.Movie{ImdbID: id}, lang)
if err != nil {
return env.RenderError(w, err)
}
return subtitles.ConvertSubtitle(url, w)
}

View File

@ -34,6 +34,7 @@ func (m *Movie) MarshalJSON() ([]byte, error) {
type Subtitle struct {
Language string `json:"language"`
URL string `json:"url"`
VVTFile string `json:"vvt_file"`
}
var subtitles []Subtitle
// If the episode is present, fill the downloadURL
@ -46,6 +47,7 @@ func (m *Movie) MarshalJSON() ([]byte, error) {
subtitles = append(subtitles, Subtitle{
Language: l,
URL: subtitleURL,
VVTFile: fmt.Sprintf("/movies/%s/subtitles/%s", m.ImdbID, l),
})
}
}

View File

@ -2,6 +2,7 @@ package shows
import (
"encoding/json"
"fmt"
"github.com/Sirupsen/logrus"
"github.com/odwrtw/papi"
@ -26,6 +27,7 @@ func (e *Episode) MarshalJSON() ([]byte, error) {
type Subtitle struct {
Language string `json:"language"`
URL string `json:"url"`
VVTFile string `json:"vvt_file"`
}
var subtitles []Subtitle
// If the episode is present, fill the downloadURL
@ -46,6 +48,7 @@ func (e *Episode) MarshalJSON() ([]byte, error) {
subtitles = append(subtitles, Subtitle{
Language: l,
URL: subtitleURL,
VVTFile: fmt.Sprintf("/shows/%s/seasons/%d/episodes/%d/subtitles/%s", e.ShowImdbID, e.Season, e.Episode, l),
})
}
}

View File

@ -9,6 +9,7 @@ import (
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/auth"
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/backend"
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/subtitles"
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/users"
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/web"
@ -384,3 +385,36 @@ func RefreshEpisodeSubtitlesHandler(env *web.Env, w http.ResponseWriter, r *http
return env.RenderOK(w, "Subtitles refreshed")
}
// DownloadVVTSubtitle returns a vvt subtitle for the movie
func DownloadVVTSubtitle(env *web.Env, w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
id := vars["id"]
lang := vars["lang"]
season, _ := strconv.Atoi(vars["season"])
episode, _ := strconv.Atoi(vars["episode"])
// Get the user
v := auth.GetCurrentUser(r, env.Log)
user, ok := v.(*users.User)
if !ok {
return fmt.Errorf("invalid user type")
}
// Create a new papi client
client, err := user.NewPapiClient()
if err != nil {
return env.RenderError(w, err)
}
url, err := client.SubtitleURL(&papi.Episode{
ShowImdbID: id,
Season: season,
Episode: episode,
}, lang)
if err != nil {
return env.RenderError(w, err)
}
return subtitles.ConvertSubtitle(url, w)
}

View File

@ -0,0 +1,43 @@
package subtitles
import (
"fmt"
"net/http"
"github.com/gregdel/srt2vtt"
)
// ConvertSubtitle downloads and converts a subtitle from srt to vvt
func ConvertSubtitle(url string, w http.ResponseWriter) error {
// Client with compression disabled
c := &http.Client{
Transport: &http.Transport{DisableCompression: true},
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return err
}
resp, err := c.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("Invalid subitle response code: %d", resp.StatusCode)
}
reader, err := srt2vtt.NewReader(resp.Body)
if err != nil {
return err
}
_, err = reader.WriteTo(w)
if err != nil {
return err
}
return nil
}

View File

@ -23,6 +23,7 @@ func setupRoutes(env *web.Env) {
env.Handle("/movies/search/{search}", movies.SearchMovie).WithRole(users.UserRole).Methods("GET")
env.Handle("/movies/{id:tt[0-9]+}", movies.PolochonDeleteHandler).WithRole(users.UserRole).Methods("DELETE")
env.Handle("/movies/{id:tt[0-9]+}/refresh", movies.RefreshMovieHandler).WithRole(users.UserRole).Methods("POST")
env.Handle("/movies/{id:tt[0-9]+}/subtitles/{lang}", movies.DownloadVVTSubtitle).WithRole(users.UserRole).Methods("GET")
env.Handle("/movies/{id:tt[0-9]+}/subtitles/refresh", movies.RefreshMovieSubtitlesHandler).WithRole(users.UserRole).Methods("POST")
env.Handle("/movies/refresh", extmedias.RefreshMoviesHandler).WithRole(users.AdminRole).Methods("POST")
@ -35,6 +36,7 @@ func setupRoutes(env *web.Env) {
env.Handle("/shows/{id:tt[0-9]+}/refresh", shows.RefreshShowHandler).WithRole(users.UserRole).Methods("POST")
env.Handle("/shows/{id:tt[0-9]+}/seasons/{season:[0-9]+}/episodes/{episode:[0-9]+}", shows.RefreshEpisodeHandler).WithRole(users.UserRole).Methods("POST")
env.Handle("/shows/{id:tt[0-9]+}/seasons/{season:[0-9]+}/episodes/{episode:[0-9]+}/subtitles/refresh", shows.RefreshEpisodeSubtitlesHandler).WithRole(users.UserRole).Methods("POST")
env.Handle("/shows/{id:tt[0-9]+}/seasons/{season:[0-9]+}/episodes/{episode:[0-9]+}/subtitles/{lang}", shows.DownloadVVTSubtitle).WithRole(users.UserRole).Methods("GET")
env.Handle("/shows/refresh", extmedias.RefreshShowsHandler).WithRole(users.AdminRole).Methods("POST")
// Wishlist routes for shows