Android作業ログ

=動画キャプチャ=

 Androidで作ったゲームはインストールの手間があるため、事前に動画でゲーム内容を伝えたい。そのためにゲームの動画をキャプチャしたい。


 普通にやる場合はSepteni Engineer's Blogなどを参考にandroidscreencastを使ってキャプチャすれば良いと思う。しかし、自分の場合はPCが貧弱なのでキャプチャがガタガタになってしまう。また、静止画のキャプチャにもズレが生じる。そこで、今回は自前で毎フレームキャプチャして連番画像として保存し、それをつなげることで動画を作ってみる。音が記録できないけど、このレベルなら後付けでなんとかできるはず。

=静止画キャプチャ=

 まず、OpenGLで描画したもののキャプチャはAndroidのOpenGL ESで地球をこの手に - Schlechte WeltのglReadPixelsあたりや、http://www.saturn.dti.ne.jp/npaka/android/SnapShotEx/index.htmlの保存まわりを参考にしつつ独自に書いた。

//Member
public byte[] m_CaptureBytes;
public Bitmap m_CaptureBitmap;
public ByteBuffer m_CaptureBuffer;
public int m_CaptureCount;

//onSurfaceChanged内
m_CaptureBytes = new byte[4 * width * height];
m_CaptureBuffer = ByteBuffer.wrap(m_CaptureBytes);
m_CaptureBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
m_CaptureCount = 0;

//drawの最後
if(m_CaptureBuffer != null){
	//結果をBufferにコピー
	gl.glReadPixels(0, 0, surfaceWidth, surfaceHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, m_CaptureBuffer);

	//バッファをBitmap化
	m_CaptureBitmap.copyPixelsFromBuffer(m_CaptureBuffer);

	//BitmapをJpeg化
	ByteArrayOutputStream os = new ByteArrayOutputStream();
	m_CaptureBitmap.compress(Bitmap.CompressFormat.JPEG, 80, os);
	byte[] w = os.toByteArray();

	//保存
	if(m_CaptureCount < 100)
	{
		String file_name = Integer.toString(m_CaptureCount++) + ".jpg";

		OutputStream out=null;
		try {
			out=openFileOutput(file_name, Context.MODE_WORLD_READABLE);
			out.write(w,0,w.length);
			out.close();
		} catch (Exception e) {
			try {
				if (out!=null) out.close();
			} catch (Exception e2) {
			}
		}
	}
}


 ただし、このコードだと上下反転した画像が保存されるっぽい。コード側での対応は面倒そうだったので、動画化してから上下反転することにした。

=保存した画像の抜き出し=

 Android内だけで動画まで作れれば良いのだけど、そういう仕組みはなさそう。(MediaRecorderでできれば良かったんだけど)
というわけで、上で作った連番画像をPCにコピーする。


 上の処理では/data/data/(パッケージ名)/files/0.jpg〜99.jpgに最初の100フレーム分の画像が保存される。
ローカルファイルの保存先について | mucchinのAndroid戦記を元に、adbのpullを使ってPCに持ってくる。
自分はパスを通してないので「"C:\Program Files\Android\android-sdk\platform-tools\adb.exe" pull 〜」と直にadbのパスを指定している。
また、どうもローカルファイルはディレクトリまるごとコピーができないようなので、仕方なく以下のようなバッチを作って1つずつコピーするようにした。(バッチについては炎のコマンドプロンプト入門/バッチファイル/繰り返し処理を参考にした)

for /l %%B in (0,1,99) do "C:\Program Files\Android\android-sdk\platform-tools\adb.exe" pull /data/data/showohealer.game.monochroll/files/%%B.jpg D:\screenshot


 ちなみに30FPS&30秒分の録画でも900枚になるので、場合によっては容量的にきついかも。

=連番画像の動画化=

 あとは抜き出した連番画像を動画に変換すれば良い。できればタイトル(一枚絵)を入れたいし、フェードイン・フェードアウトなども設定できればなお良い。

 というあたりで良さそうなツールを探してみたところ、TMPGEncと他の動画編集ソフトを組み合わせれば良さそうだった。(「テキスト動画」だと1つだけでいけそうだったんだけど、画像の一部しか表示されなかったので断念)

 連番画像から動画に変換するのはTMPGEncを使い、連番画像ファイルを動画に変換する方法(TMPG Encを使う) - Poser覚書を参考にして簡単にできた。

 あとはそれをタイトルとかとつなげたりすればOK。Windowsだと「Windowsムービーメーカー」なるものがあるので、これで良いかもしれない。ここから先はもう少し色々と試す予定。