From a7d5f94dfb966a702d4a804c620f90554d3ace62 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Mon, 13 Oct 2025 19:10:23 +0200 Subject: [PATCH] Allow clientId to be specified in query params --- api/src/controllers/videos.ts | 5 +++-- front/src/ui/player/controls/progress.tsx | 2 +- front/src/ui/player/controls/touch.tsx | 2 +- transcoder/src/api/streams.go | 7 +++++-- transcoder/src/filestream.go | 18 +++++++++--------- transcoder/src/stream.go | 6 +++--- transcoder/src/transcoder.go | 6 +++--- 7 files changed, 25 insertions(+), 21 deletions(-) diff --git a/api/src/controllers/videos.ts b/api/src/controllers/videos.ts index c840b283..e1b31b58 100644 --- a/api/src/controllers/videos.ts +++ b/api/src/controllers/videos.ts @@ -646,7 +646,7 @@ export const videosH = new Elysia({ prefix: "/videos", tags: ["videos"] }) ) .get( ":id/master.m3u8", - async ({ params: { id }, status, redirect }) => { + async ({ params: { id }, request, status, redirect }) => { const [video] = await db .select({ path: videos.path, @@ -663,7 +663,8 @@ export const videosH = new Elysia({ prefix: "/videos", tags: ["videos"] }) }); } const path = Buffer.from(video.path, "utf8").toString("base64url"); - return redirect(`/video/${path}/master.m3u8`); + const query = request.url.substring(request.url.indexOf("?")) + return redirect(`/video/${path}/master.m3u8${query}`); }, { detail: { description: "Get redirected to the master.m3u8 of the video" }, diff --git a/front/src/ui/player/controls/progress.tsx b/front/src/ui/player/controls/progress.tsx index 08f744e1..c63ad53c 100644 --- a/front/src/ui/player/controls/progress.tsx +++ b/front/src/ui/player/controls/progress.tsx @@ -40,7 +40,7 @@ export const ProgressBar = ({ setProgress={setSeek} endSeek={() => { player.seekTo(seek!); - setTimeout(player.play, 10); + setTimeout(() => player.play(), 10); setSeek(null); }} // onHover={(progress, layout) => { diff --git a/front/src/ui/player/controls/touch.tsx b/front/src/ui/player/controls/touch.tsx index b02a046c..579a1def 100644 --- a/front/src/ui/player/controls/touch.tsx +++ b/front/src/ui/player/controls/touch.tsx @@ -82,7 +82,7 @@ export const TouchControls = ({ // instantly hide the controls when mouse leaves the view if (e.nativeEvent.pointerType === "mouse") show(false); }} - {...css({ cursor: "none" as any }, props)} + {...css({ cursor: (shouldShow ? "unset" : "none") as any }, props)} > {shouldShow && children} diff --git a/transcoder/src/api/streams.go b/transcoder/src/api/streams.go index 9b3b8465..ad0dc855 100644 --- a/transcoder/src/api/streams.go +++ b/transcoder/src/api/streams.go @@ -217,9 +217,12 @@ func (h *shandler) GetAudioSegment(c echo.Context) error { } func getClientId(c echo.Context) (string, error) { - key := c.Request().Header.Get("X-CLIENT-ID") + key := c.QueryParam("clientId") if key == "" { - return "", echo.NewHTTPError(http.StatusBadRequest, "missing client id. Please specify the X-CLIENT-ID header to a guid constant for the lifetime of the player (but unique per instance)") + key = c.Request().Header.Get("X-CLIENT-ID") + } + if key == "" { + return "", echo.NewHTTPError(http.StatusBadRequest, "missing client id. Please specify the X-CLIENT-ID header (or the clientId query param) to a guid constant for the lifetime of the player (but unique per instance)") } return key, nil } diff --git a/transcoder/src/filestream.go b/transcoder/src/filestream.go index c88ff75c..8ce0b663 100644 --- a/transcoder/src/filestream.go +++ b/transcoder/src/filestream.go @@ -68,7 +68,7 @@ func (fs *FileStream) Destroy() { _ = os.RemoveAll(fs.Out) } -func (fs *FileStream) GetMaster() string { +func (fs *FileStream) GetMaster(client string) string { master := "#EXTM3U\n" // TODO: support multiples audio qualities (and original) @@ -89,7 +89,7 @@ func (fs *FileStream) GetMaster() string { master += "DEFAULT=YES," } master += "CHANNELS=\"2\"," - master += fmt.Sprintf("URI=\"audio/%d/index.m3u8\"\n", audio.Index) + master += fmt.Sprintf("URI=\"audio/%d/index.m3u8?clientId=%s\"\n", audio.Index, client) } master += "\n" @@ -139,7 +139,7 @@ func (fs *FileStream) GetMaster() string { if video == *def_video { master += "DEFAULT=YES\n" } else { - master += fmt.Sprintf("URI=\"%d/%s/index.m3u8\"\n", video.Index, quality) + master += fmt.Sprintf("URI=\"%d/%s/index.m3u8?clientId=%s\"\n", video.Index, quality, client) } } } @@ -161,7 +161,7 @@ func (fs *FileStream) GetMaster() string { } master += "AUDIO=\"audio\"," master += "CLOSED-CAPTIONS=NONE\n" - master += fmt.Sprintf("%d/%s/index.m3u8\n", def_video.Index, quality) + master += fmt.Sprintf("%d/%s/index.m3u8?clientId=%s\n", def_video.Index, quality, client) continue } @@ -172,7 +172,7 @@ func (fs *FileStream) GetMaster() string { master += fmt.Sprintf("CODECS=\"%s\",", strings.Join([]string{transcode_codec, audio_codec}, ",")) master += "AUDIO=\"audio\"," master += "CLOSED-CAPTIONS=NONE\n" - master += fmt.Sprintf("%d/%s/index.m3u8\n", def_video.Index, quality) + master += fmt.Sprintf("%d/%s/index.m3u8?clientId=%s\n", def_video.Index, quality, client) } } @@ -188,12 +188,12 @@ func (fs *FileStream) getVideoStream(idx uint32, quality Quality) (*VideoStream, return stream, nil } -func (fs *FileStream) GetVideoIndex(idx uint32, quality Quality) (string, error) { +func (fs *FileStream) GetVideoIndex(idx uint32, quality Quality, client string) (string, error) { stream, err := fs.getVideoStream(idx, quality) if err != nil { return "", err } - return stream.GetIndex() + return stream.GetIndex(client) } func (fs *FileStream) GetVideoSegment(idx uint32, quality Quality, segment int32) (string, error) { @@ -213,12 +213,12 @@ func (fs *FileStream) getAudioStream(audio uint32) (*AudioStream, error) { return stream, nil } -func (fs *FileStream) GetAudioIndex(audio uint32) (string, error) { +func (fs *FileStream) GetAudioIndex(audio uint32, client string) (string, error) { stream, err := fs.getAudioStream(audio) if err != nil { return "", nil } - return stream.GetIndex() + return stream.GetIndex(client) } func (fs *FileStream) GetAudioSegment(audio uint32, segment int32) (string, error) { diff --git a/transcoder/src/stream.go b/transcoder/src/stream.go index 027180e1..69e016ec 100644 --- a/transcoder/src/stream.go +++ b/transcoder/src/stream.go @@ -361,7 +361,7 @@ func (ts *Stream) run(start int32) error { return nil } -func (ts *Stream) GetIndex() (string, error) { +func (ts *Stream) GetIndex(client string) (string, error) { // playlist type is event since we can append to the list if Keyframe.IsDone is false. // start time offset makes the stream start at 0s instead of ~3segments from the end (requires version 6 of hls) index := `#EXTM3U @@ -376,13 +376,13 @@ func (ts *Stream) GetIndex() (string, error) { for segment := int32(0); segment < length-1; segment++ { index += fmt.Sprintf("#EXTINF:%.6f\n", ts.keyframes.Get(segment+1)-ts.keyframes.Get(segment)) - index += fmt.Sprintf("segment-%d.ts\n", segment) + index += fmt.Sprintf("segment-%d.ts?clientId=%s\n", segment, client) } // do not forget to add the last segment between the last keyframe and the end of the file // if the keyframes extraction is not done, do not bother to add it, it will be retrived on the next index retrival if is_done { index += fmt.Sprintf("#EXTINF:%.6f\n", float64(ts.file.Info.Duration)-ts.keyframes.Get(length-1)) - index += fmt.Sprintf("segment-%d.ts\n", length-1) + index += fmt.Sprintf("segment-%d.ts?clientId=%s\n", length-1, client) index += `#EXT-X-ENDLIST` } return index, nil diff --git a/transcoder/src/transcoder.go b/transcoder/src/transcoder.go index 4ba0ccca..3177913e 100644 --- a/transcoder/src/transcoder.go +++ b/transcoder/src/transcoder.go @@ -63,7 +63,7 @@ func (t *Transcoder) GetMaster(ctx context.Context, path string, client string, vhead: -1, ahead: -1, } - return stream.GetMaster(), nil + return stream.GetMaster(client), nil } func (t *Transcoder) GetVideoIndex( @@ -87,7 +87,7 @@ func (t *Transcoder) GetVideoIndex( vhead: -1, ahead: -1, } - return stream.GetVideoIndex(video, quality) + return stream.GetVideoIndex(video, quality, client) } func (t *Transcoder) GetAudioIndex( @@ -109,7 +109,7 @@ func (t *Transcoder) GetAudioIndex( vhead: -1, ahead: -1, } - return stream.GetAudioIndex(audio) + return stream.GetAudioIndex(audio, client) } func (t *Transcoder) GetVideoSegment(