使用 FFMpeg 进行流式传输:启动画面?

使用 FFMpeg 进行流式传输:启动画面?

我一直在尝试通过 FFMpeg 进行流式传输。我喜欢它的强大功能!目前我已经将其设置为流式传输我的屏幕并为我的网络摄像头添加覆盖。不过,有一件事我希望能够做到,但我不太明白:按需显示启动画面。

也许通过例子来解释会更好。假设你正在通过 Twitch 直播游戏或其他东西很长时间。然后,你必须离开。你可以

  1. 走开,或者
  2. 播放“马上回来!”启动画面或其他内容,也许还会配上一点音乐(多亏了 Pulseaudio 的出色功能,我已经搞清楚了这一部分)

我认为实现此目的的最佳方式是通过覆盖屏幕/网络摄像头覆盖的第二个覆盖。

我尝试添加类似于此的第三个输入:

 ffmpeg -f v4l2 -i /dev/video0 -f xllgrab -i :0.0+738,0 \
        -i ~/splashscreen.png -loop 1 \
        -filter_complex "[0:1][0:0]overlay=0:0[out];[out][2:0]overlay=0:0[final]" \
        -f flv ~/Videos/test.flv 

这需要比 Saucy repos 中更新的 ffmpeg 版本。

而且它确实有效,因为启动画面是透明的。我本想在需要启动画面时做些巧妙的事情,换成非透明图像,但 ffmpeg 要么缓存循环图像,要么在短暂时间内突然找不到文件时将其忽略。

我想到第二种方法可能是使用命名管道,并在需要时使用另一个 ffmpeg 实例将它们覆盖启动画面传入管道,但从我所读的内容来看,如果 ffmpeg 在管道中找不到任何数据,它将不会继续处理视频的其余部分,而是仅在可以从所有输入源中提取时才输出帧。

如果有任何 ffmpeg 专家,我很乐意听听他们的一些想法!

答案1

我做到了!当然,这需要一些后空翻,但无论如何它还是有效的 =D

以下是我使用的脚本:

#!/bin/bash

#NOTE: The framerate throttling can probably be removed due to the limit in
#the amount of data that can be written to a pipe before it blocks. My
#streams are at 1920x1080 and cat only puts 5 frames onto the pipe
#before it hangs waiting for a program to tread the pipe. I found this odd
#since my splash screen images were only 8k, whereas the pipe size is 1M.
#Therefore, it might be highly dependent on the resolution of your splash
#images. By removing the FPS logic of this script, a higher potential
#framerate can be achieved by the script if that's necessary.

#This is my third FFMpeg input. My other two are at framerates of
#10 (screen) and 30 (webcam). My output is 10 FPS. I had originally
#set this to 10 as well, but it caused FFMpeg to choke and start dropping
#frames for some reason, so I just added 5 since it's a common denominator
#of both 10 and 30. +2 may have also worked, but that seemed a little too
#close for me since even 11 had issues with output framerate, hovering
#around 9.9 FPS rather than the target 10 FPS.

framerate=15

#Tracks how many frames we've written this second
files_this_second=0
this_second=$(date +%s)

while [ 1 ]
do
  #Haven't written all the frames for this second
  if [ $files_this_second -lt $framerate ]
  then
    if [ ! -f /file/to/test/to/throw/up/splash ]
    then
      #Output the transparent "splash screen" (no splash screen)
      cat /path/to/a/transparent.png
    else
      #Output the splash screen
      cat /path/to/a/splashscreen.png
    fi
    files_this_second=$(($files_this_second + 1))
  else
    #The second has changed
    if [ "$(date +%s)" != "$this_second" ]
    then
      this_second=$(date +%s)
      files_this_second=0
    fi
  fi
done

然后我可以将该脚本的输出输入到 FFMpeg 中,如下所示:

splash.sh | ffmpeg -f image2pipe -vcodec png -framerate 15 -i - (some other video source and parameters) -filter_complex "[1:0]setpts=PTS-STARTPTS[video];[0:0]setpts=PTS-STARTPTS[splashscreen];[video][splashscreen]overlay=0:0" (output format options and file)

然后,我设置了一个热键来运行另一个简单的脚本:

#!/bin/bash

if [ -f /file/to/test/to/throw/up/splash ]
then
  rm /file/to/test/to/throw/up/splash
else
  touch /file/to/test/to/throw/up/splash
fi

当我想显示启动画面时,我会按下热键。当我想关闭它时,我会再次按下热键。

这对于以下几点很有用:

  1. 启动画面(如上所述)
  2. 输入密码或类似内容时屏幕变黑

它还绕过了上述问题中图像被缓存的问题,因此您只需用另一个图像替换该图像即可设置另一个启动画面。

我觉得这很棒!你们觉得呢?

注意:我使用的是自编译版本的 FFMpeg,因为 Saucy 存储库中提供的版本已经过时了。此外,我找不到 image2pipe 格式的文档。

相关内容