diff --git a/internal/api/routes_scene.go b/internal/api/routes_scene.go index 9688a7974..da76e3526 100644 --- a/internal/api/routes_scene.go +++ b/internal/api/routes_scene.go @@ -206,7 +206,10 @@ func (rs sceneRoutes) streamTranscode(w http.ResponseWriter, r *http.Request, st lm := manager.GetInstance().ReadLockManager streamRequestCtx := manager.NewStreamRequestContext(w, r) lockCtx := lm.ReadLock(streamRequestCtx, f.Path) - defer lockCtx.Cancel() + + // hijacking and closing the connection here causes video playback to hang in Chrome + // due to ERR_INCOMPLETE_CHUNKED_ENCODING + // We trust that the request context will be closed, so we don't need to call Cancel on the returned context here. stream, err := encoder.GetTranscodeStream(lockCtx, options) @@ -222,6 +225,7 @@ func (rs sceneRoutes) streamTranscode(w http.ResponseWriter, r *http.Request, st lockCtx.AttachCommand(stream.Cmd) stream.Serve(w, r) + w.(http.Flusher).Flush() } func (rs sceneRoutes) Screenshot(w http.ResponseWriter, r *http.Request) { diff --git a/internal/manager/running_streams.go b/internal/manager/running_streams.go index 5d010ef50..5e329e6fb 100644 --- a/internal/manager/running_streams.go +++ b/internal/manager/running_streams.go @@ -34,8 +34,21 @@ func (c *StreamRequestContext) Cancel() { } // hijack and close the connection - conn, _, _ := hj.Hijack() + conn, bw, _ := hj.Hijack() if conn != nil { + if bw != nil { + // notify end of stream + _, err := bw.WriteString("0\r\n") + if err != nil { + logger.Warnf("unable to write end of stream: %v", err) + } + _, err = bw.WriteString("\r\n") + if err != nil { + logger.Warnf("unable to write end of stream: %v", err) + } + _ = bw.Flush() + } + conn.Close() } }