diff --git a/pkg/cmd/whip.go b/pkg/cmd/whip.go index 2f67e8b66..920f47020 100644 --- a/pkg/cmd/whip.go +++ b/pkg/cmd/whip.go @@ -74,8 +74,13 @@ func (w *WHIPClient) WHIP(ctx context.Context) error { "filesrc name=filesrc ! qtdemux name=demux", "demux.video_0 ! tee name=video_tee", "demux.audio_0 ! tee name=audio_tee", - "video_tee. ! queue ! h264parse config-interval=-1 ! video/x-h264,stream-format=byte-stream ! appsink name=videoappsink", - "audio_tee. ! queue ! opusparse ! appsink name=audioappsink", + // sync=true (the default) is load-bearing here, unlike every other + // appsink in the tree: these sinks are what pace the file at realtime + // so it plays as a live stream — WriteSample pushes to WebRTC + // immediately, so without clock sync the whole file would blast + // through in one burst. + "video_tee. ! queue ! h264parse config-interval=-1 ! video/x-h264,stream-format=byte-stream ! appsink sync=true name=videoappsink", + "audio_tee. ! queue ! opusparse ! appsink sync=true name=audioappsink", // "matroskamux name=mux ! fakesink name=fakesink sync=true", // "video_tee. ! mux.video_0", // "audio_tee. ! mux.audio_0", diff --git a/pkg/media/gstreamer.go b/pkg/media/gstreamer.go index 140f9460d..f3c1f4d11 100644 --- a/pkg/media/gstreamer.go +++ b/pkg/media/gstreamer.go @@ -68,6 +68,7 @@ func SelfTest(ctx context.Context) error { sinkele, err := gst.NewElementWithProperties("appsink", map[string]interface{}{ "name": "self-test-sink", + "sync": false, }) if err != nil { return fmt.Errorf("failed to create appsink element: %w", err) diff --git a/pkg/media/thumbnail.go b/pkg/media/thumbnail.go index 1dd5a9986..7b2d0a0c6 100644 --- a/pkg/media/thumbnail.go +++ b/pkg/media/thumbnail.go @@ -71,7 +71,7 @@ func thumbnailFromMP4(ctx context.Context, flat []byte, w io.Writer, format stri pipeline, err := gst.NewPipelineFromString(strings.Join([]string{ "appsrc name=src ! decodebin ! videoconvert ! videoscale ! videorate ! capsfilter caps=video/x-raw,width=[1,1280],height=[1,720],pixel-aspect-ratio=1/1,framerate=1/999999 ! ", encoder, - " ! appsink name=appsink", + " ! appsink sync=false name=appsink", }, "\n")) if err != nil { return fmt.Errorf("create thumbnail pipeline: %w", err)