30

Recently, I wrote a PC client which can display and control my android phone screen in real-time using adb. I use the monkey to control the device and it works fine. The problem is how to grab the phone screen and display it smoothly.

The first solution I have come up with is to continually grab the framebuffer through adb (like DDMS's screen capture function). Now when I do it, the performance is quite unacceptable. The frame rate captured from framebuffer is as low as 5 per second (the frame size is 800 * 480). My program looks like its hiccuping when I slide on the phone.

My program is written in java using ddmslib to grab framebuffer.

add:
I found it much slow to encoding the raw framebuffer data into .png format, otherwise this will be a fast way to transmit a compress raw image.

How can I improve the speed of capturing the screen to a smooth level?

Robot Dreamer
  • 411
  • 1
  • 4
  • 6

12 Answers12

27
adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen.png

Source:

http://blog.shvetsov.com/2013/02/grab-android-screenshot-to-computer-via.html

steveha
  • 74,789
  • 21
  • 92
  • 117
  • 6
    For me (Windows 7 using Cygwin) the one with sed worked whereas perl resulted in corrupted file: `adb shell screencap -p | sed 's/\r$//' > screen.png` – Mikaël Mayer Feb 20 '14 at 06:53
  • Worked for me too on Mac – ieselisra Feb 18 '15 at 07:56
  • 1
    This seems to take a long time for me, anywhere between 3 and 8 seconds to complete the command and save the image to my PC using a Samsung Galaxy S5 with Android 4.3 – jenovachild Apr 23 '15 at 05:46
  • Works on OSX, but not as an alias: alias adbscreenshot='adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen_$(date +%Y%m%d_%H%M%S).png' – VivienG Nov 30 '15 at 13:07
  • For me it works just like that : `adb shell screencap -p`. Spent 2 hours searching why perl and sed did not work – Bilow Aug 31 '17 at 14:22
12

You could use:

$ adb exec-out screencap -p > test.png

update

Android 11 introduces debug over wifi and speeds the things a bit

$ time adb exec-out screencap -p > test.png

real    0m0.661s
user    0m0.050s
sys 0m0.066s

update sep 2021

Using take-screenshot from CulebraTester2 you can achieve a higher frame rate

./take-screenshot 

 Image in file:///tmp/culebra.zSSYZ6VG.png

Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
9

if the slow part is raw to png conversion (time adb shell screencap -p /sdcard/x.png is considerably slower than time adb shell screencap /sdcard/nonpng.raw, as I have it in games) and png is not necessary, then you can do like here https://github.com/sowcow/shot. It converts raw data to simple ppm format and converts ppm to bmp using imagemagick with almost no overhead after it gets raw data

upd:

This shell script by max_plenert is a better example:

adb shell screencap /sdcard/mytmp/rock.raw
adb pull /sdcard/mytmp/rock.raw
adb shell rm /sdcard/mytmp/rock.raw

// remove the header
tail -c +13 rock.raw > rock.rgba

// extract width height and pixelformat:
hexdump -e '/4 "%d"' -s 0 -n 4 rock.raw
hexdump -e '/4 "%d"' -s 4 -n 4 rock.raw
hexdump -e '/4 "%d"' -s 8 -n 4 rock.raw

convert -size 480x800 -depth 8 rock.rgba rock.png
Pyro
  • 2,101
  • 2
  • 15
  • 6
4

In .bash_profile on my mac:

function droidShot() {
  /full_path_to_droid_sdk/platform-tools/adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > $1.png
}

usage:

droidshot whatever

and the file shows up in whatever.png

William Jockusch
  • 26,513
  • 49
  • 182
  • 323
4

Using this method, my app continues to run at it's full framerate

adb pull /dev/graphics/fb0

This will pull down the raw data from the frame buffer. It seems to be the same width as the screen, but the height is padded out. The frame buffer on my device seems to be in RGBA8888 format. To get exactly what is displayed on screen, you should ignore the alpha channel.

Note that this does take ~0.8 seconds to download for me (resoultion: 480x854) but if i have it downloading on a continuous loop, it doesn't affect the device's frame rate.

Grant Peters
  • 7,691
  • 3
  • 45
  • 57
3

This a slow solution, i am sure it is the faster way you may find in adb based solutions,

# this line require a superuser privilege:
adb shell "su -c 'cat /dev/graphics/fb0 > /sdcard/capture.raw'"

adb pull /sdcard/capture.raw

ffmpeg -loglevel panic -f rawvideo -pix_fmt bgr32 -s 320x480 -i \ 
    capture.raw -vcodec png -vframes 1 capture.png; 

this is the same code into my web application

christian
  • 538
  • 5
  • 8
1

From docs :

Taking a device screenshot

The screencap command is a shell utility for taking a screenshot of a device display. While in a shell, the syntax is:

screencap <filename>

To use the screencap from the command line, type the following:

$ adb shell screencap /sdcard/screen.png

Here's an example screenshot session, using the adb shell to capture the screenshot and the pull command to download the file from the device:

$ adb shell
shell@ $ screencap /sdcard/screen.png
shell@ $ exit
$ adb pull /sdcard/screen.png

Recording a device screen

The screenrecord command is a shell utility for recording the display of devices running Android 4.4 (API level 19) and higher. The utility records screen activity to an MPEG-4 file.

Note: Audio is not recorded with the video file.

A developer can use this file to create promotional or training videos. While in a shell, the syntax is:

screenrecord [options] <filename>

To use screenrecord from the command line, type the following:

$ adb shell screenrecord /sdcard/demo.mp4

Stop the screen recording by pressing Ctrl-C, otherwise the recording stops automatically at three minutes or the time limit set by --time-limit.

To begin recording your device screen, run the screenrecord command to record the video. Then, run the pull command to download the video from the device to the host computer. Here's an example recording session:

$ adb shell
shell@ $ screenrecord --verbose /sdcard/demo.mp4
(press Ctrl-C to stop)
shell@ $ exit
$ adb pull /sdcard/demo.mp4

The screenrecord utility can record at any supported resolution and bit rate you request, while retaining the aspect ratio of the device display. The utility records at the native display resolution and orientation by default, with a maximum length of three minutes.

There are some known limitations of the screenrecord utility that you should be aware of when using it:

Some devices may not be able to record at their native display resolution. If you encounter problems with screen recording, try using a lower screen resolution. Rotation of the screen during recording is not supported. If the screen does rotate during recording, some of the screen is cut off in the recording.

Sergey Shustikov
  • 15,377
  • 12
  • 67
  • 119
0

I have improved on @steveha's solution:

Create a shell script say: 'android-screenshot' with the following contents:

adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen-`date +%Y-%m-%d_%X`.png

Place this file in your local bin directory or any other $PATH you prefer.

This would allow you to save the files with a timestamp in the current directory.

Remember to make the shell script executable using

chmod +x android-screenshot
0

Well some people said in Perl there is many ways to do one thing. :-) Anyway, this one may perform better (since there is no regular expression), and may resolve the issue in Cygwin in MS Windows (whose Perl define \n as CRLF):

adb shell screencap -p | perl -pe 'BEGIN { $/="\cM\cJ"; $\="\cJ"; } chomp;' > screen-$(date +%Y%m%d_%H%M%S).png
0

There is a screenrecord program as of Android 4.4

adb shell screenrecord /data/local/tmp/test-video.m4v
adb pull /data/local/tmp/test-video.m4v ~/test-video.m4v
Joseph Lennox
  • 3,202
  • 1
  • 27
  • 25
-1

adb shell screenrecord --bit-rate 8000000 --time-limit 30 /sdcard/example.mp4

You can change the bit rate and change the video duration also.

Manoj Behera
  • 2,736
  • 22
  • 13
-1
adb shell screencap /sdcard/screen.png && adb pull /sdcard/screen.png my_screen01.png
Roman Rhrn Nesterov
  • 3,538
  • 1
  • 28
  • 16