2012-07-25 177 views
17

ffmpeg将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中,我已经尝试过了,它不能正常工作,因为ffmpeg不仅在关闭RTMP视频流时关闭了新视频,而且还关闭了它自己。

有没有办法做到这一点? (流的视频动态播放列表与ffmpeg到RTMP服务器,而无需连接中断

+1

使用命名管道是正确的选择。你能详细说明这不适合你吗? – blahdiblah 2012-07-25 22:13:43

+0

@blahdiblah我使用了命名管道作为ffmpeg的输入,ffmpeg暂停并等待管道中的一些数据,然后我尝试了'cat video.mp4> fifo'和ffmpeg开始流式传输并在流式传输视频后退出。我认为我不知道如何使用正确的方式命名管道,当我做'cat video1.mp4 video2.mp4> fifo' ffmpeg显示错误'流4,偏移0x1d83c:部分文件'后流第一个视频。我知道这是我做错了,我必须通过管道以适当的方式传递视频数据。 – KKetch 2012-07-26 07:41:11

+1

我设法通过使用每个视频管道(ex vid1.mp4 - > pipe1,vid2.mp4 - > pipe2等)来流式传输视频的静态播放列表。然后我写入一个名为管道“流”的流,这种方式'cat pipe1 pipe2 pipe3> stream',并且我使用流管道作为FFMPEG中的输入来发布我的流,但是因为我正在寻找一个动态播放列表**我发送更多视频到“流”管道,以保持该流?**我还没有弄清楚。 (注意,除了第一个视频,我不得不使用tail命令剪切每个视频文件的元数据以获得这个工作) – KKetch 2012-07-28 14:53:07

回答

6

更新(因为我不能删除接受的答案):适当的解决方案是实现一个自定义解复用器,类似于CONCAT之一。目前还没有任何其他清洁的方式。你必须让你的手脏与代码!

下面是一个丑陋的黑客攻击,这是一个非常糟糕的方式做到这一点,只是不!

解决方案使用串联分路器并假定您的所有源媒体文件es使用相同的编解码器。这个例子是基于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. 被愤怒的系统管理员

+0

谢谢,刚才看到你的回答。我早先就用hinekyle的评论来解决它,即使我现在对这类黑客不感兴趣 – KKetch 2015-09-01 13:59:24

+0

你能详细说明你的意思吗?制作一个跟踪你当前播放列表索引并创建符号链接的脚本,为current_index + 1'飞行?这是为了什么目的? – chovy 2016-12-10 02:08:10

+0

试图为.m3u8 24/7流做同样的事情。但命令'-c copy output -f mpegts stream.m3u8'会引发错误。 – chovy 2016-12-10 02:56:54

0

可以通过管道将你的循环到缓冲区获取追逐和叫名字,从这个缓冲你管你流实例。

在外壳它会是什么样子:

#!/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的输入流
  • 我不知道为什么,但最少2个线程的MPEG压缩效果更好
  • 输入压缩需要以便输出帧速率更快,所以我们得到足够快的新输入
  • 由于非持续时间戳,我们必须忽略它们并在输出中生成一个新的输入
  • 缓冲区大小需要足够大让循环有足够的时间来获得新的剪辑。

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

ffplayout

这将使用XML格式的播放列表。播放列表是动态的,您可以随时编辑当前播放列表,并更改曲目或添加新曲目。

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' 

现在,所有你需要的是动态地改变下一个播放列表文件的内容。

相关问题