所有人都在说 AI 会写代码。可它真能帮你做出一个跨平台、能远程控制、还端到端加密的软件吗?我用一台云服务器和一个 AI 帮手,认真试了一次——结论既兴奋,又清醒。
AI 实践 · 工程复盘 · 一个人造软件 | 约 8000 字 | 含封面 + 6 张示意图
写在前面:这不是一篇炫技教程,而是一份很诚实的复盘。在「人人都说 AI 会写代码」的今天,我用 AI 当帮手,从零做了一套能在 Mac、Windows、iPhone 之间互相远程控制的软件——对标的就是向日葵、ToDesk。AI 让我起步快得不真实,可真正把它从「能连上」做到「稳得住」,才是这趟旅程真正的主角。而这中间的落差,恰好就是今天 AI 编程的能力边界。

一、远程控制,真有看上去那么简单吗
远程控制,听起来是个早就被解决的问题。向日葵、ToDesk、TeamViewer,下载、登录、授权,几分钟就能在手机上看到家里电脑的屏幕,点点划划像在本地操作一样。我也一直这么以为,直到我决定亲手做一个。
我想做的原因有两个。第一个很朴素:我想要一套「中继服务器是我自己的、画面不经过任何第三方」的远控。第二个更像一场赌气式的好奇——这两年所有人都在喊 AI 会颠覆编程,那我就想亲自验证一个问题:AI 时代,一个不算大神的人,借助 AI,到底能做出多复杂的软件?
而远程控制,恰好是检验这个问题的绝佳试金石。它不像一个待办清单 App 那样可以一个人糊弄出来,它横跨了操作系统的权限体系、实时视频的编码解码、复杂网络的穿透、鼠标键盘的注入、设备之间的安全配对,还有最后的打包分发。几乎一个「完整软件」该有的硬骨头,它一根都没落下。
做下去我才发现:远程控制根本不是一个「把屏幕画面发出去」的小工具,它是一套伪装成 App 的、小型的实时操作系统。
二、AI 帮我把原型跑起来,快得不真实
刚开始的体验,简直让人飘飘然。把 AI 当副驾驶,搭骨架的速度快得离谱:在阿里云上立起一个充当「中间人」的中继服务器,让 Mac 当被控端去采集屏幕、把画面发出去,让手机当控制端去接收画面、把点击发回来,再用一个房间号加访问码把两边配上对。原型很快就连起来了,我第一次在手机上看到家里 Mac 的桌面时,差点以为:原来做软件这么简单。

我搭的整体结构:云服务器只当「中间人」,负责把两台设备接起来、转发数据,但看不到你屏幕上的任何内容。
然后,现实开始一个接一个地打脸。Windows 端能连上服务器,画面却一直是黑的;Mac 明明在系统设置里授权了,App 却还固执地提示没授权;高级一点的画面解码,在某些电脑上直接报错崩掉;控制端一连进来,被控端的画质设置竟然莫名其妙地自己变了;画面有时像卡在某个窗口上动不了;iPhone 上画面小得可怜,手指一点就点偏到隔壁。
这些问题,AI 在我动手之前,一个都没提醒过我。它们不在任何「快速上手」的教程里,而是埋在「跑起来之后」的真实世界里。原型阶段那种「我上我也行」的轻飘飘,在第一次把软件发给朋友试用、对面回我一句「怎么是黑的」的时候,碎得干干净净。
我后来才慢慢体会到,做软件这件事,真正的难度曲线长得很反常:前面 20% 平得像散步,AI 推着你几小时就走完;后面 80% 陡得像爬墙,而且每一步都没有路标。原型让你产生「快做完了」的错觉,可那条横在「能演示」和「能交付」之间的鸿沟,才刚刚露头。
AI 能让你「开始」,几乎是免费的。但它不会提前告诉你:真正的工程量,全藏在「开始」之后。
三、第一个暴击:连上了,却一片漆黑
所有问题里,最折磨人的是黑屏。控制端屏幕上清清楚楚写着「已连接」,被控的电脑也显示在线,房间号、访问码、地址全都核对过无数遍,可那块屏幕,就是黑的。
我和大多数人一样,第一反应是去怀疑显示出了问题,去怀疑解码器坏了。那一晚,我对着接收画面的那段逻辑改了又改、删了又加,试了不下二十种写法,黑屏纹丝不动。最崩溃的不是修不好,而是我连「到底是哪一环坏了」都不知道——就像房间里一片漆黑,你却不知道是灯泡坏了、是没插电、还是整栋楼都停电了,只能闭着眼睛瞎摸。
转机来自一个我顺手做的小东西——我给服务器加了一个「体检接口」,它能告诉我每个房间最真实的状态:被控端在不在线、它到底往外发了多少帧画面、最后一帧是什么时候发的。这个当时随手加的小功能,后来成了整个项目里我最庆幸做过的决定。
我一看就傻了。被控端明明显示「在线」,可它发出去的画面帧数,是 0。
「已连接」是世界上最具迷惑性的三个字。它只说明两台电脑握了个手,根本不代表有任何一帧画面,真的在它们之间流动过。

黑屏排查地图。「已连接」根本不代表有画面,关键要看被控端这一秒到底有没有在往外吐画面。
顺着这条线查下去我才发现,「黑屏」其实是好几种完全不同的病,只是症状长得一样:有时是屏幕录制权限没被系统真正给到;有时是系统采集屏幕的功能中途停了,却没有自动自救;有时是高级编码用不了,又没有及时退回到最朴素的兼容方案。而最阴险的一种,是控制端本来只想「表达一下自己的偏好」,却被错当成了一道命令,把被控端的画质给「遥控」着改掉了。
从那以后,我把黑屏排查固化成了一条铁律:先别急着怀疑显示和画面,先冷静地问一句——被控端这一秒,到底有没有在往外吐画面?把这条链路一节一节拆开看,黑屏就从一句模糊的抱怨,变成了一个可以精确定位的工程问题。
四、我才真正明白,远控根本不是「投屏」
投屏只需要一条路:把画面送过去就行。但远程控制,要同时跑通三条路,缺一条都不行。
·画面链路,让你「看得见」——采集、压缩、传输、还原、显示,一条龙不能断。
·控制链路,让你「点得到」——你在手机上点的那个位置,要被精确翻译成远端电脑某一个像素上的一次真实点击。你把画面放大、拖动之后,下一次点击还得依然准。
·观测链路,让你「查得出」——上面任何一条断了,你都得能第一时间知道是哪儿断的。

远控不是投屏:必须同时跑通「看得见」「点得到」「查得出」三条链路,缺一条,用户就说不能用。
有意思的是,几乎所有人(包括一开始的我)都只盯着第一条:画面好不好看、清不清晰。可真正决定一个远控「能不能用」的,往往是后两条。画面再清楚,点不准也是废的;出了问题两眼一抹黑、连哪坏了都不知道,那就更没法修。
用户说「不能用」的时候,十有八九不是因为画面不好看,而是因为点不准,或者根本不知道哪里坏了。
这里我做的一个最关键的决定,说出来特别朴素:所有的坐标,我都不用具体像素,而是用「占整块屏幕的百分比」来表达。比如「屏幕正中间」就是横竖各百分之五十。这样一来,不管远端是台小破屏还是 5K 大显示器,中途有没有换过分辨率,控制都不会错位。一个看似不起眼的选择,却把「控制」和「屏幕尺寸」这两件事彻底解耦了。
而手机端的「点得到」,又是另一座大山。鼠标天生精准,手指却又粗又胖;屏幕又小,画面缩成一团,想点中一个小按钮几乎是抽奖。于是我得让用户能像看地图一样双指放大、按住拖动画面,可一旦放大、平移之后,「手指点的位置」和「远端真正该响应的位置」之间的换算,就得重新算一遍,错一点就点偏。把缩放、平移、裁剪和那套百分比坐标拧成同一套逻辑,我前后返工了好几次,才让 iPhone 上「看到哪、点到哪」这件最基本的事,变得理所当然。
五、画质、流畅、延迟,凭什么不能我全都要
做实时画面,绕不开一个残酷的三角:画质高、延迟低、什么破设备烂网络都能跑——这三样,很难同时拿满。
高级的视频编码方案,画质好、还省流量,但它太挑环境,跨平台时经常是「这台电脑能压,那台电脑却解不开」。而最老实巴交的图片方案,哪里都能显示、出了问题一眼就能看出来,缺点是费流量、帧率一高就容易卡。传输方式也是同理:一种简单、稳定、出问题好排查;另一种延迟更低、但实现复杂得多。

画质、流畅、兼容性的取舍。稳定的秘诀不是堆最高配,而是给每一种高级方案都留一条能用的退路。
踩了一圈坑之后,我的结论不是「全都上最高配」,而是一句更朴素的话:每一种高级方案的背后,都必须留一条随时能顶上的退路。高级的失败了,就自动、悄悄地退回到那个虽然朴素但一定能用的方案,连接绝不中断。用户甚至不需要知道刚刚发生过一次「降级」。
这其实是一种被很多人忽略的产品观。我们总爱追求「最优解」,可现实世界里设备五花八门、网络飘忽不定,「最优」往往意味着「最脆」。真正成熟的系统,是允许自己「不完美地活着」的——宁可这一刻画质糙一点,也好过直接黑屏给用户看。把「优雅地降级」当成一等公民来设计,而不是出了事再打补丁,是我这趟最受用的一课。
稳定,从来不是「永远不出错」。稳定是「出错之后,用户根本察觉不到」。
六、最反直觉的一课:宁可丢画面,也不让延迟堆积
这一条我想单独拎出来讲,因为它彻底改变了我对「实时」两个字的理解。
直觉会告诉你:每一帧画面都是辛辛苦苦采集、压缩、传过来的,当然要尽量都送到,一帧都别浪费。但在实时桌面这件事上,这个直觉是错的——旧的画面,一文不值。
打个比方。你在看一场直播球赛,网络突然卡了一下。你是想看那段「完整、但慢了半分钟」的回放,还是想直接跳到「此刻最新」的画面?所有人都会选后者。远程控制,正是这样:用户要的永远是「现在」,而不是「刚才」。
所以我让服务器做了一件听起来很「狠」的事:当某个用户网速跟不上、画面开始在他那头积压时,服务器不排队,而是直接把还没来得及发出去的旧画面扔掉,只保留最新的那一帧。宁可掉帧,也绝不让延迟像滚雪球一样越堆越大。这一改,操作的跟手感天差地别。而且它还顺手送了我一个礼物:哪个用户在大量丢帧,就说明他的网络扛不住了,正好可以自动给他降画质。
这件事最让我感慨的地方在于,它和我们的本能是反着来的。我们从小被教育「不要浪费」「善始善终」,可在实时系统里,最优雅的做法恰恰是「果断地放弃」。想清楚「什么东西过期了就该立刻扔掉」,比拼命「想留住一切」要难得多,也高级得多。很多让人头疼的卡顿,根子都不在网速,而在于有人舍不得丢掉那些早已没用的旧数据。
在远控里,「流畅」比「完整」重要得多。让用户的每一次操作都跟手,比一帧都不丢,值钱一百倍。
七、你点一下鼠标,远端到底发生了什么
这部分最容易被忽略,却是「控制」二字的灵魂。你在手机上轻轻一点,这个动作要漂洋过海,最终变成远端那台电脑里一次「系统级」的真实点击——注意,不是模拟,而是要让那台电脑的操作系统真的相信:有人就站在它面前,按下了那一下。
在这里,我踩了一个又蠢又典型的坑。一开始为了「保险」,我把每一次点击,都往系统里投递了两遍,想着多投一次总没坏处。结果就是——双击变成了四击,打字时每个字都蹦出来两个。删掉那行「多此一举」的代码,世界瞬间清净了。这种坑,没有任何文档会告诉你,AI 也不会,你只能自己撞上去、疼一次。
键盘则更加琐碎。打中文、打 emoji 是一条处理路径,按回车、删除、方向键是另一条,而 ⌘C、⌘V、⌘Z 这种组合键又是第三条。三条路都得分别照顾周全,少做一条,用户就会在某个瞬间骂街:「怎么连复制粘贴都不行?」我光是为了让「在手机上打一段中文、远端能原样出现」这件听起来天经地义的小事跑顺,就反复调了好几轮。
这些细节没有一个是「亮点」,你做对了,没人会夸你;可只要错一个,用户对整个软件的信任就会瞬间崩塌。远控这类软件最残酷的地方就在这儿:它不靠某个惊艳功能取胜,而是靠成百上千个「本该如此」的细节,一个都不能掉链子。这恰恰是 AI 最难帮上忙的部分——它能帮你实现功能,却很难替你守住那种「差一点都不行」的体感。
画面再清晰,只要点歪一次、打字重一次,用户立刻就走。输入的「准」,和画面的「顺」,从来是同等重要的两件事。
八、它凭什么敢说「连我自己的服务器都偷看不了你」
这是我整个项目里最在意、也觉得最该讲清楚的一点。一个能看你屏幕、能动你鼠标、能敲你键盘的软件,安全是底线中的底线。也正因如此,很多人对市面上的远控软件,心里总有一根刺:我的屏幕画面,到底经过了谁的服务器?
我的中继服务器虽然是我自己的,但我从设计的第一天起,就没打算让它「看得见」内容。用大白话来说:画面和指令,在离开你这台电脑之前,就已经被一把「只有你和对方那两台设备才算得出来」的钥匙锁死了。而这把钥匙,是用「房间名 + 你的口令」在你本地现场算出来的,根本不会上传到任何地方。
结果就是:服务器收到的,全是一堆它自己也解不开的乱码。它能帮你把这堆乱码转发给对方,能验证你有没有权限进这个房间,但它永远不知道你屏幕上到底有什么。
服务器可以转发,但不该窥视;可以验票,但不该替你做主。这是我给这套系统划的安全底线。
光「看不见内容」还不够,安全这件事是个无底洞。谁有资格进这个房间?口令是不是该能随时换?我人在外地,家里的 Mac 开着机,怎么让它在没人值守的情况下,依然只认我、不认陌生人?我把口令存成了「算得出、却反推不回原文」的形式,连我自己的服务器都拿不到你的明文密码;房间、设备、权限层层校验,少一层我都不敢往外发。这些东西用户永远不会注意到,可一旦缺了,整个软件就不配被信任。
这其实也是「自己动手」的意义之一。用商业软件,你是把「可信」这两个字,交给了厂商去保管;而自己做,你能把它,重新攥回自己手里。在一个越来越在意「我的数据到底去了哪」的时代,这种踏实,本身就值回票价。
九、在 Mac 上,「我授权了」不等于「真的授权了」
如果你以为权限就是弹个框、点一下「允许」就完事,那 macOS 会专门给你上一课。在 Mac 上,「屏幕录制」权限决定了你看不看得见画面,「辅助功能」权限决定了你控不控得了鼠标键盘——而且这俩是分开的,互不相干。
我无数次遇到这样的场景:用户(包括我自己)斩钉截铁地说「我明明已经授权了」,可软件还是一口咬定没权限。一开始我以为是用户操作错了,后来才明白,这背后是更深的东西。

在 Mac 上,「屏幕录制」决定你看不看得见,「辅助功能」决定你控不控得了,签名还会影响系统认不认你。
真相往往是:你在系统设置里看到的那个 App,和此刻真正在运行的那个,系统可能压根不认为它俩是同一个东西——只要这个软件没有正规的「身份签名」、被反复重新编译过、或者从不同的位置启动过,系统就可能把它当成一个陌生人,之前给的授权自然也就不算数了。
所以「签名」这件听起来无比枯燥的事,其实直接决定了系统认不认你。不打算上架,不等于就不需要签名——只要你想把这个软件分享给别人安装,正规签名就是绕不过去的基本功。这一课,也是 AI 不会主动提醒、只能靠真实分发时撞得头破血流才学会的。
权限和签名,还只是「分发」这座冰山露出水面的一角。下面还藏着 Windows 那边杀毒软件的误报、安装包双击之后一闪而过的尴尬、不同系统版本之间细微的脾气差异……每一个都不难,但每一个都得真有人在真实机器上踩过,才会知道它的存在。这些活,没有光环、没有成就感,却恰恰是「一个能演示的玩具」和「一个敢给别人用的软件」之间,最实打实的距离。
在 Mac 上做这类软件,权限不是一个弹框那么简单,它本身就是你这个软件「能力的边界」。
十、AI 写得出代码,却写不出「踩过的坑」
走到这里,该回到最开始的那个问题了:这一路,AI 到底帮了我多少?
答案是:非常多。它让我从「不太会」到「原型能跑」的速度,快得不真实。查文档、写样板代码、把一个模糊的想法翻译成第一版能运行的东西,这些又脏又累的活,它干得又快又好。没有 AI,我大概率在「搭起第一版」这一步,就因为畏难而放弃了。
但你回头看看前面那九节——黑屏到底卡在哪一层、为什么会双击变四击、延迟为什么越堆越高、权限为什么时灵时不灵——这些真正让我熬夜、让我成长的难题,AI 几乎都没有「主动」告诉过我。不是它不懂,而是这些坑,全都藏在「运行起来之后」,藏在真实的设备、真实的网络、真实的权限组合里。你必须自己一头撞上去,疼过一次,才知道下一次该向 AI 问什么问题。
AI 让「开始」变得几乎免费。但「把一个东西,做到真能用」的那 80%,依然要靠人,一脚一个坑,自己趟出来。
更微妙的一点是:AI 给你的答案,永远是自信满满的。它不会跟你说「这里我也不确定」「这个坑你上线后才会遇到」。它把每一段代码都写得理直气壮,于是「判断它对不对」的责任,百分之百落回到你身上。它越能干,你就越需要有那双能看穿「它这次是不是在一本正经胡说」的眼睛。
我后来想明白了:AI 没有消灭工程师,它只是把门槛,从「会不会写代码」,挪到了「知不知道该做什么、能不能判断哪里出了错」。它把体力活包圆了,于是「懂系统、懂取舍、懂用户体验」的判断力,反而变得比以前更值钱。会提问的人、能验收的人、知道一个东西「差在哪」的人,在 AI 时代不是被淘汰,而是被放大。
十一、所以,AI 时代一个人能做多复杂的软件
回到标题里那个问题。我的答案是:比你以为的要复杂得多,但也比那些标题党吹的,要苦得多。

从「原型能跑」到「产品能用」,中间隔着的这一长段,才是 AI 现在还替你走不完的路。
一个人,加上一个 AI,确实能搭出一套横跨三个操作系统、有实时画面、有端到端加密、还能无人值守的远程控制原型。放在五六年前,这是一个小团队、好几个月的工作量。从这个意义上说,AI 带来的,是一次实打实的「个人能力跃迁」。
但是,「原型能跑」和「产品能用」之间,还隔着一整段很长的路:隔着正规的签名与公证,隔着根据网络好坏自动调节画质的能力,隔着无数个只有真实用户才能撞出来的边界情况。AI 能帮你把这段路走得更快,却不能替你把它走完。真正的杠杆,从来不是「AI 替我做」,而是「我借着 AI,把我自己能驾驭的复杂度,往上狠狠抬了一大截」。
AI 不会让人人都变成工程师。但它会让那些「想做、敢做、还能做判断」的人,一个人,顶过去的一整个团队。
结语:掀开「简单」,看看底下到底有什么
回头看,这套远控对我最有价值的产出,根本不是某个具体的功能,而是我终于看清了一件事:我们平时用得无比顺手的每一个「简单」软件背后,都是一整套被精心藏起来的复杂。
向日葵、ToDesk 们,把这些复杂藏得太好了,好到我们理所当然地以为,它本来就该这么简单。直到你自己,从一个空文件夹开始,把它从零搭一遍,才能真正掂出「稳定可控」这四个字,沉甸甸的重量。
而 AI,让一个普通人,第一次有机会亲手去掀开这层「简单」,看看它底下究竟藏着什么。这件事本身,就足够让人兴奋了。
我也常常被问:那到底还要不要学技术?我的体会是,比以往任何时候都更要——只不过学的重点变了。过去你得把时间花在「怎么把这行代码写对」,现在 AI 替你扛走了大半;可「这个东西到底该怎么设计、为什么会卡、哪里藏着雷、用户为什么会嫌弃」这些判断,依然得长在你自己脑子里。AI 把「执行」变便宜了,于是「品味」和「判断」变贵了。这对真正热爱做东西的人,是天大的好消息。
如果你也正打算用 AI 折腾点什么,我想说两句心里话:别被「几分钟做出一个 App」的神话骗了,也别被「AI 啥也做不成」的唱衰劝退。真实的答案,永远在这两个极端的中间——而且,它比任何一个极端,都要有意思得多。挑一个你真正想要、却一直觉得「太难、算了」的东西,借着 AI,认真做一次。你大概率做不出第二个向日葵,但你一定会对手里那些「简单」的软件,生出全新的敬意。
⚠️ 说明:文中涉及的服务器地址、密钥、访问码等敏感信息均已隐去。本文讲的是工程思路与真实体会,不代表当前成品已达到商业软件的全部成熟度。
夜雨聆风