首页 > 解决方案 > 将标准输入输入更新到 ffmpeg 以进行 youtube 直播时如何防止屏幕撕裂

问题描述

我正在开发一个直播应用程序,该应用程序允许多个 Web 客户端通过 webrtc 将视频流式传输到“控制器”客户端,该客户端将添加他们的音轨,然后能够在这些视频源之间切换并将原始流数据输出到运行 ffmpeg 的服务器,然后将提要发送到 youtube live。

“控制器”客户端只需将一个对等视频源设置为按钮按下时的“活动”流,而将所有其他视频源设置为“非活动”。

然后将数据发送到 node.js 服务器,如下所示:

      this.mediaSources.forEach((source, _) => {
    source.recorder.ondataavailable = (e: BlobEvent) => {
        if (source.active) {
          this.socket.emit('binarystream', e.data)
        }
      }

节点服务器启动一个 ffmepg 进程,如下所示:

export class FfmpegService {
ffmpeg: ChildProcess
youtubeUrl = 'rtmp://a.rtmp.youtube.com/live2'

start(rtmpDestination: string) {
    this.ffmpeg = spawn('ffmpeg', this.getFfmpegOptions(rtmpDestination), 
        { shell: process.env.NODE_ENV !== 'production' }
    )
}

stop() {
    if (this.ffmpeg) {
        this.ffmpeg.stdin.end()
        this.ffmpeg.kill('SIGINT')
        this.ffmpeg = null
    }
}

feedStream(data: any) {
    this.ffmpeg.stdin.write(data)
}

private getFfmpegOptions(streamKey: string): string[] {
    const rtmpDestination = this.youtubeUrl + '/' + streamKey
    return [
        '-i','-',
        '-c:v', 'libx264', 
        '-preset', 'fast', '-tune', 'zerolatency',  // video codec config: low latency, adaptive bitrate
        '-c:a', 'aac', '-ar', '44100', '-b:a', '64k', // audio codec config: sampling frequency (11025, 22050, 44100), bitrate 64 kbits
        '-y', //force to overwrite
        '-use_wallclock_as_timestamps', '1', // used for audio sync
        '-async', '1', // used for audio sync
        //'-filter_complex', 'aresample=44100', // resample audio to 44100Hz, needed if input is not 44100
        //'-strict', 'experimental', 
        '-bufsize', '300k',
        '-pix_fmt', 'yuv420p',
        '-f', 'flv', rtmpDestination
    ];
}

在 youtube 现场会话中,一切都按预期工作。唯一的问题是在输入流之间切换时,在稳定下来之前大约有 5 秒的屏幕撕裂。从所有外观来看,切换是立即无缝地发生的。我觉得这可以通过调整 ffmpeg 选项来减弱/解决,但我对 ffmpeg 还是很陌生。我尝试增加/减少 -bufsize 和 -preset cli 选项,但到目前为止没有任何效果。

标签: javascriptnode.jswebsocketffmpegwebrtc

解决方案


推荐阅读