Java 无法使用Xuggler通过RTMP向FMS连续发布实时流而不停止
我正在尝试将实时RTMP流视频从link1转发到link2。但当视频在输入端停止或暂停时,我的java应用程序停止读取数据包,并出现错误“无法读取RTMP头数据包”。代码如下所示-Java 无法使用Xuggler通过RTMP向FMS连续发布实时流而不停止,java,android,flash,Java,Android,Flash,我正在尝试将实时RTMP流视频从link1转发到link2。但当视频在输入端停止或暂停时,我的java应用程序停止读取数据包,并出现错误“无法读取RTMP头数据包”。代码如下所示- import com.xuggle.xuggler.ICodec; import com.xuggle.xuggler.IContainer; import com.xuggle.xuggler.IContainerFormat; import com.xuggle.xuggler.IPacket; import c
import com.xuggle.xuggler.ICodec;
import com.xuggle.xuggler.IContainer;
import com.xuggle.xuggler.IContainerFormat;
import com.xuggle.xuggler.IPacket;
import com.xuggle.xuggler.IStream;
import com.xuggle.xuggler.IStreamCoder;
import com.xuggle.xuggler.IVideoPicture;
public class XugglerRecorder
{
public static void main(String[] args)
{
String url = "rtmp://IP:PORT/live2/16_8_2013";
IContainer readContainer = IContainer.make();
readContainer.setInputBufferLength(4096);
IContainer writeContainer=IContainer.make();
//writeContainer.setInputBufferLength(0);
IContainerFormat containerFormat_live = IContainerFormat.make();
containerFormat_live.setOutputFormat("flv","rtmp://IP:PORT/live/abc", null);
int retVal= writeContainer.open("rtmp://192.168.1.198:1935/live/abc", IContainer.Type.WRITE, containerFormat_live);
//writeContainer.setInputBufferLength(0);
if (retVal < 0) {
System.err.println("Could not open output container for live stream");
System.exit(1);
}
if (readContainer.open(url, IContainer.Type.READ, null, true, false) < 0) {
throw new RuntimeException("unable to open read container");
}
IStream video = writeContainer.addNewStream(0);
if (video == null) {
throw new RuntimeException("unable to add video stream");
}
IPacket packet = IPacket.make();
while (readContainer.readNextPacket(packet) >= 0 && !packet.isKeyPacket()) {}
IStreamCoder inVideoCoder = null;
int videoStreamId = -1;
for (int i = 0; i < readContainer.getNumStreams(); ++i) {
IStream stream = readContainer.getStream(i);
IStreamCoder coder = stream.getStreamCoder();
if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) {
inVideoCoder = coder;
videoStreamId = i;
if (inVideoCoder.open(null, null) < 0) {
throw new RuntimeException("Unable to open input video coder");
}
//for getting frame params need to decode at least one key frame
IVideoPicture picture = IVideoPicture.make(inVideoCoder.getPixelType(), 0, 0);
int bytesDecoded = inVideoCoder.decodeVideo(picture, packet, 0);
if (bytesDecoded < 0) {
throw new RuntimeException("Unable to decode video packet");
}
}
}
if (videoStreamId == -1) {
throw new RuntimeException("unable to find video stream");
}
IStreamCoder outVideoCoder = video.getStreamCoder();
outVideoCoder.setCodec(inVideoCoder.getCodec());
outVideoCoder.setHeight(inVideoCoder.getHeight());
outVideoCoder.setWidth(inVideoCoder.getWidth());
outVideoCoder.setPixelType(inVideoCoder.getPixelType());
outVideoCoder.setBitRate(inVideoCoder.getBitRate());
outVideoCoder.setTimeBase(inVideoCoder.getTimeBase());
if (outVideoCoder.open(null, null) < 0) {
throw new RuntimeException("unable to open output video coder");
}
if (writeContainer.writeHeader() < 0) {
throw new RuntimeException("unable to write header");
}
int i = 0;
doit(readContainer, packet, writeContainer);
if (writeContainer.writeTrailer() < 0) {
throw new RuntimeException("unable to write trailer");
}
}
private static void doit(IContainer readContainer, IPacket packet,
IContainer writeContainer) {
int i = 0;
while (readContainer.readNextPacket(packet) >= 0) {
if(readContainer.readNextPacket(packet)<0)
{
System.out.println("Packet null Hello");
try{
doit(readContainer, packet, writeContainer);
}catch(Exception e){e.printStackTrace();}
continue;
}
if(readContainer.readNextPacket(packet)==-1 ){
System.out.println("Packet is absent");
}
if (packet.getStreamIndex() != 0) {
continue;
}
if (writeContainer.writePacket(packet) < 0 && readContainer.readNextPacket(packet)>=0) {
try{
System.out.println(" packet sleep");
}catch(Exception e){e.printStackTrace();}
}
}
}
}
import com.xuggle.xuggler.ICodec;
导入com.xuggle.xuggler.IContainer;
导入com.xuggle.xuggler.IContainerFormat;
导入com.xuggle.xuggler.IPacket;
导入com.xuggle.xuggler.IStream;
导入com.xuggle.xuggler.IStreamCoder;
导入com.xuggle.xuggler.IVideoPicture;
公共类XugglerRecorder
{
公共静态void main(字符串[]args)
{
字符串url=”rtmp://IP:PORT/live2/16_8_2013";
IContainer readContainer=IContainer.make();
setInputBufferLength(4096);
IContainer writeContainer=IContainer.make();
//writeContainer.setInputBufferLength(0);
IContainerFormat containerFormat_live=IContainerFormat.make();
containerFormat_live.setOutputFormat(“flv”),“rtmp://IP:PORT/live/abc“,空);
int retVal=writeContainer.open(“rtmp://192.168.1.198:1935/live/abc,IContainer.Type.WRITE,containerFormat_live);
//writeContainer.setInputBufferLength(0);
如果(返回值<0){
System.err.println(“无法打开实时流的输出容器”);
系统出口(1);
}
if(readContainer.open(url,IContainer.Type.READ,null,true,false)<0){
抛出新的RuntimeException(“无法打开读取容器”);
}
IStream video=writeContainer.addNewStream(0);
如果(视频==null){
抛出新的RuntimeException(“无法添加视频流”);
}
IPacket packet=IPacket.make();
而(readContainer.readNextPacket(packet)>=0&&!packet.iskeyppacket()){}
IStreamCoder inVideoCoder=null;
int videoStreamId=-1;
对于(int i=0;i=0){
if(readContainer.readNextPacket(packet)=0){
试一试{
System.out.println(“数据包睡眠”);
}catch(异常e){e.printStackTrace();}
}
}
}
}
我能够通过RTMP向FMS发布实时视频。但无法在视频流停止或暂停之前存储视频的保存点。如果输入流有任何时间延迟,那么我的应用程序应该继续检查并等待流,而不是停止。
请帮我解决这个问题。提前谢谢
如果您有任何关于如何调试的帮助或提示,我们将不胜感激。我对Xuggler了解不多 您可以尝试捕获异常 或者您可以尝试在main方法中再次调用doit()。假设在这种情况下,若并没有更多的数据包要读取,那个么方法doit()将结束。因此,它不会再次尝试读取 或者您可以尝试添加类似的内容 而(container.readPacket==null){}在doit()的开头,或者我认为应该是 while(container.readPacket!=null){}
尝试不检查isKeyPacket,看看会发生什么。我也在使用同一个应用程序,但我有一个问题,我需要从网络摄像头并排录制视频,我需要将此视频发布到RTMP服务器(wowza媒体服务器)。有可能用上面的帖子吗。