使用FFMPEG将视频文件连续传输到RTMP服务器

时间:2012-07-25 10:36:31

标签: ffmpeg streaming pipe named-pipes rtmp

ffmpeg将RTMP流处理为输入或输出,并且运行良好。

我想将一些视频(由python脚本管理的动态播放列表)流式传输到RTMP服务器,我现在正在做一些非常简单的事情:使用FFMPEG将我的视频逐个流式传输到RTMP服务器,但这会导致每次视频结束时连接中断,并且当下一个视频开始时,流已准备就绪。

我想在没有任何连接中断的情况下流式传输这些视频,然后可以正确查看流。

我使用此命令将我的视频逐个流式传输到服务器

ffmpeg -re -y -i myvideo.mp4 -vcodec libx264 -b:v 600k -r 25 -s 640x360 \
-filter:v yadif -ab 64k -ac 1 -ar 44100 -f flv \
"rtmp://mystreamingserver/app/streamName"

我在互联网上寻找了一些解决方法很多天,我发现有些人在ffmpeg中讨论使用命名管道作为输入,我已经尝试过了,但是自从{{{ 1}}不仅会在新视频出现时关闭RTMP流,还会自行关闭。

有没有办法做到这一点? (使用ffmpeg将视频的动态播放列表流式传输到RTMP服务器,而不会出现连接中断

4 个答案:

答案 0 :(得分:5)

更新(因为我无法删除已接受的答案):正确的解决方案是实现自定义分离器,类似于concat。目前还没有其他干净的方式。你必须亲自动手并编码!

下面是一个丑陋的黑客。这是一个非常糟糕的方法,只是不这样做!

该解决方案使用 concat demuxer ,并假设您的所有源媒体文件都使用相同的编解码器。该示例基于MPEG-TS,但RTMP也可以这样做。

  1. 制作一个播放列表文件,其中包含动态播放列表的大量入口点列表,其格式如下:

    file 'item_1.ts' file 'item_2.ts' file 'item_3.ts' [...] file 'item_[ENOUGH_FOR_A_LIFETIME].ts'

    这些文件只是占位符。

  2. 创建一个跟踪当前播放列表索引的脚本,并为current_index + 1

    即时创建符号链接

    ln -s /path/to/what/to/play/next.ts item_1.ts

    ln -s /path/to/what/to/play/next.ts item_2.ts

    ln -s /path/to/what/to/play/next.ts item_3.ts

    [...]

  3. 开始播放 ffmpeg -f concat -i playlist.txt -c copy output -f mpegts udp://<ip>:<port>

  4. 由愤怒的系统管理员追踪并呼叫姓名

答案 1 :(得分:1)

您可以将循环传递到缓冲区,然后从此缓冲区传输到流式传输实例。

在shell中它看起来像:

#!/bin/bash

for i in *.mp4; do
       ffmpeg -hide_banner -nostats -i "$i" -c:v mpeg2video [proper settings] -f mpegts -
done | mbuffer -q -c -m 20000k | ffmpeg -hide_banner -nostats -re -fflags +igndts -thread_queue_size 512 -i pipe:0 -fflags +genpts [proper codec setting] -f flv rtmp://127.0.0.1/live/stream

当然,您可以使用任何类型的循环,也可以循环播放播放列表。

  • 我发现mpeg有点稳定,然后输入流为x264
  • 我不知道为什么,但mpeg压缩的最小2个线程效果更好
  • 输入压缩需要比输出帧速率快,所以我们得到足够快的新输入
  • 由于时间戳不连续,我们必须跳过它们并在输出中生成一个新的
  • 缓冲区大小需要足够大,以便循环有足够的时间来获取新剪辑。

我从事基于python的解决方案,尚未完成,但除了一些警告,我的测试流运行了多天:

ffplayout

这使用xml播放列表格式。播放列表是动态的,这样您就可以编辑当前播放列表,更改曲目或添加新曲目。

答案 2 :(得分:1)

答案很晚,但是我最近遇到了与上面的海报完全相同的问题。

我通过使用OBS和OBS Websockets插件解决了这个问题。

首先,立即设置RTMP流应用程序。但流向本地RTMP流。

然后让OBS使用本地RTMP作为源,将此RTMP流作为VLC源层加载。

然后(在您的应用中)使用OBS websockets插件,在视频结束时将VLC源切换为静态黑色视频或PNG文件。下一个视频开始后,再切换回RTMP流。这样可以防止RTMP流在视频结束时停止播放。在短暂的过渡期间,OBS将变黑,但最终的OBS RTMP输出将永远不会停止。

肯定有一种方法可以通过手动设置将中间RTMP服务器推送到最终RTMP服务器来实现,但是我发现使用OBS更容易,而且开销很少。

我希望这对其他人有帮助,这种解决方案一直对我有效。

答案 3 :(得分:0)

需要创建两个播放列表文件,并在每个文件的末尾指定指向另一个文件的链接。

<强> list_1.txt

ffconcat version 1.0
file 'item_1.mp4'
file 'list_2.txt'

<强> list_2.txt

ffconcat version 1.0
file 'item_2.mp4'
file 'list_1.txt'

现在您只需要动态更改下一个播放列表文件的内容。