capturing-screenshots-and-screenrecord について
ADB で PNG スクリーンショットや MP4 録画を取得し、JUnit4 のテスト失敗時に画像とログを集める Android 開発者向けのスキルです。バイナリ出力の破損防止、録画の制約、失敗時だけの収集方法を扱います。
主な機能
- 01ADB による PNG 撮影
- 02画面の MP4 録画
- 03JUnit4 失敗時の画像とログ収集
- 04バイナリ出力の破損防止
- 05録画時間と停止方法の制約
活用シーン
- 01失敗した CI テストの画像と logcat の保存
- 02基準端末からのビジュアル回帰画像作成
- 03QA 再現動画の録画とログ照合
- 04Windows CI での画像ストリーム破損の修正
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ skydoves/ android-testing-skills --skill capturing-screenshots-and-screenrecordインストール後、Claude Code で/capturing-screenshots-and-screenrecordを入力して読み込まれたか確認します。
詳細
スクリーンショットと画面録画のキャプチャ — テスト用の視覚的成果物
このスキルでは、adb を通じてデバイスから PNG スクリーンショットや MP4 画面録画を取得する方法と、テスト失敗時にキャプチャする JUnit4 TestWatcher パターンを扱います。Android Studio のスクリーンショットツール、Compose の captureToImage()、サードパーティ製ストリーミングツール(scrcpy/Vysor)は対象外です。
このスキルを使用する場面
- 不安定な CI テストで、失敗した瞬間のスクリーンショットと logcat ダンプが必要な場合。
- チームがビジュアルリグレッション用に、参照デバイスからゴールデンスクリーンショットを生成する場合。
- QA がバグ報告に添付するため、バグの再現手順を 30 秒間録画する必要がある場合。
- 開発者の
adb shell screencap /sdcard/out.pngが破損ファイルを生成する場合 —-pフラグがないため、PNG ではなく生の RGBA が書き込まれています。 - Windows の CI エージェントで CRLF による破損が発生したスクリーンショットを受け取る場合 —
adb exec-out screencap -pが解決策です。
このスキルを使用しない場面
captureToImage()/ Roborazzi / Paparazzi を使った Compose レベルのスクリーンショットテスト。これらはユニットテストの仕組みであり、ADB ではなく Compose のセットに属します。- デバイスを継続的にライブミラーリングする場合(プレゼンテーション、デモ)。scrcpy または Vysor を使用してください —
screenrecordではストリーミングできません。 - 先にデバイスを操作する場合(タップ、キーイベント)。
../../control/injecting-input-and-state/SKILL.mdを使用してください。 - ファイル全般を取得する場合(スクリーンショット以外)。
../../transfer/extracting-test-artifacts/SKILL.mdを使用してください。
前提条件
adb get-stateがdeviceを返すこと。../../devices/connecting-to-devices/SKILL.mdを参照してください。screenrecordを使用する場合:デバイスが API 19 以降(Android 4.4)であること —screenrecordは KitKat で追加されました。screenrecordと Wear OS の組み合わせ:サポートされていません。このユーティリティは実行を拒否します(developer.android.com/tools/adb#screenrecord)。- API 30 以降で
/sdcard/に書き込む場合:スコープ付きストレージのルールが適用されます。shellユーザーは引き続き FUSE/sdcardfs にアクセスできますが、アプリのプライベート領域への書き込みは/sdcard/Android/data/<pkg>/に振り分けられます。
screencap — PNG スクリーンショット
「
screencapコマンドは、デバイスのディスプレイのスクリーンショットを撮影するためのシェルユーティリティです。」— developer.android.com/tools/adb#screencap
screencap [-h] [-p] [-d <displayId>] [<path-on-device>]
| フラグ | 意味 |
|---|---|
| (フラグなし) | 生の RGBA フレームバッファーをファイルに書き込みます。PNG ではありません。 |
-p | PNG としてエンコードします。ホストへのストリーミング時に必須です。 |
-d <displayId> | 特定の論理ディスプレイをキャプチャします(マルチディスプレイデバイス)。 |
-h | ヘルプ。 |
よく使われる 3 つの呼び出し方:
# 1. Save to device, then pull (good when the test continues running).
adb shell screencap -p /sdcard/screen.png
adb pull /sdcard/screen.png ./screen.png
# 2. Stream PNG bytes back to host without an intermediate file.
adb exec-out screencap -p > screen.png
# 3. Multi-display capture: external display + main.
adb shell screencap -p -d 0 /sdcard/main.png
adb shell screencap -p -d 1 /sdcard/external.png
exec-out と shell — バイナリデータが破損する落とし穴
adb shell はデフォルトで PTY を設定するため、一部のホスト(特に Windows)では、出力時に \n が \r\n に変換されます。バイナリストリーム(PNG、MP4、tar アーカイブ)では、これによってファイルが破損します。adb exec-out は、標準出力をバイナリデータのまま扱う形式です。
手順 — Windows でストリーミングする場合は、adb shell screencap -p > out.png を決して使用しないでください。必ず次を使用してください。
adb exec-out screencap -p > out.png
デバイス上にファイルを書き込んでから取得する場合、この問題は発生しません(adb pull はバイナリデータをそのまま扱います)。
screenrecord — MP4 画面録画
「
screenrecordコマンドは、Android 4.4(API レベル 19)以降を搭載したデバイスのディスプレイを録画するためのシェルユーティリティです。このユーティリティは、画面上の動作を MPEG-4 ファイルに記録します。」— developer.android.com/tools/adb#screenrecord
screenrecord [--size WIDTHxHEIGHT] [--bit-rate RATE] [--time-limit TIME]
[--rotate] [--bugreport] [--verbose] <path-on-device>
| フラグ | 意味(developer.android.com/tools/adb#screenrecord の原文) |
|---|---|
--help | 「コマンド構文とオプションを表示します」。 |
--size WxH | 「動画サイズを設定します。デフォルト値は、デバイスのネイティブディスプレイ解像度(サポートされている場合)、非対応の場合は 1280x720 です」。 |
--bit-rate R | 「動画のビットレートをメガビット/秒単位で設定します。デフォルト値は 20Mbps です」。 |
--time-limit T | 「最大録画時間を秒単位で設定します。デフォルト値および最大値は 180(3 分)です」。 |
--rotate | 「出力を 90 度回転します。この機能は試験的なものです」。 |
--bugreport | バグ報告への添付に使用するテキスト形式のフレーム情報/タイムスタンプのオーバーレイを埋め込みます。 |
--verbose | 「コマンドライン画面にログ情報を表示します」。 |
厳格な制限(原文のまま)
- 「音声は動画ファイルに録音されません。」
- 「Wear OS を実行しているデバイスでは、動画を録画できません。」
- 「デバイスによっては、ネイティブのディスプレイ解像度で録画できない場合があります。画面録画で問題が発生した場合は、画面解像度を下げてみてください。」
- 「録画中の画面回転はサポートされていません。」
- デフォルトおよび最大の制限時間は180 sです。より長いシナリオをキャプチャするには、複数回の呼び出しを連結して後から結合するか、scrcpyを使用してください。
ストリーミングフラグなし — 制限事項
screenrecord はデバイス側のパスに単一の MP4 を書き込みます。標準出力にはストリーミングしません。ライブミラーリング(プレゼンテーション、デモ)には、scrcpy または Vysor を使用してください(このスキルの対象外です。どちらも screenrecord を完全に迂回します)。
出力パス
| パス | 使用する場合 |
|---|---|
/sdcard/run.mp4 | デフォルトです。ユーザーから見える動画です。API 30 以降ではスコープストレージのルールが適用されますが、shell ユーザーは FUSE/sdcardfs にアクセスできます。 |
/data/local/tmp/run.mp4 | SD カードがマウントされる前にテストアプリが出力を生成する必要がある場合、またはパブリックストレージに触れないようにする場合に使用します。常に shell で pull できます。 |
早めに停止する
screenrecord は --time-limit が経過するか、SIGINT を受信するまで実行されます。対話型シェルでは Ctrl+C を押します。スクリプトからは、デバイス上のプロセスにシグナルを送信します。
adb shell screenrecord --time-limit 180 /sdcard/run.mp4 &
REC=$!
# … run instrumentation; on failure, send SIGINT to the on-device process …
adb shell pkill -INT screenrecord
wait $REC
adb pull /sdcard/run.mp4 ./run.mp4
--bugreport オーバーレイ
--bugreport は各フレームにフレーム情報とタイムスタンプのオーバーレイを追加します。バグレポート側のタイムスタンプを logcat と一致させる必要がある QA の再現確認に便利です。adb logcat -v threadtime,year,UTC と組み合わせると、フレーム番号とログ行を照合できます(../../observability/extracting-logs-with-logcat/SKILL.md を参照)。
失敗時キャプチャのパターン(JUnit4 TestWatcher)
標準的なパターンは、TestRule または TestWatcher がテスト失敗時に failed() を実行し、screencap と logcat -d を実行して、アーティファクトをテストごとのディレクトリに pull する方法です。
class CaptureOnFailureRule(private val outputDir: File) : TestWatcher() {
override fun failed(e: Throwable, description: Description) {
val testName = "${description.className}.${description.methodName}"
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
val target = File(outputDir, testName).apply { mkdirs() }
// PNG screenshot
device.executeShellCommand("screencap -p /sdcard/fail.png")
device.executeShellCommand("logcat -d -v threadtime").let { log ->
File(target, "logcat.txt").writeText(log)
}
// The test process can pull /sdcard/fail.png via Context.getExternalFilesDir
// or push through TestStorageService — see ../../transfer/extracting-test-artifacts/SKILL.md.
}
}
CI スクリプトでのホスト側の同等の方法(完全版は ../../automation/scripting-adb-for-ci/SKILL.md を参照):
set +e
./gradlew connectedDebugAndroidTest
RC=$?
set -e
if [ "$RC" -ne 0 ]; then
mkdir -p artifacts
adb shell screencap -p /sdcard/fail.png
adb pull /sdcard/fail.png artifacts/fail.png
adb logcat -d -v threadtime > artifacts/logcat.txt
adb logcat -d -b crash -v threadtime > artifacts/crash.txt
fi
exit $RC
これにより、失敗時にのみデバイスの最後のフレームと logcat ダンプがキャプチャされます(成功した実行での CI ストレージを節約します)。テストごとのアーティファクトをより柔軟に振り分けるには、AndroidX TestStorageService API の使用をおすすめします。../../transfer/extracting-test-artifacts/SKILL.md を参照してください。
パターン
パターン:誤り — -p を付けずに screencap を実行する
# WRONG
adb shell screencap /sdcard/out.png
file /sdcard/out.png # → "data" (not a PNG)
# WRONG because: without -p, screencap writes a raw RGBA framebuffer (header + naked pixel
# bytes), not a PNG. Image viewers refuse to open it. The .png extension is misleading.
# RIGHT
adb shell screencap -p /sdcard/out.png
adb pull /sdcard/out.png ./out.png
パターン:誤り — Windows で adb shell screencap -p > out.png を実行する
# WRONG (on Windows / certain CI hosts)
adb shell screencap -p > out.png
# WRONG because: `adb shell` allocates a PTY and translates LF to CRLF on stdout. For
# binary streams (PNG bytes) this corrupts the file.
# RIGHT (binary-clean stdout)
adb exec-out screencap -p > out.png
パターン:3 分の上限を超える長時間キャプチャ
# WRONG — assumes a single screenrecord can capture 10 minutes
adb shell screenrecord --time-limit 600 /sdcard/run.mp4
# WRONG because: --time-limit is capped at 180. The utility silently truncates to 180.
# RIGHT — chain
for i in 1 2 3 4; do
adb shell screenrecord --time-limit 180 /sdcard/run-$i.mp4
done
adb pull /sdcard/run-1.mp4 ./
adb pull /sdcard/run-2.mp4 ./
adb pull /sdcard/run-3.mp4 ./
adb pull /sdcard/run-4.mp4 ./
# Concatenate with ffmpeg if needed:
# ffmpeg -f concat -i list.txt -c copy out.mp4
(または、時間無制限のキャプチャには scrcpy に切り替えてください。)
パターン:QA の再現確認用バグレポートオーバーレイ
adb shell screenrecord --bugreport --time-limit 60 \
--bit-rate 8000000 --size 720x1280 /sdcard/repro.mp4
# Each frame has a frame-info + timestamp overlay aligning with logcat -v threadtime,year,UTC.
adb pull /sdcard/repro.mp4 ./repro.mp4
adb logcat -d -v threadtime,year,UTC > repro-logcat.txt
必須ルール
screencapで PNG を出力するには、必ず-pを指定してください。指定しない場合、ファイルは生の RGBA 形式になり、画像ビューアーでは使用できません。- ストリーミングキャプチャでは、特に Windows や
\n → \r\nの変換が適用される CI ホストで、adb shell screencap -p > out.pngよりもadb exec-out screencap -p > out.pngを必ず優先してください。 screenrecord --time-limitの上限は180 sとして必ず扱ってください。それを超える場合は、呼び出しを連結するか scrcpy を使用する必要があります。screenrecordはadb shell pkill -INT screenrecordで必ず停止してください(ホストからkill -9を実行しないでください)。SIGKILL を使うと MP4 がファイナライズされず、再生できなくなります。screenrecordが音声をキャプチャすると決して想定しないでください。音声はキャプチャされません(developer.android.com/tools/adb#screenrecord)。- Wear OS では
screenrecordを使用しないでください。サポートされていません。 - **推奨:**毎回の実行ではなく、失敗時のみキャプチャしてください。CI ストレージを節約し、失敗したテストを直接特定できます。
- **推奨:**すべての
screenrecord --bugreportに、同時に取得したlogcat -v threadtime,year,UTCダンプを組み合わせてください。そうしないと、オーバーレイとの照合が困難になります。
検証
-
adb shell screencap -p /sdcard/out.png && adb pull /sdcard/out.pngの実行後に、file ./out.pngがPNG image dataを報告します。 - Windows CI では、スクリーンショットは
adb exec-out screencap -p > out.pngでストリーミングされます(\r\nによる破損はありません)。 - CI が
screencapとlogcat -dを取得するのは、テストの終了コードがゼロ以外の場合のみです。 - どのスクリプトにも、
N > 180のscreenrecord --time-limit <N>はありません。 -
screenrecordプロセスに対するkill -9はありません。MP4 を確定させるため、pkill -INT screenrecordのみを使用します。 - CI の成果物アーカイブには、
Class.methodという名前のテストごとのサブディレクトリが含まれています。
参考資料
- developer.android.com/tools/adb#screencap —
screencapの構文、-pフラグ、exec-out によるストリーミング。 - developer.android.com/tools/adb#screenrecord —
screenrecordの構文、フラグ、厳格な制限(「音声は記録されません」、180 秒の上限、Wear OS には非対応、録画中の回転には非対応)。 - developer.android.com/tools/adb#shellcommands — 引用符の使い方と、
exec-outとshellの違い。 - developer.android.com/training/testing/instrumented-tests/stability — インストルメンテーションテストにおけるスクリーンショットと再現性の衛生管理。
- リサーチノート
tasks/research/A2-adb-shell-commands.md—screencap/screenrecordの全フラグ一覧。 - リサーチノート
tasks/research/A3-adb-observability-automation.md— 失敗時に取得する CI パターン、exec-outを使用する理由。 - 関連スキル:
../../architecture/understanding-adb-architecture/SKILL.md— サーバー / デーモン /adb shellとadb exec-outの違い。 - 関連スキル:
../../devices/connecting-to-devices/SKILL.md—adb get-state、複数デバイスの指定。 - 関連スキル:
../../devices/connecting-over-wifi/SKILL.md— ワイヤレスで取得するためのadb pair。 - 関連スキル:
../../apps/installing-and-managing-apps/SKILL.md— 取得対象の APK のインストール。 - 関連スキル:
../../tests/running-instrumented-tests-via-adb/SKILL.md—am instrumentの呼び出し。 - 関連スキル:
../../control/injecting-input-and-state/SKILL.md— 取得前にジェスチャーを実行する方法。 - 関連スキル:
../../observability/extracting-logs-with-logcat/SKILL.md— 失敗時に取得するログと併せた logcat の取得。 - 関連スキル:
../../transfer/extracting-test-artifacts/SKILL.md—adb pullと TestStorageService。 - 関連スキル:
../../automation/scripting-adb-for-ci/SKILL.md— 失敗時に取得する CI パターンの全体像。 - セット横断:
../../../instrumentation/runner/running-instrumented-tests-with-androidjunit4/SKILL.md— JUnit4 のTestWatcherの仕組み。 - セット横断:
../../../instrumentation/scenarios/launching-activities-with-activityscenario/SKILL.md— 取得前に、失敗状態になるよう Activity を操作する方法。 - セット横断:
../../../fundamentals/strategies/applying-testing-strategies/SKILL.md— 失敗時の取得が毎回のスクリーンショット取得より適している場面。