【问题标题】:How to capture the screen as fast as possible through adb? [duplicate]如何通过adb尽可能快的抓屏? [复制]
【发布时间】:2021-09-29 04:49:41
【问题描述】:

最近,我写了一个PC客户端,可以使用adb实时显示和控制我的android手机屏幕。我用猴子来控制设备,它工作正常。问题是如何抓取手机屏幕并流畅显示。

我想出的第一个解决方案是通过adb不断抓取framebuffer(就像DDMS的屏幕截图功能)。现在当我这样做时,性能是相当不可接受的。从framebuffer 捕获的帧速率低至每秒 5 个(帧大小为 800 * 480)。当我在手机上滑动时,我的程序看起来像是在打嗝。

我的程序是用java编写的,使用ddmslib来获取framebuffer。

添加:
我发现将原始framebuffer 数据编码为.png 格式非常慢,否则这将是传输压缩原始图像的快速方法。

如何将截屏速度提高到流畅的水平?

【问题讨论】:

  • 也在寻找这个问题的答案。

标签: android adb


【解决方案1】:
adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen.png

来源:

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

【讨论】:

  • 对我来说(使用 Cygwin 的 Windows 7)使用 sed 的那个工作,而 perl 导致文件损坏:adb shell screencap -p | sed 's/\r$//' > screen.png
  • 在 Mac 上也为我工作
  • 这对我来说似乎需要很长时间,大约需要 3 到 8 秒才能完成命令并将图像保存到我的 PC 上使用带有 Android 4.3 的三星 Galaxy S5
  • 在 OSX 上工作,但不能作为别名: alias adbscreenshot='adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen_$(date +%Y%m%d_%H%M%S).png'
  • 对我来说就像这样工作:adb shell screencap -p。花了 2 个小时寻找 perl 和 sed 不起作用的原因
【解决方案2】:

你可以使用:

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

更新

Android 11 引入了通过 wifi 进行调试并加快了速度

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

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

2021 年 9 月更新

使用CulebraTester2中的take-screenshot可以实现更高的帧率

./take-screenshot 

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

【讨论】:

  • 是的,这是一种可行的方法。但它几乎和抢framebuffer一样的速度。
【解决方案3】:

如果缓慢的部分是原始到 png 的转换(time adb shell screencap -p /sdcard/x.png 比 time adb shell screencap /sdcard/nonpng.raw 慢得多,就像我在游戏中那样)并且不需要 png,那么你可以像这里 https://github.com/sowcow/shot 那样做。它将原始数据转换为简单的 ppm 格式,并在获取原始数据后使用 imagemagick 将 ppm 转换为 bmp,几乎没有开销

更新:

max_plenert 的这个 shell 脚本是一个更好的例子:

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

【讨论】:

    【解决方案4】:

    在我的 Mac 上的 .bash_profile 中:

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

    用法:

    droidshot whatever
    

    文件显示在whatever.png中

    【讨论】:

      【解决方案5】:

      使用这种方法,我的应用会继续以全帧速率运行

      adb pull /dev/graphics/fb0
      

      这将从帧缓冲区中提取原始数据。它似乎与屏幕的宽度相同,但高度被填充了。我设备上的帧缓冲区似乎是 RGBA8888 格式。要准确获得屏幕上显示的内容,您应该忽略 Alpha 通道。

      请注意,这对我来说确实需要大约 0.8 秒的时间来下载(分辨率:480x854),但如果我在连续循环中下载它,它不会影响设备的帧速率。

      【讨论】:

        【解决方案6】:

        这是一个缓慢的解决方案,我相信这是您在基于 adb 的解决方案中可能找到的更快的方法,

        # 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; 
        

        【讨论】:

          【解决方案7】:

          来自docs:

          截取设备截图

          screencap 命令是一个 shell 实用程序,用于截取设备显示的屏幕截图。在 shell 中,语法是:

          screencap <filename>
          

          要从命令行使用屏幕截图,请输入以下内容:

          $ adb shell screencap /sdcard/screen.png
          

          这是一个示例截图会话,使用 adb shell 捕获屏幕截图并使用 pull 命令从设备下载文件:

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

          记录设备屏幕

          screenrecord 命令是一个 shell 实用程序,用于记录运行 Android 4.4(API 级别 19)及更高版本的设备的显示。该实用程序将屏幕活动记录到 MPEG-4 文件中。

          Note: Audio is not recorded with the video file.
          

          开发人员可以使用此文件制作宣传或培训视频。在 shell 中,语法是:

          screenrecord [options] <filename>
          

          要从命令行使用 screenrecord,请输入以下内容:

          $ adb shell screenrecord /sdcard/demo.mp4
          

          按Ctrl-C停止录屏,否则在三分钟或--time-limit设置的时间限制自动停止录屏。

          要开始录制您的设备屏幕,请运行 screenrecord 命令来录制视频。然后,运行 pull 命令将视频从设备下载到主机。这是一个示例录制会话:

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

          screenrecord 实用程序可以以您请求的任何支持的分辨率和比特率进行录制,同时保持设备显示的纵横比。该实用程序默认以原生显示分辨率和方向记录,最长为三分钟。

          使用 screenrecord 实用程序时应注意一些已知限制:

          某些设备可能无法以其原始显示分辨率进行录制。如果遇到屏幕录制问题,请尝试使用较低的屏幕分辨率。 不支持在录制过程中旋转屏幕。如果在录制过程中屏幕确实旋转,则部分屏幕会在录制过程中被截断。

          【讨论】:

            【解决方案8】:

            我改进了@steveha 的解决方案:

            创建一个 shell 脚本说:'android-screenshot' 包含以下内容:

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

            将此文件放在您的本地 bin 目录或您喜欢的任何其他 $PATH 中。

            这将允许您在当前目录中保存带有时间戳的文件。

            记得使用

            使shell脚本可执行
            chmod +x android-screenshot
            

            【讨论】:

              【解决方案9】:

              好吧,有些人说在 Perl 中有很多方法可以做一件事。 :-) 无论如何,这个可能会表现得更好(因为没有正则表达式),并且可以解决 MS Windows 中 Cygwin 中的问题(其 Perl 将 \n 定义为 CRLF):

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

              【讨论】:

                【解决方案10】:

                从 Android 4.4 开始有一个screenrecord 程序

                adb shell screenrecord /data/local/tmp/test-video.m4v
                adb pull /data/local/tmp/test-video.m4v ~/test-video.m4v
                

                【讨论】:

                  【解决方案11】:

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

                  您也可以更改比特率并更改视频时长。

                  【讨论】:

                    【解决方案12】:
                    adb shell screencap /sdcard/screen.png && adb pull /sdcard/screen.png my_screen01.png
                    

                    【讨论】:

                    • 这与 Diego Torres Milano 的 answer 有什么不同?
                    猜你喜欢
                    • 2017-07-10
                    • 2020-01-13
                    • 2011-11-17
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-07-12
                    • 2019-07-24
                    相关资源
                    最近更新 更多