问题
I am working on YouTube broadcasting Java program. So far, I can create live event
using this program:
https://github.com/youtube/api-samples/tree/master/java
For more detail what I am getting so far, please see my another question:
https://stackoverflow.com/questions/30449366/how-to-send-video-stream-for-live-event-using-youtube-broadcast-in-java
Now, the next thing is I want to create a video stream which will be passed to live streaming YouTube APIs so that my video will be broadcasting as Live Event on YouTube.
For this, I am using Xuggler library 5.2. However, when I try to run sample program for Xuggler so I get following message and neither works anything nor my webcam starts.
Source code:
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamResolution;
import com.xuggle.xuggler.ICodec;
import com.xuggle.xuggler.IContainer;
import com.xuggle.xuggler.IContainerFormat;
import com.xuggle.xuggler.IPacket;
import com.xuggle.xuggler.IPixelFormat;
import com.xuggle.xuggler.IRational;
import com.xuggle.xuggler.IStream;
import com.xuggle.xuggler.IStreamCoder;
import com.xuggle.xuggler.IVideoPicture;
import com.xuggle.xuggler.video.ConverterFactory;
import com.xuggle.xuggler.video.IConverter;
public class HelloWorld {
public static void main(String[] args) {
IContainer container = IContainer.make();
IContainerFormat containerFormat_live = IContainerFormat.make();
containerFormat_live.setOutputFormat("flv", "rtmp://a.rtmp.youtube.com" + "/"+ "live2", null);
container.setInputBufferLength(0);
int retVal = container.open("rtmp://a.rtmp.youtube.com" + "/"+ "live2", IContainer.Type.WRITE, containerFormat_live);
if (retVal < 0) {
System.err.println("Could not open output container for live stream");
System.exit(1);
}
Dimension size = WebcamResolution.QVGA.getSize();
IStream stream = container.addNewStream(0);
IStreamCoder coder = stream.getStreamCoder();
ICodec codec = ICodec.findEncodingCodec(ICodec.ID.CODEC_ID_H264);
coder.setNumPicturesInGroupOfPictures(4);
coder.setCodec(codec);
coder.setBitRate(500000);
coder.setPixelType(IPixelFormat.Type.YUV420P);
coder.setHeight(size.height);
coder.setWidth(size.width);
System.out.println("[ENCODER] video size is " + size.width + "x" + size.height);
coder.setFlag(IStreamCoder.Flags.FLAG_QSCALE, true);
coder.setGlobalQuality(0);
IRational frameRate = IRational.make(24, 1);
coder.setFrameRate(frameRate);
coder.setTimeBase(IRational.make(frameRate.getDenominator(), frameRate.getNumerator()));
coder.open();
container.writeHeader();
long firstTimeStamp = System.currentTimeMillis();
long lastTimeStamp = -1;
int i = 0;
try {
// Robot robot = new Robot();
Webcam webcam = Webcam.getDefault();
webcam.setViewSize(size);
webcam.open();
while (i < 100000000) {
//long iterationStartTime = System.currentTimeMillis();
long now = System.currentTimeMillis();
//grab the screenshot
BufferedImage image = webcam.getImage();
//convert it for Xuggler
BufferedImage currentScreenshot = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
currentScreenshot.getGraphics().drawImage(image, 0, 0, null);
//start the encoding process
IPacket packet = IPacket.make();
IConverter converter = ConverterFactory.createConverter(currentScreenshot, IPixelFormat.Type.YUV420P);
long timeStamp = (now - firstTimeStamp) * 1000;
IVideoPicture outFrame = converter.toPicture(currentScreenshot, timeStamp);
if (i == 0) {
//make first frame keyframe
outFrame.setKeyFrame(true);
}
outFrame.setQuality(0);
coder.encodeVideo(packet, outFrame, 0);
outFrame.delete();
if (packet.isComplete()) {
container.writePacket(packet);
System.out.println("[ENCODER] writing packet of size " + packet.getSize() + " for elapsed time " + ((timeStamp - lastTimeStamp) / 1000));
lastTimeStamp = timeStamp;
}
System.out.println("[ENCODER] encoded image " + i + " in " + (System.currentTimeMillis() - now));
i++;
try {
Thread.sleep(Math.max((long) (1000 / frameRate.getDouble()) - (System.currentTimeMillis() - now), 0));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
On running, getting this message:
23:13:38,807 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
23:13:38,808 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]
23:13:38,811 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Setting up default configuration.
23:13:38,878 |-WARN in ch.qos.logback.core.ConsoleAppender[console] - This appender no longer admits a layout as a sub-component, set an encoder instead.
23:13:38,878 |-WARN in ch.qos.logback.core.ConsoleAppender[console] - To ensure compatibility, wrapping your layout in LayoutWrappingEncoder.
23:13:38,878 |-WARN in ch.qos.logback.core.ConsoleAppender[console] - See also http://logback.qos.ch/codes.html#layoutInsteadOfEncoder for details
23:13:46.644 [main] ERROR org.ffmpeg - RTMP_ReadPacket, failed to read RTMP packet header
Could not open output container for live stream
23:13:46.650 [main] ERROR com.xuggle.xuggler - URL: rtmp://a.rtmp.youtube.com/live2; Error: could not open file (../../../../../../../csrc/com/xuggle/xuggler/Container.cpp:516)
I don't understand what's going wrong. Why my webcam won't start?
回答1:
Read manifest file (MANIFEST.MF) of xuggler library 5.2 jar for correct version of dependency jars, collect correct version jars and add them in the class path to resolve the dependency and version issues.
来源:https://stackoverflow.com/questions/30489734/could-not-open-output-container-for-live-stream