From edfec467b648f37f39f23d4f4d96a21424f274f8 Mon Sep 17 00:00:00 2001 From: emranemran Date: Tue, 31 May 2022 21:58:29 -0600 Subject: [PATCH] core/vidplayer: add useful debug info to http response headers When viewing HLS manifests/segments, it is often useful to view information on how those segments were generated. This commit adds fields such as git-sha and node identifiers to the HTTP response headers. --- core/lpms.go | 5 ++++- segmenter/video_segmenter_test.go | 6 ++++-- vidplayer/player.go | 25 ++++++++++++++++++++++++- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/core/lpms.go b/core/lpms.go index 62a87d804b..1b1f620ffb 100644 --- a/core/lpms.go +++ b/core/lpms.go @@ -56,6 +56,9 @@ type LPMSOpts struct { // on the mux; LPMS won't initialize it. // If set, HttpPort and HttpDisabled are ignored. HttpMux *http.ServeMux + + // Used to tag HTTP headers with useful debug info. + HttpDebug vidplayer.VidPlayerDebug } func defaultLPMSOpts(opts *LPMSOpts) { @@ -78,7 +81,7 @@ func New(opts *LPMSOpts) *LPMS { if !opts.HttpDisabled && opts.HttpMux == nil { httpAddr = opts.HttpAddr } - player := vidplayer.NewVidPlayer(rtmpServer, opts.VodPath, opts.HttpMux) + player := vidplayer.NewVidPlayer(rtmpServer, opts.VodPath, opts.HttpMux, opts.HttpDebug) listener := &vidlistener.VidListener{RtmpServer: rtmpServer} return &LPMS{vidPlayer: player, vidListener: listener, workDir: opts.WorkDir, rtmpAddr: opts.RtmpAddr, httpAddr: httpAddr} } diff --git a/segmenter/video_segmenter_test.go b/segmenter/video_segmenter_test.go index 95d39fcae5..14b6efc8c0 100644 --- a/segmenter/video_segmenter_test.go +++ b/segmenter/video_segmenter_test.go @@ -120,7 +120,8 @@ func TestSegmenter(t *testing.T) { opt := SegmenterOptions{SegLength: time.Second * 4} vs := NewFFMpegVideoSegmenter(workDir, strm.GetStreamID(), strmUrl, opt) server := &rtmp.Server{Addr: ":1939"} - player := vidplayer.NewVidPlayer(server, "", nil) + debug := vidplayer.VidPlayerDebug{DebugEnabled: false, LivepeerVersion: "deadbeef"} + player := vidplayer.NewVidPlayer(server, "", nil, debug) player.HandleRTMPPlay( func(url *url.URL) (stream.RTMPVideoStream, error) { @@ -264,7 +265,8 @@ func TestSetStartSeq(t *testing.T) { opt := SegmenterOptions{SegLength: time.Second * 4, StartSeq: startSeq} vs := NewFFMpegVideoSegmenter(workDir, strm.GetStreamID(), strmUrl, opt) server := &rtmp.Server{Addr: ":1936"} - player := vidplayer.NewVidPlayer(server, "", nil) + debug := vidplayer.VidPlayerDebug{DebugEnabled: false, LivepeerVersion: "deadbeef"} + player := vidplayer.NewVidPlayer(server, "", nil, debug) player.HandleRTMPPlay( func(url *url.URL) (stream.RTMPVideoStream, error) { diff --git a/vidplayer/player.go b/vidplayer/player.go index b913c8efae..dcd6bdb079 100644 --- a/vidplayer/player.go +++ b/vidplayer/player.go @@ -29,6 +29,16 @@ var ErrRTMP = errors.New("ErrRTMP") var ErrHLS = errors.New("ErrHLS") var PlaylistWaittime = 6 * time.Second +// vars to tag http response headers w/ debugging info +var ( + lpVersion string +) + +type VidPlayerDebug struct { + DebugEnabled bool + LivepeerVersion string +} + //VidPlayer is the module that handles playing video. For now we only support RTMP and HLS play. type VidPlayer struct { RtmpServer *joy4rtmp.Server @@ -40,7 +50,7 @@ type VidPlayer struct { func defaultRtmpPlayHandler(url *url.URL) (stream.RTMPVideoStream, error) { return nil, ErrRTMP } //NewVidPlayer creates a new video player -func NewVidPlayer(rtmpS *joy4rtmp.Server, vodPath string, mux *http.ServeMux) *VidPlayer { +func NewVidPlayer(rtmpS *joy4rtmp.Server, vodPath string, mux *http.ServeMux, httpDebugHeaders VidPlayerDebug) *VidPlayer { if mux == nil { mux = http.DefaultServeMux } @@ -48,6 +58,7 @@ func NewVidPlayer(rtmpS *joy4rtmp.Server, vodPath string, mux *http.ServeMux) *V if rtmpS != nil { rtmpS.HandlePlay = player.rtmpServerHandlePlay() } + player.setDebugHeaders(httpDebugHeaders) return player } @@ -97,6 +108,15 @@ func (s *VidPlayer) HandleHLSPlay( }) } +// Used to set header properties on HTTP responses generated by a B/O/T nodes. +// This is useful for debugging. +func (s *VidPlayer) setDebugHeaders(httpDebugHeaders VidPlayerDebug) { + if (!httpDebugHeaders.DebugEnabled) { + return + } + lpVersion = httpDebugHeaders.LivepeerVersion +} + func handleLive(w http.ResponseWriter, r *http.Request, getMasterPlaylist func(url *url.URL) (*m3u8.MasterPlaylist, error), getMediaPlaylist func(url *url.URL) (*m3u8.MediaPlaylist, error), @@ -107,6 +127,7 @@ func handleLive(w http.ResponseWriter, r *http.Request, w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Expose-Headers", "Content-Length") w.Header().Set("Cache-Control", "max-age=5") + w.Header().Set("Livepeer-Version", lpVersion) ext := path.Ext(r.URL.Path) if ".m3u8" == ext { @@ -220,6 +241,8 @@ func handleVOD(url *url.URL, vodPath string, w http.ResponseWriter) error { w.Write(dat) } + w.Header().Set("Livepeer-Version", lpVersion) + http.Error(w, "Cannot find HTTP video resource: "+url.String(), 404) return nil }