Scrcpy 的投屏控制,开发者调试神器
Scrcpy 的投屏控制,开发者调试神器
去年在调试一个桌面小部件(AppWidget)的刷新问题时,我遇到了一个典型的 Android 开发者困境:测试机平放在桌上,USB 线连着电脑跑日志,但每次解锁看 UI 状态都要歪着头瞄屏幕。那天手头正好在跑一组长时间的压力测试,需要间歇性检查界面是否出现 ANR 弹窗。我试过拿手机支架垫高,也试过用摄像头对着屏幕拍延时,体验都很差。后来同事在旁边丢了一句:你用 Scrcpy 直接投到显示器上不就行了?那是我第一次认真用这款工具,十分钟后,我把之前付费买的 Vysor 从书签栏里删掉了。
Scrcpy 由 Genymobile 维护,开源在 https://github.com/Genymobile/scrcpy,协议是 Apache 2.0,完全免费。它不像市面上那些需要注册账号、后台常驻服务的手机助手,也不基于浏览器插件。它就是一个命令行程序,加上 adb 就能跑,Windows、macOS、Linux 全平台支持。如果你做的是 Android 开发、测试或者需要频繁在真机上验证交互,它几乎是目前投屏控制方案里最干净、延迟最低的选择。
协议层:为什么它的延迟能做到肉眼不可感
很多人第一次用 Scrcpy 会误以为它是个录屏软件,只不过把画面传到了电脑上。这种理解差得太远。录屏是单向采集、存储或推流,而 Scrcpy 的核心设计是一条基于 adb forward 的双向隧道。
当你执行 scrcpy 命令时,PC 端会先把一个名为 scrcpy-server 的 jar 包 push 到设备的 /data/local/tmp/ 目录下。这个 server 本身是用 Java 写的,但设备端不需要预装任何应用,因为它通过 app_process 借助 adb shell 的权限直接拉起。server 启动后,会利用 Android 的 MediaProjection API 捕获屏幕帧,再交给设备自带的硬件编码器(默认通常是 H.264)进行压缩。编码后的视频流通过本地 socket 经由 adb forward 传输到 PC。PC 端用 FFmpeg 解码,SDL2 渲染窗口。你的鼠标点击和键盘事件则通过另一条通道,由 PC 端封装成 Android 输入事件注入回设备。
整个链路跑在本地 USB 或局域网内,不经过外部服务器。这也是为什么在 USB 3.0 连接下,端到端延迟通常能压到 30 毫秒以内,几乎和直接触摸屏幕没有可感知的差别。相比之下,那些基于网络 WebSocket 或 RTMP 的投屏方案,光是握手和缓冲就要吃掉上百毫秒,操作起来会有明显的“粘滞感”。Scrcpy 的轻量还体现在资源占用上:PC 端不需要庞大的 Electron 框架,设备端也没有悬浮窗或常驻通知栏的 apk,用完即走。
值得一提的是,Scrcpy 在设备端获取屏幕数据时,是以 shell 用户身份运行的。这意味着它不需要你的应用申请任何权限,也不需要 root。当然,这也带来了一个硬性限制:遇到设置了 FLAG_SECURE 的窗口,比如银行 App、支付界面、DRM 视频播放,屏幕内容会直接黑屏。这不是 bug,而是 Android 的安全机制在起作用,Scrcpy 也没有绕过它的意图。
藏在命令行里的生产力参数
Scrcpy 的默认参数已经足够好用,但真正让它成为调试神器的,是那些细粒度到令人发指的命令行开关。如果你只用鼠标双击图标启动,可能只发挥了它三成的能力。
举个例子,做 UI 自动化测试或者需要留存崩溃现场时,我会用 scrcpy --no-display --record=bugreport.mp4。这条命令不会在 PC 上弹出窗口,但会在后台把屏幕画面无损录制下来。配合 adb logcat 一起跑,复现问题后你既有视频又有日志,排查效率极高。另一个常用的参数是 --stay-awake,它会让设备在连接期间保持亮屏,省去了反复去按电源键的麻烦,长时调试时特别省心。
折叠屏和外接显示器的兴起让多屏场景变多了。Scrcpy 支持 --display 参数来指定镜像哪一块屏幕,在 Android 10 以上的设备上,你甚至可以配合 --new-display=1920x1080 创建一个虚拟显示器。这对于测试应用在副屏上的行为非常有用,比如验证你的 Activity 在分辨率变化时是否正确重建,而不需要真的去借一台折叠屏。虚拟显示器的画面直接在 PC 窗口里呈现,你可以用鼠标像操作普通窗口一样去拉伸、点击。
做技术分享或者给产品演示交互时,--show-touches 和 --always-on-top 是标配。前者会在画面上显示一个白点标记触摸位置,后者确保演示时窗口不会被 PPT 或其他文档盖住。如果你不想让观看者误操作设备,加上 --no-control 就能切到纯旁观模式。
对于老设备或者需要降低带宽的场景,-b 2M -m 1024 可以把码率压到 2Mbps、分辨率限制在 1024px,牺牲一点画质换取帧率稳定。反过来,如果你的机器性能充裕,--max-fps=120 配合高刷设备,能得到非常顺滑的滚动体验。
还有一个容易被忽略的模式是 OTG。执行 scrcpy --otg 时,Scrcpy 会通过 USB 的 AOA(Android Open Accessory)协议,把你的电脑键盘和鼠标模拟成 HID