如何在生成视频时在线传输视频以及失败的 CGI 方法
我有一个可以实时生成视频的程序。现在我想在生成该视频时在线流式传输该视频。有人知道一个简单的方法吗?
我正在描述一种我尝试过但没有成功的 CGI 方法,但请注意,我对所有能够实现我的目标的选择持开放态度。我只是想知道是否有人知道为什么我的方法不起作用以及我应该如何修复它,
例如我将内容类型设置为 mpeg,并定期打印 mpeg 文件中的一大块数据。但视频只持续很短的时间并停止播放。我的代码是这样的(Python)。
print "Content-type: video/mpeg"
print
f = open("test2.mpg")
while (True):
st = f.read(1024*1024)
sys.stdout.write(st)
time.sleep(0.5)
虽然这会很好用。我真的不明白为什么这两个程序的输出不同。但显然我不能使用这种方法,因为我不能等到整个文件生成后再读入。
print "Content-type: video/mpeg"
print
f = open("test2.mpg")
print f.read()
I have a program that can generate video in real time. Now I would like to stream this video online while it is being generated. Does anybody know an easy way to do it?
I am describing a CGI approach I tried but did not work, but please note that I am open to all options that would achieve my goal. I am just wondering if anybody knows why my approach doesn't work and how I should fix it
I set the content-type to mpeg for example, and print out a chunk of data in the mpeg file periodically. But the video only lasts for very short amount of time and stop streaming. My code is something like this (in Python).
print "Content-type: video/mpeg"
print
f = open("test2.mpg")
while (True):
st = f.read(1024*1024)
sys.stdout.write(st)
time.sleep(0.5)
Though this would work fine. I really don't see why the output of these two programs are different. But obviously I can't use this approach since i can't wait until the entire file is generated before reading in.
print "Content-type: video/mpeg"
print
f = open("test2.mpg")
print f.read()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
test2.mpg
是什么类型的文件?如果它是
mpeg4
文件,您的方法将不起作用,因为文件的开头或结尾处将包含标头。如果您的文件是 mpeg2 传输流,那么这应该可以工作。
What type of file is
test2.mpg
?If it's an
mpeg4
file your approach won't work because you will have headers at the start or end of the file.If your file is an
mpeg2
transport stream, then this should work.您可能遇到了文件结尾,因此您的循环失败,要么出现 EOFError,要么在某个地方崩溃。如果视频是实时生成的,除非 test2.mpg 是一个 FIFO 管道(使用 mkfifo 创建 - 在这种情况下一次只能有一个读取器) - 从管道读取可能不会返回任何数据,并且你的循环的运行速度可能比保存视频数据的速度快得多。所以你需要一个处理 EOF 的策略。
另外,您需要确保刷新输出——无论是在该程序中的 sys.stdout.write() 行之后,还是在另一个程序中的视频流之后。由于您的循环没有结束条件,也没有输出,并且您可能永远不会最终写入任何数据,因此可能在循环的一次迭代之后出现故障,并且网络服务器会丢弃缓冲的数据。
此外,一次读取 1MB 的恒定大小可能会导致延迟问题。为了获得更好的延迟,最好使用较小的尺寸;但是,为了获得更好的质量和吞吐量,您可以使用更大的尺寸。然而,如果生成视频的程序、您的 cgi 脚本或网络服务器没有定期刷新,那么延迟点就没有意义。
我还建议研究“select”或“poll”/epoll——这两种方法都可以让您更好地控制读取,并且可以通过休眠直到数据可用来帮助您解决文件结尾问题。如果您发现自己需要睡眠(0.5),那么正确使用 select/poll 可能会更好。
You're probably hitting end-of-file and so your loop is failing, either with EOFError or crashing somewhere. If the video is being generated in real time, unless test2.mpg is a FIFO pipe (created using mkfifo -- in which case you can only have one reader at a time) -- reading from the pipe may return no data, and your loop is likely to run much, much faster than your video data is being saved. So you need a strategy to handle EOF.
Also, you need to make sure to flush your output -- both after the sys.stdout.write() line in this program, and after the video stream in the other program. Since your loop has no end condition and no output, and you may never end up writing any data, it could be that after one iteration of the loop, something fails, and the webserver discards the buffered data.
Additionally, reading a constant size of 1MB at a time may cause latency issues. For better latency, it's good to use smaller sizes; however, for better quality and throughput, you can use larger sizes. However, the latency point is moot if the program generating the video, your cgi script, or the webserver aren't all flushing at regular intervals.
I'd also suggest looking into "select" or "poll"/epoll -- either of those methods will give you better control over reading, and might help you solve the end-of-file issue by sleeping until data is available. If you find yourself needing to sleep(0.5), you might be better off using select/poll correctly.