如何在不使用WebRTC的情况下使用ffmpeg实现视频直播?

问题描述 投票:0回答:1

跟进我之前的问题,我想询问使用 ffmpeg 进行实时视频流传输的替代方法(由于某些限制,我不想在这里讨论,因此 WebRTC 不是一个选项)。

背景:

我有一个 Go 应用程序,其中 Goroutine 启动 ffmpeg 来处理视频流,然后通过

chan []byte
将视频流传递到主 Goroutine。我尝试使用 WebSocket,但遇到了上一个问题中描述的问题。由于显着的延迟和视频上的绿色方块等伪影,HLS 也无法正常工作。

根据上一个问题中的评论,我尝试通过简单的 GET 请求来流式传输视频。这是我实现的 Go 处理程序:

func stream(helperApp agent.Helper) func(rw http.ResponseWriter, rr *http.Request) {
   a := atomic.Bool{}
   return func(rw http.ResponseWriter, rr *http.Request) {
      if !a.CAS(false, true) {
         http.Error(rw, "already running", http.StatusInternalServerError)
         return
      }

      rw.Header().Set("Access-Control-Allow-Origin", "*")
      rw.Header().Set("Content-Type", "video/mp2t")

      out := make(chan []byte)

      // create StreamParam
      go ScreenCaptureForLiveStream(StreamParam, out) // ffmpeg process starts inside

      r, w := io.Pipe()
      go func() {
         for data := range out {
            w.Write(data)
            fmt.Println(len(data))
         }
      }()
      io.Copy(rw, r)
   }
}

在客户端(HTML):

<video id="video" muted="muted" src="http://localhost:8080/stream" controls></video>

在浏览器控制台中,我可以看到正在接收数据,但视频无法播放。

FFmpeg 使用以下参数执行:

-loglevel error -f avfoundation -framerate 5 -capture_cursor 1 -capture_mouse_clicks 1 -i 1 -c:v libx264 -pix_fmt yuv420p -vf pad='ceil(iw/2)*2:ceil(ih/2)*2' -threads 0 -preset veryfast -bf 2 -f mpegts pipe:1

为了验证,我跑了:

ffmpeg -i http://localhost:8080/stream -c copy out.mp4

视频已成功保存并播放。

问题: 除了 WebRTC 之外,还有哪些替代方法可以使用 ffmpeg 实现实时视频流?为什么当前通过 HTTP GET 请求流式传输视频的方法在浏览器中无法正常运行,如何解决这个问题?

go ffmpeg http-live-streaming
1个回答
0
投票

您将无法将 MPEG-TS 发送到视频元素。 我建议您使用 WebM 或 MP4。

对于 WebM,在 FFmpeg 命令中使用

-f webm
,然后对于
Content-Type
使用
video/webm

对于 MP4,您还必须配置分段,因此使用

-f mp4 -movflags frag_keyframe+empty_moov
,然后对于
Content-Type
,使用
video/mp4

如果您的

Content-Type
中还包含编解码器,则可以减少缓冲时间。

此外,由于您的直播是“直播”,我强烈建议您在视频标签中设置

preload="none"
。 否则,即使用户没有播放视频,浏览器也可能会毫无意义地进行流式传输。

如果您想更好地控制延迟,请密切关注

buffered
属性,并让
playbackRate
稍微超过
1.0
以赶上实时。 但不要走得太远,否则会出现缓冲区不足。 当然,如果发生了根本性的事情,并且您发现自己落后了 20 秒,您可以随时将
currentTime
设置为最新时间。

使用这些方法,我无需特殊优化即可将玻璃到玻璃的速度控制在 300 毫秒以下。 如果您仔细控制编解码器参数,您可以低于这个值...请记住,一切都是权衡。

© www.soinside.com 2019 - 2024. All rights reserved.