点了停止录屏,结果音视频数据还在后台流——这就是只 stop 不 release 的代价。

做录屏功能的时候,最开始思路很简单:创建个采集实例,点开始就 start,点停止就 stop。完事了。
跑了一段时间发现问题:录屏停了之后,内存一直涨,CPU 也下不来。用户退出页面之后更离谱,录屏进程还在后台跑着,摄像头和麦克风的指示灯一直亮着。
这时候才意识到:录屏不是点一下 start/stop 就完事的,它背后是一整条数据采集管线,每一环都要正确释放。
一、录屏的数据流向是什么样的
先把整条管线理清楚:
屏幕画面 → 视频源
系统声音 → 音频源
麦克风声音 → 音频源
↓
AVScreenCapture 实例
↓
Surface(视频输出)
↓
Buffer(数据回调)
↓
你的应用处理
可以把整个录屏想成一条流水线:
- 视频源负责拿屏幕画面;
- 音频源负责拿系统声音和麦克风声音;
- AVScreenCapture 是总调度;
- Surface 是视频的输出通道;
- Buffer 是数据回调,把原始数据传给你。
每一环都有自己的资源,stop 了不代表资源就释放了。
二、只 stop 不 release 的问题
最开始写的代码是这样的:
capture.start();
// … 录屏中 …
capture.stop();
点了停止,确实画面不录了,声音也没了。但是后台资源还在:
- Surface 还占着;
- Buffer 回调还在注册;
- 音频采集还没完全停;
- 实例本身也没释放。
跑几次 start/stop 之后,内存涨上去了,CPU 也降不下来。这就是只 stop 不 release 的后果。
正确的做法是:stop 之后,要把所有资源都释放掉,包括 Surface、回调、实例本身。
三、音频源配置为什么容易乱
录屏的音频源有好几种:
| 系统声音 | 设备播放的声音 |
| 麦克风声音 | 麦克风输入 |
| 混合声音 | 系统 + 麦克风 |
很多人配置的时候搞不清楚,要么只录了系统声音没录麦克风,要么两个都录了但混音比例不对。
还有个坑:音频源和视频源是分开配置的。你要录系统声音,就要单独配置音频源;要录画面,就要单独配置视频源。不是选一个"录屏"就全帮你搞定了。

四、Surface 和 Buffer 的关系
视频输出有两种方式:Surface 模式和 Buffer 模式。
| Surface 模式 | 画面直接送 Surface,不经过应用 | 实时预览、快速编码 |
| Buffer 模式 | 每帧数据回调给应用 | 自定义处理、后期编码 |
两种模式不要搞混了。如果你要实时预览录屏内容,用 Surface 模式;如果你要拿到每帧数据自己处理,用 Buffer 模式。
Buffer 模式还有个坑:消费不及时。每帧数据都回调给你,如果你处理得慢了,Buffer 就堆在那里,内存就涨上去了。一定要及时消费,不要堆着。
五、前后台切换的状态处理
录屏的时候,用户切到后台了怎么办?
这个很多人没处理。结果就是:用户切到后台了,录屏还在跑;或者切回来之后,录屏卡住了,画面不动了。
正确的做法是:
- 切到后台的时候,根据业务决定是继续录还是暂停;
- 切回来的时候,要检查录屏状态是不是正常;
- 不能假设切回来之后一切都正常。
还有个情况:系统权限弹窗、来电、其他应用打断录屏,这时候录屏会被异常停止。你要监听停止事件,及时更新 UI,不要让用户以为还在录。
六、完整的生命周期
把正确的生命周期理一遍:
| 初始化 | 创建 AVScreenCapture 实例 |
| 配置 | 设置视频源、音频源、分辨率 |
| 准备 | 配置 Surface / Buffer 回调 |
| 启动 | start() |
| 运行 | 数据正常流过来 |
| 停止 | stop() |
| 释放 | 释放 Surface、释放回调、release() 实例 |
每一步都不能少。尤其是最后释放那一步,很多人就是漏了。
七、几个容易踩的坑
第一个坑:只 stop 不 release。表面上录屏停了,后台资源还占着。
第二个坑:音频源配置混乱。要么漏了系统声音,要么漏了麦克风,要么混音不对。
第三个坑:Surface/Buffer 消费不及时。数据堆在那里,内存越涨越高。
第四个坑:切后台状态未处理。切后台录屏还在跑,或者切回来卡住了。
第五个坑:重复 start/stop。没停干净就又 start,资源冲突。

这次做录屏功能最大的体会是:录屏是一条完整的资源管线,不是一个简单的开关。从创建、配置、启动、运行到停止、释放,每一环都有自己的资源要管。只点 start/stop 是不够的,每一步都要想清楚——这一步创建了什么资源,后面要在哪里释放。
网硕互联帮助中心








评论前必须登录!
注册