把Android手机变成电脑摄像头,开发者倒苦水:40行代码搞定,但需要40个项目文

把Android手机变成电脑摄像头,开发者倒苦水:40行代码搞定,但需要40个项目文

编译|苏宓

出品|CSDN(ID:CSDNnews)

开发一款App,难不难?

软件工程师ThomasSIMON闲暇之余用实践回答道:其实说难也不难。

当他拿起一个Android手机,想要将其作为电脑摄像头和麦克风使用时,他只写了40行代码就实现了这一功能。

只不过,令他苦恼的是,写40行代码背后需要安装超过20GB的工具、也需要创建数十个项目文件才能以运行。

当他把自己的这段经历分享到网上时,没想到,引起了多位开发者的共鸣,纷纷表示,这种感觉太熟悉了。

把Android手机变成电脑摄像头,开发者倒苦水:40行代码搞定,但需要40个项目文

在分享的文章中,ThomasSIMON引用马斯克曾经说过的一句话,「聪明工程师会犯的最常见错误,就是优化本不该存在的东西」。开发本身或许并不难,只是被平白增加了很多的复杂性。

接下来,我们将从ThomasSIMON的经历中了解开发者那些本该避开的坑。


需要一个App,把Android手机变成电脑摄像头和麦克风

后来,ThomasSIMON决定和一位朋友一起录制他们技术分享,并将其作为播客片段上传到网络上,期间需要对录制的文件进行剪辑、制作等等,还是电脑好操作一些。

不过,ThomasSIMON的Linux系统电脑并没有摄像头,所以在他的计划中,原来是想要将Linux电脑作为主设备进行录制,然后使用手机上的摄像头和麦克风加入通话。

然而,在录制期间需要管理两台设备非常麻烦,况且搭载Linux系统的电脑设备本身就有一个不错的麦克风,所以,此时只要有一个Linux兼容的网络摄像头存在就可以解决难题。

在研究市场上现有的网络摄像头之后,ThomasSIMON认为那些设备不仅价格昂贵,而且质量还不如几年前的中档手机后置摄像头。

恰巧他手头正好有一部三星S20,手机的后置镜头是长焦镜头,非常适合拍摄人像,平行光线让人脸看起来清晰、漂亮。

在这样的背景下,ThomasSIMON萌生了自己开发一个AndroidApp的想法,只需要通过Wi-Fi或其他方式将手机摄像头的数据流重定向到他的电脑上,让他的Linux电脑相信Android手机是一个摄像头,或者让Linux的应用程序(如GoogleMeet和Zoom)相信它是一个摄像头即可。

也许有人会说,其实市场中也早已有了这样的软件,譬如DroidCam。DroidCam软件分为两部分,一部分是手机上安装的软件,称为服务器;另一部分是PC上安装的软件,称为客户端。只需要PC和手机连接到同一个Wi-Fi,就可以把手机作为电脑摄像头。

不过,ThomasSIMON在使用后发现,DroidCam是一款被广告限制且需要付费的应用程序,而且并非所有摄像头都能显示。同时,经过测试,它的质量令人无法接受,即使是720p的低分辨率也被官方推荐。

无法忍受之下,ThomasSIMON决定自己开发一款AndroidApp,把Android手机相机变成电脑的摄像头。


这有什么难的?

所以,对于ThomasSIMON而言,开发一款AndroidApp难度其实并不大。而且在他的规划中,他只想要一个包含选择相机、分辨率和退出键这几个菜单栏的App,并不需要有太多的设计感。

于是,ThomasSIMON开始寻找制作Android应用程序的最简单方法。他发现,几乎每个专家都在积极推动AndroidStudio作为IDE开发环境。

不难想象,他下载了一个AndroidStudio,结果发现,这是一个1.1GB的.压缩包,一旦安装了所需的工具,最终会占用20GB(分布在多个文件夹中)的空间。

安装好工具之后,ThomasSIMON开始寻找可以处理摄像头的官方APIs。

简而言之,ThomasSIMON试过cameraX,这是一个Jetpack库,旨在帮助简化相机应用程序的开发,但它太高级了。所以ThomasSIMON最终使用了camera2。

ThomasSIMON下载了一个camera2的官方示例项目,其实他只想拼接一个http服务器并用来传输帧,在他的设想中,整个过程应该只需要几分钟就可以完成的。没想到,厄运从这里才真正开始

ThomasSIMON表示,这个官方示例项目(/android/camera-samples/tree/main/Camera2Basic)的作用只有「显示摄像头、并拍摄一张照片」,但是没想到它包含了很多文件。

把Android手机变成电脑摄像头,开发者倒苦水:40行代码搞定,但需要40个项目文

仅以gradle为关键词搜索,就有一大堆文件:

$:/tmp/Camera2Basic$find.-typef-name"_gradle_"./././gradlew././utils/./gradle/wrapper/./gradle/wrapper/././app/

ThomasSIMON表示,自己不可能花时间去慢慢理解这些东西,他只是要修改一些代码,来实现自己想要的功能。

不过,还没等他开始寻找代码片段,AndroidStudio就开始跳出了一个提示:


于是,事情似乎进入了循环:

事情发生了变化,左侧窗格中的文件改变了结构,标签页反复打开和关闭。

显示许多选项,其中一些已预选,一个按钮上写着"运行选定步骤"。

事情发生了变化,左侧窗格中的文件改变了结构,选项卡反复打开和关闭。

"建议更新项目,单击启动AGP升级助手

显示大量选项,其中一些已预选,一个按钮显示"运行选定步骤"。

事情发生了变化,左侧窗格中的文件改变了结构,标签反复打开和关闭。

折腾了一会,ThomasSIMON的AGP和gradle终于不再跳出更新提示。

接下来,正式进入代码部分。

写过不少Java和Scala代码的ThomasSIMON发现这部分的代码是用Kotlin写的。

“从这里开始,我喜欢我所看到的,代码很清晰。它在xml中定义一个视图,在代码中用标识符与之关联,非常标准且可预测。清晰的代码让我不需要学习任何东西就能提高工作效率”,ThomasSIMON说道。

紧接着,ThomasSIMON调用一个AndroidAPI来制作一个简单的http服务器,然后把它插入、测试,它就能工作了!

现在,ThomasSIMON的电脑浏览器标签页上有一个mjpeg流。对于实时调用来说,质量和延迟都还可以。这样,他就可以在终端输入一行命令将其转换为Linux网络摄像头设备:

ffmpeg-fmjpeg-i""-vf"format=yuv420p"-fv4l2/dev/video0

整体而言,ThomasSIMON表示,网络世界虽然有一些不必要的步骤和配置,但这个Android世界简直是疯了。

他下载了官方示例之后,删除了未使用的视图,添加了选择相机、分辨率和质量的下拉菜单,将所有功能移至前台服务,以便在锁定手机的情况下保持激活状态,并将其发布在GitHub上(),整个项目花了他两个下午的时间(其中大部分时间都在了解Android希望你怎么做)。


实际工作量应该如何?

ThomasSIMON认为,在理想的情况下,在手机端,只需一行代码就足够了,根本不需要上面那样复杂的操作。倘若我们想编写一个应用程序,只是为了准确地指定数据流,而不是依赖天才们已经开发出来的高级工具(如桌面上的ffmpeg和v4l2)。

在理想的世界里,具有这种规格的App应具备:

允许配置相机、分辨率和质量/比特率

没有设计,只有原始功能

在本地网络上传输帧流

ThomasSIMON表示,只需一个40行伪代码(pseudocode,又称虚拟代码,是一种高层次描述算法的方法,它可能综合使用多种编程语言的语法、保留字,甚至会用到自然语言)的文件就能实现以上功能:

1()orquit()
2()orquit()
3
4queue=Producer(size=1)
5
6server=(port=8080)
7=req-
8()//onlyallows1client,dropoldones
9("Content-Type","multipart/x-mixed-replace;boundary=FRAME")
10(frame,consumer-
11data="--FRAME=\r\nContent-Type=image/jpeg\r\n".bytes+
12(data)(consumer)
13()//Freecameramemoryofthisframe
14)
15()
16
17options=("config")or{sensor:0,format:"jpeg",fps:30,resolution:[1280,720]}
18
19session=(options)
20=(frame)()
21
22().text="Chooseasensor:"
23dropdownSensors=()
24=
25=(_.name)
26=index-
27("config",options+{sensor:index})
28restart()
29
30().text="Choosearesolution:"
31dropdownResolution=()
32=()
33=(_.0+"x"+_.1)
34=index-
35("config",options+{resolution:[index]})
36restart()
37
38quitBtn=()
39=quit
40="quit"

这段伪代码虽然简单,但明确指出了所需的内容。其中,对API的访问如CAMERA(摄像头)、NETWORK(网络)、UI(用户界面)和STORAGE(存储)等都非常明显易懂。

把Android手机变成电脑摄像头,开发者倒苦水:40行代码搞定,但需要40个项目文