Red5视频流录制正在中断
Posted
技术标签:
【中文标题】Red5视频流录制正在中断【英文标题】:Red5 video stream recording is breaking up 【发布时间】:2012-10-02 11:50:00 【问题描述】:最后,我创建了一个流式视频录像机 flash 应用程序及其简单的 Red5 后端,但 Red5 又一次给我开了个玩笑。大多数情况下,录制的视频已损坏,如果不随机停止 - 恢复,挂出播放器..和我,就无法播放它们。为什么要这样做?
我研究了互联网,发现了这个问题,但没有解决方案!我尝试不录制视频,而是将其切换为直播并附加一个 ffmpeg 来完成这项肮脏的工作,但自然 ffmpeg 无法连接到 red5 输出上的以下错误消息:
执行调用时出错:Service: null Method: play Num Params: 1 0: my_little_stream ... blabla bla
在我尝试集成Xuggler 的东西之前我真的不想问你,我该怎么做,我可以附加ffmpeg 还是red5 服务器中的配置我应该更改.. 或任何事物!谢谢!
编辑:我使用的是 Red5 1.0 RC2
Edit#2:我用 red5 1.0.0rc2 服务器文件从主干源编译了 oflaDemo 应用程序,然后用一个简单的 flex 应用程序创建了一个直播流,只是为了测试 ffmpeg 记录器是否工作。现在它可以连接到red5,但结果是一样的!视频似乎已损坏...
【问题讨论】:
code.google.com/p/red5/issues/detail?id=42#c8 说要修复这个错误,但我对此了解不多。 你能解决这个问题吗?我遇到了完全相同的问题,并且按照您经历的所有步骤(使用 seba.wagner)没有修复! 【参考方案1】:*但是我应该在 packetReceived() 函数中添加什么? *
我将此添加到单独的答案中以正确突出显示:
要将数据包写入磁盘,您需要: 1)数据包, 2) 将数据包转换为 ITag 3) 获取一个ITagWriter的实例
1) 数据包数据 http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/flvrecord/listener/StreamVideoListener.java?view=markup 50号线附近
public void packetReceived(IBroadcastStream broadcastStream,
IStreamPacket streampacket)
streampacket => 要写入磁盘的数据包。
2) 通过将数据包转换为 ITag 来写入数据包
http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/flvrecord/listener/async/StreamVideoWriter.java?view=markup 90ff线左右
IoBuffer data = streampacket.getData().asReadOnlyBuffer();
if (data.limit() == 0)
return;
if (startTimeStamp == -1)
// That will be not bigger then long value
startTimeStamp = streampacket.getTimestamp();
timeStamp -= startTimeStamp;
ITag tag = new Tag();
tag.setDataType(streampacket.getDataType());
// log.debug("data.limit() :: "+data.limit());
tag.setBodySize(data.limit());
tag.setTimestamp(timeStamp);
tag.setBody(data);
writer.writeTag(tag);
3) 获取 Writer 的实例
http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/flvrecord/listener/async/BaseStreamWriter.java?view=markup 90ff线左右
protected ITagWriter writer = null;
private void init() throws IOException
file = new File(OmFileHelper.getStreamsSubDir(this.scope.getName()), this.streamName + ".flv");
IStreamableFileFactory factory = (IStreamableFileFactory) ScopeUtils
.getScopeService(this.scope, IStreamableFileFactory.class,
StreamableFileFactory.class);
if (!this.file.isFile())
// Maybe the (previously existing) file has been deleted
this.file.createNewFile();
else if (!file.canWrite())
throw new IOException("The file is read-only");
IStreamableFileService service = factory.getService(this.file);
IStreamableFile flv = service.getStreamableFile(this.file);
this.writer = flv.getWriter();
所以这是一个艰难的过程。从这个意义上说,您可以继续前进。
http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/data/flvrecord/listener/async/BaseStreamWriter.java?view=markup
类还包含一个队列来收集数据包。
IStreamPacket.getType == 9 是视频,我认为 8 是音频(但您需要验证)。
塞巴斯蒂安
【讨论】:
好的,效果很好!我是根据你的指示和 flvrecord 包制作的。 时间戳是相对于录制开始的。因此,当您按“开始”时,时间戳应该从零开始计数。我认为重要的是当用户按下“开始”而不是第一个数据包实际到达时开始计数,因为如果存在带宽问题,数据包可能永远不会或很晚到达。所以从零开始计数很重要。 我不明白。事实上,它应该是完全相反的方式。原因:正如您已经面对的那样:将数据包写入磁盘比接收数据包要慢更多。这就是为什么您的 red5 应用程序确实变慢了 => 数据包需要写入磁盘。现在:如果您调用“停止”,实际上数据包写入器应该仍在忙于将数据包写入磁盘。你不应该停止它,你应该等到所有数据包都被写入。否则效果将是每次录制结束时可能会丢失 5-20 秒。 这可能是因为您没有捕捉到所有视频帧。你知道:它正在流式传输。因此,如果您附加一个流侦听器,它只会捕获当前数据包。您看到的视频中的图像不会总是发送完整的图像,它将屏幕划分为 xx 个图块,并且只发送变化的图块。如果您附加您的记录器,您必须强制 NetStream 发送整个图像的完整刷新。我在某处看到了一些这样做的代码,但您可能会尝试朝那个方向进行调查。 可能有一个 NetStream 状态事件会引发产生一个“关键帧”。可能还有一种方法可以在客户端中模拟此事件。但我不能告诉你怎么做。您应该打开一个新问题,例如,诸如“如何强制 NetStream 创建关键帧”之类的主题以及您的问题的描述。【参考方案2】:你现在用什么录音方式? Red5中其实有2种方法可以记录: 1) NetStream.record => 这很简单 2) 您执行 NetStream “live”,但您有一个服务器端 StreamListener,您将其附加到流,然后将流写入光盘。
我已在http://incubator.apache.org/openmeetings/ 成功实施了这两种解决方案 没有断断续续的视频或随机停止/暂停。
无需集成 FFMPEG 或 Xuggler 即可使用 Red5 进行简单的录制!如果您想修改生成的视频并添加水印,FFMPEG 可能会很有用。 对于音频编辑,您可以使用 SoX 等工具。然而......只是简单的记录和播放根本不需要这些工具!
塞巴斯蒂安
【讨论】:
感谢您的回答,但您能告诉我更多关于第二种解决方案的信息吗?这不类似于我通过将 ffmpeg 附加到直播流中尝试的方式吗? 不,一点也不。例如这里描述了第二种解决方案sziebert.net/posts/server-side-stream-recording-with-red5 我将我的应用程序修改为第二种方法。我认为它没有解决问题,还有另一个问题,也许这就是这个问题的根源。 another topic可以看看吗? 你能检查一下吗=> 我已经发布了我们为解决服务器端录制中的性能问题而制定的解决方案 好的,现在我开始明白了..:) 我创建了一个 StreamLinstener 并将其添加到流中。但是我应该在 packetReceived() 函数中添加什么?我找到了一些示例代码,但它们太复杂了我无法理解它们..以上是关于Red5视频流录制正在中断的主要内容,如果未能解决你的问题,请参考以下文章
使用 Red5 媒体服务器和 oflaDemo 应用程序提高录制视频的质量
如何防止使用 AVFoundation 录制视频中断当前正在播放的任何全局音频(Swift)?
使用Flex进行网络摄像头录制是否严格要求媒体服务器(FMS,Red5,Wowza等)?