米家摄像头RTSP拉流实战:清晰度配置与音频传输完整方案

发布时间:2026/9/8 10:45:32
米家摄像头RTSP拉流实战:清晰度配置与音频传输完整方案 直接说结论如果你手里有台米家摄像头又不满足于App里那几个固定档位想把它真正接进自己的播放链路、想让RTSP流里也带上声音那Miloco v0.1.6这个版本值得你花十分钟好好看看。Miloco是我一直在维护的一个小工具定位很纯粹不搞云平台不做App替代品只在局域网里把米家摄像头的能力“抠”出来用。v0.1.6这版主要补了两块一是清晰度配置不再是App里“自动/高清/超清”这种黑盒切换而是直接把分辨率、码率、帧率、关键帧间隔这些参数拿到手二是RTSP音频传输让拉出来的视频流不只是画面还能把摄像头的声音一并带走。这正好解决了家用摄像头二次开发里最常遇到的两个问题。这篇记录适合手里有米家/小米摄像头、正在折腾RTSP拉流、或者想把它接进自己视频系统的人看。无论你是想接到HomeAssistant、NVR还是只为了在电脑上用一个趁手的播放器看监控画面下面的内容都可以直接照着抄。1. 项目概述与需求拆解1.1 Miloco到底解决什么问题先说说我为什么会写这个东西。米家摄像头的App做得确实顺手远程看画面、云台控制、回放都挺省心。但一旦你想把摄像头的视频流接入到自己的系统里问题就来了。第一个坑是取流方式。米家摄像头默认支持RTSP协议拉流但很多教程只告诉你“输入一个地址就能看”没人告诉你这个地址背后其实还有一堆参数可以调。比如画质档位App里只有几个按钮可实际摄像头固件里同时支持多档分辨率、码率、帧率组合只是你够不到而已。第二个坑是音频。RTSP拉出来的视频流经常是纯视频或者虽然有音频流但播出来要么没声音、要么格式不被播放器识别。我一开始也以为摄像头麦克风坏了后来抓包才发现是音频编码和传输方式的问题。于是我在v0.1.6里专门做了音频传输这块的兼容处理。说白了Miloco就是一个“能力解锁器”。它通过局域网访问摄像头控制接口把清晰度相关参数用代码方式直接配置进去同时把RTSP的音频通道打通。整个工具是命令行式的没有花哨界面但每一步做什么、返回什么结果都写得清清楚楚。1.2 核心能力拆解清晰度配置与音频传输把v0.1.6的功能掰开来看其实就是两条线。清爽度配置这条线Miloco做的不只是“把分辨率从720p切到1080p”这么简单。它会先向摄像头查询当前支持的编码参数范围再根据你的目标档位计算出一个合理的组合包含分辨率、视频码率、视频帧率、关键帧间隔这四项。这四个参数互相牵制分辨率上去了码率跟不上画面就糊帧率太高码率不足时会出现明显马赛克。Miloco会把设置结果回读一遍确认写进去的参数真的生效了这个“回读校验”是我踩过坑之后才加上的。音频传输这条线核心解决的问题是“RTSP流里有音轨但播放端拿不到”。我实测发现某些固件版本里摄像头默认走的是复合流传输方式视频和音频混在一起不少播放器直接不认还有的摄像头把音频格式固定成了G711A而电脑上的播放器默认按PCM解码自然就出怪声或者没声音。Miloco的做法是在拉流时主动携带音频参数协商能力并提供一个转封装命令把摄像头输出的音频流统一转成播放器更友好的格式再输出。2. 原理拆解米家摄像头的RTSP与清晰度控制2.1 RTSP拉流协议到底是什么RTSPReal Time Streaming Protocol全称实时流传输协议。你可以把它理解成一个“播放控制通道”。它本身不负责传视频数据而是负责协商客户端告诉服务器“我要看哪路流、用什么方式传、用TCP还是UDP”服务器返回“好的数据开始发往某端口”。举个例子你用播放器打开一个RTSP地址播放器会先发一个OPTIONS请求看看服务器支持哪些命令接着发DESCRIBE问清楚这个流里面有几个轨道、视频是什么编码、音频是什么编码、分辨率多少再然后发SETUP把传输通道建立起来最后发PLAY画面就出来了。这四步的前三步都是文本协议用Wireshark抓包可以直接看懂没有加密这也是调试RTSP时最有用的地方。所以RTSP拉流本质上是个“先谈再传”的过程。理解这一点后面排查问题就有方向了。比如播放器中打开地址一直转圈但不出画面很多情况下是SETUP阶段协商失败而不是画面数据本身的问题。再比如为什么有些地址带端口号有些又是默认554端口不写其实都是协商路径不同。2.2 RTSP地址构造与取流示例RTSP地址的格式通常是这样rtsp://[用户名:密码]IP地址:端口/流路径常见端口默认是554但很多设备为了区分多路流或者其他原因会改端口。米家摄像头不同型号的路径也不完全一样我手上这台v0.1.6调试通过的典型格式是rtsp://192.168.1.100:554/stream1也有的固件支持按通道区分主码流和子码流类似于rtsp://192.168.1.100:554/ch0_0.h264 rtsp://192.168.1.100:554/ch0_1.h264这里多说一句海康威视的经典取流地址是/ch1/main/av_stream和/ch1/sub/av_stream分别对应主码流和子码流。虽然品牌不同但地址规律是通用的同一个摄像头通常有两路流主码流清晰度高适合本地录像和全屏观看子码流画质低但带宽占用小适合手机远程预览和网格视图。Miloco清晰度配置里也保留了选择主码流还是子码流的选项。我在本地实测时用的是这样一条完整命令ffprobe -v trace -rtsp_transport tcp -i rtsp://192.168.1.100:554/stream1正常响应后你应该能在输出里看到类似信息Stream #0:0: Video: h264 (High), yuv420p(progressive), 1920x1080 Stream #0:1: Audio: aac, 16000 Hz, mono看到两行Stream说明视频和音频轨都在这一步能跑通后面就省心多了。2.3 清晰度配置的实现思路这一块是最容易让人卡住的地方。很多教程讲到RTSP拉流就结束了但“怎么把清晰度从720p调成1080p”能找到的资料并不多。米家摄像头App里的画质切换底层其实是在修改一组编码器参数只是App把它封装成了“自动”“高清”“超清”这种档位。Miloco的做法是绕过App这一层直接在局域网里访问摄像头的控制接口把参数精确地写进去。有两条路径可以实现这个目的。有些摄像头支持ONVIF标准协议通过ONVIF的SetVideoEncoderConfiguration可以设置分辨率、码率上限、帧率等。ONVIF的好处是标准化程度高只要设备支持不需要逆向私有协议。另一条路径是调用摄像头厂商的局域网私有接口比如米家系的摄像头大多有一套自己的控制API通过HTTP POST发送JSON数据来改参数。Miloco的清晰度配置模块优先走ONVIF探测探测不到再尝试私有接口算是兼容性优先的做法。实际配置时需要关注四个参数分辨率决定画面的像素总量一般有1920x1080、1280x720、640x360等档位。视频码率单位kbps码率决定数据量大小。1080p下建议设置在2048到4096之间。视频帧率每秒多少帧画面常见的是15fps、20fps、25fps。不是越高越好帧率太高发热和带宽都会上来。关键帧间隔每多少个普通帧插入一个I帧I帧越多拖动进度条时出画面越快但码率消耗越大。这四个参数互相影响缺一不可。我第一次做清晰度配置时只改了分辨率和码率结果画面临时提高但声音画面不同步就是因为帧率没有同步调整。调试久了我总结出一个习惯改清晰度的同时一定要把码率、帧率、关键帧间隔放在一个配置事务里一起下发避免参数被切到一半的状态。3. Miloco v0.1.6实操过程3.1 环境准备与安装实操之前先把环境准备好。Miloco是命令行工具依赖比较轻python3.8以上就行额外需要requests库和ffmpeg工具链。在Ubuntu或者树莓派上安装依赖sudo apt update sudo apt install python3 python3-pip ffmpeg pip3 install requests然后把Miloco仓库拉下来进入目录后直接看帮助python3 miloco.py --help能看到子命令列表v0.1.6里有几个关键子命令config list列出当前摄像头支持的清晰度参数组合。config set下发清晰度配置。stream info查看RTSP流的实时信息包括实际码率、分辨率。audio fix对音频传输做兼容处理把音频转封装成目标格式。我觉得“先list再set”是特别重要的习惯。不同型号摄像头支持的参数范围不一样比如同是1080p有的设备码率上限是6144kbps有的只有4096kbps。如果直接set一个超范围的参数设备可能直接忽略或者写入成功后实际不生效。先用list拿到真实范围再按范围取值能避免不少无效操作。3.2 清晰度配置实战假设我现在想把这台摄像头的主码流配置成1080p、25fps、中等偏上的画质。先执行python3 miloco.py config list --host 192.168.1.100 --channel 0返回结果大概长这样Channel 0 supported configs: 1920x1080 25fps, bitrate 2048-6144, gop 25-60 1280x720 30fps, bitrate 1024-4096, gop 25-60 640x360 25fps, bitrate 512-2048, gop 25-60我选择1080p、码率3072kbps、帧率25fps、关键帧间隔40参数组合比较均衡。执行python3 miloco.py config set --host 192.168.1.100 --channel 0 \ --width 1920 --height 1080 --bitrate 3072 --fps 25 --gop 40Miloco下发配置之后会马上回读一次摄像头当前的编码参数确认写入值和目标值一致。这一步回读很关键我在开发的时候发现有些设备的固件会把不支持的参数“静默丢弃”也就是说你下发1080p它不报错但实际还是按720p跑。有了回读校验假配置就不会被误以为成功。改完配置后用ffprobe再次验证这时候分辨率应该已经变成1920x1080ffprobe -rtsp_transport tcp -i rtsp://192.168.1.100:554/stream13.3 RTSP音频传输打通音频传输这块是我的v0.1.6重点改的部分。先解释一下为什么默认状态下拉流有时候没声音。RTSP的音频传输有两种主流做法。一种是视频轨和音频轨分开用不同的RTP端口传输这叫“独立RTP传输”还有一个是视频音频打包在同一条RTP流里复用同一个端口此时需要用RFC 7826里定义的方式把多个轨道交织在一起。后者的好处是穿透性更强但对播放器的要求也更高不是所有播放器都支持“交织传输”。米家摄像头某些固件默认就是交织模式用VLC播放没问题但换某些轻量播放器就可能只有画面没有声音。Miloco的处理思路是拉流时强制要求服务器把音视频轨分开传输。在RTSP的SETUP阶段客户端可以指定transport方式Miloco会主动声明可以接收raw udp、interleaved、tcp三种模式并优先使用tcp下的交织方式。这个策略实测下来兼容性最好。如果摄像头本身提供的音频编码格式是G711Aalaw而你的播放链路只认AACMiloco提供了一个转封装命令python3 miloco.py audio fix --input rtsp://192.168.1.100:554/stream1 \ --output udp://127.0.0.1:5000 --audio-codec aac这是通过ffmpeg的转封装能力实现的先拉流再把音频轨用AAC编码后重新封装成RTSP流输出到本地另一个端口。这样你既保留了原摄像头的视频编码不动又让下游播放器拿到一个音频格式更友好的流。视频编码转换开销大所以只转音频是性价比最高的做法。3.4 验证播放ffplay、VLC与抓包对照配置都做完以后验证是少不了的。我最常用的验证工具是ffplay因为它启动快还能看到实时的流信息ffplay -rtsp_transport tcp -i rtsp://192.168.1.100:554/stream1如果看到画面且右下角有声音波动条说明视频和音频都通了。VLC也可以但VLC默认会用UDP传输在某些Wi-Fi环境下会断流。建议在VLC里手动设置工具-偏好设置-输入/编解码器把“Rtsp over TCP”勾上这样稳定很多。喜欢用命令行验证也可以试一下avprobe或者avpro系列的播放工具原理都一样关键看是否能拉出带音轨的流。我用ffprobe验证时会专门看两行Stream信息一条Video一条Audio这比看画面更直接。还得会抓包。RTSP控制命令走的是TCP 554端口视频数据走的是RTP抓包的时候需要同时观察。比如你在Wireshark里看到DESCRIBE请求和200 OK响应都正常但没有SETUP和PLAY那基本可以判断是播放器在协商阶段就放弃了问题出在客户端而不是摄像头。这时候换一个播放器测试或者检查URL路径是否正确比盲目调摄像头配置有效得多。3.5 工具选型对照我开发Miloco过程中对比过几类工具顺便列个表方便你按场景选择工具/方案适合场景优点局限ffmpeg / ffprobe拉流、转码、验证功能全几乎所有格式都能处理命令行操作上手门槛略高VLC人工查看画面图形界面操作简单默认UDP传输Wi-Fi下易断GStreamer自建RTSP服务、链路测试组件化强可灵活拼装管道调试命令比较复杂新手不友好Miloco米家摄像头配置音频兼容针对性强一个命令闭环只覆盖局域网场景选工具的关键看你要做什么只是看一眼画面用VLC要自动化处理用ffmpeg要想测试RTSP服务器本身GStreamer是首选要操作米家摄像头参数Miloco就是那把最趁手的螺丝刀。4. 常见问题与排查实录4.1 Wireshark看不到RTSP包怎么办这个坑我見过很多人栽在上面。摄像头RTSP端口如果没有用默认的554而是用了一个自定义端口Wireshark默认不会把它识别为RTSP协议。这时候你抓到的包要么是“Unknown”要么是一堆看起来像乱码的TCP数据段。解决方法有两个。最简单的就是右键任意一条TCP包选择Decode As在列表里把协议指定为RTSP。另一个更持久的方法是Edit - Preferences - Protocols - RTSP在TCP Port列表里加上你摄像头的端口号。这样Wireshark就能自动识别。还有一点RTSP over TCP和RTSP over UDP的抓包结果完全不一样。RTSP本身是基于TCP的RTP数据一般走UDP。如果你看到Wireshark里只有TCP的SETUP/PLAY信息没有RTP数据显示多半是播放器还没开始真正拉流或者数据走的是interleaved模式RTP包被封装在TCP里面发Wireshark里要展开TCP段才能看到RTP内容。4.2 有画面没声音的排查步骤画面正常但没有声音这是RTSP播音最经典的问题。按下面的顺序排查基本能定位到80%的原因。第一步先确认摄像头本身是否采集到声音。用一个支持RTSP的播放器打开看音频轨道信息。如果Stream信息里压根没有Audio这一行说明摄像头那边的音频通道没启用去摄像头设置里开启麦克风或者检查隐私权限。第二步确认音频编码。如果ffprobe显示Audio是alaw或mulaw但你的播放链路只支持AAC那就是编码格式不匹配。我上面提到过Miloco的audio fix子命令就是为这种情况准备的先用它把音频转成AAC再喂给下游。第三步确认播放器解码配置。有些播放器默认把G711A当成PCM来解声音会变成刺耳的噪音这种情况不是流有问题是播放器解码规格选错了。另一些播放器需要手动启用第二音轨检查一下有没有“声音被静音”这种低级错误——我调试的时候不止一次发现自己犯了这种错误。4.3 移动端播放卡顿和缓存问题在安卓手机上播放RTSP流时很多播放器默认会把整个音频流缓存到播放器本地再播放导致画面延迟越来越高。RTSP本身是流式协议不适合用整段缓存的方式播放。解决办法是尽量选择支持低延迟模式的播放器或者让播放器走TCP模式而不是UDP模式。UDP在局域网里延迟低但丢包会直接造成花屏TCP传输虽然增加了一点封装开销但重传机制让画面更稳定。对于本地摄像头监控场景我强烈建议RTSP over TCP。还有一个容易忽略的点米家摄像头的子码流和主码流在移动端的体验差异很大。如果你在手机上看流带宽一般都不是问题但解码能力可能不够。老一点的手机播放1080p主码流会发热、掉帧这时候把播放端切到子码流画面虽然不如主码流精细但流畅度会好很多。Miloco支持选择通道道理就在这里——不是所有场景都要最高码率的。4.4 用GStreamer搭一个模拟RTSP源来测试有时候摄像头不在手边但你得调播放器或者测试拉流命令。这时候我习惯用GStreamer直接在本地搭一个模拟RTSP源把一条标准测试流发出去。GStreamer自带rtsp服务器示例编译后进入gst-rtsp-server目录执行./test-launch videotestsrc ! x264enc ! rtph264pay namepay0 pt96执行后会在本地起一个RTSP服务器默认地址是rtsp://127.0.0.1:8554/test。这时候用任意播放器打开这个地址就能看到有一个彩条测试画面在动。这个模拟源对调试播放链路特别好用——如果模拟源能播放但摄像头不行问题大概率出在摄像头那侧的地址或编码参数上如果模拟源也播放不了那就要回头查播放器配置和网络。如果需要音频测试把audiotestsrc加进管道里./test-launch videotestsrc ! x264enc ! rtph264pay namepay0 pt96 ! audiotestsrc ! voaacenc ! rtpmp4apay namepay1 pt97这样拉流后应该能听到一个持续的单频测试音视频画面彩条也在动。用来验证你手里的播放链路支不支持音视频同时播放非常直观。注意GStreamer的管道是一个很灵活的东西不要被它生成的命令行长度吓到核心思路就是“生成视频源 - 编码 - RTSP打包”只是多段用感叹号串起来而已。调试完毕之后用同样的方法测试真实摄像头画面清晰、声音正常这一套链路就算彻底打通了。5. 实测心得与扩展方向5.1 参数选择画质和稳定性的平衡v0.1.6开发和调试过程中我自己手里的摄像头反复验证了不少参数组合有一点心得想单独说一下。米家摄像头这类家用设备实际用下来最稳的1080p配置是码率3072kbps、帧率25fps、关键帧间隔40。码率再往上提到4096画面细节会多一些但Wi-Fi环境不好时容易在RTP传输阶段丢包画面出现花块的概率明显上升。帧率25fps足够日常监控比30fps省带宽而且夜间低照度环境下25fps和30fps的观感差异几乎看不出来。音频侧米家摄像头自带麦克风音频采样率一般是16000Hz单声道这个规格在智能家居环境里听人声、报警声完全够了。要转AAC的话建议固定AAC-LC采样率不变码率64kbps。高于64kbps不会有可感知的提升低于48kbps的话人声会有明显压缩感。如果你有录像需求我特别推荐一个做法主码流保持高的清晰度用来保存录像子码流调低一档用来实时预览和手机端播放。Miloco里可以分开配两路流的参数这个思路实现起来不麻烦但使用体验的提升是实打实的。5.2 把Miloco接进自己的播放链路很多朋友折腾这个不是为了看个画面而是想把摄像头接进自建的智能家居系统或者视频监控平台。Miloco v0.1.6的好处是它并不绑定你的下游系统它做的是把米家摄像头的音频和清晰度问题处理成“标准RTSP输入”下游不管是HomeAssistant、NVR还是自研播放器你只需要把拉流地址指到Miloco处理过的那一路流上即可。比如我目前的使用场景是白天用默认RTSP地址直接接入HA摄像头配置由Miloco管理晚上或者长时间录像时把音频修复后的本地流地址接到NVR做不间断录制。这个链路的好处是保住了原始视频画质又给下游系统提供了统一的音视频格式接口避免因为格式兼容性反复折腾。5.3 关于后续版本的一些想法v0.1.6解决了清晰度配置和音频传输两个主要难点但说实话还有不少可以优化空间。比如目前音频修复是通过转封装实现的转封装会在局域网里增加一跳后续版本我想尝试直接通过RTSP协商让摄像头原生输出AAC格式省掉这一步。还有就是对多摄像头批量配置的支持现在还是一个一个来后续打算加一个配置文件批量下发的功能。另外我观察到一个有意思的场景Unity这类游戏引擎里播放RTSP视频流确实是很多做数字孪生项目的人会碰到的需求。Unity本身不内置RTSP解码一般需要通过插件或者转成低延迟流再喂给引擎。Miloco这种“中间层兼容”的思路其实很适合这种情况——它不管引擎那边怎么解码只保证推给引擎的流是标准的、带音频的。以后有条件我想针对这个场景写一个专门的适配模块。最后再分享一个实际操作中的小技巧改摄像头参数前先截图保存一下当前的完整配置万一新参数不理想恢复原配置会方便很多。我就是因为在一次夜间调试中乱调了一通参数导致画面丢失了一晚上从此养成了每次操作都先备份的好习惯。