阅读视图

发现新文章,点击刷新页面。

[视频攻略] Betterified VI – Bestified 以及闲扯(附游戏下载)

比录视频更困难的是剪视频,比剪视频更困难的是传视频。

vlcsnap-2024-09-21-01h22m32s292-1_2x-1

  • 注1:本文不是攻略内容。本文为制作此视频攻略的闲扯。
  • 注2:文内视频引用为 Youtube 的视频,如您无法观看,请自行找办法解决。
  • 注3:游戏文本为英语。如您无法阅读英语,请自行找办法解决。
  • 注4:为什么做视频攻略而不是文字攻略或图文攻略?因为懒!

攻略视频链接

Youtube: [SMBX2] Betterified VI – Bestified – walkthrough: https://www.youtube.com/playlist?list=PLDwDrQvfAje57psgPq4Ih7nQGrVlx-sqF

如果你只是想看看游戏的视频,确认一下自己想不想也玩一下这个游戏,这里有几个国内可以直接访问的B站视频链接:

B站的那个播放列表我上传到20几个视频后就放弃了,实在是不舒服。你对付看也行。后面的内容才更有趣,但是我不打算再上传到B站了。

(突然意识到这游戏前面几关的Boss怎么都是银河战士的)


游戏引擎SMBX2

机缘巧合下看到别人玩的 Betterified VI – Bestified 这游戏的直播片段,感觉挺好玩的,毕竟这几年的传统的2D马里奥游戏,同质化已经让人厌倦得连任天堂都把传统2D马里奥引擎扔了重做了一个Wonder。

游戏引擎是 SMBX2 。

说到游戏引擎,SMBX2 的前身一看就知道是 SMBX 。我电脑里还有个 2010年版本的 SMBX1 引擎。这玩意曾是大名鼎鼎的马里奥同人游戏引擎,2015年任天堂才作出 Mario Maker,而 2010 年那阵,玩家制作马里奥同人基本就是 SMBX 。

只不过搜了一下,1.2 版本时期,相关论坛因管理员问题,变得极为狗血。当然了,很多游戏社区都有各种狗血问题和隐患。后来还有任天堂下场叫停,总之很坎坷。

SMBX2 基本上算是 SMBX 1.3 在 2015年的一个 Fork,现在已经开源 TheXTech/TheXTech

代码基本上是用 C++ 重写的 VisualBasic 6,按维护者自己的说法也是,代码质量很烂,毕竟 VB6 时代根本没什么正经人重视代码质量。

游戏内容的语言则是 lua ,理论上是个比 Python 屁事少很多的语言。但是,没有括号全靠自觉缩进来肉眼「测量」代码块这事情我是坚决不能接受,尤其是项目里又有空格又有TAB而lua本身对代码块并没有强制要求导致其代码质量有时候比Python还烂。

不过抛开引擎开发,这个引擎应该是可以作出远超过 马里奥制造2 的好游戏,只不过开发复杂度同样很高。毕竟本身同人免费游戏开发是一件非常费力不讨好的事情,很少能有人用心去做。


游戏 Betterified VI – Bestified

Betterified 应该是一个大系列,看 Release Trailer 可知作者做了许多作品,仅 Betterified 就包括6作,属实不容易。

当然我也没精力全玩一遍,前作到底是个几十分钟就能搞定的小同人,还是得肝几十个小时的超级大作,我也不知道剧情是不是连着的。

从八月初玩到九月末,可以说这游戏值得玩。难度适中,也有各种各样的降低难度的方式。根据网上的评价,这游戏的关卡机制和Boss战机制,作为一个同人马里奥游戏就是天花板。部分关卡和Boss战,放到整个游戏界都算是超一流超优秀的设计。除此之外,也有纯爽玩关卡和纯搞怪关卡。当然了,也是有纯粹恶心人的粪关卡的,可能作者就是想气一下你的这种感觉。尤其是第一关其实就很气人,感觉就是那种开场先警告你玩不起别玩的劝退关卡。

vlcsnap-2024-09-19-22h36m25s575

vlcsnap-2024-09-22-23h18m01s077

vlcsnap-2024-09-18-20h09m45s882

screenshot_on_b85m_by_flameshot_at_2024-09-11_02-16-08


录制视频

一开始是想在B站一边直播一边录制。但是B站的那直播环境实在是不怎么地。(尤其是这游戏在国内根本搜不到)

解谜关卡有时候需要相当多的思考时间,很多高难关卡还要很多专门试错的尝试(此游戏没有生命数限制,没有官方马里奥那种GAME OVER就得从头或者从大关第一关开始的设定,可以在当前关卡一直玩下去,直到通关),这也意味着废稿会非常多,而废稿存在硬盘里毫无意义,但直播又没法很方便的丢弃废稿。所以最后就放弃直播了,改为安心游戏了。不去关心什么之后,专心玩游戏录视频后,整体效率快了非常多。而且由于直播必须是连续的,而自己玩的话可以随时控制时间,游戏压力也小了很多。

Betterified VI – Bestified 我肝了一个多月,剪出来的攻略视频超过17个小时,视频原稿有多长更没法统计了,录制盘容量根本不够用,已经删了一堆了,剩下的没删的还有30多个小时。是的,带解谜而谜面又极其晦涩或者根本没有谜面的游戏就这么恶心,你就得到处跑,有些元素第一次找到的时候和再次找到的时候给的玩意都不一样,生怕误打误撞把第一次就这么给趟过去了,所以大部分原稿都是一直留到杀青了才敢删。

screenshot_on_b85m_by_flameshot_at_2024-10-05_01-38-12


制作攻略

Betterified VI – Bestified 这游戏秘密太多,而且也不知道作者是有意还是无意的,塞了一堆根本没头绪的隐藏秘密也就算了,还在特明显的地方塞了一堆根本没实现的解谜要素。

我先是自己不看攻略过了一遍,然后再看 Youtube 上其他玩家的视频。他们的视频基本就是随玩随录的,所以想找一个特定关卡特定位置的秘密特别困难。尤其是到游戏后期的秘密的提示或解锁位置是前面的关卡,翻来翻去超级困难。

最后就是自己看游戏的 lua 文件。然后发现,我自己是真的很暴力,直接用IDE,也就是我现在正在用的 Pulsar 编辑器搜关键代码,把整个游戏扒了一遍,基本每个能在游戏内看到的解谜要素,我都缕了一遍对应关卡的代码。

vlcsnap-2024-09-23-20h18m37s153

screenshot_on_b85m_by_flameshot_at_2024-10-05_01-59-51

基本上可以说我做的这一份视频攻略能做到此游戏的解谜要素全互联网最高覆盖率!


制作视频

做视频这一块我的原则是能不二次编码绝不二次编码,毕竟带宽只是时间,反正所有线上视频网站都会二压视频,所以我没必要浪费我的 CPU/GPU 时间。

H.264/MPEG-4 AVC 视频(以下接以AVC代称)的无损切割我是专门研究过的,用图形化的 Avidemux 就能轻松搞定。如果出现无损切割有困难实现不了的情况,就仅编码需要编码的小切片,一般也只有2秒钟左右。

screenshot_on_b85m_by_flameshot_at_2024-10-06_22-19-55

然后是拼接视频。如果一个原稿能直接无损剪出来,就不需要拼接。但是游戏打到后期,解谜的地方就越攒越多,就会有多个原稿关联到同一个解谜要素的情况,这种是躲不掉的,就必须把多个原稿的片段剪出来,然后用 FFMPEG 再贴到一起。其实基本上也就是个硬盘读写时间,都是眨眼就能完成,根本没什么难度。

screenshot_on_b85m_by_flameshot_at_2024-10-05_00-41-08

其实要说这一块,首先是 AVC 视频的 无损切割 ,当时刚开始学做视频的时候,我是研究过 AVC 编码技术的,其本质就是个 PNG 图片后面接上个运动补偿算法。如果想用大白话讲的话我可以再写一片文章。

无损拼接视频也是 AVC 视频的一种特性。但把多个视频贴到一起虽然有图形化界面的 Avidemux 应该能做到,但实际上总莫名其妙出错。Avidemux 编码器基本上也是 FFMPEG 套皮,但是对视频源要求太多,并没有 FFMPEG 那么野性,FFMPEG 报错也很野性,图形化界面根本控制不了。而且多个视频拼接基本上就是选一堆文件,这个在图形界面上反而效率太低,不如脚本来的快。所以拼接最安心的办法还是用 FFMPEG,而 FFMPEG 对于多个视频,用一个文本文件做文件列表最方便,但其 concat 又需要一个指定格式,所以最靠谱的方法是准备一个文件列表,然后命令行里中途生成一个临时文件,这就又需要新知识点 mktemp

你看,切个视频搞出来俩知识点,能写两篇文章。做视频真有意思。

这其间还遇到个一个诡异的情况,我整个过程中并没有修改过OBS的编码器,但是在某个时间段,输出文件的编码参数竟然还变了。

screenshot_on_b85m_by_flameshot_at_2024-09-16_01-21-47

诡异。

说尴尬的地方就是,这其间其实遇到过不少专门从国外往国内搬视频的「所谓大佬」。那种拿着 bandicam 或 Fraps 带着水印对着浏览器录屏的烂操作也就算了,巨大个视频抠下来,只为了掐头去尾,先搞各种「大神」工具,然后压崩,又专门整个 Adobe Premiere 把视频重新压一遍,再漫不经意来一句「又不费时间」。

顿时又觉得做视频没意思了。


上传视频

其实做这攻略的中途我是有打算放弃的,因为这游戏有些解谜实在太晦涩了,好烦。感觉整个流程最闹心的步骤大概就是这一块了。但是好歹最后咬牙挺过来了,而且把游戏做到全解密(至少自己能做到的全做了),还整了成了视频,做完了之后成就感还挺高的。再加上是互联网上并没有针对这个游戏的任何攻略资料,只有几个高玩随便玩玩时录的视频,并没怎么整理成流程攻略,所以新玩家如果卡关了,在网上是无法直接搜到对应的攻略的。这让我成就感更高了。

但是我却确实是没想到这才是整个过程中最痛苦的阶段。

我最初的想法就是玩一部分后就上传一部分,但是玩到游戏中期就发现这游戏总出现后面关卡的谜面对着的是前面关卡的谜底,也就是说前后关联性特别密切,先上传的视频很可能出现误导性,作为整个解谜攻略来讲,早期的稿件很可能变成大坑,是要删除的。虽然回头玩一下先前关卡也就几分钟的事情,剪切也就是跟着新稿一起剪,但是上传以及写描述这个阶段在整体上的占比就太大了,不如索性先不要上传,把游戏整体都打通之后确保不会把废稿上传上去后,一起上传最好。

然后恶心的地方就来了。我最初是想B站和Youtube都上传的,先上传B站。但是B站的那个破机制实在是恶心。同一天大量上传稿件就会被降权,有传闻一天最好不要上传超过6个视频。我特么有170多个视频,天天上传视频我得上传一个月。再加上B站的那个网页端烂得要死,视频展示页面就更烂得要死(描述会被截断,所以你会发现很多人把视频描述写在置顶评论里),去他的破逼站吧,爷不伺候了。

(做B站的UP主,算是打白工还是打黑工?)

那就传 Youtube。Youtube 的上传系统倒是正常的,没啥大毛病,但确实你得完全自己做缩略图,Youtube 的封面缩略图功能基本还是10年前的逻辑,除非你整个视频上传完,否则不能生成缩略图,缩略图也不能线上编辑,这点也算能忍。然后发现 Youtube 的定时发布的功能设计也是10年前的。甚至最后你能发觉 Youtube 的所有功能都是行业10年前的设计,基本跟行业都脱节了,除了一堆生怕被欧盟和少数派团体暴打的破选项玩意之外,其他功能都是没跟上时代步伐,基本是停留在2014年了。

然后就是相当漫长的写描述做封面的阶段。这比打游戏剪视频痛苦多了。

screenshot_on_b85m_by_flameshot_at_2024-10-05_01-56-11

而且由于是攻略,我得考虑好各种 SEO 因素,至少要保证如果有人搜关键词,是要能搜到我的视频,然后看到我做的封面图之后,能确定这是相应视频,点进来。

screenshot_on_b85m_by_flameshot_at_2024-10-05_01-58-35

整个上传流程共计用掉了2个星期,太长了。有些视频切完了放在硬盘里好几天,等要上传,或者都已经上传完了之后,才发现视频内容有误,然后翻原稿,重新剪,重新传,有时候真得叹口气庆幸好在当时的原稿没有被删除。录制盘是我老笔记本的拆机盘,一共才120G,其实已经吃紧非常久了。

screenshot_on_b85m_by_flameshot_at_2024-10-05_02-06-55

最后共计172个视频上传完成,累够呛。

我开始玩游戏的时候这游戏是 v1.0.9.1 版本,等我上传完视频,这游戏都更新到 v1.0.11.1 了。作者回复我说只是修了些Bug,我自己对比了代码,有一些看不懂的改动,但是不影响我视频的内容,也就这样吧,这事就完结了。

(其实我的游戏流程离理论完美还差一小段,但是我不想继续做下去。至少现在不想)


游戏下载

假如你要入坑的话:

官网:[SMBX2] Betterified VI – Bestified + FULL SMBX EASY INSTALL VERSION

官方提供一个游戏内容包,可以自行添加到你已经安装的 SMBX2 引擎之中。官方也提供一个二合一包,不需要自己手动安装 SMBX2 。官方还提供一个增量升级包,是给有 Betterified VI – Bestified 1.0 用户用的,如果你已安装旧版本,可以用增量包升级更新。

官方提供的下载链接都是 Google Drive 的。如果你无法顺利访问 Google Drive ,这里提供 InfiniCLOUD 网盘的 Betterified VI – Bestified v1.0.11.1 游戏内容包和 SMBX2+Betterified VI 二合一包。

文件太大,我就不上传微云了,没空间了。


结语

也算是了了一件心事。

The post [视频攻略] Betterified VI – Bestified 以及闲扯(附游戏下载) first appeared on 石樱灯笼博客.

从写一个 WordPress 插件说起

之前博客的《目录》页面用的是 List category posts 这个插件生成。可这个插件虽然功能比较多,但是不支持(还是我不知道?)我要生成的页面。

再往前用的插件是 Dagon Design Sitemap Generator,它可以生成一个以「分类目录」为主题的文章页面列表(例子可以看文章存档 – 木遥的窗子)。但是这个插件很长时间没更新了,甚至它的官网都打不开了,没办法重新下载这个插件。

考虑到这个插件功能并不复杂,索性自己写好了。我的文章本身不多,因此也不用做分页或者其他的配置,用最简单的方式即可。这个插件应该符合以下功能:

  • 生成一个双层级的 bullet list
    • 以「分类目录」为第一层,排序方式按单词字母正序
    • 以该分类目录下属的文章为第二层,排序方式按文章创建时间倒序
  • 「分类目录」的展示需要加前缀 “Category”,且这个前缀需要加粗
  • 「分类目录」的内容为分类标题,该标题为该分类的 URL
  • 文章列表都是可点击的 URL
  • 文章标题后面增加文章创建的时间

以上功能其实不复杂,最后只用把它们拼成 HTML 语法的代码即可。

问题在于,我从来没写过 WordPress 插件,甚至我也不会 PHP。换在两年前,如果需要完成这项任务我应该需要:

  1. 用至少 2 天时间学习 PHP 的基本语法,其中可能包括:
    • 找到合适的上手文档/教材
    • 搜索无数次 StackOverflow 搭一套可运行环境
    • 学点基础语法,并且在写的过程中反复查文档
  2. 用至少 2 天时间学习 WordPress 的开发过程,其中可能包括:
    • 为了性能和效率,先在本地机器跑起一个 WordPress 页面
    • 从 WordPress 的文档看怎么写出一个 Hello World 插件
    • 搜索无数次 StackOverflow 看别人怎么解决各种意想不到的问题

但是自从有了生成式 AI 后,完成这么一项任务变得无比简单。以这次写插件为例,用的是 Anthropic 新发布的模型 Claude 3.5 Sonnet,前后只用了 30 分钟就完成了。我并没有学 PHP 的基础语法,也没有查过 WordPress 的文档。只需要通过合适的 Prompt 引导 AI 生成合适的代码,同时让 AI 告诉我怎么把插件安装到 WordPress 即可。

当然,初次生成的代码不是完美的,但是把需要改进的内容告诉 AI 即可慢慢引导到正确的结果。

这与程序员目前写代码是一样的过程:刚开始写好的大概率是不完善的,有错误或此前没考虑到的地方,一步步改好重新运行,通过不断的试错达到最终的效果。

这就是 Sam Altman 提到的完全使用自然语言编程。几十年前的程序员写的是汇编语言,而今天绝大多数的程序员都不再用,而是通过 Python 等高级语言(这里的高级并非褒义词,而是高度封装的意思,类似于预制菜和炒菜的区别)完成任务。而如今的 AI 是一个新的编译器,它可以让大多数人直接通过自然语言编程。

或者类比一下,coder 有点类似于国内较早学习英文的人,有能力将中英文互相翻译。而现在的 AI 可以充当一个翻译器,让人可以直接用自然语言和计算机交流。

但这并不意味着编程就成为一件无门槛的事—尽管门槛降低了些。我们依然要整理好需求和思路才能完成任务。以刚刚的 WordPress 插件为例,如果只是说「做一个插件支持以『分类目录』归类展示文章列表」,那么有可能会作出很多不同版本的插件。

事实上,这也是 software engineer 和 coder 的区别。前者更多的工作在于将一个较大的任务拆分成小任务,通过合适的方式组合起来完成;而后者更强调翻译这项工作。

这也让我想起,前段时间和朋友聊起,我们这行未来能做什么。我并没有想好这个问题,但是会让我想到如果要转行,什么能力是通用的?在我看来其中一个就是解决问题的思路。小的问题比如家里一颗灯泡坏了怎么修?大的问题类似如果要设计一套银行系统需要怎么完成(我现在自然还不能胜任这项工作)?

也正是因此,前段时间教两个朋友编程的时候,我并没有怎么注重语法,而是更关注解决问题的思路。通过自然语言把问题拆解出步骤,然后翻译成代码。回想起当年自己自学的时候那种无力感实在痛苦,已经忘记是怎么熬过来的了。幸运的是,现在的人不必如此。

前段时间去了趟大英博物馆,看到了镇馆之宝罗塞塔石碑。两百多年前,法国人商博良 (Jean-François Champollion) 以这块石碑为突破口,破译了古埃及圣书体,成为埃及学创始人。这块石碑上印有三种文字,分别是古埃及圣书体、世俗体及古希腊文。或许在未来,非自然语言的代码都会被人遗忘。而某一段写着自然语言注释的代码会成为新的罗塞塔石碑。

银弹飞过先锋大厦

TL;DR 本文13200+字,全文阅读约需20分钟。其中2680字的示例部分为ChatGPT生成,因此可以说本文GPT含量20%,不过该部分详细内容与本文主旨关系不大,且由GPT-4生成,可略过不看。本文简要回顾了从软件及计算机诞生到当前大模型AI时代的软件工程发展历史,并试图从软件工程历史和ChatGPT实践案例中探讨在大模型时代的软件开发模式。

从神经网络到 Hugging Face

TL;DR 本文8200+字,全文阅读约需15分钟。从去年开始,我读了十余本人工智能方面入门的书籍(参见文末附2),酝酿了两个月,花了两周时间写作此文。本文简要回顾了从感知机到深度学习及Hugging Face的历史,并试图以通俗的语言来介绍神经网络和深度学习的原理。

Git 纪元

19世纪末,弗雷德里克·泰勒在美国一些工厂推广他的科学管理方法,这包括用科学的方法来代替人工经验判断、对工人进行专业训练以及按专业分工。亨利·福特在他的汽车工厂里也开始应用泰勒科学管理,并且在汽车生产上创新性的采用了流水线作业。1908年,第一辆福特T型车从流水线上面世,而经过优化的流水线在几年后甚至可以达到93分钟内生产一部汽车,强大的生产效率让福特超过了其他所有汽车厂商生产能力的总和。福特的流水线生产很快被其他厂商所借鉴,也迅速普及到了其他工业领域。可以说,福特T型车流水线作业的发明开启了大规模工业生产的时代,人类的生产力得到了巨大的提升。从英国移居到美国的阿道司·赫胥黎对此深受启发,在他的带有科幻色彩的反乌托邦小说《美丽新世界》中,描写未来的人类“文明社会”,人们不再用公元纪年,也不信仰上帝,改尊亨利·福特为唯一的神,以福特为纪元,并以第一辆福特T型车流水线生产的1908年为福特元年。

Git 纪元

19世纪末,弗雷德里克·泰勒在美国一些工厂推广他的科学管理方法,这包括用科学的方法来代替人工经验判断、对工人进行专业训练以及按专业分工。亨利·福特在他的汽车工厂里也开始应用泰勒科学管理,并且在汽车生产上创新性的采用了流水线作业。1908年,第一辆福特T型车从流水线上面世,而经过优化的流水线在几年后甚至可以达到93分钟内生产一部汽车,强大的生产效率让福特超过了其他所有汽车厂商生产能力的总和。福特的流水线生产很快被其他厂商所借鉴,也迅速普及到了其他工业领域。可以说,福特T型车流水线作业的发明开启了大规模工业生产的时代,人类的生产力得到了巨大的提升。从英国移居到美国的阿道司·赫胥黎对此深受启发,在他的带有科幻色彩的反乌托邦小说《美丽新世界》中,描写未来的人类“文明社会”,人们不再用公元纪年,也不信仰上帝,改尊亨利·福特为唯一的神,以福特为纪元,并以第一辆福特T型车流水线生产的1908年为福特元年。

文件的消逝

一、应用

写这篇文章的时候我想起来的是之前看到的一段轶事。具体的文字已经不可考,但大致如下:

在一节计算机课堂上,教授跟学生说:「请大家打开 C 盘下的 xxx 文件。」这时有学生问道:「教授,请问我要用哪个 App 来做到这件事?」后来教授惊讶地发现,这一代的学生有些从来没有接触过文件管理器这个概念。他们从小到大接触到的都是一个个的 App,以及 App 内一个个具象的视频、音乐、文档等。对于他们来说,文件及文件夹是一个陌生的概念。

这一现象是什么时候开始的?或许有些人会认为是 iPhone 的诞生作为开端,但我更倾向与认为是 2004 年 Gmail 的诞生引领了这一趋势。

2004 年的愚人节,Google 正式发布了第一个版本的 Gmail,并宣布提供给每个用户 1GB 的存储空间。这在当年是非常具有轰动性的产品。在那之前,用户使用邮箱是通过客户端(Outlook 或者 Thunderbird)把邮件下载到本地后使用。因为当年邮箱提供商给予用户的免费空间一般按 MB 来计算,因此 Gmail 的推出一下子引发大量用户的迁移。

或许有很多人对 2004 年这一概念感到模糊,但我印象还算比较深。因为 2004 年正是我家刚买入第一台个人电脑的那年。当年我们家选配的硬盘为 80GB。

可能你会疑惑,只是增大免费容量为什么会作为一个趋势的起点?在我看来,这带来了用户使用习惯的改变。前文提到,在那之前用户使用邮箱是需要把邮件下载到本地后处理,因为邮箱提供商分配的空间有限,这意味着邮件的处理都是发生在本地的行为。邮箱提供商主要的服务仅仅在于发送与接收。但是当存储空间提升后,用户为什么还要将邮件下载到本地后处理呢?用户可不可以直接在网页上处理呢?事实上,当时已经有人这么做了。

注意,在以上的描述中我还没引入云的概念。对于大多数用户来说,最先让用户意识到云这一概念的产品是 iCloud。但在这之前还有一项划时代的产品需要介绍。同样出自 Google 之手,那便是今天大多数人的浏览器 — Google Chrome 的内核 Chromium。

二、基础设施

今天,除了苹果的 Safari 和 Mozilla 的 Firefox,大多数现代浏览器都是以 Chromium 为内核的应用。在当年,IE6 已经很久没有人维护了,网页技术的发展停滞不前。Chrome 的推出迅速刺激了沉寂已久的技术发展,人们意识到原来浏览器可以如此的快。注意,这里的快不仅是网页加载得快,而是在网页上做出复杂操作的时候响应速度的快。

同时,Chrome 也将 Web App 这一概念第一次让广大用户认知。但 Web App 这一概念并非由 Google 提出,

让我们把时间再往前几年,1995 年 Netscape 推出了 Javascript 编程语言。这一编程语言允许浏览器在网页上进行动态处理。2007 年,在 Chrome 推出的一年前,Mozilla 便推出了一个项目 — Mozilla Prism。Prism 将 Web App 和桌面操作系统深度整合,用户可以在桌面上直接打开某个 Web App。与在桌面建立某个网页书签不同,Prism 允许用户针对不同的网页配置不同的偏好设置。

以上一项为技术基础,一项更偏向理念,Google 在推出 Chrome 的时候便充分受益于此。在 Chrome 发布前夕,Google Blogoscoped 的作者 Philipp Lenssen 便将 Chrome 的主要特性总结为以下几点

  • Chrome 是 Google 的开源浏览器项目(编者注:此处说法有误,Chromium 才是开源的项目)
  • Chrome 会包含一个新的 Javascript 引擎叫 V8
  • Chrome 的标签页会放置在地址栏顶部
  • Chrome 会有快速拨号页
  • Chrome 会有隐私浏览模式
  • Web App 拥有自己的浏览器窗口
  • Chrome 内置防病毒及恶意软件功能

在我看来,以上特性中,真正具有革命性的功能为 V8 引擎以及将 Web App 的概念在浏览器设计之初便作为其重要特性。前者是后者的技术基础,而后者是消灭文件的基础。

三、云

2011 年,随着 iOS 5 一起发布的还有 iCloud 服务。至此,所有的拼图都完成了。iCloud 类的远程存储让广大用户意识到数据存储在本地不一定是安全的。这里的安全并不是私密性上的安全,而是能极大地降低数据丢失的风险。同时,只要网络条件允许,用户可以在任何物理设备上访问到自己的数据。换言之,本地存储不再是唯一选项。甚至随着网速的提升及网络延迟的降低,除了数据敏感性高的内容外,一切数据都可以放在云端。

但 iCloud 并不是第一个做云端硬盘的公司,早在 2005 年,Aaron Levie 就发布了 Box.net 这一云端硬盘产品。它允许用户将自己的文件放置于网盘上,并且可以像在本地文件一样管理。更先进的产品是 2008 年发布的 Dropbox,与 Box.net 一样提供云端硬盘服务。不同的是它提供了增量同步功能。这意味着如果用户对一个文件进行修改,Dropbox 可以做到只同步修改的部分。

从技术上看,Dropbox 将用户的文件拆分为许多小块,并将这些小块的属性计算出一个数值。我们只需要知道如果某一小块的数据有变更,那么这一小块的数值便会改变。通过对比本地和云端的数值便可以决定需要同步本地及云端的哪些内容。

增量同步除了提高同步速度外,还意味着文件存储形式的改变。用户的文件不再是原来的文件,而是被拆分成一段段数据,通过后期的拼接组合成用户原来的文件。虽然文件在本地硬盘的存储方式也是类似,但与本地存储不同,云端硬盘可以将用户文件拆分出来的一段段数据分散存储在不同的硬盘,甚至不同的数据中心。这一特性还有什么应用我们在此按下不表,后面会讲到。

iCloud 更为激进,在刚开始发布时它直接屏蔽了用户访问具体文件的选项。与 iOS 类似,用户使用 iCloud 是通过一个个 App 来实现。iCloud 和系统的整合更深,用户无法感知文件的存储及同步过程,本地存储和云端存储的边界更模糊了。用乔布斯的话来说就是 It Just Works。

但在这一步走得更远的依旧不是苹果。作为一家卖硬件为主要利润的公司,iCloud 主要的服务对象依然是苹果用户。对于其他操作系统,iCloud 显得过于封闭。而打破这一局面的仍然是 Google。在 iCloud 发布一年后,Google 也推出了自己的云端网盘 Google Drive。一开始发布时我以为这是一款比上不足比下有余的产品。它没有 Dropbox 的增量同步,也没有 iCloud 那般与操作系统深度整合的能力。似乎是一款可有可无的产品。但经过这些年发展,我发现它走的是另一条路,一条真正杀死用户文件的路。

四、文件的消逝

让我们暂且把目光转向更娱乐的地方 — 音乐。

我还记得以前听音乐的流程。在酷狗音乐上搜索自己喜欢的作品,然后点击下载。通过酷狗或者其他播放器打开刚才下载的 mp3 文件收听。有些音乐在各大音乐平台找不到,便到百度搜索,通过 BT 或者网盘下载到本地并整理好文件的元数据(歌手、专辑等)。在整理好后,将一些最近比较火的音乐整理好传到 MP3 里听。

后来我发现了豆瓣 FM。豆瓣 FM 和酷狗音乐最大的区别在于,豆瓣 FM 是纯流媒体的模式,即我们没法下载单曲,而只能在网页上播放。与之带来的变化是,我不再与一个个 mp3 文件打交道,将其手动整理好存到电脑里。甚至我不再需要下载程序,只需要登上豆瓣 FM 的网页就能开始听音乐。另外在存储空间不再是掣肘后,收听的音乐种类大大拓宽。通过不同的电台,我可以听到许多未曾接触的音乐。

这便是流媒体。

在今天这显得非常普遍,我们在 Netflix 上看电影,在 Spotify 上听音乐。理想情况下,我们不再需要下载这些内容,甚至下载这一概念已经变得陌生,取而代之的是离线观看(收听)。用户不再需要跟文件打交道,服务商也可以将这些内容用 DRM 锁定防止盗版,并更激进地使用私有协议。比如苹果通过 Apple Music 推出 Spatial Audio,在以往是很难实现的。

同时得益于流媒体的发展,获取新内容的成本大大降低。因为大多数流媒体都是按月收费,即用户付出一定的成本后,获取新内容的边际成本几乎为 0。这便带来了更多长尾内容。以往一个创作者创作出一张专辑,要说服未曾听过的人购买是很难的。但当获取新内容的边际成本降低为 0 后,用户消费新内容的门槛更低了,独立创作者的内容也更容易被消费到。

用户失去了文件的所有权,但也换来了更蓬勃的生态,以及更方便的使用体验。

这不仅发生在内容消费领域,在内容生产领域也略显端倪。

以文档处理为例,以往文档处理工具便是 Microsoft Office 三件套。诚然,Office 三件套功能十分强大,但它一开始的设计并没有考虑到云时代,所有文档的操作都是基于单一文件。而 Google Docs 则完全建立在云时代的基础上,也正是得益于这一后发优势,Google Docs 从设计之初就考虑到团队协作。也正是对用户屏蔽了文件这一形式,在线协作才成为可能,因为单一文件在修改的时候总是具有排他性的。

事实上,Google Docs 的文档会在 Google Drive 上显示出来,但如果我们将其下载下来会发现,这个文件只是一个链接。这也是我在前面提到的 Google Drive 设计的更先进之处 — 对于用户来说,文件并没有用,用户需要的是文件的应用。而与苹果的 iCloud 不同,Google Drive 真正做到了全平台。用户在本地不需要安装任何应用,在 Google Drive 上无数开发者提供了许多 Web App 让用户使用这些文件。与 Dropbox 不同的是,Google Drive 本身不实现增量同步,而是将这一工作下放给应用方实现。在线协作正是增量同步的体现。

Google Drive 的设计真正得益于前面三部分 — 应用、基础设施、云。通过应用(Google Docs)随时随地在基础设施(Google Chrome)上打开云(Google Drive)上的数据生产或消费。Google Drive 并不是传统的网盘,它更像是一个入口。

不止 Google,如今许多其他的应用也如雨后春笋般出现。比如 Figma,在 2016 年推出后迅速成为设计师最爱的生产力工具。比如 Notion,几乎只需要维护一份代码便可以提供全平台应用。

上述两个应用在创立之初都摒弃了传统文件的概念,比如在 Figma 里,我们不需要关心一个项目的所有 Page 是否是同一个文件。也正得益于屏蔽文件的设计,协作办公可以非常自然地实现。设计师和产品经理不再需要传输一个个 Sketch 文件,在某个有疑问的地方圈圈点点地沟通,而是直接在设计的过程中添加注释(改需求)。

即便是对文件系统最熟悉的程序员也逐步有屏蔽文件系统的趋势。在 Golang 里,外部依赖包是通过包的自定义地址引入。比如我要引用 MySQL 包,只需要在引入里写上 github.com/go-sql-driver/mysql 即可。在未来,Golang 是否还需要将外部包下载到本地再使用呢?进一步来推进,是否可以有一款新的编程工具如 Figma 那样,用户不再需要像现在一样整理文件的编排,而是用类似 Page 的形式整理,通过类似标签的形式引用别处的代码?

上述应用的发展都充分体现了一点:传统操作系统正在式微,而浏览器正在取代操作系统。事实上,Chrome 也推出了 ChromeOS 操作系统以及对应的 ChromeBook 笔记本。

目前这一替代还未成熟,对于计算密集型的应用还无法替代。比如音视频剪辑的应用还未成熟,虽然已经有产品正在尝试(比如 Dropbox Replay)。更难替代的是专业的工业软件。但对于大多数用户,文件确实已经消失了。尽管文件是操作系统最基本的单位,但用户并不需要知道这些。

小记备份:从账本说起

毕业后工作一段时间以来感觉自己的花销越来越不可控,之前听闻一个朋友说毕业后第一年基本是存不下钱的,当时还不以为然,结果后来真的应验了。于是在今年国庆后正式开始记账。作为整天与纯文本打交道的程序员自然更青睐于纯文本的记账工具,于是在看了 BYVoid 兄的这个系列文章以及 SKYue 兄的这篇文章后也开始用上了 Beancount+Fava

与之而来的问题是账本作为一种私密性极高的数据,我不希望在他人的服务器上有留下任何明文的数据。Dropbox 或者类似的网盘同步显然不合适,棱镜计划的存在让我放不下心。虽说自己的数据并没有涉及到犯罪,但是这些监控行为在价值观上也与我相悖。账本一旦有他人获得明文数据后几乎可以勾勒出我从记账开始后的生活轨迹,我不希望除了自己以外有其他人能看到。墙的存在也是一个考虑因素,虽说在用上 Clash/Surge 后已经可以做到在中国/国际互联网上无缝自由穿梭,但始终会有顾虑。

在 BYVoid 兄的文章 4 中提到了用 Git+git-crypt 的组合,但是使用了 git-crypt 也有弊端。因为 git-crypt 加密后在 Git 的记录都是加密的二进制信息,这就带来了在多设备环境中 merge 的问题。如果在编辑前忘记把最新的 commit pull 下来,在解决 conflict 的时候就没法像明文数据那样比较。虽说可以看 commit 时候的 message 来区分,但是因为是账本信息 commit 的 message 不应该写得很具体,否则也会泄露隐私。

于是在试过几次解决 merge conflict 后我放弃了这个方案,转而使用 P2P 同步的方式在多设备同步。目前我已经切换到 Syncthing 并且(在折腾了一段时间搞不懂它的同步逻辑失败多次后)稳步运行了起来。目前账本的信息保存在家里的电脑、家里的树莓派和自己的笔记本上,这样每次修改账本都可以几乎实时同步到另外几台设备上。

但是在听了《内核恐慌》的 56 期后了解了备份的 3-2-1 原则,想到事实上数据做了同步但是并没有做到很好的备份,而如果家里电脑、树莓派、笔记本一起挂掉(考虑到自己瞎折腾的频率和水平这种可能性并不低)那我的账本就消失了。于是开始着手于完成那个 1,即一份数据在远程。但是如我在上文提到的不能明文存储在他人服务器,在存储到另一台服务器的时候则需要先加密后上传。

(下文偏技术向)

首先我们需要准备几个东西:

  1. 一个 GPG 密钥
  2. 一个远程服务的帐号(我用的是 Backblaze B2
  3. 一台 24*7 运行的设备(非必需)

一、准备 GPG 密钥

首先生成一个 GPG 密钥:

gpg --full-generate-key

一路选默认就可以,如果你之前已经有一个 GPG 密钥,那么可以导入。

gpg --import /path/to/keyfile

之后信任这个密钥

gpg --edit-key YOURKEYFINGERPRINT

如果你导入了你的密钥,按一下 Tab 后应该就会出现了,或者可以用 gpg --list-keys 找到你的密钥,输入 pub 的第二行就好。之后键入 trust。因为是我自己生成的密钥,我就选了 I trust ultimately

二、注册个 Backblaze 的帐号

略……同时创建好一个 B2 的 bucket。

三、安装工具

首先要有 Python 环境,如果你是在 Debian/Ubuntu 上也直接可以通过 apt 安装 backblaze-b2,或者在其他设备可以通过 pip 来安装,具体可以参考官方文档

sudo apt install backblaze-b2 -y / pip3 install b2

安装往后把 backblaze-b2 或者 b2 路径添加到 PATH 里,一般已经自动添加好了。

之后授权 b2 绑定到自己帐号,具体可以看官方文档

b2 authorize-account [<applicationKeyId>] [<applicationKey>]

准备工作就完成了,接下来写个自动化脚本定时跑备份就好了。

四、备份

首先压缩成一个文件,因为只是作为备份而且 Backblaze 有10G 的免费空间,我们尽量把文件压缩到最小。另外可能账本中有些文件是不想包含在压缩包里的,比如编辑器的配置,或者 Git 的记录,可以把它们剔除掉。然后我们用我们的密钥加密这个压缩文件。之后上传到 Backblaze B2 上。

跑脚本前先定义几个变量:

  1. LEDGER_DIR 是存放我们账本的文件夹的上级目录,比如账本在 /home/user/Private/Ledger,那么这个参数就是 /home/user/Private
  2. LEDGER_NAME 即账本文件夹的名字,比如上面的例子就是 Ledger
  3. NOW 就是现在的时间,因为定时备份脚本是把历史都备份起来,所以通过时间命名文件可以知道该备份是何时生成的。可以通过 $($(which date) --iso-8601=seconds) 获得。
  4. GPG_PUB_KEYGPG 密钥的 Fingerprint,即 edit-key 时的那串字符。
  5. BACKBLAZE_BUCKET 是在 B2 上创建的 bucket 名字。
  6. BACKBLAZE_REMOTE_FILE_DIR 是在 bucket 里备份账本的文件夹的名字。

(我在上文或者下文用了很多 $(which xxx),这样可以获得 xxx 程序的绝对位置。因为不知道为什么在 crontab 上有时不这样写会有问题。)

然后跑下面这段脚本。

$(which tar) --exclude=".vscode" --exclude=".git" --create --directory $LEDGER_DIR $LEDGER_NAME | $(which gzip) --best | $(which gpg) --encrypt --recipient $GPG_PUB_KEY --output /tmp/$LEDGER_NAME.$NOW.tgz.gpg

exclude 很好理解,剔除掉部分文件,这里的 --create 即创建一个压缩文件,--directory 是我们先移动到存放我们账本的文件夹的上级目录,之后压缩我们的账本。如果不使用这个参数那么我们的压缩文件会把整个路径的文件夹都放进来,虽然不会把整个路径下所有的文件到包含进来但是就不太好看了。然后我们用 Gzip 进一步压缩文件到最小体积,再交由 GPG 加密,保存到 /tmp 文件夹下。最后就是上传到 Backblaze B2 上。

$(which b2) upload-file $BACKBLAZE_BUCKET /tmp/$LEDGER_NAME.$NOW.tgz.gpg $BACKBLAZE_REMOTE_FILE_DIR/$LEDGER_NAME.$NOW.tgz.gpg

这样就大功告成了。完整的脚本地址我已经存在 GitHub 上,chmod +x backup_ledger.sh 给予可执行权限后在 crontab 里设置定时任务就好了。比如每 3 个小时配分一次的话:

0 */3 * * * /path/to/backup_ledger.sh >/dev/null 2>&1

以上就是我的部分备份工作流。当然这样不止可以备份账本,还有其他重要的私密文件,比如录音录像这些也可以这样保存。这样也可以做到在保护隐私的同时保护数据安全。

(最后希望 Backblaze 不要被墙_(:3」∠)_

❌