ARTICLE · 1253884
实战|Kotlin原生实现:把旧安卓手机改造成RTSP网络摄像头
实战|Kotlin原生实现:把旧安卓手机改造成RTSP网络摄像头识别前后置/外接镜头,自动过滤设备不支持的分辨率 RTSP服务(8554端口)支持TCP/UDP,支持Basic鉴权 RTP‑UDP广播(9998端口),探测即可接入 前台服务息屏后台持续推流;横竖屏、镜头切换毫秒级完成 实时展示帧率、码率、客户端连接数、丢包统计 实测(老旧华为Android9机型,1080P30):编码帧率26‑27fps,码率3.8‑4.4Mbps,支持2路RTSP客户端同时拉流,息屏后台可稳定工作。 很多推流方案采用两套独立链路:一路给预览,一路给编码器。缺点是旋转、镜像、画面比例两套逻辑很难对齐,横竖屏切换极易出现预览和推流画面不一致。 本项目采用单GL管线同源渲染: Camera2 → SurfaceTexture → OpenGL管线(旋转、镜像、裁剪) ├─→预览EGLSurface(手机屏幕预览) └─→编码EGLSurface(MediaCodec硬件编码)→H.264 ├─RTSP服务端(8554) └─RTP‑UDP广播(9998) 纹理坐标旋转:不改动顶点,只修改纹理采样 s/t 坐标实现旋转,叠加镜像,避免画面拉伸变形。 时间戳透传:直接把相机SurfaceTexture的原生时间戳给到编码器,保证PTS连续,RTP时间戳不会抖动。 单GL线程执行:所有EGL操作统一在独立HandlerThread,防止Surface销毁时并发崩溃。 不硬编码分辨率列表,程序自动求三者能力交集: Camera2相机输出规格 SurfaceTexture支持尺寸 MediaCodec H.264编码器支持尺寸 同时读取传感器FOV区分超广角、广角、长焦镜头;单镜头设备自动隐藏镜头切换UI,避免用户误操作。 采用CBR恒定码率,关闭B帧,开启编码器低延迟模式。参数做API版本判断,异常捕获,兼容不同厂商硬件编码器差异。 码率按像素自动计算: bitrate = clamp(宽×高×帧率×0.07, 0.8Mbps, 12Mbps) 1080P30 ≈ 4.35Mbps,720P30 ≈ 1.94Mbps 关键帧间隔固定1秒:新接入客户端最多等待1秒拿到IDR关键帧,网络丢包也能1秒内画面自愈。 自行实现RTSP/1.0最小子集,实现OPTIONS、DESCRIBE、SETUP、PLAY、TEARDOWN等指令。 SDP根据实时SPS/PPS动态生成;未获取参数集时返回503,让客户端重试。 H.264 NAL单元做FU‑A分片,单包控制在1400字节以内。 每个RTSP客户端拥有独立RTP打包器、独立发送队列,互不干扰。 早期版本编码线程直接执行socket发送,只要一个客户端网络卡顿,会阻塞编码线程,全部客户端一起卡顿。 优化方案:每个客户端独立发送线程+队列。 队列溢出策略:关键帧优先完整入队;非关键帧直接整帧丢弃,不拆包破坏NAL单元,丢包数据计入统计面板。 9998端口UDP广播并非真正组播,采用「探测注册模式」: 播放器向手机9998发送任意UDP数据包完成注册; 手机复制RTP包发给已注册客户端; 15秒无数据包交互自动清理客户端。 Android系统对后台应用限制严格,不靠前台服务息屏后很快就会被杀。 前台服务声明 foregroundServiceType="camera",申请WakeLock锁防止CPU休眠。 业务层设计为进程单例,Activity与Service共享状态。 Activity销毁时:推流状态下只解绑预览Surface,相机、编码、网络继续运行;用户下次打开APP重新挂载预览即可恢复画面,推流不中断。只有未推流才释放全部资源。 ❌ 预览、编码两条独立渲染链路 → 画面方向、构图不一致;✅ 同源GL管线。 ❌ FU‑A分片首片携带原始NAL头 → 画面局部花屏;✅ 剥离原始NAL头。 ❌ 镜像、旋转顺序颠倒 → 画面180度翻转;✅ 先镜像,后旋转纹理坐标。 ❌ 编码线程直接写socket,慢客户端拖垮全部流;✅ 每客户端独立发送队列。 ❌ Activity销毁直接释放相机;✅ 推流状态仅解绑预览Surface,后台继续运行。 ❌ 硬编码分辨率列表;✅ 自动探测相机、编码器能力交集。 ffplay -rtsp_transport tcp rtsp://手机IP:8554/live/cam0 播放器先向手机9998端口发送UDP探测包,再加载对应SDP文件接收流。 该项目没有依赖重量级第三方音视频库,把Camera2、OpenGL、MediaCodec、RTSP/RTP每一层逻辑自主实现。适合旧安卓设备改造为局域网摄像头,也适合Android音视频开发者参考学习底层链路。 项目地址:https://github.com/suihanlansnow/android_rtsp
项目介绍:一款约4000行Kotlin原生Android应用,不依赖FFmpeg、第三方流媒体SDK。基于Camera2+MediaCodec+OpenGL,将手机摄像头转为局域网RTSP视频源,支持RTSP服务、RTP‑UDP广播、息屏后台保活,1080P@30可稳定输出4Mbps H.264码流。适合旧手机二次利用,本文梳理核心设计思路与踩坑经验。
一、核心能力
说明:当前版本仅输出视频,无音频;UDP广播建议仅在内网可信环境使用。
二、核心架构:同源渲染,一套GL管线输出两路画面
关键收益:旋转、镜像、构图只修改一处,预览和输出码流画面100%保持一致。
关键设计要点
三、相机与分辨率:让设备告诉我们它能干什么
好处:不同机型安装后,只展示硬件真正可运行的档位,不会出现选4K直接黑屏崩溃。
四、MediaCodec低延迟编码配置
五、自研RTSP服务端:避开第三方SDK黑盒
重点坑:FU‑A分片首片必须剥离原始NAL头,否则播放器解析异常出现局部花屏。
解决慢客户端阻塞问题
六、RTP‑UDP广播机制
局限:只收不发的播放器(部分ffplay/VLC)不会发送探测包,15秒会被清理,需要外部定时心跳。
七、后台息屏保活处理
八、高频踩坑清单
九、简单使用示例
RTSP拉流
RTP‑UDP广播
十、总结
限制:无音频,仅适用于局域网,不支持公网穿透。















































































