mirror of
https://github.com/zoriya/Kyoo.git
synced 2026-03-29 04:42:11 -04:00
Transcoder: Audio: Add quality to AudioKey + param to api endpoint
This commit is contained in:
parent
42ba285948
commit
7f800f82d0
@ -20,9 +20,9 @@ func RegisterStreamHandlers(e *echo.Group, transcoder *src.Transcoder) {
|
||||
e.GET("/:path/direct/:identifier", DirectStream)
|
||||
e.GET("/:path/master.m3u8", h.GetMaster)
|
||||
e.GET("/:path/:video/:quality/index.m3u8", h.GetVideoIndex)
|
||||
e.GET("/:path/audio/:audio/index.m3u8", h.GetAudioIndex)
|
||||
e.GET("/:path/audio/:audio/:quality/index.m3u8", h.GetAudioIndex)
|
||||
e.GET("/:path/:video/:quality/:chunk", h.GetVideoSegment)
|
||||
e.GET("/:path/audio/:audio/:chunk", h.GetAudioSegment)
|
||||
e.GET("/:path/audio/:audio/:quality/:chunk", h.GetAudioSegment)
|
||||
}
|
||||
|
||||
// @Summary Direct video
|
||||
@ -115,7 +115,7 @@ func (h *shandler) GetVideoIndex(c echo.Context) error {
|
||||
// This route can take a few seconds to respond since it will way for at least one segment to be
|
||||
// available.
|
||||
//
|
||||
// Path: /:path/audio/:audio/index.m3u8
|
||||
// Path: /:path/audio/:audio/:quality/index.m3u8
|
||||
//
|
||||
// PRIVATE ROUTE (not documented in swagger, can change at any time)
|
||||
// Only reached via the master.m3u8.
|
||||
@ -124,6 +124,10 @@ func (h *shandler) GetAudioIndex(c echo.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
quality, err := src.AudioQualityFromString(c.Param("quality"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := getClientId(c)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -133,7 +137,7 @@ func (h *shandler) GetAudioIndex(c echo.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
ret, err := h.transcoder.GetAudioIndex(c.Request().Context(), path, uint32(audio), client, sha)
|
||||
ret, err := h.transcoder.GetAudioIndex(c.Request().Context(), path, uint32(audio), quality, client, sha)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -190,7 +194,7 @@ func (h *shandler) GetVideoSegment(c echo.Context) error {
|
||||
//
|
||||
// Retrieve a chunk of a transcoded audio.
|
||||
//
|
||||
// Path: /:path/audio/:audio/segments-:chunk.ts
|
||||
// Path: /:path/audio/:audio/:quality/segments-:chunk.ts
|
||||
//
|
||||
// PRIVATE ROUTE (not documented in swagger, can change at any time)
|
||||
// Only reached via the master.m3u8.
|
||||
@ -199,6 +203,10 @@ func (h *shandler) GetAudioSegment(c echo.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
quality, err := src.AudioQualityFromString(c.Param("quality"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
segment, err := parseSegment(c.Param("chunk"))
|
||||
if err != nil {
|
||||
return err
|
||||
@ -212,7 +220,7 @@ func (h *shandler) GetAudioSegment(c echo.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
ret, err := h.transcoder.GetAudioSegment(c.Request().Context(), path, uint32(audio), segment, client, sha)
|
||||
ret, err := h.transcoder.GetAudioSegment(c.Request().Context(), path, uint32(audio), quality, segment, client, sha)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -19,7 +19,12 @@ type FileStream struct {
|
||||
Out string
|
||||
Info *MediaInfo
|
||||
videos CMap[VideoKey, *VideoStream]
|
||||
audios CMap[uint32, *AudioStream]
|
||||
audios CMap[AudioKey, *AudioStream]
|
||||
}
|
||||
|
||||
type AudioKey struct {
|
||||
idx uint32
|
||||
quality AudioQuality
|
||||
}
|
||||
|
||||
type VideoKey struct {
|
||||
@ -32,7 +37,7 @@ func (t *Transcoder) newFileStream(path string, sha string) *FileStream {
|
||||
transcoder: t,
|
||||
Out: fmt.Sprintf("%s/%s", Settings.Outpath, sha),
|
||||
videos: NewCMap[VideoKey, *VideoStream](),
|
||||
audios: NewCMap[uint32, *AudioStream](),
|
||||
audios: NewCMap[AudioKey, *AudioStream](),
|
||||
}
|
||||
|
||||
ret.ready.Add(1)
|
||||
@ -71,27 +76,28 @@ func (fs *FileStream) Destroy() {
|
||||
func (fs *FileStream) GetMaster(client string) string {
|
||||
master := "#EXTM3U\n"
|
||||
|
||||
// TODO: support multiples audio qualities (and original)
|
||||
for _, audio := range fs.Info.Audios {
|
||||
master += "#EXT-X-MEDIA:TYPE=AUDIO,"
|
||||
master += "GROUP-ID=\"audio\","
|
||||
if audio.Language != nil {
|
||||
master += fmt.Sprintf("LANGUAGE=\"%s\",", *audio.Language)
|
||||
for _, quality := range AudioQualities {
|
||||
for _, audio := range fs.Info.Audios {
|
||||
master += "#EXT-X-MEDIA:TYPE=AUDIO,"
|
||||
master += fmt.Sprintf("GROUP-ID=\"audio-%s\",", quality)
|
||||
if audio.Language != nil {
|
||||
master += fmt.Sprintf("LANGUAGE=\"%s\",", *audio.Language)
|
||||
}
|
||||
if audio.Title != nil {
|
||||
master += fmt.Sprintf("NAME=\"%s\",", *audio.Title)
|
||||
} else if audio.Language != nil {
|
||||
master += fmt.Sprintf("NAME=\"%s\",", *audio.Language)
|
||||
} else {
|
||||
master += fmt.Sprintf("NAME=\"Audio %d\",", audio.Index)
|
||||
}
|
||||
if audio.IsDefault {
|
||||
master += "DEFAULT=YES,"
|
||||
}
|
||||
master += "CHANNELS=\"2\","
|
||||
master += fmt.Sprintf("URI=\"audio/%d/%s/index.m3u8?clientId=%s\"\n", audio.Index, quality, client)
|
||||
}
|
||||
if audio.Title != nil {
|
||||
master += fmt.Sprintf("NAME=\"%s\",", *audio.Title)
|
||||
} else if audio.Language != nil {
|
||||
master += fmt.Sprintf("NAME=\"%s\",", *audio.Language)
|
||||
} else {
|
||||
master += fmt.Sprintf("NAME=\"Audio %d\",", audio.Index)
|
||||
}
|
||||
if audio.IsDefault {
|
||||
master += "DEFAULT=YES,"
|
||||
}
|
||||
master += "CHANNELS=\"2\","
|
||||
master += fmt.Sprintf("URI=\"audio/%d/index.m3u8?clientId=%s\"\n", audio.Index, client)
|
||||
master += "\n"
|
||||
}
|
||||
master += "\n"
|
||||
|
||||
// codec is the prefix + the level, the level is not part of the codec we want to compare for the same_codec check bellow
|
||||
transcode_prefix := "avc1.6400"
|
||||
@ -204,25 +210,25 @@ func (fs *FileStream) GetVideoSegment(idx uint32, quality VideoQuality, segment
|
||||
return stream.GetSegment(segment)
|
||||
}
|
||||
|
||||
func (fs *FileStream) getAudioStream(audio uint32) (*AudioStream, error) {
|
||||
stream, _ := fs.audios.GetOrCreate(audio, func() *AudioStream {
|
||||
ret, _ := fs.transcoder.NewAudioStream(fs, audio)
|
||||
func (fs *FileStream) getAudioStream(idx uint32, quality AudioQuality) (*AudioStream, error) {
|
||||
stream, _ := fs.audios.GetOrCreate(AudioKey{idx, quality}, func() *AudioStream {
|
||||
ret, _ := fs.transcoder.NewAudioStream(fs, idx, quality)
|
||||
return ret
|
||||
})
|
||||
stream.ready.Wait()
|
||||
return stream, nil
|
||||
}
|
||||
|
||||
func (fs *FileStream) GetAudioIndex(audio uint32, client string) (string, error) {
|
||||
stream, err := fs.getAudioStream(audio)
|
||||
func (fs *FileStream) GetAudioIndex(idx uint32, quality AudioQuality, client string) (string, error) {
|
||||
stream, err := fs.getAudioStream(idx, quality)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
return stream.GetIndex(client)
|
||||
}
|
||||
|
||||
func (fs *FileStream) GetAudioSegment(audio uint32, segment int32) (string, error) {
|
||||
stream, err := fs.getAudioStream(audio)
|
||||
func (fs *FileStream) GetAudioSegment(idx uint32, quality AudioQuality, segment int32) (string, error) {
|
||||
stream, err := fs.getAudioStream(idx, quality)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ type ClientInfo struct {
|
||||
sha string
|
||||
path string
|
||||
video *VideoKey
|
||||
audio *uint32
|
||||
audio *AudioKey
|
||||
vhead int32
|
||||
ahead int32
|
||||
}
|
||||
@ -151,7 +151,7 @@ func (t *Tracker) DestroyStreamIfOld(sha string) {
|
||||
stream.Destroy()
|
||||
}
|
||||
|
||||
func (t *Tracker) KillAudioIfDead(sha string, path string, audio uint32) bool {
|
||||
func (t *Tracker) KillAudioIfDead(sha string, path string, audio AudioKey) bool {
|
||||
for _, stream := range t.clients {
|
||||
if stream.sha == sha && stream.audio != nil && *stream.audio == audio {
|
||||
return false
|
||||
@ -191,7 +191,7 @@ func (t *Tracker) KillVideoIfDead(sha string, path string, video VideoKey) bool
|
||||
return true
|
||||
}
|
||||
|
||||
func (t *Tracker) KillOrphanedHeads(sha string, video *VideoKey, audio *uint32) {
|
||||
func (t *Tracker) KillOrphanedHeads(sha string, video *VideoKey, audio *AudioKey) {
|
||||
stream, ok := t.transcoder.streams.Get(sha)
|
||||
if !ok {
|
||||
return
|
||||
|
||||
@ -94,6 +94,7 @@ func (t *Transcoder) GetAudioIndex(
|
||||
ctx context.Context,
|
||||
path string,
|
||||
audio uint32,
|
||||
quality AudioQuality,
|
||||
client string,
|
||||
sha string,
|
||||
) (string, error) {
|
||||
@ -105,18 +106,18 @@ func (t *Transcoder) GetAudioIndex(
|
||||
client: client,
|
||||
sha: sha,
|
||||
path: path,
|
||||
audio: &audio,
|
||||
audio: &AudioKey{audio, quality},
|
||||
vhead: -1,
|
||||
ahead: -1,
|
||||
}
|
||||
return stream.GetAudioIndex(audio, client)
|
||||
return stream.GetAudioIndex(audio, quality, client)
|
||||
}
|
||||
|
||||
func (t *Transcoder) GetVideoSegment(
|
||||
ctx context.Context,
|
||||
path string,
|
||||
video uint32,
|
||||
quality Quality,
|
||||
quality VideoQuality,
|
||||
segment int32,
|
||||
client string,
|
||||
sha string,
|
||||
@ -141,6 +142,7 @@ func (t *Transcoder) GetAudioSegment(
|
||||
ctx context.Context,
|
||||
path string,
|
||||
audio uint32,
|
||||
quality AudioQuality,
|
||||
segment int32,
|
||||
client string,
|
||||
sha string,
|
||||
@ -153,9 +155,9 @@ func (t *Transcoder) GetAudioSegment(
|
||||
client: client,
|
||||
sha: sha,
|
||||
path: path,
|
||||
audio: &audio,
|
||||
audio: &AudioKey{audio, quality},
|
||||
ahead: segment,
|
||||
vhead: -1,
|
||||
}
|
||||
return stream.GetAudioSegment(audio, segment)
|
||||
return stream.GetAudioSegment(audio, quality, segment)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user