quicktime_video_hack如何建立屏幕流会话:15步USB握手协议逐步图解
【免费下载链接】quicktime_video_hackRecord iOS device audio and video项目地址: https://gitcode.com/gh_mirrors/qu/quicktime_video_hack
想在没有 Mac 电脑的情况下,直接录制 iPhone 或 iPad 的屏幕吗?quicktime_video_hack是一个用 Go 编写的跨平台工具,它通过 USB 与 iOS 设备完成一套15 步握手协议,建立 QuickTime 屏幕流会话,把 H.264 视频和 WAV 音频流原样拉到 Linux 或 macOS 上。本文逐图解开这套 USB 握手的每一步,让你真正看懂屏幕镜像会话是如何建立的。
准备工作:配对设备与发现 USB 设备
建立会话的前提是设备已被信任配对。运行qvh devices可以列出主机上所有带 usbmux 端点的 iOS 设备。工具会在 USB 描述符中寻找 SubClass 为0xFE的 usbmux 配置(见 discovery.go),并记录设备序列号——不同 iPhone 的 VID/PID 可能完全相同,只能靠序列号区分。
qvh devices -v💡 如果提示
device not found,请先在手机上点击"信任此电脑"。
第 1~2 步:解锁隐藏的 QuickTime USB 配置
这是整个协议最"hack"的一步。iOS 设备默认只有 usbmux 配置;当 Mac 上的 QuickTime 开始录屏时,设备会断开并重新连接,多出一套隐藏的 QuickTime 配置(SubClass0x2A),里面带有 4 个 Bulk 端点,专门用来收发音视频数据。
quicktime_video_hack 通过发送一条特定的 USB 控制请求(0x40, 0x52, 0x00, 0x02)主动触发这个行为,然后轮询等待设备带着新配置重新上线(见 activator.go):
| 步骤 | 动作 | 说明 |
|---|---|---|
| 1 | 启用隐藏配置 | 发送控制请求,设备断线重连,多出 QT 配置 |
| 2 | 占用端点 | 激活 QT 配置,声明收/发 Bulk 端点,清空 Feature 状态(见 usbadapter.go) |
第 3~4 步:PING 心跳握手
端点就绪后,设备会主动发来第一个包:PING。它的结构非常简洁:
| 4 字节长度 (16) | 4 字节 Magic (PING) | 4 字节 0x0 | 4 字节 0x1 |
|---|---|---|---|
| 10000000 | 676E6970 | 00000000 | 01000000 |
工具收到 PING 后立即回发一个 PING,握手才算真正开始(见 messageprocessor.go)。
| 步骤 | 方向 | 包 |
|---|---|---|
| 3 | 设备 → 主机 | 等待 PING |
| 4 | 主机 → 设备 | 回复 PING |
第 5~9 步:音频时钟协商(CWPA 与 AFMT)
屏幕流会话的核心是时钟同步。第 5 步设备发来 SYNCCWPA包,附上设备侧的音频时钟引用(ClockRef);主机在第 6 步创建本地时钟,并把自己的 ClockRef 写进 RPLY 回复。
紧接着两个 ASYN 包把音频通道"点亮":
| 步骤 | 方向 | 包 | 作用 |
|---|---|---|---|
| 7 | 主机 → 设备 | ASYNHPD1 | 上报主机设备信息,准备视频流 |
| 8 | 主机 → 设备 | ASYNHPA1 | 携带第 6 步收到的设备音频 ClockRef,开启音频流 |
| 9 | 设备 → 主机 | SYNCAFMT | 告知音频格式(48kHz LPCM 未压缩),主机回复{"Error": 0}表示一切正常 |
注意AFMT包里引用的正是你在CWPA回复中交给它的那个时钟——设备用它标注后续每一个音频缓冲。
第 10~12 步:视频通道建立(CVRP 与 NEED)
第 10 步设备发来 SYNCCVRP包,这是信息量最大的一包(约 649 字节):内含 H.264 的SPS/PPS 参数集(已编码为 NALU,可直接用于流媒体)和时序信息,以及设备的视频 ClockRef。
| 步骤 | 方向 | 包 | 作用 |
|---|---|---|---|
| 11 | 主机 → 设备 | RPLY | 回复本地视频 ClockRef,之后所有 FEED 帧都引用它 |
| 12 | 主机 → 设备 | ASYNNEED | 携带设备视频 ClockRef,告诉设备"请持续发视频" |
NEED包整个会话内容恒定,只需初始化一次后反复发送即可(见 asyn.go)。每收到一个 FEED 帧就回发一个 NEED,相当于流控反馈。
第 13~15 步:属性设置与时钟对齐收尾
| 步骤 | 方向 | 包 | 作用 |
|---|---|---|---|
| 13 | 设备 → 主机 | 2 × ASYNSPRP | 设置视频流属性:ObeyEmptyMediaMarkers=true、RenderEmptyMedia=false |
| 14 | 设备 → 主机 | SYNCCLOK | 要求主机新建一个时钟并回复其 ClockRef |
| 15 | 设备 → 主机 | 2 × SYNCTIME | 主机两次回复当前CMTime(纳秒精度,Scale=10^9),完成双向时间对齐 |
15 步走完,握手阶段结束 🎉 设备开始推送FEED(视频帧)和EAT!(音频帧)两类 CMSampleBuffer 数据包。
会话结束后:优雅关闭流
停止时(Ctrl+C),工具会按相反方向走一遍:先发HPA0停音频、HPD0停视频,收到SYNC STOP后回 8 字节零,再接收两条 ASYNRELS(时钟释放通知),最后释放 USB 端点、把设备切回纯 usbmux 配置(见 messageprocessor.go)。
一分钟速查:15 步完整清单
| # | 包/动作 | 方向 | 关键词 |
|---|---|---|---|
| 1 | 启用隐藏 QT 配置 | USB 控制 | 0x40/0x52 |
| 2 | 占用 Bulk 端点 | 主机 | StartReading |
| 3 | PING | 设备 | 等待 |
| 4 | PING | 主机 | 回应 |
| 5 | SYNC CWPA | 设备 | 音频 ClockRef |
| 6 | CWPA RPLY | 主机 | 本地时钟 |
| 7 | ASYN HPD1 | 主机 | 视频准备 |
| 8 | ASYN HPA1 | 主机 | 开启音频 |
| 9 | SYNC AFMT | 设备 | 48kHz LPCM |
| 10 | SYNC CVRP | 设备 | SPS/PPS + 视频时钟 |
| 11 | CVRP RPLY | 主机 | 本地视频时钟 |
| 12 | ASYN NEED | 主机 | 催发视频 |
| 13 | 2× SPRP | 设备 | 流属性 |
| 14 | SYNC CLOK | 设备 | 新建时钟 |
| 15 | 2× TIME | 设备 | CMTime 对齐 |
想深入源码?从这里开始
- 协议全文(含每种包的十六进制格式表):doc/technical_documentation.md
- 隐藏配置激活逻辑:screencapture/activator.go
- USB 端点读写与分帧:screencapture/usbadapter.go
- 全部 SYNC/ASYN 包处理:screencapture/messageprocessor.go
- 二进制报文样例(写单测必备):screencapture/packet/fixtures/
- 会话入口
startWithConsumer:main.go
掌握这 15 步握手后,你甚至可以照着 packet/fixtures/ 里的报文转储,用任意语言重新实现一套自己的 iOS 屏幕流会话协议栈。
【免费下载链接】quicktime_video_hackRecord iOS device audio and video项目地址: https://gitcode.com/gh_mirrors/qu/quicktime_video_hack
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考