ユーザーが特定のアクティビティを実行しているときに、ユーザーの画面、ウェブカメラ、マイクを記録するアプリケーションに取り組んでいます。研究目的で利用させていただきます。このアプリケーションは Windows で正常にテストされていますが、Mac OS X (Maverick with ) では、記録を開始するとJava 7.0.45
アプリケーションが遅くなり、応答しなくなります。
これが私がこれを理解するのが難しいと思う理由です:
- 記録は別のスレッドで行われますが、別のスレッドの応答性にどのように影響するのでしょうか? 特に、各実行後に
Thread.yield()
orThread.sleep(...)
が呼び出されるように。 - ログは、 で記録しようとしたとき
15 FPS
に、結果のフレーム レートが であったことを示してい2 FPS
ます。そのため、単一フレームのキャプチャを行うコードが遅すぎる可能性があります。しかし、なぜWindowsでうまく動作するのでしょうか?
簡単なメモ: このアプリケーションは、Windows の多数のユーザーによって正常にテストされましたが、1 台の Mac でしかテストできませんでした。ただし、それはフォーマットされたばかりで、OS X Maverick、Java (および Netbeans) がクリーン インストールされています。
以下に、画面を記録し、Xugglerを使用してビデオに書き込むコードを示します。ウェブカメラを記録するためのコードは似ていますが、音声を記録することと関係があるとは思えません。私の質問は:
アプリケーションが応答しなくなる原因は何ですか? 、 と
コードをより効率的にして FPS を改善するにはどうすればよいでしょうか?
IMediaWriter writer = ToolFactory.makeWriter(file.getAbsolutePath());
Dimension size = Globals.sessionFrame.getBounds().getSize();
Rectangle screenRect;
BufferedImage capture;
BufferedImage mousePointImg;
writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, size.width, size.height);
int i = 0;
while (stop == false) {
// Get mouse cursor to draw over screen image.
PointerInfo mousePointer = MouseInfo.getPointerInfo();
Point mousePoint = mousePointer.getLocation();
Point screenPoint = new Point((int) (mousePoint.getX() -
Globals.sessionFrame.getBounds().getX()), (int) (mousePoint.getY() -
Globals.sessionFrame.getBounds().getY()));
// Get the screen image.
try {
screenRect = new Rectangle(Globals.sessionFrame.getBounds());
capture = new Robot().createScreenCapture(screenRect);
} catch ( ... ) { ... }
// Convert and resize the screen image.
BufferedImage image = ConverterFactory.convertToType(capture,
BufferedImage.TYPE_3BYTE_BGR);
IConverter converter = ConverterFactory.createConverter(image,
IPixelFormat.Type.YUV420P);
// Draw the mouse cursor if necessary.
if (mouseWithinScreen()) {
Graphics g = image.getGraphics();
g.drawImage(mousePointImg, (int) screenPoint.getX(),
(int) screenPoint.getY(), null);
}
// Prepare the frame.
IVideoPicture frame = converter.toPicture(image, (System.currentTimeMillis() -
startTimeMillis()) * 1000);
frame.setKeyFrame(i % (getDesiredFPS() * getDesiredKeyframeSec()) == 0);
// Write to the video
writer.encodeVideo(0, frame);
// Delay the next capture if we are at the desired FPS.
try {
if (atDesiredFPS()) {
Thread.yield();
} else {
Thread.sleep(1000 / getDesiredFPS());
}
} catch ( ... ) { ... }
i++;
}
writer.close();