30

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,我已经尝试过它并没有很好地工作,因为ffmpeg它不仅在新的时候关闭 RTMP 流视频来了,但也会自行关闭。

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

4

4 回答 4

9

更新(因为我无法删除已接受的答案):正确的解决方案是实现一个自定义解复用器,类似于 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. 被愤怒的系统管理员追赶并骂人

于 2015-03-14T14:57:24.670 回答
5

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

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'

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

于 2018-03-01T06:41:03.583 回答
3

您可以将循环通过管道传输到缓冲区,然后从该缓冲区传输到流实例。

在 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播放列表格式。播放列表是动态的,您可以随时编辑当前播放列表,更改曲目或添加新曲目。

于 2018-02-02T10:42:58.593 回答
1

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

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

首先,像现在一样设置您的 RTMP 流媒体应用程序。但流到本地 RTMP 流。

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

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

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

我希望这对其他人有所帮助,这个解决方案对我来说非常有效。

于 2020-02-04T21:55:14.400 回答