OK ,讲了那么多系统底层的东西,接下来让我们看看与用户打交道最直接的,软件层级的用户交互体验。
真正上手体验过,你才会明白大伙之前对张小龙的态度有点过于严格了,他可能真的算是相对比较好的产品经理。
套件分析:文件管理
2023 年很少能够找到一个连 Explorer 都做得有点问题的软件开发商了。我们都知道绿联的这套东西是基于 Electron 的前端项目,所以里面有相当一部分交互被受限于纯前端的逻辑。
首先是这个前进后退键。说起来你可能不信,在 Explorer 中浏览文件,你不能够跳跃式地浏览目录,因为顶上的地址栏,是一个装饰品,你不能在上面键入任何的路径或者快速跳转。想要进入到某个目录,你只能从根目录一路递归到你想到达的地方,然后用多了几次你会发现,这两个箭头的逻辑是反 PC 的:
「后退」键实际上是../,就是 Windows Explorer 里面的上移,后退到父目录
「前进」在浏览绝大多数目录的时候它都是灰色的,只有你选中了一个文件夹,或者当前路径下只有一个文件夹时它才会亮起——就是说,它的作用是代替双击😅
这两个键不绑定监听鼠标侧键,鼠标侧键在这个软件里没有任何用处
也就是说文件管理不记录你任何的访问历史路径,你只能递归查找(除非“添加到快捷入口”或“桌面快捷方式”)
后退/前进键的功能对于左侧侧边栏来说是独立的,左侧侧边栏跳转的每一条导航视作一个 Page 的话,这两个键只对 Page 内部有效
(纯粹的前端逻辑,Navigation 页面路由、组件隔离)
来看看你微软爹是怎么做 Explorer 的……
其次就是当我上传文件的时候,它总是会先问我,究竟是选择跳过、替换还是保留两者,而无论你要导入的文件是否存在重复。就好像是我高考先把志愿报了再进考场考试一样。那我肯定是希望当拷贝的时候把所有的冲突项记录下来,最后列表让我决定怎么做( Windows 逻辑),而它只有闭着眼睛闷头干,或者每次都询问我,不允许对每个文件进行单独的决策。
套件分析:相册
我的父亲是一位很热爱生活的人,很多年前他买了一台相机,游山玩水的时候会记录很多照片,回到家分门别类整理好放在每一个文件夹里,从 2010 年一直带到现在,光看目录就知道当时去了哪,在干什么。
那么,把整理得这么细致的照片放到绿联相册里会是什么样的呢?😅……
是的,绿联云在设计这个东西的时候一定是参考手机 OS 的 Gallery ,就是往一个叫做 DCIM 的文件夹里猛塞图片就好了。我从来没见过相册归纳软件竟然能完全抛弃子目录信息。我当然可以辛苦自己每个 subfolder 单独创建一个相册,但是人生的时间不是这么浪费的:
[ol]
[/ol]
我发现一件事情,上面的第 2 点和“参考手机 OS 的 Gallery”交互理念是冲突的,手机 OS 的 Gallery 意图是让用户把图片全部丢进去就好,它去自动 AI 分析,省心,但是 UGOS 只省了一半,我还是得自己管理贴张图,是这个意思吗?
很难理解负责相册和 Explorer 的 UX (如有)在想什么,把图像和文件之间的管理搞得乱七八糟,而最关键所需的功能却见不到:
套件分析:云影院
实际上我自己长期以来在用的媒体库是 Jellyfin ,已经在 Jellyfin 搭建好了成型的接近 3TB 的庞大影视资源库。但问题在于,让完全不懂操作的家里人去弄端口登录,还额外下个 APP 也不现实,那就试试云影院好了。
(另外一个原因是,我的 Jellyfin 还提供一些同龄人看的东西,跟我的兄弟也好教、会折腾)
云影院更是一个重量级选手。它提供两种刮削源,一个内置的“智能识别”,以及 TMDB ( TheMovieDB ),让我们先来欣赏一下智能识别的准确率:
于此相比,同样的资源在 Jellyfin:
官方的智能识别源可谓是一塌糊涂。他犯下了一个质量差的刮削器能犯下的所有错误,比如说,把 Fate/Stay Night UBW 识别成了 Fate/Stay Night (近似错误)、把花絮和 Special 识别成了毫不相干的其它影视资源(随机错误)、把 Tenet.2020 识别成了册那 2020 (匹配错误)等。
而且在 PC 端,这个播放窗口竟然不能调整大小……只有 540P 小屏和全屏,并在在我的机器上( 5900X+3090 )部分视频源无论放什么视频都会在播放大概 2-3 秒之后停住不动,而拖动进度条却能继续播放,怀疑是播放器写得有问题,卡在了关键帧解码。至于字幕渲染质量什么的我也不好意思继续提,因为即使是与视频文件同名的字幕它都匹配不到,让我在文件夹里手动选……还是先把匹配做明白再去苛求质量吧。
然后你猜怎么着,这个云影院是有适配鼠标侧键前进后退的,然而文件管理却没有。
那我们把官方的“智能匹配”取消掉,使用 TheMovieDB 呢?当然没有问题,因为 Jellyfin 也将 TheMovieDB 作为数据源之一,能在 Jellyfin 正确识别的片源 90%以上都能单纯依靠 TheMovieDB 源识别成功。所以我建议原来在 Plex/Emby/Jellyfin 库迁移过来的朋友,使用纯 TheMovieDB 源。但我需要跟随官方一篇教程去花十来分钟注册 TheMovieDB 、申请 APIKEY 、测试解析配置 Hosts ,有一种传统互联网的美。
那如果我的老豆老母老姐老哥恰巧喜欢看外国电影、看美剧,而我自己不看怎么办?我还要一个个去教他们怎么去一个全英文的网站申请 API key 、测延迟选 Hosts 吗?
我想了想,也许这是我的问题。遵守国际源刮削规范的影片很明显在“智能匹配”识别率并不高,我在怀疑相比这样的名字:
Fast.and.Furious.F9.The.Fast.Saga.2021.DC.1080p.BluRay.x265-RARBG
是不是这种识别率更高呢?
速 d 与 j 情 9[1080P 蓝光超清][高清电影网]
既然云影院能够添加公共空间的视频,那么从这个云影院是公共的这件事也就合乎常理了。但是阿绿再一次选择了打破常规:我教我老姐如何使用 APP 的时候,惊奇地发现她的云影院是空的。我找了半天去哪里将片库设为公用,发现满屏幕只有“个人影院”,把个人影院四个字点烂了也只是一个筛选器在疯狂地伸缩,最后发现所谓的公共影院的功能叫做“一起看”,还是邀请制的,你分享一个片库需要被分享人同意……
就好像在一个悠闲的周末晚上我邀请大伙一起看电影,然后把片库分别发送到大家的手机上,电视放在那不开,大家点击自己的手机各看各的。并且经过实测,这个叫做“一起看”的功能完全没有类似异地放映室播放进度同步的机制,它只是单纯地把片源共享,有一些名不副实。产品经理知道什么叫做“一起”吗?
云影院的用户隔离机制无关技术问题,单纯是产品经理脑子出了问题,产品定义到这突然就混乱了,放着好好的公共/私人域不做,突然异想天开搞邀请分享制。
套件分析:云音乐/有声书
我相信这个东西应当不会有人用。不支持选择输出设备、不支持读取 FLAC 内置的 TAG(导致所有在 Foobar2000 分类整理好的歌单导进来全部变成文件名)、不支持导入公共空间资源、不支持 AIFF 、不支持 CUE ,道阻且长,绿联加油吧。
晚 22:00 更新:
它不是不支持读取 tag ,而是读得非常慢,晚上回来一看歌曲元数据慢慢都蹦出来了,怀疑在后台建库建索引,那么慢一定用的是 MySQL 。
套件分析:备份
我对 NAS 的另一个重要需求就是文件自动备份(和微信备份,但是这台 NAS 不支持),而且只要求备份不要求同步,因为我的主力机已经有 2TB+8TB 的空间。
我一般习惯把工作目录放在桌面,代码项目放在~/*Projects ,过一段时间后归档到硬盘中,现在有了绿联云 NAS 自动备份……
已经连续 4 天没有关机了。
PycharmProjects 文件夹总大小 101GB ,文件数量 536957 ,文件夹数量 66488 ,这套套件的 PC 端备份在遇到十万以上数量级时会出现严重的性能问题,以至于现在我 4 天没有关机,第一次全量备份的完成度还未达到一半。而且备份文件的速度会越来越慢,在连续运行十来个小时之后会停滞不前,“我的备份”窗口会直接无响应挂掉,必须退出绿联私有云客户端再重新启动,它才会以一个比较慢的速度继续运行备份。而且是每十几个小时需要重新启动一次,天知道我离第一次备份成功还有多远。
不过这种极限工况不是所有人都会遇到的,目前我的相册自动备份大概 3000 张,比较流畅,不会有什么问题。
套件分析:百度云
我自己是向来不用百度云盘的,从拥有自己的电脑开始,数据一直牢牢掌握在本地硬盘里,需要的资源也总能从云盘以外的地方找到替代品。
但是家里其他的年轻人会用。我在邀请他们加入私有云后,我说我不用百度云盘的,但是你可以登陆试试,把云盘上的东西下载到家里,本地化。然后她在她的手机点了一下百度云盘插件。
提示“仅限管理员使用”,她让我给她开下权限,这个时候我人已经麻了,因为我已经意识到百度网盘估计只有管理员能用这一事实。
所以现在我的账户上很无奈地登录着别人的网盘,挂着别人的下载,等到下载完之后还要操作移到公共空间给其他人取用(没错,百度网盘的保存位置,又不支持公共空间了)
我尝试理解这件事情,虽然不懂技术的人根本不会管为什么不能用。我推测这类第三方工具本身限制在一个系统里面运行多个实例,出于之前分析的用户机制,实例只能交给管理员用户运行。
那这种情况在不考虑法律风险的时候怎么解决呢?虚拟机或者容器化方案。这就是新的问题了:
[ol]
现阶段绿联根本没把虚拟机做出来,在当前用户机制的约束下做出来的难度比拿正经 Linux 重构还大
假设我们使用容器来承载多个实例,并且对用户隐藏,可以做到吗?
[/ol]
答案是不完全可以。docker 是不支持隐藏 container 的,但是 docker 支持每个用户运行不同的dockerd,那系统镜像就交给 root 运行好了,其他用户以自己的身份管理自己的dockerd,方案很不错。
但是非管理员的用户在 Linux 不真实存在,并且现在套件里的 dockerd 就是以 root 身份运行,如果要更新,那么怎么处理 root 容器降权迁移的问题?
另外,dockerd 多用户机制依赖systemd,而 Openwrt 正是**不使用systemd**的一个 Linux 发行版,意味着多用户容器方案在当前架构下不可能实现。
下集预告
对这个奇葩系统的分析就此结束了。我们接下来将会基于这些分析的结论寻找解决方案,结合我踩坑的经验,告诉大家在这台机器上,想要部署一个普通的三方媒体库和下载插件需要经过哪些步骤,使用过程中又会遇到什么样的坑。
[ol]
[/ol]
附录
根据 Nginx Conf 生成的反代列表,传入数据不合规的时候会被 rewrite 跳转至 404“固件版本过低”页。
列表由 GPT 整理,因为上下文过长,GPT 遗忘机制导致可能会出现一定的错误,请自行前往/etc/nginx比对甄别
# Generated by ChatGPT
LISTEN 9999 [::]:9999
# NAS server
/ -> :9996
# Ugreen launcher
/home -> /data/app/com.ugreen.ugos.launcher/www/index.html
# Docker Hub API
/docker/image/search -> https://hub.docker.com/api/content/v1/products/search/
# Core server
/v1/user/login -> :9994
# Album server
/v1/album_svr/ -> :9982
/v1/ai/album/ -> :9982
/v3/ai/album/ -> :9982
/v1/album/manage/ -> :9982
/v2/album/group/ -> :9982
/v3/cloud/album/ -> :9982
/v1/ai/task/ -> :9982
/v1/ai/scan/ -> :9982
/v1/ai/similar/ -> :9982
/v1/ai/blur/ -> :9982
/v1/ai/face/ -> :9982
/v1/ai/file/ -> :9982
/v1/album/people/ -> :9982
/v1/tidy/ -> :9982
/v1/myself/del_myself_folder -> :9982
# Baidu Pan server
/v1/baidu/rest/2.0/xpan/ -> https://pan.baidu.com/rest/2.0/xpan/
/v2/baidu/oauth/token -> https://pan.baidu.com/rest/2.0/xpan/
# MiniApp Yun server
/v3/cmcc/devapp/ -> https://miniapp.yun.139.com/richlifeApp/devapp/
/v3/cmcc/open-mpplatform/oauth2/ -> https://miniapp.yun.139.com/open-mpplatform/oauth2/
# Docker web
/docker/web -> /ugreen/docker/www
# TTYD server
/ttyd -> :DYNAMIC
# Docker images export
/docker/images/export/ -> :9375
# Docker image search
/docker/image/search -> https://hub.docker.com/api/content/v1/products/search/
# Docker image repositories
/docker/image/repositories/ -> https://registry.hub.docker.com/v2/repositories/
# External backup server
/v1/file/external_backup/ -> :9984
# Favorites server
/v1/favorites/set -> :11024
/v1/favorites/get -> :11024
/v1/favorites/cancel -> :11024
# File collect server
/ugos/v1/file_collect/ -> :12028
# File share server
/v1/share/get_shared_files_of_users -> :11025
/v1/share/get_users_of_share_file -> :11025
/v1/share/share_files -> :11025
/v1/share/cancel_shared_files -> :11025
/v1/share/get_all_users -> :11025
/ugos/fileshare/v1/shared_user/list -> :11025
# File search server
/ugos/globalsearch/v1/ -> :12029
# IPC server
/v1/task/ -> :9992
/v1/baidu/ -> :9992
/v1/transcode/ -> :1080
/v1/disk/ -> :9992
/v1/storage/ -> :9992
/v2/storage/ -> :9992
/v1/stormng/ -> :9992
/v1/dl/ -> :9992
/v1/cmcc/ -> :9992
/v3/cmcc/ -> :9992
/v1/file/storages -> :9992
/v1/file/disks -> :9992
/v1/category/ -> :9992
/v2/category/ -> :9992
/v3/category/ -> :9992
/v3/storage/ -> :9992
/v4/storage/ -> :9992
/v5/storage/ -> :9992
# LBook server
/ugos/lbook/v1/ -> :11029
# Log Center server
/ugos/log_center/v1/ -> :10002
# Media Player server
/v1/mediaplayer/ -> :1085
# Movies server
/v1/movies/ -> :9980
/v2/movies/ -> :9980
/v3/movies/ -> :9980
# Music server
/ugos/music/v1/ -> :11028
# Service Manager server
/ugos/service_mgr_svr/v1/ -> :19010
# Thunder server
/device/info/watch -> :5050
/device/now -> :5050
/device/authlogin -> :5050
/device/v1/ -> :5050
# Thunder web
/web/thunder/ -> :5050
# Transcode server
/v1/transcode/online/ -> :1080
/v1/transcode/online/info/ -> :1080
/v1/transcode/online/ -> :1080
/v1/transcode/online/status -> :1080
/v1/transcode/online/switch_resolution/ -> :1080
# Data app
/data/app/ -> /
# App
/app/ -> :9999
# User Management server
/v1/quota/project -> unix:/var/run/user_manage.sock
/v1/quota/user -> unix:/var/run/user_manage.sock
/v1/quota/volume -> unix:/var/run/user_manage.sock
/v1/timemachine/query -> unix:/var/run/user_manage.sock
/v1/timemachine/set -> unix:/var/run/user_manage.sock
/v1/cache/write -> unix:/var/run/user_manage.sock
/v1/cache/remove -> unix:/var/run/user_manage.sock
/v1/cache/clean -> unix:/var/run/user_manage.sock
/v1/cache/query -> unix:/var/run/user_manage.sock
/v1/localuser/list -> unix:/var/run/user_manage.sock
/v1/localuser/exists -> unix:/var/run/user_manage.sock
/v1/localuser/create -> unix:/var/run/user_manage.sock
/v1/localuser/modify -> unix:/var/run/user_manage.sock
/v1/localuser/delete -> unix:/var/run/user_manage.sock
# WPS server
/v1/wps_doc/ -> :11027