我正在尝试使用 Xuggler 和 YouTube 的直播 API 将视频从我的网络摄像头流式传输到 YouTube。按照此处提供的示例,我成功连接到 YouTube 并创建了广播。
我使用 Xuggler 对视频进行编码,并使用下面的代码将其发送到 YouTube。编码视频的步骤取自此处的帖子。
当我运行我的程序时,我的控制台没有收到任何错误,但流没有在 Youtube 中直播。在 Youtube Live 控制室中,它一直显示一条消息“我们没有从您的编码器接收数据。请确保在 Ingestion Settings 页面中正确配置它。”
我究竟做错了什么?任何帮助或指示将不胜感激......
String url = returnedStream.getCdn().getIngestionInfo().getIngestionAddress();
String fileName = returnedStream.getCdn().getIngestionInfo().getStreamName() ;
IContainer container = IContainer.make();
IContainerFormat containerFormat_live = IContainerFormat.make();
containerFormat_live.setOutputFormat("flv", url + "/"+ fileName, null);
container.setInputBufferLength(0);
int retVal = container.open(url + "/"+ fileName, 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(true);
while (i < framesToEncode) {
//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();
}