Захват экрана и запись видео

Рейтинг: 74.1% · 11 голосов
Полный курс по Android Debug Bridge: установка, подключение, shell, логи, dumpsys, автоматизация, root, беспроводная отладка. Уроки по главам с обсуждением.
Ответить
Аватара пользователя
android_roman
Сообщения: 45
Зарегистрирован: 11 май 2026, 05:31

Захват экрана и запись видео

Сообщение android_roman »

АкадемияADB: Android Debug BridgeГлава 14 из 29
Оглавление курса (29)
  1. Введение в Android Debug Bridge
  2. Установка и настройка рабочей среды
  3. Подключение устройства (проводное и беспроводное)
  4. Базовые команды ADB и управление сервером
  5. Команды состояния и перезагрузки
  6. Навигация по файловой системе
  7. Управление пакетами приложений
  8. Логирование с помощью logcat
  9. Системные дампы и диагностика (dumpsys)
  10. Анализ производительности в реальном времени
  11. Эмуляция ввода (input)
  12. Управление Activity и Intent (am)
  13. Работа с оконным менеджером (wm)
  14. Захват экрана и запись видео (вы здесь)
  15. Root-доступ и его применение
  16. Модификация системных настроек через settings
  17. Команды для поставщиков контента (content)
  18. Резервное копирование и восстановление (backup)
  19. Проброс портов и туннелирование
  20. Беспроводная отладка (Wi-Fi)
  21. Взаимодействие с эмуляторами
  22. Написание скриптов на Bash/CMD/PowerShell
  23. ADB в языках программирования
  24. Автоматизация тестирования с ADB
  25. Безопасность и лучшие практики
  26. ADB на Android TV, Wear OS и IoT
  27. Восстановление и низкоуровневые операции
  28. Расширенные возможности оболочки и инструменты
  29. Отладка самого ADB и устранение неполадок
В главе 8 вы ловили баги в logcat, в главе 13 крутили экран через wm. Теперь научимся фиксировать происходящее на дисплее: снимать скриншоты и писать видео без единого стороннего приложения, только средствами adb. Это фундамент для баг-репортов, документации и автотестов, к которым вернемся в главе 24.

Скриншот через screencap:

На устройстве живет встроенная утилита screencap. Флаг -p заставляет ее отдавать PNG. Канонический способ получить картинку сразу на компьютер:

Код: Выделить всё

adb exec-out screencap -p > screen.png
Команда молчит, просто появляется файл:

Код: Выделить всё

$ file screen.png
screen.png: PNG image data, 1080 x 2400, 8-bit/color RGBA, non-interlaced
Почему exec-out, а не shell. adb shell исторически ходит через псевдотерминал, который умеет калечить бинарный поток (на Windows перевод строки LF превращался в CRLF, и PNG приходил битым). exec-out передает stdout процесса байт в байт, без обработки. Старые рецепты, где вывод screencap прогоняли через sed для зачистки лишних символов, забудьте, exec-out закрывает проблему правильно.

Второй вариант, через файл на устройстве:

Код: Выделить всё

adb shell screencap -p /sdcard/screen.png
adb pull /sdcard/screen.png ./screen.png
adb shell rm /sdcard/screen.png

Код: Выделить всё

/sdcard/screen.png: 1 file pulled, 0 skipped. 38.5 MB/s (1474560 bytes in 0.037s)
На шаг длиннее, зато удобно, когда снимок делает скрипт на самом устройстве. Писать можно в /sdcard или /data/local/tmp, а попытка сохранить в /data без root кончится ошибкой Permission denied.

Если дисплеев несколько (складные аппараты, десктопный режим, Android Auto), сначала узнайте id:

Код: Выделить всё

$ adb shell dumpsys SurfaceFlinger --display-id
Display 4619827259835644672 (HWC display 0): port=0 pnpId=GGL displayName="EMU_display_0"
И снимайте нужный:

Код: Выделить всё

adb exec-out screencap -p -d 4619827259835644672 > cover.png
Без -p и без расширения .png утилита выдает сырой буфер RGBA с коротким заголовком (ширина, высота, формат пикселя). Это пригодится разве что самописным инструментам ради скорости, в обычной работе всегда ставьте -p.

Запись видео через screenrecord:

Утилита /system/bin/screenrecord существует со времен Android 4.4 и пишет MP4 с кодеком H.264. Звук она не записывает вообще, это ограничение самой утилиты, и root тут не помогает. Запись идет в файл на устройстве:

Код: Выделить всё

adb shell screenrecord /sdcard/demo.mp4
Запись продолжается до Ctrl+C или до истечения лимита времени. Лимит по умолчанию, он же максимум, составляет 180 секунд, и это зашито в код:

Код: Выделить всё

adb shell screenrecord --time-limit 30 /sdcard/demo.mp4

Код: Выделить всё

$ adb shell screenrecord --time-limit 600 /sdcard/demo.mp4
Time limit 600s outside acceptable range [1,180]
Флаг --size задает разрешение видео, по умолчанию берется родное разрешение основного дисплея. Уменьшение кадра заметно облегчает файл и разгружает кодировщик:

Код: Выделить всё

adb shell screenrecord --size 720x1600 /sdcard/demo.mp4
Размер должен поддерживаться аппаратным AVC-кодировщиком. Экзотические значения роняют запись, классика жанра:

Код: Выделить всё

ERROR: unable to configure video/avc codec at 1083x2412 (err=-38)
Безопасные варианты: 1280x720, 720x1280 или родное разрешение без флага.

Флаг --bit-rate принимает битрейт в битах в секунду, можно с суффиксом M. На свежих Android по умолчанию 20 Мбит/с (на старых было 4). Для ролика в чат разумно ужать:

Код: Выделить всё

adb shell screenrecord --bit-rate 4M --time-limit 60 /sdcard/bug.mp4
Флаг --verbose печатает параметры сессии, полезно при диагностике:

Код: Выделить всё

$ adb shell screenrecord --verbose --time-limit 10 /sdcard/demo.mp4
Main display is 1080x2400 @60.00fps (orientation=0)
Configuring recorder for 1080x2400 video/avc at 20000000bps
Content area is 1080x2400 at offset x=0 y=0
Encoder stopping; recorded 594 frames in 10 seconds
Stopping encoder and muxer
Еще два флага, о которых редко вспоминают. --bugreport накладывает на кадры таймстампы, такие ролики удобно прикладывать к тикетам. --display-id (на Android 11 и новее) выбирает физический дисплей, id берется из того же dumpsys SurfaceFlinger --display-id.

Прерывание и корректная остановка:

В интерактивной сессии запись останавливается по Ctrl+C. screenrecord ловит SIGINT, дописывает индекс MP4 (атом moov) и закрывает файл. Убивать процесс через kill -9 нельзя: контейнер останется без индекса, и плеер такой файл не откроет (ffmpeg иногда вытаскивает поток, но рассчитывать на это не надо).

Фоновую запись останавливайте тем же сигналом:

Код: Выделить всё

adb shell pkill -2 screenrecord
После остановки дайте процессу секунду-другую на финализацию файла и только потом забирайте его, иначе утащите обрезанный хвост.

Извлечение записи:

Код: Выделить всё

$ adb pull /sdcard/demo.mp4 .
/sdcard/demo.mp4: 1 file pulled, 0 skipped. 41.2 MB/s (24816512 bytes in 0.574s)
$ adb shell rm /sdcard/demo.mp4
Бонус для любопытных: у screenrecord есть недокументированный флаг --output-format. Со значением h264 утилита отдает голый видеопоток без MP4-контейнера, а значит его можно гнать в stdout и смотреть экран почти вживую:

Код: Выделить всё

adb exec-out screenrecord --output-format=h264 - | ffplay -framerate 60 -probesize 32 -sync video -
Задержка ощутимая, для постоянной работы берите scrcpy, но прием выручает на голой машине, где кроме platform-tools и ffmpeg ничего нет. Флаг недокументирован и может исчезнуть в любом релизе Android, в скрипты его не зашивайте.

Обработка скриншотов в скриптах:

Серия снимков с таймстампами в имени:

Код: Выделить всё

#!/usr/bin/env bash
set -euo pipefail
SERIAL="RF8X20KQ1ZT"
OUT=./shots
mkdir -p "$OUT"
for i in $(seq 1 10); do
    adb -s "$SERIAL" exec-out screencap -p > "$OUT/shot_$(date +%Y%m%d_%H%M%S).png"
    sleep 2
done
Флаг -s обязателен при нескольких подключенных устройствах, иначе получите error: more than one device/emulator (про выбор устройства была глава 4).

Скриншоты отлично стыкуются с ImageMagick. Сравнить два состояния экрана и получить число отличающихся пикселей:

Код: Выделить всё

$ magick compare -metric AE before.png after.png diff.png
14302
Проверить цвет конкретной точки, например что кнопка стала зеленой, не открывая картинку глазами:

Код: Выделить всё

$ magick screen.png -format "%[pixel:p{540,1200}]" info:
srgb(76,175,80)
В связке с input tap из главы 11 это дает примитивный, но рабочий автотест без единого фреймворка.

Отдельная боль на Windows. В классическом Windows PowerShell 5.1 оператор перенаправления перекодирует поток, и PNG приходит битым даже через exec-out. Лечится запуском через cmd:

Код: Выделить всё

cmd /c "adb exec-out screencap -p > screen.png"
Либо переходите на PowerShell 7.4 и новее, там конвейер между нативными программами и редирект в файл наконец передают байты без перекодировки. В обычных cmd-скриптах проблемы нет изначально.

Запись видео вокруг прогона тестов, целиком:

Код: Выделить всё

#!/usr/bin/env bash
set -euo pipefail
adb shell "screenrecord --bit-rate 8M --time-limit 180 /sdcard/test_run.mp4" &
REC_PID=$!
./run_ui_tests.sh || true
adb shell pkill -2 screenrecord || true
wait "$REC_PID" 2>/dev/null || true
sleep 2
adb pull /sdcard/test_run.mp4 ./artifacts/
adb shell rm /sdcard/test_run.mp4
Частые ошибки и грабли:

Черный прямоугольник вместо содержимого. Окно выставило FLAG_SECURE, и система не отдает его пиксели ни скриншоту, ни записи. Банковские приложения (Сбер, Kaspi), Госуслуги, DRM-видео, поля с паролями. Штатного обхода нет, и это правильно. В своем приложении флаг можно убрать в debug-сборке.

Черный скриншот при погасшем экране. screencap снимает то, что выводится на дисплей, спящее устройство дает черный кадр. Разбудите его через input keyevent KEYCODE_WAKEUP (глава 11).

PNG не открывается на Windows. Смотрите выше про PowerShell 5.1, либо у вас древние platform-tools и снимок делался через adb shell с перенаправлением. Обновитесь до актуальной ветки 36.x и используйте exec-out.

Time limit outside acceptable range. Попытка задать --time-limit больше 180. Длинные записи делайте сегментами в цикле или через scrcpy --record file.mp4.

unable to configure video/avc codec. Кодировщик не принял запрошенный --size. Берите стандартные размеры или родное разрешение.

Файл не воспроизводится. Процесс убили через kill -9 или выдернули кабель до финализации. Только Ctrl+C или pkill -2, потом пауза, потом pull.

Поворот экрана во время записи. screenrecord не меняет ориентацию на лету: видео остается в той ориентации, в которой стартовало, контент после поворота вписывается с полями или обрезается. Не вертите устройство в кадре, либо режьте ролик на дубли.

На эмуляторе screenrecord работает в свежих системных образах, а у самого эмулятора есть и собственный механизм записи, про него поговорим в главе 21. В следующей главе займемся root-доступом и тем, что он открывает поверх уже знакомых команд.
👍3 ❤️3 🔥2 😄 🤔1
✔ Лучший ответ сформирован автоматически — Obsid88
android_roman писал(а):дайте процессу секунду-другую на финализацию файла а как это нормально сделать в CI? sleep 2 выглядит как лотерея, на слабом железе может и 5 секунд писать. опрашивать pidof screenrecord в цикле пока не сдохнет, или есть способ красивее?
Перейти к ответу →
Аватара пользователя
Obsid88
Сообщения: 1
Зарегистрирован: 29 май 2026, 08:57

Re: Захват экрана и запись видео

Сообщение Obsid88 »

✔ Лучший ответ — сформирован автоматически
android_roman писал(а):дайте процессу секунду-другую на финализацию файла
а как это нормально сделать в CI? sleep 2 выглядит как лотерея, на слабом железе может и 5 секунд писать. опрашивать pidof screenrecord в цикле пока не сдохнет, или есть способ красивее?
👍2 ❤️1 🔥1 😄 🤔
Аватара пользователя
haskell8
Сообщения: 1
Зарегистрирован: 12 май 2026, 15:29

Re: Захват экрана и запись видео

Сообщение haskell8 »

подтверждаю про powershell 5.1, в свое время убил два часа пока понял что это шелл портит байты, а не adb. перешел на pwsh 7.4 и все снимается без плясок. и еще из опыта: на xiaomi с hyperos запись на дефолтных 20 мбит периодически фризит, понизил через --bit-rate 8M и стало ровно
👍 ❤️ 🔥 😄 🤔
Аватара пользователя
anasai
Сообщения: 1
Зарегистрирован: 14 май 2026, 06:26

Re: Захват экрана и запись видео

Сообщение anasai »

мелкая поправка: pkill есть не везде, на старье до android 6 в toolbox его нет, приходится делать kill -2 $(pidof screenrecord). на современных девайсах с toybox все ок, но если парк старый, имейте в виду
👍1 ❤️1 🔥1 😄 🤔
Аватара пользователя
ivan42
Сообщения: 2
Зарегистрирован: 12 май 2026, 15:53

Re: Захват экрана и запись видео

Сообщение ivan42 »

а если надо записать дольше 3 минут без scrcpy, цикл с сегментами же будет терять кадры на стыках? между остановкой одного screenrecord и стартом следующего явно есть дырка в секунду-две. или запускать второй процесс параллельно с перехлестом и потом склеивать в ffmpeg?
👍 ❤️ 🔥 😄 🤔1
Ответить
← Предыдущая глава
Работа с оконным менеджером (wm)
Следующая глава →
Root-доступ и его применение

Все главы курса «ADB: Android Debug Bridge»

Поделиться темой: ✈ Telegram VK

Вернуться в «ADB: Android Debug Bridge»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость