こんにちは、なんとか 30 fps でビデオを撮影できました。または、私のアイデアから 60 fps でビデオを取得することもできます。ビデオは非常にスムーズです。
興味のある方はこちらをチェックしてみてください。
アイデアは単純で、60fps または 29.97fps (私のビデオ) のすべてのフレームのスクリーン ショットが必要です。
3 つの手順で実行します: 1) 画面のデルタ時間として 1/60 ですべてをレンダリングします。
2) すべてのフレームのスクリーンショットを撮る
3)これらすべてのpngファイルのビデオを作成します(私はAdobe Premier Proを使用しています)
ステップ 1) libgdx で Game クラスを拡張し、新しいクラス MyGame extends Game または class MyGame extends ApplicationListener を作成し、一時的に使用するためにレンダリング メソッドを変更します
ScreenShotUtils screenShotUtils=new ScreenShotUtils();
@Override
public void render () {
//if (screen != null) screen.render(Gdx.graphics.getDeltaTime());
//write your video fps as 1f/29.97f or 1f/30f
if (screen != null){
screen.render(1f/60f);
screenShotUtils.update();
}
}
ステップ 2) ScreenShotUtils クラスのキャプチャ メソッドを使用してスクリーンショットをキャプチャする キャプチャが必要な場合はキャプチャ メソッドを呼び出します
//call on start click
screenShotUtils.capture(true);
//call on stop click
screenShotUtils.capture(false);
注: キャプチャを開始すると、ゲームが遅延し、非常に遅くなりますが、レンダリング デルタ時間により、UI が 60 fps 未満で更新されず、スクリーンショットが 60 fps で取得され、この遅延中にゲームがプレイされます。ビデオのパブリッシング中にスムーズな画像シーケンスが得られます
public class ScreenShotUtils {
String filefolder="D:/capturefolder";// your folder to put the images in
String filenameprefix="";
int frameid=0,captureLimit=-1;
private boolean isCapturing=false;
public void setCaptureLimit(int frames){
captureLimit=frames;
}
public boolean isCapturing(){
return isCapturing;
}
public void capture(boolean capture){
if(capture){
if(!isCapturing) {
isCapturing = true;
filenameprefix="Demo"+System.currentTimeMillis();//Images Prefix
frameid=0;
}
}else{
isCapturing=false;
captureLimit=-1;
frameid=0;
}
}
public void capture(boolean capture, int frames){
if(capture){
if(!isCapturing) {
isCapturing = true;
filenameprefix="Demo"+System.currentTimeMillis();//Images Prefix
frameid=0;
}
captureLimit=frames;
}else{
isCapturing=false;
captureLimit=-1;
frameid=0;
}
}
public void update() {
// render before capturing
if(isCapturing) {
if(captureLimit<0)
saveScreenshot();
else
if(captureLimit==0){
isCapturing = false;
captureLimit=-1;
}else{
saveScreenshot();
captureLimit--;
}
}
}
private void saveScreenshot() {
int MAX_DIGITS = 6;
String fname = "" + (frameid++);
int zeros = MAX_DIGITS - fname.length();
for (int i = 0; i < zeros; i++) {
fname = "0" + fname;
}
FileHandle file = new FileHandle(filefolder+"/"+filenameprefix +"-"+ fname+".png");
Pixmap pixmap = getScreenshot(0, 0, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight(), true);
PixmapIO.writePNG(file, pixmap);
pixmap.dispose();
}
private Pixmap getScreenshot(int x, int y, int w, int h, boolean flipY) {
Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1);
Pixmap pixmap = new Pixmap(w, h, Pixmap.Format.RGB888);
ByteBuffer pixels = pixmap.getPixels();
Gdx.gl.glReadPixels(x, y, w, h, GL20.GL_RGB, GL20.GL_UNSIGNED_BYTE, pixels);
if (flipY) {
final int numBytes = w * h * 3;
byte[] lines = new byte[numBytes];
final int numBytesPerLine = w * 3;
for (int i = 0; i < h; i++) {
pixels.position((h - i - 1) * numBytesPerLine);
pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
}
pixels.clear();
pixels.put(lines);
}
return pixmap;
}
}
3) 動画作成には Adobe Premier Pro を使用しました。他のツールを使用して Google 検索 (画像シーケンスを動画に変換)
https://helpx.adobe.com/premiere-pro/using/importing-still-images.html
セクション:イメージをイメージ シーケンスとしてインポートする
注:アルファビットが画像の境界線をいじっていたので、RGBAではなくRGB形式のスクリーンショットを使用しています。あなたはそれを試すことができます
さらに、ファイルを Android SD カードに保存するようにコードを変更することもできます。私はデスクトップ バージョンを使用しました。saveScreenshot メソッドのファイル ハンドルを変更するだけです。
免責事項: 私は screnshot コードを使用し、この Web サイトhttp://www.wendytech.de/2012/07/opengl-screen-capture-in-real-time/から変更しました。