将中国物联网摄像头变成猫头鹰直播
摘要
一篇博客文章,详细介绍了如何使用S4 Pro中国物联网摄像头和NiView应用程序直播大角猫头鹰巢的过程,并需要技术变通方法才能共享视频流。
<p><a href="https://lobste.rs/s/poxkva/turning_chinese_iot_camera_into_owl">评论</a></p>
查看缓存全文
缓存时间: 2026/07/07 08:14
# 把中国制造的物联网摄像头变成猫头鹰直播 - Vox Silva
来源:https://blog.alexbeals.com/posts/owl-cam
2026年4月15日
我哥哥Spencer(https://www.instagram.com/beals.art)是一位阿什维尔(Asheville)的艺术家。他也热衷于自然保护,带领一个自然笔记课程(https://www.instagram.com/p/C9VEjd1sTUC/),并经常将生态学和当地野生动物融入他的作品中。
为了纪念阿尔忒弥斯二号的近期任务,这里有一幅主题作品(购买印刷品(https://www.spencerbeals.com/product-page/heron))!
artemis-heron(https://blog.alexbeals.com/images/owl-cam/24.jpg)
当北卡罗来纳大学阿什维尔分校(UNC Asheville)宣布计划将当地一片城市森林改造成足球场时,他提出了反对。有关更多信息,请访问保护森林(https://www.saveuncawoods.org/)网站,签署请愿书(https://actionnetwork.org/petitions/petition-to-protect-the-unca-urban-forest/),或关注他的Instagram(@beals.art(https://www.instagram.com/beals.art))获取更多前线更新。
为了提高人们对森林益处的认识,他开始组织自然漫步(https://www.instagram.com/beals.art/p/DV1PyFEEdlG/),布置艺术装置如蝙蝠乐园(Batland)(https://www.instagram.com/p/DSvxQNGAc1B/)(至少直到它被北卡罗来纳大学阿什维尔分校移除(https://wlos.com/news/local/unc-asheville-removes-art-exhibit-south-campus-woods-citing-safety-concerns-university-batland-artist-liability-protest-urban-forest-community-nature-north-carolina)为止。但如果你在该地区并想参观,它已经找到了新家(https://www.instagram.com/p/DTi4JawkcH7/)!),最近还带领观鸟活动(https://www.instagram.com/beals.art/p/DVbfB9UkVTW/),展示一个美洲雕鸮家庭和它们的三个幼鸟。Spencer设置了一个24/7摄像头拍摄它们的巢穴,但想直播那段画面却不知道如何实现——于是我登场了!虽然这不简单(有些人可能会说这是因为过度工程化,我本应该用手机录屏。我会说他们是喷子。),但这里是最终成功的方案(不过不幸的是,当你读到这时,它们已经飞走了,直播也已结束)。
[](https://blog.alexbeals.com/images/owl-cam/17.png)
## 摄像头和App体验
我哥哥最终购买的摄像头是Premium Invention(https://premiuminvention.com/products/wireless-camera-s4-4g)的S4 Pro,他迅速把它放在65英尺高的树上。太阳能板和4G支持使其非常适合设置后遗忘的安全监控,但App的直播体验并不好;画面*是*由一款名为NiView(https://niview.app/)的App控制的,但唯一的查看方式是Spencer(作为摄像头所有者)分享链接。
[](https://blog.alexbeals.com/images/owl-cam/4.png)
[](https://blog.alexbeals.com/images/owl-cam/5.png)
尽管“控制”有点误导,因为摇杆有5秒延迟,而且每次重新连接到设备时,摄像头角度似乎都会重置。
主屏幕列出可用摄像头
可控视角
要求人们下载App并获取链接无法很好地扩展,而且多个连接会迅速消耗摄像头的电池寿命。但它已经安装好了,他不会再爬上去。如果我们能弄清楚摄像头画面如何在App中呈现,本地缓存它,然后在他的网站(https://spencerbeals.com/)上重新广播给任何想看的人呢?我原本以为会有某种Web查看器,或者至少有一些`.m3u8`(标准的流媒体播放列表文件,支持绝大多数直播[需要引用](https://xkcd.com/285/))文件,我们可以获取并直接使用。
## Web查看器死胡同
我做的第一件事是检查是否有Web查看器。虽然这被卖为Premium Invention的S4 Pro,但实际上它只是Nice Intelligence(https://www.niceviewer.com/5-2/)的Y5摄像头的重新包装(而且在AliExpress上售价为其一半(https://www.aliexpress.us/item/3256803798918605.html))。
[](https://blog.alexbeals.com/images/owl-cam/6.png)
[](https://blog.alexbeals.com/images/owl-cam/7.png)
NiView App是Nice Intelligence的App,但他们虽然有适用于Android的`apk`(包括一个针对中国大陆的独立APK,我觉得挺有趣。不知道为什么:我没有用`diff`比较它们。)(https://blog.alexbeals.com/images/owl-cam/8.png)以及iOS应用,但我在`https://niview.app/`和`https://www.niceviewer.com/`上查看的所有链接都没有网页浏览器(尽管Premium Invention的网站声称有。也许这是指这个仅在中国可用的Windows App包装器(https://apps.microsoft.com/detail/xpdctsfdb7x9nk?hl=en-US&gl=CN)?(https://blog.alexbeals.com/images/owl-cam/9.png)),使得提取它变得非常困难。
## `mitmproxy` 死胡同
我关于逆向工程Letterboxd API(https://blog.alexbeals.com/posts/extracting-letterboxd-tokens-with-mitmproxy)的帖子更详细地介绍了如何设置这个,但总的来说`mitmproxy`是在我的笔记本电脑上设置HTTP代理的软件。将我的手机指向它运行所有URL(通常App可以通过说“只有当我与真实服务器通信时才成功”来阻止某些URL,但因为我的手机已越狱(https://blog.alexbeals.com/posts/debugging-fitness-sf-qr#dopamine)并且我运行了“SSL Kill Switch 3”,我可以绕过负责该检查的证书固定。),这些URL是手机通过该代理查询的,我们可以看到它在查询什么以及得到了什么。提醒一下,我在寻找一个明确的请求到某个摄像头服务,我可以将其重新用于广播。不幸的是,情况并非如此:虽然我得到了对`https://cloud-us1.niceviewer.com:8463/v1/device/devices`和`https://cloud-us1.niceviewer.com:8463/v2/device/getDeviceStatus`的请求,但它们只是关于我可以看到哪些摄像头的信息。根据错误页面,这个API使用Spring,根据主IP 301到`https://niview-prod-na-pic-1302374016.cos.na-siliconvalley.myqcloud.com/server_static/index-na.html`,这表明它托管在腾讯云(https://www.tencentcloud.com/)上,类似于他们的AWS。我没有找到任何简单的API文档。
[](https://blog.alexbeals.com/images/owl-cam/10.png)
此外,所有请求响应都是加密的。如果我想进一步挖掘,很明显我必须开始在App里探索。
[](https://blog.alexbeals.com/images/owl-cam/11.png)
## 转储App
默认情况下,Apple应用使用FairPlay(https://en.wikipedia.org/wiki/FairPlay#Apps)加密,但我们可以从已越狱的iPhone中转储加载到内存中的解密应用,使用`bfdecrypt`(详情请参阅我转储Fitness SF App以逆向工程二维码的帖子(https://blog.alexbeals.com/posts/debugging-fitness-sf-qr#dumping-the-ipa))。我们只需要从`https://alias20.gitlab.io/apt/`安装`bfdecryptor`,并为NiView App启用它。然后,当我们打开App时,它会自动下载为`decrypted-app.ipa`。我们可以运行以下命令列出所有下载的包:
```
find /private/var/mobile/Containers/Data/Application -name decrypted-app.ipa -type f | while read f; do \
dir=$(dirname "$f"); \
plist="$dir/../.com.apple.mobile_container_manager.metadata.plist"; \
bundle=$(grep -ao 'com\.[a-zA-Z0-9._]*' "$plist" 2>/dev/null | head -1); \
[ -n "$bundle" ] && echo "$bundle: $f"; \
done
```
其中`com.niceviewer.nview`对应NiView。总是有更多进行中的帖子,Bay Wheels帖子即将推出™。
```
com.fitnesssf.ios: ./9F262F33-1140-4FCB-B76E-6DB1594D2E8F/Documents/decrypted-app.ipa
com.motivateco.gobike: ./E9B21C12-C082-4315-B630-271290AC2902/Documents/decrypted-app.ipa
com.niceviewer.nview: ./CD61972E-8C82-4F94-99D9-4C701C6638D9/Documents/decrypted-app.ipa
```
之后,使用`scp [email protected]:/private/var/mobile/Containers/Data/Application/CD61972E-8C82-4F94-99D9-4C701C6638D9/Documents/decrypted-app.ipa`(这是一个相对较小的文件,48 MB的`.ipa`。作为比较,Instagram目前列为535 MB(https://apps.apple.com/us/app/instagram/id389801252)。)将其本地复制,并重命名为`niview.zip`,我们可以解压缩并检查内部文件。
## Hopper 和 `LLDB`
我主要使用反汇编器(我使用Hopper(https://blog.alexbeals.com/posts/reverse-engineering-ios-deeplinking-for-shortcuts#hopper))和`lldb`。当你点击进入一个画面时,会显示诸如“设备正在连接...”和“通信模块正在网络连接...”之类的消息。尽管有语法错误,但我认为这是一个检查类是否初始化服务器连接的合适起点。
[](https://blog.alexbeals.com/images/owl-cam/12.PNG)
通常,你可以通过搜索Hopper中的`.app` Strings部分找到这些,但这次没有结果,所以我转而检查了`en.lproj/Localizable.plist`中的本地化字符串(`rg --binary "The communication module is networking"`也有助于缩小位置。),它有用地将此映射到…… `Loading_Fake_Tips_Networking`。
[](https://blog.alexbeals.com/images/owl-cam/13.png)
[](https://blog.alexbeals.com/images/owl-cam/14.png)
*Hopper Strings 视图* *Localizable.plist*
用Hopper快速检查表明,它只是每隔几秒将一个`Loading_Fake_Tips`附加到UI上作为占位符,同时在后台执行实际操作。
[](https://blog.alexbeals.com/images/owl-cam/15.png)
让我们用`lldb`试试另一种方法!使用`ps aux`,我可以识别正在运行的App的PID为508:
```
> ps aux | grep Bundle/Application
mobile 632 2.1 0.2 407918656 3120 s000 R+ 9:24AM 0:00.03 grep Bundle/Application
mobile 599 0.0 0.6 407955328 11728 ?? Ss 9:23AM 0:00.34 /private/var/containers/Bundle/Application/390E30D0-E390-4DBC-BA3B-46666CA028E4/SequoiaTranslator.app/PlugIns/CacheDeleteExtension.appex/CacheDeleteExtension -AppleLanguages ("en-US")
mobile 569 0.0 0.0 408064400 464 ?? Ss 9:23AM 0:00.00 /var/containers/Bundle/Application/60422DE1-AF5C-457A-9114-D12247C5C353/Spotify.app/Spotify
mobile 508 0.0 2.0 408613936 42000 ?? Ss 9:22AM 0:02.39 /var/containers/Bundle/Application/65F285D6-1496-42D2-8525-09E971EF236E/NiView.app/NiView
```
然后在我的iPhone上,我可以使用`debugserver-16 "0.0.0.0:1234" --attach=508`来设置一个可以连接的LLDB服务器。你可以在这篇之前的帖子(https://blog.alexbeals.com/posts/debugging-fitness-sf-qr#attaching-lldb)中看到更多细节。从笔记本电脑的另一个终端窗口,我可以运行`lldb`和`process connect connect://192.168.0.247:1234`来连接到该运行实例。导航到摄像头画面并运行`process interrupt`和`po [[UIWindow keyWindow] recursiveDescription]`也能很好地了解UI布局。特别是`NVLivePlayerView`和`IVVideoRender`感觉是最佳候选。
```
; layer = > | > | | > | | | > | | | | > | | | | | > | | | | | | ; layer = > | | | | | | | > | | | | | | | | > | | | | | | | | | > | | | | | | | | | | > | | | | | | | | | | | (layer) | | | | | | | | | | > | | | | | | | | | | | ; layer = ; contentOffset: {0, 0}; contentSize: {375, 421.875}; adjustedContentInset: {0, 0, 0, 0}> | | | | | | | | | | | | > | | | | | | | | | | | | | ; layer = > | | | | | | | | | | | > | | | | | | | | | | | > | | | | | | | | | | | | > | | | | | | | | | | | > | | | | | | | | | | | | > | | | | | | | | | | | | > | | | | | | | | | | | > | | | | | | | | | | | | > | | | | | | | | | | | | | > | | | | | | | | | | | | > | | | | | | | | | | | | | > | | | | | | | | | | | > | | | | | | | | | | | | | > | | | | | | | | | | | > | | | | | | | | | | | | ... | | | | | | | | | | | > | | | | | | | | | | | | ... | | | | | | | | | | | ; layer = > | | | | | | | | | | | | ... | | | | | | | | | | > | | | | | | | | | | | ... | | | | | | | | | | > | | | | | | | | | | | ... | | | | ; layer = > | | | | | ... | | | | > | | | | | ...
```
在Hopper中检查`IVVideoRender`会得到`-[IVVideoRender startRenderingWithAVHeader:channel:dataSource:]`方法,但它只获取渲染尺寸和像素格式。它还直接调用IoTVideo SDK,这让我不太有信心逆向工程这个连接会很简单。
[](https://blog.alexbeals.com/images/owl-cam/16.png)
深入挖掘`IoTVideo`类和`IVConnection`发现,它作为`[IoTVideo _registerWithAccessId:accessToken:]`的一部分向`IOT_HOST_P2P`发起请求。这个字符串指向`list.iotvideo.tencentcs.com`,用于通过腾讯服务器建立P2P中继。P2P代表点对点,这意味着如果我物理上在阿什维尔附近靠近摄像头,我可以直接连接到它。另一方面,从旧金山连接则需要腾讯更多的帮助。我们可以通过在iPhone初始化连接时使用`tcpdump -i en0 -w /tmp/capture.pcap`来证实这一点,并看到加密的P2P视频数据的握手。无论是在Wireshark(https://www.wireshark.org/)中,还是通过LLM使用`tshark`分析它(鉴于我对Wireshark的了解充其量只是皮毛),逆向工程这一点感觉是可行的,但需要足够的努力(归根结底,它只是代码),但我在网上或GitHub上搜索这些类和URL时没有找到其他人这样做的强有力线索。所以让我们作弊。
## 构建一个iOS插件来重新广播画面
确实,我们没有清晰的路径了解`IVVideoRender`如何获取帧数据。但我们知道它*获取*了帧数据,并且它通过`_renderVideoFrame`渲染帧。因为我的iPhone已越狱,我们可以编写我们自己的插件代码。然后我们可以将该代码注入到NiView App中:当它渲染一帧时,我们抓取数据,将其从YUV数据格式转换为JPG(这是一个术语的滥用。YUV是一种像RGB一样的颜色表示方法,但RGB将每种颜色表示为**R**红、**B**蓝和**G**绿的组合,而YUV则用亮度值Y和两个色差通道U和V来表示。这是从黑白电视过渡到彩色电视时通过附加更多信号而留下的产物,但像所有标准(https://xkcd.com/927/)一样,没有什么是会消亡的。另一方面,JPG是一种图像文件格式,而不是颜色表示法。它偶然地在内部使用类似于YUV的东西(YCbCr)来能够以不同于亮度(人类视觉擅长亮度,但不擅长颜色)的方式压缩颜色,但因为我是通过`CGImage`创建图像,所以实际上是YUV -> RGB -> YCbCr到JPG。),并将其流式输出到一个URL,然后我们可以从该URL读取并重新广播。我过去开发过很多插件:ShiftCycle(https://blog.alexbeals.com/posts/shiftcycle)、Mercury(https://blog.alexbeals.com/posts/mercury-tweak-and-fun-code)(这是我个人最喜欢的。我老实说仍然会越狱以便能够使用它。)、OnceMore(https://blog.alexbeals.com/posts/oncemore)(现在很幸运地已包含在标准iOS中)以及Grayscale Lock(https://blog.alexbeals.com/posts/grayscale-lock-combating-phone-addiction)(我现在用快捷指令(https://blog.alexbeals.com/posts/make-your-phone-grayscale)来实现),等等——但自大学以来我就没再构建过。我*过去*直接在我的iPhone上进行构建,但现在我们在Mac上做,完成后用`scp`传输过去。所以我必须重新发现如何做到这一点!
作为第一步,我使用以下命令安装了Theos(https://github.com/theos/theos)。Theos是一个基于Make(https://www.gnu.org/software/make/)的构建系统,曾经是插件开发的主流框架(不确定现在是否仍是这样,但我当然不会去学一个新的)。
```
bash -c "$(curl -fsSL https://raw.githubusercontent.com/theos/theos/master/bin/install-theos)"
```
我的越狱iPhone运行的是iOS 15.8.4。我们需要下载相关的
相似文章
我将我的安全摄像头改造成了自动鸟类识别系统
本文详细介绍了如何将安全摄像头与BirdNet-Go工具集成,以创建一个实时鸟类识别系统,利用本地AI模型进行音频检测并支持社区数据共享。
鸟类访客
一个在阳台上安装USB麦克风捕捉鸟鸣的项目,使用BirdNET-Pi进行物种识别,并在网站上叠加花鸟画拼贴展示。
@itsolelehmann: 我真的很喜欢这些AI与动物的结合。这款AI喂鸟器是我近期见过的最酷产品创意之一。 …
一款AI喂鸟器使用多个摄像头和AI技术识别鸟类物种,自动记录访问,并将视频片段发送到用户的手机上,配有太阳能充电功能,适合户外使用。
为可伸缩网络摄像头打造定制支架
一篇个人博客文章,详细介绍了可折叠伸缩网络摄像头支架的设计与制作过程,该支架通过连接显示器的VESA接口来改善视频通话中的眼神交流。
Show HN: CheapSecurity – 轻量级自托管CCTV,适用于Linux单板计算机
CheapSecurity 是一个轻量级、自托管的CCTV解决方案,适用于Linux单板计算机,提供注重隐私的家庭监控,支持运动检测、录像和Telegram提醒,无需云订阅。