我正在尝试找到流式传输Java应用程序中生成的实时视频的方法。该应用程序需要获取其自身的屏幕截图,并将其编码为视频流,然后发布该流。
到目前为止,我一直在使用Xuggler(FFMPEG之上的Java库)将屏幕截图编码为视频文件。这很好。Xuggler声称能够通过RTMP传输实时视频,但是我还没有找到任何有关如何以编程方式进行此操作的文档。
我确实在这里的Xuggler论坛上发现其他人在问一个非常类似的问题,但没有任何回应。
我研究了JMF,由于其他原因,它不是一个选择。
import com.xuggle.xuggler.Configuration;
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;
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class XugglerRtmpReferenceImpl {
private static String url = "rtmp://your.test.server/screen/";
private static String fileName = "test/teststream";
private static int framesToEncode = 60;
private static int x = 0;
private static int y = 0;
private static int height = 480;
private static int width = 640;
public static void main(String[] args) {
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);
}
IStream stream = container.addNewStream(0);
IStreamCoder coder = stream.getStreamCoder();
ICodec codec = ICodec.findEncodingCodec(ICodec.ID.CODEC_ID_H264);
coder.setNumPicturesInGroupOfPictures(5);
coder.setCodec(codec);
coder.setBitRate(200000);
coder.setPixelType(IPixelFormat.Type.YUV420P);
coder.setHeight(height);
coder.setWidth(width);
System.out.println("[ENCODER] video size is " + width + "x" + height);
coder.setFlag(IStreamCoder.Flags.FLAG_QSCALE, true);
coder.setGlobalQuality(0);
IRational frameRate = IRational.make(5, 1);
coder.setFrameRate(frameRate);
coder.setTimeBase(IRational.make(frameRate.getDenominator(), frameRate.getNumerator()));
Properties props = new Properties();
InputStream is = XugglerRtmpReferenceImpl.class.getResourceAsStream("/libx264-normal.ffpreset");
try {
props.load(is);
} catch (IOException e) {
System.err.println("You need the libx264-normal.ffpreset file from the Xuggle distribution in your classpath.");
System.exit(1);
}
Configuration.configure(props, coder);
coder.open();
container.writeHeader();
long firstTimeStamp = System.currentTimeMillis();
long lastTimeStamp = -1;
int i = 0;
try {
Robot robot = new Robot();
while (i < framesToEncode) {
//long iterationStartTime = System.currentTimeMillis();
long now = System.currentTimeMillis();
//grab the screenshot
BufferedImage image = robot.createScreenCapture(new Rectangle(x, y, width, height));
//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 (AWTException e) {
e.printStackTrace();
}
container.writeTrailer();
}
}
我有一个EXE,用python编写,然后将其转换为exe,当我运行exe direclty时,我可以在控制台实时看到输出,但当我在java中运行exe时,我看不到输出,直到exe完成过程。 我有在线搜索,但没有什么是工作,这里是示例代码。 公共类FaceAnalysis实现了AILibrary{私有静态最终记录器log=LoggerFactory.getLogger(FaceAnalysis.cl
问题内容: 是否有使用Java直播视频的良好库?理想情况下,管道的两端都应使用Java编写,但我最关心的是视频播放器。您会推荐什么软件? 更新 :似乎VLC引入了1-2秒的延迟。我需要真正的实时视频流。记录到播放的延迟必须小于300ms。 问题答案: 我见过的最好的视频播放/编码库是ffmpeg。它播放您扔给它的所有内容。(它是MPlayer使用的。)它是用C编写的,但是我发现了一些Java包装器
问题内容: 用代码退出Java应用程序的最佳方法是什么? 问题答案: 您可以用于此目的。 根据oracle的Java 8文档: 终止当前正在运行的Java虚拟机。参数用作状态码;按照惯例, 非零状态代码表示异常终止 。 此方法在类Runtime中调用exit方法。此方法永远不会正常返回。 该调用实际上等效于该调用:
我用于处理和文件的一般java代码是: 我必须处理3.0版本的才能使用以下函数: parse-xml-fragment() 预期产出: 谁能提供一个解决方案吗?
问题内容: 如何从Java应用程序中打开和关闭监视器? 如果您想知道为什么,这是一个自助服务终端样式的应用程序,晚上最好关闭显示器。是的,您可以在计算机的屏幕保护程序设置中执行此操作,但是最好以编程方式执行此操作,而不必在每台计算机上进行配置。 问题答案: 假设您在Windows上部署Java应用程序,则可以使用以下WIN32API函数: 然后,为调用上述功能的函数编写一个C-JNI小型包装器,并
问题内容: 我尝试使用下面的代码来运行我从Apple脚本创建的独立实用程序应用程序,但是出现“无文件或目录不存在”错误。 我在项目,dist,父目录中放置了相同的副本(用于测试),但没有帮助。 因此,我的问题是:我对运行该应用程序的调用是否不好(也许是因为它不是Windows exe)?如何从Java运行Mac App? 谢谢 问题答案: Mac App Bunde不是可执行文件,而是具有特殊结构