<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>SQYBI.com Blog</title>
        <link>https://sqybi.com/blog/</link>
        <description>Change is a part of life and takes part in finding us who we are.</description>
        <lastBuildDate>Tue, 02 Dec 2025 23:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh-Hans</language>
        <copyright>Copyright © 2023-2026 SQYBI.com.</copyright>
        <item>
            <title><![CDATA[已经崩溃的舆论战场不值得被总结]]></title>
            <link>https://sqybi.com/blog/already-collapsed-battlefield-of-public-opinion-not-worth-summarizing/</link>
            <guid>https://sqybi.com/blog/already-collapsed-battlefield-of-public-opinion-not-worth-summarizing/</guid>
            <pubDate>Tue, 02 Dec 2025 23:00:00 GMT</pubDate>
            <description><![CDATA[今年的年度文章，我本来希望能够就现在互联网的舆论环境进行一番讨论，顺便也深入地思考一下为什么今年完全没有写作动力，特别是对于稍微深入一些的话题彻底失去了讨论的欲望。]]></description>
            <content:encoded><![CDATA[<p>今年的年度文章，我本来希望能够就现在互联网的舆论环境进行一番讨论，顺便也深入地思考一下为什么今年完全没有写作动力，特别是对于稍微深入一些的话题彻底失去了讨论的欲望。</p>
<p>但随着我一边写、一边查资料、一边思考和提炼，我越来越发现现在的互联网舆论环境已经真的不支持人们进行任何有信息量的思考输出了。即使是在相对小众的中文博客圈，大部分订阅比较多的博客也都在进行情绪输出和知识搬运，而非思想的碰撞。</p>
<p>战场。现在的互联网舆论环境就像是一个末日的战场，各方势力在战场上交战，但已经没有人知道最初的战争是因何而开始的。或许每个人最初都是为了自卫，但当他们以自卫为理由攻击他人的时候，这个世界就已经毁灭了。</p>
<p>战场上没有赢家。观众和读者们一边期待着“活人”的出现，一边亲手把匕首捅进每一个看起来像“活人”的目标胸口，因为战场上对他们威胁最大的就是另一个“活人”。</p>
<p>人们预设了一个拯救者，但当拯救者的行为和他们的预设有了哪怕是一点点偏差，他们立刻会将这个拯救者钉上十字架。不需要担心人手不够，因为这些刽子手们从来没有统一过他们的预设，所以总会有人参与这场行刑的狂欢。</p>
<p>在为了这篇年度文章深入思考的这几周，新闻中似乎没有一点好事，但坏事却源源不断。我的精神状态也在这个过程中逐渐变差，直到今天不小心把手机屏幕摔碎的时候，我突然觉得是时候扔掉这一切，扔掉互联网了。</p>
<p>约了修手机上门取件，用备用机订机票，订酒店，租车。备用机上没有社交媒体，也没有微信和 TG。至少这一周，我不再需要这些东西。</p>
<p>什么年度文章，让它自生自灭去吧。我要去享受看得见摸得着的物质世界了，留猪猡们在互联网上继续互相厮杀。</p>
<p>互联网是一片已经崩溃的舆论战场，它不值得被总结。</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 碎碎念</category>
        </item>
        <item>
            <title><![CDATA[关于 Quote/0 的那些你在购买前还不知道的特性]]></title>
            <link>https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/</link>
            <guid>https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/</guid>
            <pubDate>Sun, 07 Sep 2025 01:00:00 GMT</pubDate>
            <description><![CDATA[（文末有小彩蛋！）]]></description>
            <content:encoded><![CDATA[<p>（文末有小彩蛋！）</p>
<p>在一两年之前用 Arduino 套件搞了一个空调温度 PID 控制器，以及给 Titan2 手柄转换器写了一些简单的连发脚本之后，我已经很久没有再碰过嵌入式设备了。</p>
<p>最近看到少数派上新了一款叫做 Quote/0 的设备，就买了一台来玩玩。在下单之前我本来想先看看大家对这个设备的评价，以及这个设备的一些功能细节，但是无论是官方文档还是各种平台上的体验文章，都有很多没有提及的参数和软硬件体验细节完全没人提及过。</p>
<p>想了一下，一百来块钱的价格就算打水漂了也不贵，买来之后正好可以写一篇文章（就是现在这篇）介绍一下这些我在购买前没有找到的信息，供其他想买的人参考。于是我就开开心心地下单啦。</p>
<p>这篇文章中会讲解一些我在购买前比较好奇但是又没有找到介绍的特性，主要集中在产品的功能性和使用体验上，特别是关于 API 调用与刷新机制的一些网上找不到的说明。文章中不会对设备的目标用户、替代产品等商业目标进行评价，也不会评价产品整体的好与坏，每部分的评价都是就事论事。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quote0-是什么">Quote/0 是什么<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#quote0-%E6%98%AF%E4%BB%80%E4%B9%88" class="hash-link" aria-label="Quote/0 是什么的直接链接" title="Quote/0 是什么的直接链接" translate="no">​</a></h2>
<p>这里我就不花太多篇幅来详细介绍这款产品了，直接转一个官方的说明：</p>
<blockquote>
<p>Quote/0 搭载高度自由的信息配置系统，可选 <strong>摘录</strong>、<strong>RSS</strong>、<strong>天气</strong>、<strong>待办</strong> 等模块，即可将内容常亮显示于这块 <strong>无扰的墨水屏</strong> 上。
无需唤醒手机，重要信息 <strong>一瞥即得</strong>，让你保持专注，远离信息过载。无需下载 App，仍可通过 NFC 功能唤醒 <strong>iOS 轻 App</strong> 或网页中查看详情，或是 <strong>快捷指令</strong>。
一次充电，<strong>续航可达一年</strong>，真正做到安静长久陪伴。</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="硬件和外观">硬件和外观<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E7%A1%AC%E4%BB%B6%E5%92%8C%E5%A4%96%E8%A7%82" class="hash-link" aria-label="硬件和外观的直接链接" title="硬件和外观的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="电子器件构成">电子器件构成<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E7%94%B5%E5%AD%90%E5%99%A8%E4%BB%B6%E6%9E%84%E6%88%90" class="hash-link" aria-label="电子器件构成的直接链接" title="电子器件构成的直接链接" translate="no">​</a></h3>
<p>首先感谢知乎网友 @元可可 YoCoco 的拆解记录 <a href="https://zhuanlan.zhihu.com/p/1938764983941968757" target="_blank" rel="noopener noreferrer" class="">透视 Quote/0</a>，这可能是我搜到的最有用的一篇文章了。</p>
<p>从这个拆解中，可以看到 Quote/0 大致的电子器件构成是：</p>
<ul>
<li class="">ESPC3-20 芯片，几块钱的芯片还带 Wi-Fi 和蓝牙，也就没什么性能可言</li>
<li class="">一块不到 3 英寸的墨水屏，我测量的大小大约是 6cm x 3cm</li>
<li class="">一块 800mAh 的电池</li>
<li class="">一块带 NFC 线圈的电路板</li>
<li class="">一个塑料外壳</li>
<li class="">一块软磁铁</li>
</ul>
<p>虽然我并不太熟悉嵌入式硬件，但是随便在淘宝搜搜，也能看出这一套硬件的成本应该是百元以下的价格区间。</p>
<p>这么看的话，这个产品虽然利润率并不一定很高（毕竟还有服务器和开发成本），但如果有 DIY 能力且想要一套类似的技术方案，它显然毫无性价比可言。但是如果你并没有足够的技术、DIY 能力或设备，那这个产品的价格也不算很离谱。比如我就觉得家里没有 3D 打印机的情况下，买一堆套件之后想要搞个外壳是非常麻烦的事情。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="磁吸但没完全吸住">磁吸，但没完全吸住<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E7%A3%81%E5%90%B8%E4%BD%86%E6%B2%A1%E5%AE%8C%E5%85%A8%E5%90%B8%E4%BD%8F" class="hash-link" aria-label="磁吸，但没完全吸住的直接链接" title="磁吸，但没完全吸住的直接链接" translate="no">​</a></h3>
<p>Quote/0 的背后有一块软磁铁，用于把产品固定在各种金属表面。</p>
<p>但实际的使用中，我明显感觉到这块软磁铁的吸力并不太强。对于完全平面的铁质书架，这个磁铁可以稳稳地隔着一层漆面吸在上面；但是在一些有弧度或空隙的铁质物体上，比如我家的暖气片，这块磁铁就完全吸不住了。</p>
<p>之所以选择暖气片测试，是因为我的电脑桌附近没有特别好的金属平面可以吸附，但是正好有一个高度合适的暖气片。如果我想坐在电脑前面就能看到这块屏幕的话，最好的选择就是吸在这块暖气片上——可惜现在暂时做不到了，除非我自己再贴一层磁铁上去。</p>
<p>当然我想把它贴在暖气片上还有一个原因：作为一个怎么看都是桌搭的产品，Quote/0 竟然没有提供任何磁力或粘贴的桌面支架。甚至如果你想把它贴在一些无磁性表面上，比如这些年很流行的玻璃门冰箱，你还需要自己买一块引磁片，或者加钱买它的七夕套装。</p>
<p>鉴于产品上面带的这块磁铁属实拉跨，我很怀疑七夕套装里面的引磁片到底好不好用，而七夕套装加的这十块钱足够买十片不止的 3M 引磁片了。如果真的有这个需求，还是单独去买 3M 的产品吧。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="别出心裁的小设计">别出心裁的小设计<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E5%88%AB%E5%87%BA%E5%BF%83%E8%A3%81%E7%9A%84%E5%B0%8F%E8%AE%BE%E8%AE%A1" class="hash-link" aria-label="别出心裁的小设计的直接链接" title="别出心裁的小设计的直接链接" translate="no">​</a></h3>
<p>Quote/0 的外壳整体上是磨砂材质的。但是在它的右下角，有一小块区域是和其他区域不同的光滑材质。在灯光照射下，从某个特定的角度可以看到这个区域的形状。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="一块小的反光区域" src="https://sqybi.com/assets/images/small-reflective-pattern-7fe2851285a2d6e7294592a5d721d9d7.webp" width="1080" height="1080" data-zoomable="" class="img_ev3q"><div class="img-caption">一块小的反光区域</div></div><p></p>
<p>其实这个形状就是 Quote/0 所搭配的手机应用“Dot.”的 logo。使用这种光滑材质来呈现这个 logo，不得不说还是有一些设计上的小巧思在的，我第一次发现这个图案的时候确实有一种非常惊喜的感觉。</p>
<p>反面写有型号和电压等信息的铭牌看起来也是用类似的工艺处理的，但是实在有点难拍，就不上照片了。</p>
<p>虽然这个设计还是不错的，但从图片中也可以隐约看出，这个刚买了没几天的 Quote/0 上面已经出现了一些划痕。这些划痕应该也和这种磨砂材质相关，我不太在意这类产品的划痕问题，但这些划痕的产生看起来几乎是必然的，如果很在意的话在购买之前一定要三思。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="网络连接和硬件初始化">网络连接和硬件初始化<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E7%BD%91%E7%BB%9C%E8%BF%9E%E6%8E%A5%E5%92%8C%E7%A1%AC%E4%BB%B6%E5%88%9D%E5%A7%8B%E5%8C%96" class="hash-link" aria-label="网络连接和硬件初始化的直接链接" title="网络连接和硬件初始化的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="连接不上成本所限">连接不上？成本所限<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E8%BF%9E%E6%8E%A5%E4%B8%8D%E4%B8%8A%E6%88%90%E6%9C%AC%E6%89%80%E9%99%90" class="hash-link" aria-label="连接不上？成本所限的直接链接" title="连接不上？成本所限的直接链接" translate="no">​</a></h3>
<p>在首次连接的过程中，我和网上很多吐槽 Quote/0 的用户一样，都遇到了网络连接不上的问题。</p>
<p>而多次调整和尝试之后，我发现至少我遇到的这个问题其实非常简单：正如前文所说，或许是因为 Quote/0 的整体成本问题，这块同时带有蓝牙和 Wi-Fi 功能的芯片成本只有几块钱。这也就意味着 Wi-Fi 肯定只能用 2.4GHz 频段了，而且芯片的 Wi-Fi 接收性能也一定好不到哪儿去。</p>
<p>实际上，在路由器绝对不拉胯的情况下，这个芯片和路由器之间只要隔着一堵墙就完全没有办法收到信号。相比之下，我的手机在 5GHz 频段到了隔着两堵墙的厨房阳台也依旧信号稳定，而一些其它 2.4GHz 频段的智能家居设备也不太会出现一堵墙后就完全无法连接的情况。</p>
<p>最终，因为卧室能够不隔墙直连路由器的部分都没有电源，所以这篇文章的后续测试都是在 Quote/0 放在客厅直接与路由器面对面，而我需要在卧室的电脑和客厅之间来回跑的状态下进行的。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="错误提示在哪里">错误提示在哪里<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E9%94%99%E8%AF%AF%E6%8F%90%E7%A4%BA%E5%9C%A8%E5%93%AA%E9%87%8C" class="hash-link" aria-label="错误提示在哪里的直接链接" title="错误提示在哪里的直接链接" translate="no">​</a></h3>
<p>除了本身性能受限，设备的错误提示不清晰也是一个小问题。</p>
<p>事实上，无论是最初连接的时候 Wi-Fi 信号差，还是后续把设备移动到信号较差的地方无法刷新内容，设备上都几乎不会有任何直接的关于信号差的提示信息。</p>
<p>在早期不熟悉设备执行逻辑的情况下，确实很难分辨到底是推送的配置出了问题，设备的切换出了 bug，还是单纯没有收到 Wi-Fi 信号。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="只能用来固件升级的-usb-口">只能用来固件升级的 USB 口<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E5%8F%AA%E8%83%BD%E7%94%A8%E6%9D%A5%E5%9B%BA%E4%BB%B6%E5%8D%87%E7%BA%A7%E7%9A%84-usb-%E5%8F%A3" class="hash-link" aria-label="只能用来固件升级的 USB 口的直接链接" title="只能用来固件升级的 USB 口的直接链接" translate="no">​</a></h3>
<p>Quote/0 可以通过自带的 Type-C 口连接到电脑上，并通过网页程序直接进行固件升级。整体升级的操作很顺畅，界面也非常简单，这里要给一个好评。</p>
<p>但是这个 Type-C 口真的只能用来升级固件，并没有任何控制功能。比如这个 Type-C 口上是没有提供任何能够配置设备网络信息的功能的，配网一定要手机 App 连接蓝牙才行。</p>
<p>我大概能理解整体的产品逻辑是：Dot. App 是整个生态链的入口，Quote/0 只是这个生态链下的第一款产品，所以后续所有产品都要走这个统一的入口来配置和使用。而这样的设计就必然会带来一些问题，其中也包括一会儿要讲的所有推送都要走 Dot. 服务器的问题。至于这种设计是好是坏，那就见仁见智了。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="api-和数据更新机制">API 和数据更新机制<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#api-%E5%92%8C%E6%95%B0%E6%8D%AE%E6%9B%B4%E6%96%B0%E6%9C%BA%E5%88%B6" class="hash-link" aria-label="API 和数据更新机制的直接链接" title="API 和数据更新机制的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="不如求助一下微软改名部">不如求助一下微软改名部<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E4%B8%8D%E5%A6%82%E6%B1%82%E5%8A%A9%E4%B8%80%E4%B8%8B%E5%BE%AE%E8%BD%AF%E6%94%B9%E5%90%8D%E9%83%A8" class="hash-link" aria-label="不如求助一下微软改名部的直接链接" title="不如求助一下微软改名部的直接链接" translate="no">​</a></h3>
<p>写这篇文章的时候，有一个吐槽我一直忍到了现在：这个产品的命名实在是 <strong>太·垃·圾·了</strong>！</p>
<p>首先产品的名称叫“Quote/0”，而生态链 App 的名称则叫“Dot.”——无论哪个都是在搜索引擎上难以搜到的名字。而 Quote/0 的 API 文档所在的文档站叫“<a href="https://dot.mindreset.tech/docs" target="_blank" rel="noopener noreferrer" class="">Dot. 手册</a>”，URL 也和 Quote/0 没有任何关系，让搜索引擎上找到 Quote/0 文档站这件事更是变得难上加难。</p>
<p>上次见到的命名这么垃圾的产品叫 Follow，但是现在人家都改名叫 <a href="https://folo.is/" target="_blank" rel="noopener noreferrer" class="">Folo</a> 了，希望 Quote/0 至少能把文档站优化一下吧。</p>
<p>有的时候我真的感觉，正是有这些产品在，微软改名部的存在（并不代表真的存在，至少我在微软的时候没见到过他们）似乎也有了一些意义。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="基本的-api-使用">基本的 API 使用<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E5%9F%BA%E6%9C%AC%E7%9A%84-api-%E4%BD%BF%E7%94%A8" class="hash-link" aria-label="基本的 API 使用的直接链接" title="基本的 API 使用的直接链接" translate="no">​</a></h3>
<p>从上面的文档站可以看到一系列关于产品的文档，但是真正和 API 调用相关的只有 <a href="https://dot.mindreset.tech/docs/server/template/api" target="_blank" rel="noopener noreferrer" class="">API</a> 部分。</p>
<p>API 本身也是非常简单易用，在 App 上申请到密钥之后，把申请到的密钥作为 Bearer token 填到 header 里，并在请求中带上 <code>deviceId</code>（也就是设备的 MAC 地址）就可以了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="卡片切换逻辑">卡片切换逻辑<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E5%8D%A1%E7%89%87%E5%88%87%E6%8D%A2%E9%80%BB%E8%BE%91" class="hash-link" aria-label="卡片切换逻辑的直接链接" title="卡片切换逻辑的直接链接" translate="no">​</a></h3>
<p>首先，Quote/0 的基本设计是：有很多种不同的卡片，可以将这些卡片加入到轮换列表中，产品会根据配置的时间间隔轮换展示它们。</p>
<p>但是对于 API 调用，这个切换的逻辑有所不同：两个 API（<a href="https://dot.mindreset.tech/docs/server/template/api/text_api" target="_blank" rel="noopener noreferrer" class="">文本 API</a> 与 <a href="https://dot.mindreset.tech/docs/server/template/api/image_api" target="_blank" rel="noopener noreferrer" class="">图像 API</a>）对应了两张不同的卡片，而当某个 API 被调用且 JSON 中包含 <code>"refreshNow": true</code> 参数时，如果设备处于“活跃状态”，那么就会以极短的延迟直接切换到对应的这张卡片。如果设备上已经在展示这张卡片了，则是立刻刷新上面显示的内容。</p>
<p>虽然根据使用体验和文档，这里的“活跃状态”都应该基本等同于“插电状态”，但我在第一天使用的时候确实遇到过在插电状态下从 App 上看到设备依旧不是活跃状态的情况，不知道是有某些特殊的判断方法还是奇怪的 bug，或者也可能只是当时的网络情况不太好。</p>
<p>所以，如果你的需求是希望 API 调用后能够立刻在 Quote/0 上立刻显示出内容，请务必给设备长期通电，并放置在一个网络足够良好，和路由器之间没有任何遮挡的位置。要是受条件所限做不到这两点，那购买这个产品可能就不是一个正确的选择了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="渲染任意内容格式的技巧">渲染任意内容格式的技巧<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E6%B8%B2%E6%9F%93%E4%BB%BB%E6%84%8F%E5%86%85%E5%AE%B9%E6%A0%BC%E5%BC%8F%E7%9A%84%E6%8A%80%E5%B7%A7" class="hash-link" aria-label="渲染任意内容格式的技巧的直接链接" title="渲染任意内容格式的技巧的直接链接" translate="no">​</a></h3>
<p>Quote/0 的图像 API，是可以在整个屏幕上渲染一张完整黑白图片的。</p>
<p>借助这一点，一个技巧是可以把任何希望显示的内容生成为一张全屏比例的图像，然后把这个图像推送到设备上。这样你就可以拥有不同样式的排版、不同大小的字号、不同字体等等在文字 API 中不支持的功能了。</p>
<p>官方淘宝店并没有给出这块屏幕的参数，我暂时也没有搜到任何关于这块屏幕参数的信息。好在官方图像 API 的文档中有推送一张全屏图片到设备上的样例，我把这张图片的 base64 转回 png 之后，看到它的大小是 296 x 152。</p>
<p>不出意外的话，这应该就是屏幕的像素数了，如果自己渲染图片应该可以参考这个大小。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="不要相信云服务">不要相信云服务<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E4%B8%8D%E8%A6%81%E7%9B%B8%E4%BF%A1%E4%BA%91%E6%9C%8D%E5%8A%A1" class="hash-link" aria-label="不要相信云服务的直接链接" title="不要相信云服务的直接链接" translate="no">​</a></h3>
<p>可能是出于后续构建生态链的考虑，Quote/0 的所有 API 请求都需要经过 Dot. 的服务器，再下发到产品上（同时也能从 App 上预览到产品即将展示的内容）。</p>
<p>但之前的智能家居产品（说的就是你，小米）已经告诉过我们答案了：任何云服务都是不稳定的，必须依赖云服务的智能家居早晚会掉链子。</p>
<p>这个不稳定的设计也让这个产品很难真正成为智能家居的一个关键环节。我也看到了一些用户在网上提到自己想用 Quote/0 展示一些智能家居的信息，如果不是作为一个单纯的玩具，这里也只能建议他们再多考虑考虑吧。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="彩蛋">彩蛋<a href="https://sqybi.com/blog/things-you-didnt-know-about-quote-0-before-buying/#%E5%BD%A9%E8%9B%8B" class="hash-link" aria-label="彩蛋的直接链接" title="彩蛋的直接链接" translate="no">​</a></h2>
<p>因为我暂时也没想好要怎么用这个产品，所以暂时放一个小彩蛋在这里吧：</p>
<p>你可以使用下面的这个按钮，来给我的这个设备发送一条留言。如果你的留言没有被其他人刷掉的话，我或许就能在家里某次路过这个设备的时候看到它了！</p>
<!-- -->
<button style="background:#0066cc;color:white;padding:5px 10px;border-radius:0.5em;border:none;cursor:pointer">发送留言</button>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 计算机技术</category>
        </item>
        <item>
            <title><![CDATA[从工位牛马到海中人鱼：马尔代夫的大续命术]]></title>
            <link>https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/</link>
            <guid>https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/</guid>
            <pubDate>Wed, 12 Feb 2025 01:00:00 GMT</pubDate>
            <description><![CDATA[最近几年每到春节前夕，对于我来说最重要的事情都不是抢回家的车票，而是开始规划出门旅游的行程。]]></description>
            <content:encoded><![CDATA[<p>最近几年每到春节前夕，对于我来说最重要的事情都不是抢回家的车票，而是开始规划出门旅游的行程。</p>
<p>对于在北京工作的天津人，因为距离实在太短，城际列车实在太方便，所以回家成为了一件随时都可以做的事情。正因为如此，把春节这样一个全年最长的假期拿来回家躺着而不是出去旅游，就有点过于浪费了。</p>
<p>加上家里没什么亲戚，父母也没有过年一定要回家的要求，这些年的春节就变成了一个纯粹的假期：去年去了湖南，前年去了哈尔滨。</p>
<p>而今年，我的一位朋友正好想一起组团春节出去玩，所以两家四个人一起商量了一下，准备出国搞个大的。最开始是想去新西兰，但是查了一下现在新西兰一趟还是蛮贵的，想玩爽了人均大概要几万块钱。本来是抱着吐槽的心态说这价格都能去马尔代夫了，结果四个人一合计：既然都这么说了，不如干脆就去马代吧！</p>
<p>感谢当时我们这个未曾深思熟虑的决定，这个世界上现在又多了几个被续了一大口命的打工人。</p>
<p>偷偷放两张前两年春节出去旅游时拍的照片，湖南（我们去了长沙和衡阳）跟哈尔滨的体验也是蛮不错的！不过现在好像去哈尔滨的人有点太多了，我们当时恰好躲过了后面两年人们扎堆去东北的热潮。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="衡阳江景" src="https://sqybi.com/assets/images/river-b6cadc489714b270ca927872063d80ea.webp" width="2047" height="1365" data-zoomable="" class="img_ev3q"><div class="img-caption">衡阳江景</div></div><p></p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="哈尔滨东北虎" src="https://sqybi.com/assets/images/tiger-2d67d80dcf4c95a01b5f8d75649dff8c.webp" width="2048" height="1365" data-zoomable="" class="img_ev3q"><div class="img-caption">哈尔滨东北虎</div></div><p></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="选岛">选岛<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E9%80%89%E5%B2%9B" class="hash-link" aria-label="选岛的直接链接" title="选岛的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="制定基本方针">制定基本方针<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E5%88%B6%E5%AE%9A%E5%9F%BA%E6%9C%AC%E6%96%B9%E9%92%88" class="hash-link" aria-label="制定基本方针的直接链接" title="制定基本方针的直接链接" translate="no">​</a></h3>
<p>因为马代的岛确实太多，所以全都选一遍显然是不现实的。</p>
<p>我们采取的选岛策略是：制定基本方针 -&gt; 初选 -&gt; 收集详细信息 -&gt; 复选 -&gt; 找旅行社询价 -&gt; 排序 -&gt; 按照顺序看哪个能订到票。因为我们预定的时间比较晚了（接近 12 月底），所以很多想去的岛最后没有订上。不过即使并非第一备选，最终的 Nova Maldives 这个岛的体验还是堪称完美，不愧是马尔代夫。选岛的时候其实也不需要太纠结，马代这边的岛还是比较一分钱一分货的。</p>
<p>这次我们选岛的基本方针是：小孩少 + 浮潜还行 + 景色别太差 + 食物够丰富，当然在这个方针之外也要划定一个大概的心理价位。</p>
<p>初选的时候使用了只要在马代选岛就一定听说过的马代实验室，上面的信息虽然可能已经 out-of-date 了，但多少能做个大致方向上的参考，筛选掉一些实在不行的岛。</p>
<p>而后续收集详细信息就主要靠小红书了，不得不说不管是国内还是国外旅游，小红书的信息量和真实性都是独一份的。当然这个过程中也可以参考一些国外网站比如 Booking.com，这些网站上可以不走旅行社自己订马尔代夫的岛，所以也有不少来自世界各地的真实评价。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="浮潜和景色可以兼得">浮潜和景色可以兼得<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E6%B5%AE%E6%BD%9C%E5%92%8C%E6%99%AF%E8%89%B2%E5%8F%AF%E4%BB%A5%E5%85%BC%E5%BE%97" class="hash-link" aria-label="浮潜和景色可以兼得的直接链接" title="浮潜和景色可以兼得的直接链接" translate="no">​</a></h3>
<p>先说浮潜和景色，有人会说这两者其实是不可兼得的：浮潜的两个重要因素是浪小+鱼多，浪小意味着岛上得有防浪堤，鱼多则意味着鱼要有地方藏身，而最好的藏身处是海草。但无论是防浪堤还是海草，都会影响到景色的美观。</p>
<p>但实际体验下来，我觉得这个说法有些过于极端了。以我自己的体验修正一下这个说法，那就是：顶级的非出海浮潜体验，和职业自媒体账号运营级别的拍照出片，二者不可兼得。</p>
<p>很显然，大部分人都不需要这么顶级的浮潜体验（有很多岛也是可以选择出海浮潜的），拍的照片也只是发朋友圈而不是用来起号赚钱的。</p>
<p>就以这次我们去的 Nova 举例，浮潜的鱼种还是很丰富的，水屋直接下水的鱼就很多，浮潜点附近更是鱼量和种类都爆炸多。甚至我这种去马代之前游泳都不会的新手，一样可以在海里追到不止一种鲨鱼。</p>
<p>与此同时，这个岛上并没有什么海草，取而代之的是大量礁石，礁石一样可以吸引鱼群，海星海葵海参海胆也都不少。而这个岛设计得非常好的一点是防浪堤也是用礁石替代的，而且高度合适，涨潮的时候甚至会直接被水没过去。虽然这会导致浪确实大了一些，但只要别选在光线很差或者海浪半米高的时候下海，新手一样可以顶着浪下去浮潜——当然作为新手，还是安全第一：绳子绑好，注意洋流方向，戴好脚蹼，保存体力。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="浮潜好，海景也好" src="https://sqybi.com/assets/images/sea_view-657131dea54060a2b82251fa480e096c.webp" width="1664" height="1440" data-zoomable="" class="img_ev3q"><div class="img-caption">浮潜好，海景也好</div></div><p></p>
<p>换一个例子，对于一个一心浮潜的爱好者来说，也大概率不会在乎海面上拍照好不好看——反正照片视频都是水里的 GoPro 和 Action 拍的。或许只有我们这样的新手第一次马代选岛的时候，才会纠结这些有的没的。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="规避小孩">规避小孩<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E8%A7%84%E9%81%BF%E5%B0%8F%E5%AD%A9" class="hash-link" aria-label="规避小孩的直接链接" title="规避小孩的直接链接" translate="no">​</a></h3>
<p>我们这一次选岛还有一个重要的目标，就是尽量选小孩子少一些的岛，避免岛上过于吵闹，也是怕作为浮潜新手下水的时候小孩子太多有危险（虽然很多小孩子比我们熟练多了，但毕竟小孩子不像大人一样会躲人和规避风险）。</p>
<p>总的来说，有两个选岛的方向可以完成规避。</p>
<p>第一个当然就是直接选“成人岛”，也就是标注了 XX+ 的岛。举个例子，我们这次本来的首选芙拉瓦丽（Hurawalhi）就是一个 15+ 的岛，15 岁以下的客人是不能预定的。每个岛的年龄限制也不太相同，比如菲诺岛（Finolhu Villas）是 10+，你和我岛（You &amp; Me，一看名字就是个蜜月岛）是 16+。这应该是最直接的筛选方式。</p>
<p>除此之外，也可以关注岛上有没有儿童设施。有一些岛是有儿童俱乐部的，这很显然就是给带小孩的客人准备的。规避这些岛，也可以选到一些小孩子比较少的岛。当然反过来，如果有带小孩的需求，就可以考虑这些岛了——前提是你的孩子英语要过关，毕竟带小孩的人、岛上的其他小孩、甚至儿童俱乐部的电视节目都是说英语的。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="民以食为天">民以食为天<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E6%B0%91%E4%BB%A5%E9%A3%9F%E4%B8%BA%E5%A4%A9" class="hash-link" aria-label="民以食为天的直接链接" title="民以食为天的直接链接" translate="no">​</a></h3>
<p>中国人或许是马代选岛的时候最关注吃的怎么样的一批人了。</p>
<p>一方面，大家本来就对吃很挑剔；另一方面，大部分马代的岛吃的无论好坏都是白人饭，所以吃惯了中餐的话不适应也是正常的。</p>
<p>好在我们同行的几个人都相对适应白人饭，所以也没在这上面花太多心思。事实证明，如果不是非中餐不可的话，我们这次的 Nova 算得上是 AI 自助餐的食物种类和质量都很不错的岛了。</p>
<p>既然这里提到了，给没有过选岛经验的小伙伴展开说一下什么是 AI：这个 AI 不是人工智能，也不是 Adobe Illustrator，而是 all inclusive 的缩写，也就是一价全包。</p>
<p>不知道是不是有什么当地的旅游局在规范着，马代的度假岛上套餐形式是统一的，通常就是 BB / HB / FB / AI 这几种。</p>
<p>BB / HB / FB 的区别一般就是有几顿免费的饭：BB 只有早餐，HB 会包含早餐和一顿正餐（通常是午餐），FB 则是一日三餐。当然大部分用餐都是有可能限定餐厅的，一般以自助餐厅居多，也有一些可以允许在非自助餐厅点限量的菜或者点特定的套餐。</p>
<p>AI 会在 FB 的基础上增加额外的饮品或其它服务，比如我们这次的 AI 就包含了岛上部分有酒精和无酒精饮品（虽然说是部分但也足够喝了）畅饮，以及若干乘船出海和免费拍照之类的活动。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="畅饮鸡尾酒" src="https://sqybi.com/assets/images/drink2-f1b3363e829bb67de2bb300f0b7ed4af.webp" width="1664" height="1440" data-zoomable="" class="img_ev3q"><div class="img-caption">畅饮鸡尾酒</div></div><p></p>
<p>有趣的是，我们上岛之后才知道，这个套餐是中国代理专享的。对于国外的代理，套餐会包含非自助餐厅的三餐选择，但是减少了出海和拍照的活动。在额外掏钱体验了岛上另一家餐厅的正餐之后，不得不说这些国内代理还是很有眼光的。与其吃一顿让人昏昏欲睡又不怎么好吃的西餐，还是这些活动更吸引我们。不过这个套餐还是保留了一顿漂浮早餐和一顿沙滩上的晚餐，这两顿饭相对来说都还是很合我们胃口的。</p>
<p>顺带一提，偶尔还会看到有一种套餐叫 RO，是 room only 的意思。这个套餐最简单，也就是除了住宿，别的都要额外花钱啦。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="采购">采购<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E9%87%87%E8%B4%AD" class="hash-link" aria-label="采购的直接链接" title="采购的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="浮潜装备">浮潜装备<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E6%B5%AE%E6%BD%9C%E8%A3%85%E5%A4%87" class="hash-link" aria-label="浮潜装备的直接链接" title="浮潜装备的直接链接" translate="no">​</a></h3>
<p>因为我们之前都没有浮潜经验，所以整套浮潜装备都要从头准备。</p>
<p>虽然岛上据说是可以租借的，但吹嘴和面镜这种东西还是用自己的比较干净和安全。加上怕到时候万一哪一种租借不到导致没法浮潜，我们最终决定除了脚蹼和救生衣以外所有装备都自己准备。</p>
<p>对于浮潜新手来说，一定要准备的东西，包括了面镜+吹嘴+呼吸管+水母衣+潜水手套。其中呼吸管和吹嘴是一套，我们选择了干式的，事实证明非常有用。虽然有人说干式呼吸管比较危险，但实际测试下来我觉得只要在下海之前做足够多的练习（主要是万一躺过来怎么翻身的练习），干式呼吸管对新手一定是更安全的。而水母衣和手套是必需的，它们全程三四天的时间应该帮我避免了五六个大大小小的伤口。要知道海水有极强的腐蚀性，很容易造成伤口感染，一旦身上有了伤口下水就是很麻烦的事情。同时，水母衣也有比任何防晒霜防晒泥更好还更简单的防晒效果。</p>
<p>除此之外，安全方面，我们还购买了安全绳和求生哨。求生哨当然是没用上的，但是这东西有一个总比没有安心（酒店的救生衣上也有一个，但没去之前很难得知）。安全绳的话，我更推荐住水屋可以自己从屋里下水的时候购买，对于新手的前 2-3 次下水很有帮助，主要是起到一个安心的效果。不过如果你是从浮潜中心这种公共潜点下水的话，安全绳可能会影响其他人的浮潜，就不太适合绑了。</p>
<p>另外一些可选的装备是手机防水袋、漂流袋、潜水袜。手机防水袋我们全程没有用到，浮潜的时候根本不会有心思看手机的。漂流袋可以看作是一个可以防水的书包，我并没有真的把它扔到海里（同样是因为浮潜的时候是不会用到里面东西的），但无论是出海坐船还是带东西到海边，以及临走的时候把没有晾干的衣服收进去，它都是一个用来进行干湿分离的优秀容器。</p>
<p>潜水袜这个东西有些见仁见智：我在穿了几次之后就不穿了，因为租到的脚蹼尺码比较小，脚蹼本身的保护作用也很好了，没必要再套一层。但我的朋友就很喜欢穿，甚至可以拿它代替鞋子，穿上就可以出门。浮潜新手出海是一定要戴脚蹼的，不然很容易逆流游不回来，所以仅考虑下海使用的话我认为可以不买。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="拍摄设备">拍摄设备<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E6%8B%8D%E6%91%84%E8%AE%BE%E5%A4%87" class="hash-link" aria-label="拍摄设备的直接链接" title="拍摄设备的直接链接" translate="no">​</a></h3>
<p>运动相机看起来是浮潜必定会准备的东西。</p>
<p>但作为之前连游泳都不会的新手，我还是想唱唱反调。</p>
<p>我们这次是租了两台 GoPro 带过去的，但这次在岛上的四天时间，我全程都没有使用过它们。一方面原因是第三天下午开始我才能比较自由地掌控在水里的动作，同时追上一些游得不快的鱼（鲨鱼还是追不上的），这之前拿着 GoPro 也拍不到啥，而且第一次下海已经很紧张了很难分心。另一方面，我的朋友作为会游泳的浮潜新手，第一天就在海里弄丢了一台 GoPro。</p>
<p>综合我们两个人的经历考虑，我觉得如果对自己的浮潜水平不自信，同行的人又有水下拍摄设备，可以就考虑不准备第二台了。反正菜鸡拍出来的画面肯定比较一般，不如直接偷对方的图和视频吧！</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="GoPro 水下拍鲨鱼" src="https://sqybi.com/assets/images/shark1-fee03993573095fcd967cb5b059e1eba.webp" width="1440" height="799" data-zoomable="" class="img_ev3q"><div class="img-caption">GoPro 水下拍鲨鱼</div></div><p></p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="手机水上拍鲨鱼" src="https://sqybi.com/assets/images/shark2-fdd711e67ee65489852dbe28bab6b435.webp" width="1440" height="2141" data-zoomable="" class="img_ev3q"><div class="img-caption">手机水上拍鲨鱼</div></div><p></p>
<p>另外绝大部分岛考虑到隐私问题都是不能飞无人机的，所以通常就不用准备了。因为起飞就会拍到隔壁，很多房间有露天泳池、露天淋浴甚至露天浴缸，确实不太合适。</p>
<p>有一些岛有能包场的拖尾沙滩或者无人岛可以去，这些地方可能是可以飞的。至于为了飞这一次拎着无人机来回一趟值不值，就要自己考虑了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="其它有的没的">其它有的没的<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E5%85%B6%E5%AE%83%E6%9C%89%E7%9A%84%E6%B2%A1%E7%9A%84" class="hash-link" aria-label="其它有的没的的直接链接" title="其它有的没的的直接链接" translate="no">​</a></h3>
<p>驱虫用品：岛上虽然都会做驱蚊，但是通常房间里还是会有一些蚊虫的，而且房间外的开放空间蚊虫相当多。不过事实证明蚊子吃谁主要还是看谁好吃，和喷了多少驱蚊剂也没什么关系。聊胜于无吧。</p>
<p>美元：每人带一百刀左右，到了马累机场或者岛上之后，都换成一刀和五刀的零钱，四天的话完全够用了。</p>
<p>转换插头：不同的岛似乎不太一样，Nova 是不需要的（都是多种插头通用的接口），不过还是备上比较保险。</p>
<p>衣服：岛上昼夜有一定的温差，白天的状态是热+晒，晚上相对比较舒适，可能有一点点冷。考虑到物理防晒是最好的防晒，个人推荐薄的短袖上衣+薄的长裤+防晒衣+遮阳帽是最好的组合，漂亮衣服带一两身用来拍照就可以了，拍完赶紧换回防晒套装。我这次后面两天浮潜的几个小时因为懒所以放弃了面部防晒，就这几个小时导致回家之后脸直接黑了两个色号。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="上岛">上岛<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E4%B8%8A%E5%B2%9B" class="hash-link" aria-label="上岛的直接链接" title="上岛的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="每天干什么">每天干什么<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E6%AF%8F%E5%A4%A9%E5%B9%B2%E4%BB%80%E4%B9%88" class="hash-link" aria-label="每天干什么的直接链接" title="每天干什么的直接链接" translate="no">​</a></h3>
<p>说了这么多，似乎一直没有提到一个问题：去了马代之后，在岛上究竟能干什么？</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="Welcome drink" src="https://sqybi.com/assets/images/drink-87833eccdf7e2c94015e4364f8beb18c.webp" width="1440" height="2141" data-zoomable="" class="img_ev3q"><div class="img-caption">Welcome drink</div></div><p></p>
<p>因为每个人喜欢的活动都不一样，我只能说一下我们这段时间在岛上的体验。好在我们这次活动安排的比较全，各种类型的娱乐基本都体验到了。我这里列一个时间线，应该可以作一定的参考。</p>
<p>通常我们会在当地时间的晚上 10-11 点睡觉，第二天早晨 6-7 点起床。</p>
<p>起床之后简单洗漱就可以顶门去吃早餐了，在没有活动的日子，早餐之后我们通常会选择躺平休息或者在屋里潜水。早晨和上午是很适合潜水的时间，通常比较风平浪静，鱼也相对比较多，太阳也不会太晒。</p>
<p>上午的时间其实过去的还蛮快的，中午再大吃一顿之后，下午 3-4 点之前一般是躺平的时间。躺平休息的方式也有很多，比如泡泡泳池上来冲个澡，或者在躺椅上吹吹海风。也可以干脆在房间里吹吹空调睡个午觉，毕竟这个时间是一天里最热的时间，屋外还是很晒的。</p>
<p>下午 4 点左右就可以考虑继续去潜水了，通常下午的时间我会出门到码头的潜点下水。选择下午去潜点主要是因为上午时间比较少，一个来回就要花费不少功夫，还要换衣服洗澡，在房间里就更合适一些。</p>
<p>晚饭开始得比较晚，如果是选择非自助餐厅一般都需要预约，时间可能就会更晚一些。吃完可能已经 9 点 10 点甚至更晚啦，回去洗个澡休息一会儿就能睡觉了，一睁眼又是新的一天！</p>
<p>实际上只看这个时间表，感觉每天也没干什么，除了躺着就是潜水。但是不管是躺着还是潜水都很开心，就是那种身体在大自然里感受到的从内而外的开心，把身上的班味儿洗得一干二净。</p>
<p>对于现代人来说，躺平吹吹海风可能才是最难得的快乐。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="出海活动">出海活动<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E5%87%BA%E6%B5%B7%E6%B4%BB%E5%8A%A8" class="hash-link" aria-label="出海活动的直接链接" title="出海活动的直接链接" translate="no">​</a></h3>
<p>除了赠送的日落巡航以外，我们还报名了深潜和出海追蝠鲼的活动。</p>
<p>深潜不必说，体验过的话应该都会喜欢的，只是岛上的深潜并不坐船出海，只是去岸边的海沟下面，稍微有点玩的不够爽。</p>
<p>追蝠鲼（也就是 manta，一种长得有点像鳐鱼的鱼）本身是一个很有意思的活动，小黑会开船出去找蝠鲼经常聚集的地方，找到之后就可以直接从船上跳进水里跟着蝠鲼一起浮潜。本来我们对这个活动的担忧是作为新手能不能安全地在海中央下水，没想到的是我们这趟的运气比较差，两个小时都没有找到蝠鲼的影子。中间有一次小黑似乎发现了蝠鲼，赶紧招呼大家下水，结果几个先锋队跳到水里之后发现不对，然后我们在船上的人就看到小黑从远处捞上来了一个黑色的塑料袋……可以说是不要在海边乱扔垃圾的教育片了。</p>
<p>说回日落巡航，这个是赠送的活动，船上看起来也都是华人。简单来说就是坐着小船出海，日落之前朝着太阳开，日落之后朝着岛开。但就是这种单纯的吹风聊天喝饮料看落日，带来的体验却是直击心灵的。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="来一瓶可乐吧！" src="https://sqybi.com/assets/images/sunset-dc1d43552161e02c934a1e6bbc1c20ed.webp" width="1440" height="2141" data-zoomable="" class="img_ev3q"><div class="img-caption">来一瓶可乐吧！</div></div><p></p>
<p>现代人真的被钢筋水泥困住得太久太久了。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="放松紧绷的神经">放松紧绷的神经<a href="https://sqybi.com/blog/from-office-workhorse-to-mermaid-in-the-sea-maldives/#%E6%94%BE%E6%9D%BE%E7%B4%A7%E7%BB%B7%E7%9A%84%E7%A5%9E%E7%BB%8F" class="hash-link" aria-label="放松紧绷的神经的直接链接" title="放松紧绷的神经的直接链接" translate="no">​</a></h2>
<p>在选岛的时候，有一个条件最开始并不在我们的目标里，但随着选岛的过程逐渐成为了筛选条件的一部分：岛上的服务。</p>
<p>但在实际上岛之前，我们对马尔代夫岛上服务的好和坏并没有一个准确的预期，只是大致知道这个价位的岛应该没有一对一的管家服务，以及筛选掉了一些差评中提到对亚裔有明显歧视的岛。</p>
<p>或许是运气真的不错，Nova 这个岛的服务体验下来是相当好的。这种好并不是有什么无微不至的照顾，而是一种“没有压力”的感觉。</p>
<p>最开始选岛的时候，我们就发现 Nova Maldives 这个岛在国内平台上的信息相当少。实际上岛之后，岛上也确实几乎没有什么中国人，部分看起来像华人的人听语言也大多是港台的，或者也可能是新加坡的，说普通话的人寥寥无几。直到下岛前的最后一天，我们才碰到了两个来自苏州的超级大 E 人，第一次用中文跟其他游客聊上了两句。</p>
<p>可能也正因为如此，这个岛上的服务状态是欧美的那种大开大合：上岛第一天前台的唯一一个中文管家就告诉我们这个岛上没有一对一管家服务，但是有什么问题都可以来前台或者打电话找人解决。当然可能是因为我们塞了一些小费的原因，后续她还是加了我们的微信，帮忙解决了不少问题。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="岛上的黄昏" src="https://sqybi.com/assets/images/sunset2-e481f00c296c7744a975112369873d5c.webp" width="1664" height="1440" data-zoomable="" class="img_ev3q"><div class="img-caption">岛上的黄昏</div></div><p></p>
<p>等到真的待够了四天，你会发现虽然确实没人跟着你帮忙安排每件事情，但如果你主动提出什么问题，一定会有人来帮你解决。岛上的工作人员看到你都会打个招呼，但也只是一个简单的招呼。岛上的活动可能会有额外的收费项目，但一定有人在开始之前一条一条地解释每个收费项目具体的价格，并附带一句这都是自愿选择的，不买这些额外项目也会有很不错的体验。</p>
<p>这个“自愿选择”并不是单纯的“明码标价”，而是一种“即使不选择也可以获得很多快乐”的自由。互联网催生的商业模式很多时候都会利用人性的弱点设置一些看似自愿实则强迫的氪金点，最常见的就是免费版本阉割到用着难受，以此来让用户觉得自己的消费很“值得”。</p>
<p>但没有人是傻子，大家接受这个模式并不是真的喜欢它，而是一种被逼无奈，一种向大环境做出的妥协，一种相互让利的行为。但让利就意味着算计，意味着勾心斗角，意味着本来就因为工作压力紧绷的神经，在一次次的利益计算和无可奈何中继续被拉紧，拉紧，不知道什么时候就会断掉。</p>
<p>当你发现马尔代夫的岛上有这样一种商业模式，你花出去的钱真的可以买到自己想要的东西，而非那些你本来就应该获得但被克扣之后额外施舍给你的东西时，那种精神上的放松感实在是难以用语言形容。</p>
<p>小费的问题也是一样，在岛上的这些天，我们一直都是在服务完全结束之后才给小费的。觉得服务员提供了额外的服务就给一些，只是正常服务就不给。服务人员也都不在意，依旧提供着该有的服务。</p>
<p>某一天的晚餐是套餐赠送的，叫做沙滩晚餐。简单来说就是把桌子摆到沙滩上吃，餐品就是前菜+汤+主食+甜点的正常组合。我们这桌的服务员也是个 E 人，全程在找话题聊天，大家都很开心。最后一道甜点吃完的时候，沙滩的另一侧正好开始了一场火焰杂技表演，我们就在桌子上留下了小费跑去看表演了。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="沙滩晚餐" src="https://sqybi.com/assets/images/dinner-bbfbe43df6c76e1ab9aa4e6296ed2168.webp" width="1664" height="1440" data-zoomable="" class="img_ev3q"><div class="img-caption">沙滩晚餐</div></div><p></p>
<p>等表演结束，我们走回房间路过沙滩上的桌子，正好看到刚才的服务员在收拾桌上的餐具。可能是因为拿到了意料之外的小费，他开心地哼起了歌；就像这些日子每次有了新鲜体验的我们一样——</p>
<p>快乐得像个孩子。</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 碎碎念</category>
        </item>
        <item>
            <title><![CDATA[国航第二架 C919 乘坐体验]]></title>
            <link>https://sqybi.com/blog/experience-flying-on-air-china-second-c919/</link>
            <guid>https://sqybi.com/blog/experience-flying-on-air-china-second-c919/</guid>
            <pubDate>Sat, 30 Nov 2024 23:00:00 GMT</pubDate>
            <description><![CDATA[上周从上海出差回北京，返程的航班和之前一样选择了国航。结果等到临近值机的时候，突然发现航旅纵横上显示的机型是 919/100B。一时间我还没反应过来，直到退出去看了一眼，这不是 C919 嘛！]]></description>
            <content:encoded><![CDATA[<p>上周从上海出差回北京，返程的航班和之前一样选择了国航。结果等到临近值机的时候，突然发现航旅纵横上显示的机型是 919/100B。一时间我还没反应过来，直到退出去看了一眼，这不是 C919 嘛！</p>
<p>我不是什么飞迷，也没有那么了解各种关于飞机的门道。不过即使是这样，作为去年中国在机械制造和高新科技领域的最大成果之一，C919 这个机型应该还是广为人知的。</p>
<p>实际上，中国的客运大型机项目开始的时间可能早于包括我在内大部分人的认知：在 2001 年被提出，在 2003 年开始论证，2007 年就已经立项——这时北京奥运会甚至都还没有开始，中国商飞也在 2008 年才正式成立。</p>
<p>不过直到去年也就是 2023 年的 5 月 28 日，C919 才进行了第一次商业飞行。此后的一年多内，只有东方航空一家公司承接了 C919 执飞的航线。而国航的第一架 C919 首飞，已经是今年 9 月 10 日的新鲜事了。</p>
<p>我这次乘坐的 B-919Y，是国航的第二架 C919 飞机。它的首飞，如果我没弄错的话，在 11 月 14 日——这和我乘坐这架飞机的 11 月 19 日仅仅隔了 5 天，一周不到的时间！而且这真的是一个随机事件，我甚至在购买机票的时候都没有注意过执飞的机型（或许注意了当时也还不是 C919，毕竟那时飞机都还没有正式投入使用）。</p>
<p>既然这么幸运，那就不得不小小地记录一下啦。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="亲儿子的待遇">亲儿子的待遇<a href="https://sqybi.com/blog/experience-flying-on-air-china-second-c919/#%E4%BA%B2%E5%84%BF%E5%AD%90%E7%9A%84%E5%BE%85%E9%81%87" class="hash-link" aria-label="亲儿子的待遇的直接链接" title="亲儿子的待遇的直接链接" translate="no">​</a></h2>
<p>不知道从何时开始，我已经很久没有坐到过京沪通勤在廊桥登机的航班了——或许有一些航班写着“廊桥”，但至少登机和离机的其中之一，通常都需要坐一个时间不短的地铁进行换乘，这和摆渡车也没什么两样。</p>
<p>而因为各种天气原因，京沪之间飞机晚点延误也已经是常态。偶尔坐到半夜一点落地的飞机，第二天还要早起上班，真的是头都要炸了。</p>
<p>不过这次 C919 最大的体验就是，亲儿子果然不是盖的：不仅起降都是廊桥，而且降落的廊桥是离行李转盘最近的那个，走到行李转盘区域只需要目测不到 50m 的距离；同时虽然前序航班到达有些晚，但基本上是飞机收拾好了就能登机，登机完成就去起飞。怪不得很多人都提到，不管什么飞机，现在统统得给 C919 让路呢。</p>
<p>虽然最后还是在天津附近绕了个圈，但是飞机全程只用了不到 2 小时就平稳落地，速度也是拉满了。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="在天津绕了一个圈" src="https://sqybi.com/assets/images/route-7abcce017c9d46623f48b6a729e5af91.webp" width="908" height="1920" data-zoomable="" class="img_ev3q"><div class="img-caption">在天津绕了一个圈</div></div><p></p>
<p>感觉机上的机组人员也很兴奋。登机的时候我问了一句这是不是一架新飞机，空姐非常自豪地介绍：对，是上周四才开始飞的！整个机组完全没有其它航班那种打工人的疲态，机上的服务和餐食也让我有种回到了十多年前坐飞机时的感觉。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="这不是能把饭做好吗">这不是能把饭做好吗！<a href="https://sqybi.com/blog/experience-flying-on-air-china-second-c919/#%E8%BF%99%E4%B8%8D%E6%98%AF%E8%83%BD%E6%8A%8A%E9%A5%AD%E5%81%9A%E5%A5%BD%E5%90%97" class="hash-link" aria-label="这不是能把饭做好吗！的直接链接" title="这不是能把饭做好吗！的直接链接" translate="no">​</a></h2>
<p>既然提到了餐食，就不得不说一下 C919 的飞机餐了。</p>
<p>作为对比，这次出差从北京飞往上海的飞机，是国航几乎同样时间起飞的 C1589 航班。让我们看看这个航班上的飞机餐：一小袋零食，一瓶矿泉水，没有了。对，作为一个 8 点半起飞的航班，这趟去程的航班是没有正餐的！好在公司能报销机场的晚饭，首都机场那几个休息室的食物真的是不怎么好吃。</p>
<p>而这趟 C919 的航班号是 CA1550，起飞时间仅仅早了 5 分钟，机上的 C919 特制餐盒长这个样子：</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="餐盒外包装" src="https://sqybi.com/assets/images/meal_box_outside-27a9cf5db3c38efb402815da5e29c326.webp" width="1247" height="1080" data-zoomable="" class="img_ev3q"><div class="img-caption">餐盒外包装</div></div><p></p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="餐盒内包装" src="https://sqybi.com/assets/images/meal_box_inside-cae26ebe5a97f703bc47da1f639eb3cf.webp" width="1248" height="1080" data-zoomable="" class="img_ev3q"><div class="img-caption">餐盒内包装</div></div><p></p>
<p>里面的食物包括：</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="餐盒内全部餐食" src="https://sqybi.com/assets/images/meal-00714cec0826c9aa3280fdddd05582bd.webp" width="1247" height="1080" data-zoomable="" class="img_ev3q"><div class="img-caption">餐盒内全部餐食</div></div><p></p>
<p>主食的牛肉饭基本就是十年前飞机餐的水平，虽然说不上好吃，但是不至于像现在某些航班的正餐那么难以下咽。我在已经吃过一顿饭的情况下（因为根本没想到会有正餐！），还是吃了半盒。</p>
<p>而旁边的几个小菜、甜品，就个顶个的好吃了。</p>
<p>最一般的可能是右边的油辣子，和之前飞长沙时航班上的黄辣椒相比，确实差了些，主要还是这东西不热着吃多少有点油腻。</p>
<p>其次是两个小盒中靠右的那盒冷荤沙拉，作为金枪鱼沙拉难得没有什么腥味，大概是用品质不错的罐头制作的。</p>
<p>而剩下一盒则是 C919 特制小甜品，我还特地拍了一张大图：</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="甜品特写" src="https://sqybi.com/assets/images/dessert-b9f38ef16eea9eed41723a2b597dc1aa.webp" width="1080" height="1247" data-zoomable="" class="img_ev3q"><div class="img-caption">甜品特写</div></div><p></p>
<p>其实就是一个小蛋糕加上国航 C919 的巧克力牌，巧克力我是没吃的，但是这个小蛋糕真的相当好吃，感觉已经不知道多少年没有在飞机上吃到这么好吃的甜点了。所以说现在的航司是真的在降本增效，你看这不是还能把飞机餐做好吗！</p>
<p>当然在得知航班是 C919 的第一时间，我的反应是这么难得的机会，肯定要升个舱体验一下。不过可惜的是，因为看到得比较晚，唯八的商务舱座位已经都卖出去了。好在后面看了一些视频，似乎 C919 宽敞的经济舱才是亮点，仅有的几个商务舱座位其实并不太舒服，那就下次有机会再体验吧。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="合格的机舱设施">合格的机舱设施<a href="https://sqybi.com/blog/experience-flying-on-air-china-second-c919/#%E5%90%88%E6%A0%BC%E7%9A%84%E6%9C%BA%E8%88%B1%E8%AE%BE%E6%96%BD" class="hash-link" aria-label="合格的机舱设施的直接链接" title="合格的机舱设施的直接链接" translate="no">​</a></h2>
<p>假设我不知道这架飞机是 C919 的情况下坐上了飞机，第一反应应该就是：腿部空间好大！</p>
<p>虽然之前刷视频的时候就听说了 C919 经济舱的宽敞程度，不过实际坐了之后确实会发现腿部空间不是一般地舒适。我的体型相当胖，很多窄体客机可能坐到座位上都费劲，如果要一直保持一个姿势不动也很容易疲惫。但 C919 的空间保证了我全程腿部都可以随意改变姿势，舒适程度++。</p>
<p>不过似乎经济舱的座椅也有和商务舱类似的问题：硬。虽然腿部舒适，但是臀部和背部一趟不到 2 小时的航班下来都有点微微发麻了，这也确实是往返京沪的航班上很少遇到的情况。</p>
<p>除了座位以外，机舱内的多媒体屏幕也是一个小亮点。虽然没有个人娱乐系统只有公共屏，但是这块公共屏的分辨率非常清楚，可能这就是新飞机的优势吧：</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="清晰的公共多媒体屏幕" src="https://sqybi.com/assets/images/screen-2f098b521ccedabb4842ef02de5e8066.webp" width="1248" height="1080" data-zoomable="" class="img_ev3q"><div class="img-caption">清晰的公共多媒体屏幕</div></div><p></p>
<p>可惜的是这块屏幕尺寸有点小，不过高分辨率即使是小屏看着也是很舒服的。毕竟还是早期的国产客机，硬件没那么跟得上也能理解。</p>
<p>只是相比多媒体屏幕这种可有可无的设备而言，有些其它的硬件着实让人有点难受。</p>
<p>当然没有多媒体屏幕的情况下，这块座椅后的空间也没有闲置：C919 设计了一块小板子，可以用来放置手机和平板这种电子设备。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="别出心裁的电子产品支架" src="https://sqybi.com/assets/images/phone_stand-0ab1284f5a497397085a98a1256cd12a.webp" width="1249" height="1080" data-zoomable="" class="img_ev3q"><div class="img-caption">别出心裁的电子产品支架</div></div><p></p>
<p>这块板子不是桌板，桌板在它的下方另外可以打开。我尝试了一下，放一个手机还是蛮正好的。只不过因为没有上下的限位装置，飞机颠簸的时候还是有点担心手机会飞出去。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="嗡嗡嗡嗡嗡嗡嗡">嗡嗡嗡嗡嗡嗡嗡<a href="https://sqybi.com/blog/experience-flying-on-air-china-second-c919/#%E5%97%A1%E5%97%A1%E5%97%A1%E5%97%A1%E5%97%A1%E5%97%A1%E5%97%A1" class="hash-link" aria-label="嗡嗡嗡嗡嗡嗡嗡的直接链接" title="嗡嗡嗡嗡嗡嗡嗡的直接链接" translate="no">​</a></h2>
<p>整趟飞行下来，最难以忍受的莫过于飞机的噪音了。</p>
<p>或许是使用了动力更强劲的引擎，这架飞机的噪音明显高于我坐过的其它窄体客机。因为京沪航线比较短，加上通常起飞降落都不允许戴耳机，所以我最近出差已经不会带降噪耳机了。结果这一次，全程的嗡嗡声确实有那么一点点超出了我的忍受范围。</p>
<p>掏出航旅纵横看了一下机上模式的分贝数，基本是卡着 85dB 不怎么变了。之前其它客机基本上也会在 81-85 之间跳动，让我不禁怀疑这个数字的准确性。</p>
<p>而相比单纯的噪音，更难受的是整个机体都有些随着发动机一起共振。特别是起飞前的阶段，震动的声音是会传递到全身的。好在到了平飞阶段，这个问题多少有所缓解。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="“赏月航班”的窗外风景" src="https://sqybi.com/assets/images/night_view-03f9b064f2cceec5b4ce8563d2966854.webp" width="1080" height="1608" data-zoomable="" class="img_ev3q"><div class="img-caption">“赏月航班”的窗外风景</div></div><p></p>
<p>如果说下次还想坐 C919 是因为亲儿子般的待遇和机上的餐食，那万一下次不想坐了，就一定是因为这严重的噪音。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="有人没有人">有人？没有人？<a href="https://sqybi.com/blog/experience-flying-on-air-china-second-c919/#%E6%9C%89%E4%BA%BA%E6%B2%A1%E6%9C%89%E4%BA%BA" class="hash-link" aria-label="有人？没有人？的直接链接" title="有人？没有人？的直接链接" translate="no">​</a></h2>
<p>从排队登机的时候，就能明显感觉出这架飞机没有坐满。而航旅纵横上显示的舱位图更是神奇：</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="神奇的舱位图（长图预警！）" src="https://sqybi.com/assets/images/seats-f41b1540c3f780154d3fea9e68e54bb2.webp" width="293" height="1920" data-zoomable="" class="img_ev3q"><div class="img-caption">神奇的舱位图（长图预警！）</div></div><p></p>
<p>可以看到很多座位包括商务舱的座位，都是被锁上的。而且我特地去国航的值机界面看了一下，这些座位也一样是被锁上不能选择的。</p>
<p>不过实际登机之后我观察了一下，这些座位应该基本都是有人的。只是不知道这些人是怎么值机的，莫非是什么特殊保留票？</p>
<p>但即使考虑所有这些乘客，不得不说以京沪之间航线的繁忙度，这架飞机也可以用空旷来形容了。中间的两列座位几乎没有乘客，不知道有没有安全方面的考虑，还是说跟廊桥待遇类似，单纯是为了给大家一个飞机坐起来很舒服的初印象。</p>
<p>无论如何，自己家的飞机，应该还是会得到不少自己人的支持吧。</p>
<p>蛮期待民用航空领域也能像我曾经蹭了几年从业经验的汽车行业一样，有中国自己生产的飞机占据主要市场地位的那一天出现。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="帅气的机头" src="https://sqybi.com/assets/images/plane-cc138db51892e8f62b4d7b6c16761851.webp" width="1248" height="1080" data-zoomable="" class="img_ev3q"><div class="img-caption">帅气的机头</div></div><p></p>
<p>最后以一张离开飞机后拍到的机头照片收尾。因为不小心拍到了三位机长，所以浅浅打了个码。</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 碎碎念</category>
        </item>
        <item>
            <title><![CDATA[独特性和一周年的自我]]></title>
            <link>https://sqybi.com/blog/uniqueness-and-the-self-after-one-year/</link>
            <guid>https://sqybi.com/blog/uniqueness-and-the-self-after-one-year/</guid>
            <pubDate>Wed, 20 Nov 2024 20:00:00 GMT</pubDate>
            <description><![CDATA[在去年的今天，同样是 11 月 20 日，我重新搭建了我的博客，并发表了 SQYBI.com：时隔十年的重新上线 这篇文章。]]></description>
            <content:encoded><![CDATA[<p>在去年的今天，同样是 11 月 20 日，我重新搭建了我的博客，并发表了 <a class="" href="https://sqybi.com/blog/sqybi-com-relaunching-after-a-decade/">SQYBI.com：时隔十年的重新上线</a> 这篇文章。</p>
<p>而过去的这一年中，我也确实没有太荒废这个博客：这一年总共有 17 篇文章发表（其中有一篇凑数的），其中也包括两个系列更新的四篇文章。虽然中间也有过两三个月的天窗，不过站在自我评价的角度，我还是认为可以说这个博客上有持续的产出——这多少还是能令我自己满意的。</p>
<p>花开两朵，各表一枝。站在客观的角度，文章产出的数量还算差强人意；但不得不承认的是，从下半年开始，用来写文章的时间和动力是在逐步降低的。得益于抽空写了这个 <a class="" href="https://sqybi.com/archive/">所有文章</a> 页面，可以快速地看到 6-8 月和 10-11 月是两个大的天窗期。如果不是 9 月初突然爆肝，其实就等于开了一个 6 月开始接近半年的大窗。</p>
<p>那么，就让我们从这两段天窗说起吧。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="遮羞布下没有银弹">遮羞布下没有银弹<a href="https://sqybi.com/blog/uniqueness-and-the-self-after-one-year/#%E9%81%AE%E7%BE%9E%E5%B8%83%E4%B8%8B%E6%B2%A1%E6%9C%89%E9%93%B6%E5%BC%B9" class="hash-link" aria-label="遮羞布下没有银弹的直接链接" title="遮羞布下没有银弹的直接链接" translate="no">​</a></h2>
<p>回顾这段时间，不仅仅是博客在开天窗。前段时间开始培养的一些习惯和爱好，比如每天的锻炼和摄影修图，其实也都在开天窗。仔细想一下，从 6 月开始似乎就没有在个人爱好上投入太多时间了，最多就是稍微（真的是稍微）改装了一下新买的小电驴。</p>
<p>说实话，现在我的这份工作中，并没有一个人或者一个体系强制性地要求我把精力和业余时间都转移到工作上。简而言之，就是蛮 work-life-balance 的一份工作，至少是中国版本的 work-life-balance，大部分时间也能按时下班。</p>
<p>但即使如此，在每天把大量脑力投入到工作上之后，回到家依旧还是会有轻度的精疲力尽感。这个感觉大概就是：明知道运动能分泌多巴胺，但就是不想站起来；明知道全身心投入到爱好之后触发心流状态很爽，但就是不想打开 Lightroom 开始修图。</p>
<p>这其实是一件很可怕的事情。</p>
<p>在更年轻的时候，我粗浅的认知曾以为无论是锻炼身体还是培养一项爱好就像一个任务，一个必须去完成的任务。而当第一次亲身感受到，一些事情相比“任务”，其实更像是人类从基因上对某些东西的原始渴望的时候，我曾经以为我不必再努力“坚持”了。</p>
<blockquote>
<p>我不认为一个健康的身体，会因为身体的原因让一个灵魂变得优秀。相反我认为反过来可能正确：一个优秀的灵魂，会因为灵魂自身的原因让一个身体尽可能地强壮。
——柏拉图，《理想国》</p>
</blockquote>
<p><strong>“既然这样，那我之前坚持不下去，其实就是没有顺从自己的内心，没有体验过这些原始的渴望。现在亲身体验过这种渴望之后，这些事情就一定能持续地做下去。”</strong> 那时的想法，大致就是这样的。</p>
<p>系统学习过软件工程的朋友，应该都读过《没有银弹》这本书，它的主旨是在软件工程中不存在一种如同“银弹”的工具，能够一劳永逸地解决所有“怪物”，也就是软件工程中的问题。“没有银弹”来自一句英语俚语“No silver bullet”，比较准确的意译是“没有灵丹妙药”（<a href="https://zh.wikipedia.org/wiki/%E9%8A%80%E8%89%B2%E5%AD%90%E5%BD%88" target="_blank" rel="noopener noreferrer" class="">来自 Wikipedia</a>）。</p>
<p>上面加粗部分的想法就像是把“原始的渴望”当作一颗“银弹”，或者说当作一层掩盖更深层内心的遮羞布，期望它能够解决一切问题。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="银弹 | 由 Midjourney 生成" src="https://sqybi.com/assets/images/silver_bullet-6b33a181dd07d6579426a3e48d186707.webp" width="1024" height="1024" data-zoomable="" class="img_ev3q"><div class="img-caption">银弹 | 由 Midjourney 生成</div></div><p></p>
<p>而现在，这层遮羞布开始慢慢地被掀开了：即使我已经理解并体验过不是作为 to-do list 上的一个一个条目，而是全身心地投入某件事，并从中获得快乐以后，精力依旧不允许我在任何时刻都做好迎接它的准备。或许我天生的能量，不太足以支持在每天略超 8 小时的高强度脑力工作之外，额外投入到其它事情上。</p>
<p>遮羞布的下面空空如也，幻想中的银弹不知所踪。</p>
<p>对不存在的银弹的恐惧，到底是不是真的无法避免？如果工作并不是能完全追求自我的手段，那么在没有时间的情况下，我还有什么办法去完成发现自我这一人生的终极目标？</p>
<p>让我们暂且搁置这件事，在真正揭开这块遮羞布之前聊一些其它的话题，算是我这一年以来对这件事情思考的一个小小地总结。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="不能算是二次元">不能算是二次元！<a href="https://sqybi.com/blog/uniqueness-and-the-self-after-one-year/#%E4%B8%8D%E8%83%BD%E7%AE%97%E6%98%AF%E4%BA%8C%E6%AC%A1%E5%85%83" class="hash-link" aria-label="不能算是二次元！的直接链接" title="不能算是二次元！的直接链接" translate="no">​</a></h2>
<p>虽然并没有真的做过社会调查，但我一直相信每个人都会经历过类似的一段迷茫期：在青春期这段对世界的一切充满好奇，对所有新知识都燃起探索欲的黄金时刻过后，通常也是从投身于朝九晚五的工作开始，我们能够接触到的新鲜刺激突然会以几何级数般减少。</p>
<p>在这之前，似乎每一天都能了解到世界的一片新角落；而突然有一天，我们发现自己已经很久没有那种本能的探求新鲜感的冲动了。</p>
<p>作为个体，在这种人生价值的体验上自然是有不小的差别。例如我在 <a class="" href="https://sqybi.com/about/">网站的自我介绍页面</a> 中提到过<a href="https://en.wikipedia.org/wiki/The_Hedgehog_and_the_Fox" target="_blank" rel="noopener noreferrer" class="">“刺猬和狐狸”</a>分类法，越偏向于“刺猬”类型的人，应该会比我这种“狐狸”类型的人更晚碰到这个瓶颈。而我的身边也有很多“狐狸”类型的人，通过不断地拓宽自己的交际面、不断地追求新的刺激，从而同样地推迟了这一刻的到来。</p>
<p>但无论如何，能够完全避开这段迷茫期的人，大概少到可以从统计学上忽略不计。这和哲学家们自古以来都绕不开的一个话题相关：自我。</p>
<p>越是在心智不成熟的时候，人越希望通过一些来自表面的“独特性”展现自我。不论是七八十年代的爆炸头喇叭裤，九零年代的非主流，还是零零后的二次元和国风，本质上都是在最沉迷于展现自我但人生积累最少的那个时期，希望通过最简单直接的方式向这个世界证明：我和别人不一样。</p>
<p>但这种对独特性的探求，看起来却是矛盾的。一方面，每个人都希望自己和世界上的所有人都不一样。另一方面，每个人也都希望有一个圈子，能够认可和理解自己的爱好——而这个圈子里的人，自然会是和自己相似的人。</p>
<p>一个人对自我的锚定来自于他人承认的独特性，而一旦有人能够承认这种独特性，则意味着这种独特性已经不再独特。当我们用文字的方式把这个矛盾点描述出来，它看起来就是一个纯粹的悖论。</p>
<p>好在我们善于偷奸耍滑的大脑，不自觉地就会偷偷修改关于独特性的定义，通过接受“和少量的人相似也是独特”规避了这个问题。一个一个的“小圈子”，就这样自然而然地形成——当然互联网的普及，也起到了推波助澜的作用，至少把这些“小圈子”摆上了台面。</p>
<p>这样我们也不难理解一些小圈子，特别是青春期的年轻人集中的小圈子，通过制定各种“规则”来排外的目的了：如果任何一个人都能简单地宣布自己加入了这个圈子，那圈子的独特性就不复存在。</p>
<p>十年前，这些规则具现化的方式是“连 XXX 都不知道，不能算是二次元”。而现在，具现化的方式则变成了动辄几十条的“圈规”。用过时的流行语来说，这就是“毅种循环”。</p>
<p>虽然大脑机智地回避了上面的问题，但世界的逻辑就是这么残酷。问题永远是问题，它可以被暂时掩盖，但不会自己消失。</p>
<p>无论是通过某些方式形成排外的小圈子，还是通过鄙视链证明自己和其他人不同，无非都是在给自我加定语的行为。我要做一个独特的二次元，但仅仅是看过动画和漫画就叫二次元的话不够独特，那就限定看过 A 的人才算二次元就好了——当然我自己必然是已经看过的。而看过 A 的人也太多了，那就限定看过 B、看过 C……的人才能算二次元，而且这是可以不断叠加的。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="小圈子 | 由 Midjourney 生成" src="https://sqybi.com/assets/images/circle-c0a8d95801bdadea14e1e92eec5f853c.webp" width="1024" height="1024" data-zoomable="" class="img_ev3q"><div class="img-caption">小圈子 | 由 Midjourney 生成</div></div><p></p>
<p>作为一个理性的成年人，只要是站在第三者的角度客观地分析，都会发现其中的滑稽之处：叠加是无止境的，而且如果每个人对于某件事都有自己不同的定义，那么就意味着这件事的定义实际上并不存在。</p>
<p>但这件事真的就像互联网上很多人作出的下意识判断一样，骂一句“玩 XXX 的都是傻 X”，然后就没有讨论和思考的价值了吗？</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="玫瑰花的时间">玫瑰花的时间<a href="https://sqybi.com/blog/uniqueness-and-the-self-after-one-year/#%E7%8E%AB%E7%91%B0%E8%8A%B1%E7%9A%84%E6%97%B6%E9%97%B4" class="hash-link" aria-label="玫瑰花的时间的直接链接" title="玫瑰花的时间的直接链接" translate="no">​</a></h2>
<p>来转换一下思考的切入点。《小王子》里面的一段话，或许已经是绝大部分人耳熟能详的了：</p>
<blockquote>
<p>“正因为你为你的玫瑰花费了时间，这才使你的玫瑰变得如此重要。”</p>
</blockquote>
<p>虽然很多人会认为这种所有人都了解的，没有“独特性”的句子看起来很俗，但一个惊人的事实是我们很少会看到试图反驳它的人。在现代什么大事小事都会被拉出来批判一番的互联网上，这件事实属难得。</p>
<p>事实上，时间确实是造就独特性的关键。在人们的想象中通常都会有这样一种“完美匠人”，他把自己一生的全部时间都投入在了某件事情上，而且从未放弃。如果这个人是你写的一本小说中的角色，你会觉得他不独特吗？绝无可能。</p>
<p>而我们年轻时参与的这些小圈子的排外行为，本质上就是对于堆砌时间造就独特性的一种拙略模仿。如果我定义 XXX 才算是二次元，那就必然意味着我需要花一定的时间做过 XXX，否则我就把自己排除出了这个圈子之外。被定义的 XXX 越多，那么我做过的 XXX 也就越多，自然投入在这个圈子里的时间也就越多——这和上面的“完美匠人”做的事情其实如出一辙。</p>
<p>只不过，世界上绝大部分的人都没有这种一生投入于一件事的崇高理想，而经历过的人生越是短暂，能够投入在某件事情上的时间也就越短。青春期对于独特自我的本能追求，又促使着年轻人们通过这种拙略模仿的方式来达到表达自我的目的。这种拙略模仿，很可能只是我们的基因进化出的，在认识世界的过程中一种快速学习的方式。</p>
<p>站在客观的角度，至少我是会理解这种行为的，因为它本质上和每个人第一次尝试走路但摔倒的时候没有什么不同。而一个正常人面对一个蹒跚学步时摔倒在自己身上的小孩，也很难有什么真正的恶意，甚至愿意去扶一把。如果互联网没有把这种行为片面地无限制地放大，事情可能会简单很多。</p>
<p>毕竟即使是心智成熟的成年人，也终究避不开这种对他我的独特性的追求：</p>
<blockquote>
<p>若不披上这件衣裳，众生又怎知我尘缘已断，金海尽干？</p>
</blockquote>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="玫瑰和袈裟 | 由 Midjourney 生成" src="https://sqybi.com/assets/images/kasaya_robe-07b93e5b497f382c79fb507c22a7168a.webp" width="1024" height="1024" data-zoomable="" class="img_ev3q"><div class="img-caption">玫瑰和袈裟 | 由 Midjourney 生成</div></div><p></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="哲学的巧合">哲学的巧合<a href="https://sqybi.com/blog/uniqueness-and-the-self-after-one-year/#%E5%93%B2%E5%AD%A6%E7%9A%84%E5%B7%A7%E5%90%88" class="hash-link" aria-label="哲学的巧合的直接链接" title="哲学的巧合的直接链接" translate="no">​</a></h2>
<p>年少的时候，作为一个早早就接触了理工科教育的学生，我一向是对于历史和哲学嗤之以鼻的：历史只是死记硬背，哲学只是无痛呻吟，有什么好学的？</p>
<p>但随着年龄的增长，我慢慢意识到历史和哲学也是人类社会发展中不可或缺的一环：所有你一生追求和思考的问题，或者是在历史中有迹可循，或许是已经有哲学家做出过更加深入的思考。在没有了解过这些学科之前，盲目地下定论必然是武断的。所谓思而不学则怠，便是如此。</p>
<p>而对于自我这个人生最终极的话题，哲学家们自然也有自己的看法。我自认才疏学浅无法深入探究，但无论是古早哲学家们比如柏拉图和苏格拉底对自我的最初认知，将自我从人本身作为独立的特性甚至神性剥离出来，还是笛卡尔对自我存在性的思考，亦或是黑格尔和萨特关于自我是通过实践进程产生的观点，无不代表了某一个阶段的人类对这个问题的探讨中最深入的理解。</p>
<p>而我个人则更偏向于尼采的“自我超越”观点，这可能和我们从小受到的马克思唯物主义与人类主观能动性的价值观教育相关。我无法很准确地描述这个观点，大致上的意思是人生对于自我的探求其实是一种不断超越自我、寻求“超人”这种精神超越性的过程。我多次讨论过的博客首页的这句话或许可以更准确地表达这个观点：</p>
<blockquote>
<p>Change is a part of life and takes part in finding us who we are.</p>
</blockquote>
<p>可以看到，随着哲学的发展，不论是尼采的观点，还是黑格尔和萨特的观点，都无一例外地指向了一件事。那就是一个人锚定自我的过程，是和自我的反思、对自我的探寻、对他我的认知相关的。而这些认知是一个实践的过程，那么它也就不可或缺地会消耗人生中唯一无法增加的资源：时间。</p>
<p><strong>这是一种神奇的巧合：无论是我们崇敬的这些大哲学家，还是受人唾弃圈地自萌的小圈子，本质上似乎都在探索同一件事情，那就是如何通过消费时间来追求自我。</strong></p>
<p>之所以会有这样的巧合，我认为是因为何为自我这件事，本身就是一代又一代的哲学家们甚至普通人们用自己的一生时间去探讨的，接近人类最本质的东西。而在花费时间探寻自我的过程中，人们也完成了各自追求自我的过程。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="花束般的自我">花束般的自我<a href="https://sqybi.com/blog/uniqueness-and-the-self-after-one-year/#%E8%8A%B1%E6%9D%9F%E8%88%AC%E7%9A%84%E8%87%AA%E6%88%91" class="hash-link" aria-label="花束般的自我的直接链接" title="花束般的自我的直接链接" translate="no">​</a></h2>
<p>说来惭愧，我最近才读了前几年很火的一本小说（也有很多人了解的方式是电影）《花束般的恋爱》。而我的一位好友也曾经写过一篇很不错的文章 <a href="https://blog.hoppinglife.com/2023/11/%e8%8a%b1%e6%9d%9f%e8%88%ac%e7%9a%84%e6%81%8b%e7%88%b1%e5%92%8c%e7%8b%ac%e7%89%b9%e6%80%a7/" target="_blank" rel="noopener noreferrer" class="">《花束般的恋爱和独特性》</a> 讨论这个作品，所以读过作品之后我又回去重读了这篇文章。</p>
<p>事实上，这篇文章探讨的方向和我的这篇文章是如出一辙的，这也是我决定把这个话题作为一周年文章主题的原因之一。我这里也很愿意引用其中的两句话：</p>
<blockquote>
<p>如果经历喜好都无可避免的会出现重合，那能保证独特性的大概是时空本身。<br>
……<br>
一种更积极的解释是，带来独特性的并不是标签，而是标签下方的自我。</p>
</blockquote>
<p>如果你也恰好读过这本小说或者看过它的影视作品，希望可以容许我就着这个作品再多讨论几句。</p>
<p>在《花束般的恋爱》中，男主和女主的相遇就很像是上面讨论过的“小圈子”的一个理想情况：这个圈子只有他们两个人，而两个人的喜好是如此一致，以至于他们可以把其它所有人都排除在外的同时互相承认对方的他我——一种在幻想作品中才会出现的完美状态。</p>
<p>不过即使是这样的两个自我，随着时间的变化和社会性的限制，也会逐渐产生差异。男主因为不再有固定的生活费而被迫融入更大的圈子，渐渐地失去自己的独特性；而女主则是更持续地对抗着这个世界，以降低金钱和社会名望的需求为代价，保持着相比之下更独特的自我。</p>
<p>而他们两个人走过的这条路，在探寻自我的过程中必然会发生。没有两个人会完全一样，而能够找到在过去的人生中能和你极度相似的人，本身就是一种奇迹。但奇迹只是奇迹，奇迹总是会结束的。</p>
<p>不过从小就受到辩证法熏陶的我们也必然会发现这一点：既然没有两个人会完全一样，那么也必然没有两个人会完全不同。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="相似的人 | 由 Midjourney 生成" src="https://sqybi.com/assets/images/similar-3b6742b7f78700acf7b968eea907b9e0.webp" width="1024" height="1024" data-zoomable="" class="img_ev3q"><div class="img-caption">相似的人 | 由 Midjourney 生成</div></div><p></p>
<p>事实上，在明确了这一点之后，回顾过去的时间，我们的人生也没有那么的不堪。非常凑巧的是，就在我完成这篇文章的过程中，公司组织了一场团建聚餐，而聚餐时大家进行了一个非常有名的聚会小游戏，正好提供了一个让我能够以不同的视角回顾自己人生中独特性的机会。</p>
<p>游戏的名称叫 Never ever，或者也可以称作 Never have I ever。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="never-and-ever">Never, and Ever<a href="https://sqybi.com/blog/uniqueness-and-the-self-after-one-year/#never-and-ever" class="hash-link" aria-label="Never, and Ever的直接链接" title="Never, and Ever的直接链接" translate="no">​</a></h2>
<p>这个游戏的目标其实非常简单，抛开和文章无关的奖惩规则，大致上就是：</p>
<p>每个人轮流说一件自己认为觉得在场的人中只有自己做过的事情。如果有其他人也做过，那么你就输了这一局，否则你就赢下了这一局。</p>
<p>因为我们的聚餐有接近 30 人，所以游戏开始前大家都认为赢下自己的那局游戏是很困难的事情——毕竟几十人中有一个人的经历和我相同，还是很可能的。</p>
<p>但等到真的经过了一轮下来，实际上输掉游戏的人只有五六名，而且大部分情况下，两个人的经历都是巧合到让全场发出“wow”（或者说“原来你也……”）的地步。</p>
<p>我在一开始的时候，也绞尽脑汁地思考自己到底能有什么独特的经历。不过从想到第一个经历开始，就像打开了水闸一样，能让我笃定其他人大概率没有做过的事情一件接一件地涌现出来。</p>
<p>我当时只是顺手把每一个想到的经历都写在了手机上，直到游戏结束的时候看了一眼手机上的记录，才发现原来我自己在几十人的群体中也能独一无二的事情竟然有这么多。而且毫不夸张地说，这些人里有很多人都做过不止一件传统意义上“独一无二”的事情。</p>
<p>这之后，就是一种豁然开朗的感觉：原来我花在人生中的时间，看似大部分都毫无意义，实际上也已经把我变成了一个如此独特的人。</p>
<p>而且这个游戏还有一个很有趣的点。每个游戏中都会有一些希望“投机取巧”（无贬义）的人，而这个游戏中的取巧者，一定会发现一个游戏的漏洞：只要定语足够多，那么某段经历就几乎一定是独一无二的。</p>
<p>反之也是一样，只要定语足够少，那么这件事情就一定是别人也经历过的。一个最极端的 <em>真空中的球形鸡般的</em> 例子就是，“我做过一件事”——谁没有做过事呢？</p>
<p>游戏是如此，我们对于自己独特性的理解其实也是如此。如果我希望，那么我可以是和任何一个人有任何共同经历的。而同样如果我希望，我也可以说出一段和任何一个人不同的经历。</p>
<p>自我的独特性，无非是来源于我们主观加之于自我的“定语”。所谓失去了自我或是独一无二的自我，只是我们被社会上的主流观点固化了这个“定语”以后的结果。但定语毕竟只是用于描述的词语，它和真正的自我本身并无关系。</p>
<p>就像红色的苹果、绿色的苹果、腐烂的苹果、新鲜的苹果，甚至是伊甸园的苹果，最后无非还是一个苹果罢了。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="各种苹果 | 由 Midjourney 生成" src="https://sqybi.com/assets/images/apples-ef672b257d49d287f87e94fb0d053c15.webp" width="1024" height="1024" data-zoomable="" class="img_ev3q"><div class="img-caption">各种苹果 | 由 Midjourney 生成</div></div><p></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="遮羞布下没有羞耻">遮羞布下没有羞耻<a href="https://sqybi.com/blog/uniqueness-and-the-self-after-one-year/#%E9%81%AE%E7%BE%9E%E5%B8%83%E4%B8%8B%E6%B2%A1%E6%9C%89%E7%BE%9E%E8%80%BB" class="hash-link" aria-label="遮羞布下没有羞耻的直接链接" title="遮羞布下没有羞耻的直接链接" translate="no">​</a></h2>
<p>终于可以回到最初的问题了。为什么当我发现自己的精力无法支持 8 小时工作之外花费额外的时间在其它爱好上时，会觉得这是一件可怕的事情？</p>
<p>经过上面的讨论，这个答案已经初见端倪。我害怕的无非是如果没有足够的时间，我就不能构建出一个足够独特的自我。而失去自我，就意味着无尽的迷茫，意味着失去生活的意义和方向。</p>
<p>好在既然我们能够知道问题是什么，那问题就不再是不可解决的。一方面，在明确问题之后，我自然可以通过各种方式来调整自己，让自己不至于完全没有时间。另一方面，就像上面提到的，我们能够用于构建自我独特性的时间，其实也没有想象得那么少。</p>
<p>时间对所有人都是公平的。</p>
<p>人们要追寻的最终还是自我本身，探寻独特性只是追寻自我道路上的一个必然的过程。那些原始的渴望固然不会是那颗塑造独特性的银弹，但如果仅仅为了追求独特性而放弃追寻自我，那就本末倒置了。</p>
<p>当我们掀开了遮羞布，发现自己一时迷失在对独特的追寻上，也不是什么值得羞耻的事情。因为只有发现了解决问题的银弹根本不存在，人们才会专注于问题本身。</p>
<p>更何况塑造自我的，永远是在追寻自我的过程中投入的独一无二的时间。而只要不放弃思考，不断地通过自我探索找到属于自己的道路，就已经在超越自我、发现自我的路上越走越远了。</p>
<blockquote>
<p>Ich bin ein Wanderer und ein Bergsteiger, sagte er zu seinem Herzen, ich liebe die Ebenen nicht und es scheint, ich kann nicht lange still sitzen.<br>
我是一个旅行者与登山者，他向他的心说，我不爱平原，我似乎不能作长时间的静坐。<br><br>
Und was mir nun auch noch als Schicksal und Erlebniss komme, - ein Wandern wird darin sein und ein Bergsteigen: man erlebt endlich nur noch sich selber.<br>
无论我将遭遇什么命运与经验，——旅行与登山总会是不可少的成分：因为到头来，一个人所经验的只是自己。<br><br>
Die Zeit ist abgeflossen, wo mir noch Zufälle begegnen durften; und was könnte jetzt noch zu mir fallen, was nicht schon mein Eigen wäre!<br>
我隶属于机缘的时候已经过去了；什么事情能发生在我的命运里，而不曾属于我过呢！<br><br>
Es kehrt nur zurück, es kommt mir endlich heim - mein eigen Selbst, und was von ihm lange in der Fremde war und zerstreut unter alle Dinge und Zufälle.<br>
我的「我」——它只是回向我来，它和它的四处漂泊的散在万物与机缘里的各部分，终于到家了。<br><br>
——尼采，《查拉图斯特拉如是说》</p>
</blockquote>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 碎碎念</category>
        </item>
        <item>
            <title><![CDATA[让 Docusaurus 变得更好：SQYBI.com 上线评论系统]]></title>
            <link>https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/</link>
            <guid>https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/</guid>
            <pubDate>Sun, 08 Sep 2024 23:30:00 GMT</pubDate>
            <description><![CDATA[从上次 SQYBI.com 下线开始，我就尝试过很多次自己手写实现一个博客系统。]]></description>
            <content:encoded><![CDATA[<p>从上次 SQYBI.com 下线开始，我就尝试过很多次自己手写实现一个博客系统。</p>
<p>这件事看起来简单，但实际上还是蛮难的，在 <a class="" href="https://sqybi.com/blog/sqybi-com-relaunching-after-a-decade/">SQYBI.com：时隔十年的重新上线</a> 中我有提到过少量细节。当时虽然有 Django 这样基础的框架，也（忍着痛苦）写完了对应的基本功能，但是那时的前端框架实在过于简陋，除了 CSS 的问题以外，基于 AJAX 的动态更新逻辑写起来也是很麻烦的。</p>
<p>好在随着这十年的技术发展，大量新框架、新语言和新服务提供商涌现出来。感谢 Node.js、React、Docusaurus、Cloudflare、ChatGPT、Brevo、Github、wysimark、Giscus 以及可能我没有提到的其它基础设施，我才能这么快速地搭建起来现在这个网站。</p>
<p>之前博客上线之后，我一直在使用 Giscus 作为评论系统。但是我发现，慢慢地就没有人再发表评论了。</p>
<p>Giscus 背后是基于 Github 的，而众所周知在国内 Github 是不能访问的状态。加上一些之前配置的问题，让 Giscus 在部分手机端即使有梯子也无法显示出来。</p>
<p>虽然不知道这到底影响了多少人回复的意愿，但我还是决定用自己写的评论系统替换掉它，毕竟我不能简单地认为所有访问者都有梯子。同时，这其实也是让我重新捡起当年没写完的博客系统的机会，至少完整地完成一次大块的功能。</p>
<p>另一个原因可能就是最近重新装修了一下这个网站之后，Giscus 的前端看起来有点格格不入了。虽然调整 CSS 或许也能做到，但工作量想必也不会小。事实证明，即使是开发自己的系统，大部分时间也是花在了调整 CSS 上。</p>
<p>小小的自夸一下，这算是深度定制 Docusaurus 了吧。不知道有没有其他人像我一样使用 Docusaurus 搭建博客，还做了这么多的二次开发。如果有的话，我也想围观一下他的网站。</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>尝试一下</div><div class="admonitionContent_BuS1"><p>既然上线了新的评论系统，看到这里的你，不如就直接来试着发表一条评论吧！</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="简单介绍新的评论系统">简单介绍新的评论系统<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E7%AE%80%E5%8D%95%E4%BB%8B%E7%BB%8D%E6%96%B0%E7%9A%84%E8%AF%84%E8%AE%BA%E7%B3%BB%E7%BB%9F" class="hash-link" aria-label="简单介绍新的评论系统的直接链接" title="简单介绍新的评论系统的直接链接" translate="no">​</a></h2>
<p>首先来简单介绍一下这套新评论系统的主要功能和亮点设计。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="发表评论区域">发表评论区域<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E5%8F%91%E8%A1%A8%E8%AF%84%E8%AE%BA%E5%8C%BA%E5%9F%9F" class="hash-link" aria-label="发表评论区域的直接链接" title="发表评论区域的直接链接" translate="no">​</a></h3>
<p>最基础的功能，自然就是发表评论的功能。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="发表评论区域" src="https://sqybi.com/assets/images/post-comment-dbcd1e56c6ece16db5adeada1d69399b.webp" width="733" height="670" data-zoomable="" class="img_ev3q"><div class="img-caption">发表评论区域</div></div><p></p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="配色">配色<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E9%85%8D%E8%89%B2" class="hash-link" aria-label="配色的直接链接" title="配色的直接链接" translate="no">​</a></h4>
<p>在这个区域，我特地将评论框的各种颜色都调整成了和博客新主题类似的配色，同时移除了原有的各种边框。另外，我还特地调整了字体，让这部分的字体和全局统一。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="文本编辑器">文本编辑器<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E6%96%87%E6%9C%AC%E7%BC%96%E8%BE%91%E5%99%A8" class="hash-link" aria-label="文本编辑器的直接链接" title="文本编辑器的直接链接" translate="no">​</a></h4>
<p>文本编辑器是一个 <a href="https://en.wikipedia.org/wiki/WYSIWYG" target="_blank" rel="noopener noreferrer" class="">WYSIWYG</a> 的编辑器，后台会转换为 Markdown 语法。本来打算使用一个简单文本框的，但是既然设计的目标是减少发表评论的难度，那也不太可能要求来评论的每个人都学习 Markdown。这里需要感谢 <a href="https://github.com/mundimark/awesome-markdown-editors" target="_blank" rel="noopener noreferrer" class="">mundimark 的总结</a>，这个简单好用的编辑器就是在这个列表中找到的。</p>
<p>不过现在还有一些小问题，比如编辑器里的 blockquote 和我自己 CSS 中加的样式冲突了，可以看到图中大引号下面有一个重叠的竖线。这个不会太难改，有空的时候再修吧。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="发表评论按钮">发表评论按钮<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E5%8F%91%E8%A1%A8%E8%AF%84%E8%AE%BA%E6%8C%89%E9%92%AE" class="hash-link" aria-label="发表评论按钮的直接链接" title="发表评论按钮的直接链接" translate="no">​</a></h4>
<p>发表评论按钮的逻辑也花了我一些时间处理，现在的状况大概是这样的：</p>
<ul>
<li class="">如果评论内容是空，则按钮不可用。</li>
<li class="">如果评论者的昵称是空，则按钮也不可用。</li>
<li class="">当按钮可用并点击发送的时候，会有一个发送动画出现。</li>
<li class="">发送失败的情况下，按钮会恢复可用状态，且所有内容不清空，等待重新发送。</li>
<li class="">发送成功之后，会清空编辑区内容但保留评论者信息，同时按钮恢复不可用无动画状态，等待发送下一条。</li>
<li class="">当昵称为空的时候，会在周围显示红圈提示必须填写。</li>
</ul>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="昵称为空的情况" src="data:image/webp;base64,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" width="236" height="48" data-zoomable="" class="img_ev3q"><div class="img-caption">昵称为空的情况</div></div><p></p>
<p>感谢 React，让这所有的逻辑（也包括下面的大量逻辑）变得简单易写，否则我可能真没有精力和动力手撸这么一套系统。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="嵌套评论">嵌套评论<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E5%B5%8C%E5%A5%97%E8%AF%84%E8%AE%BA" class="hash-link" aria-label="嵌套评论的直接链接" title="嵌套评论的直接链接" translate="no">​</a></h4>
<p>对于已经发表的评论，右侧会出现一个“回复此评论”的按钮。这个功能的交互细节会在下面聊到评论区域的时候再讲，简单来说就是点了这个按钮以后，发表评论区域的标题会变成“回复评论”，底下的按钮也会变成“发表回复”，同时多出一个“取消回复评论”按钮。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="回复评论" src="https://sqybi.com/assets/images/post-comment-reply-9c2a61c3fbdd6bc3043527722ef36cb9.webp" width="733" height="342" data-zoomable="" class="img_ev3q"><div class="img-caption">回复评论</div></div><p></p>
<p>这部分 UI 我自认为设计的还是不错的，现在唯一的问题是虽然加上了时间戳，但还是比较难以判断自己回复的是哪条评论。老婆在测试的过程中就发错过一次，后面可能要想办法高亮一下对应的评论，或者干脆把被回复评论的内容贴在下面。</p>
<p>如果点击了“取消回复评论”，一切就会回到初始状态。但是放心，已经输入的评论内容不会丢失。</p>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>丢失数据风险请注意！</div><div class="admonitionContent_BuS1"><p>这里有一个小问题是刷新页面还是会丢失评论内容，后续的版本里会修复这个问题。</p></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="评论者信息">评论者信息<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E8%AF%84%E8%AE%BA%E8%80%85%E4%BF%A1%E6%81%AF" class="hash-link" aria-label="评论者信息的直接链接" title="评论者信息的直接链接" translate="no">​</a></h4>
<p>每个评论者可以输入三个信息：必须输入的昵称，和可选的邮箱与网址。</p>
<p>和大部分评论系统一样，如果你输入了网址信息，那么你的评论中名称上面就会出现到这个网址的链接。而如果你输入了邮箱，首先你的头像会变成 <a href="https://gravatar.com/" target="_blank" rel="noopener noreferrer" class="">Gravatar</a> 上设置的头像（前提是你注册过，如果没有也可以去注册一下，之后就能看到了！）。其次，当你发表评论或收到评论回复的时候，就会收到对应的邮件。</p>
<p><strong>我非常建议所有人在评论的时候都填写一下自己的邮箱，因为有人评论你的时候能够收到邮件，还是蛮关键的一件事。</strong></p>
<p>此外，这个区域还有一个小功能，但是我感觉是非常非常重要的功能：当你输入过一次自己的信息（名称、邮箱、网址）之后，就会在浏览器中记录这些信息并在下一次自动填写。除非你换了浏览器或者清空了历史数据，否则通常都不需要再重新填写这些信息了。</p>
<p>我想如果没有这个功能的话，每次面对着空空如也的昵称区域，发表评论的兴趣肯定会大减吧。</p>
<p>最后，如果你没有输入邮箱或者输入了没有 Gravatar 头像的邮箱，处理的逻辑是这样的：</p>
<ol>
<li class="">如果输入了没有 Gravatar 头像的邮箱，则会根据这个邮箱生成一个头像；同时当这个邮箱注册了 Gravatar 之后，会更新为 Gravatar 的头像。</li>
<li class="">如果没有输入邮箱，则会根据昵称生成一个头像，且保证整个网站上这个昵称对应的头像都是一样的。</li>
</ol>
<p>这样即使有人不想输入自己的邮箱，也不会出现在评论区不能快速判断哪些评论是同一个人发送的情况。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="邮件系统">邮件系统<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E9%82%AE%E4%BB%B6%E7%B3%BB%E7%BB%9F" class="hash-link" aria-label="邮件系统的直接链接" title="邮件系统的直接链接" translate="no">​</a></h3>
<p>接下来，在介绍评论区之前，我想提前介绍一下这次实现的功能中最有用的一个：邮件系统。</p>
<p>简单来说，在填写了邮箱以后，你会收到两种类型的邮件：</p>
<ul>
<li class="">发送了一条评论之后，会收到一封邮件。</li>
<li class="">有人评论了你发送的评论之后，你也会收到一封邮件提示有新的回复（当然他也会收到自己发送了评论的邮件）。</li>
</ul>
<p>这部分逻辑不复杂，但是我被 Cloudflare Worker 的邮件发送逻辑坑了很久才发现根本没法实现需求。</p>
<p>最后研究了半天最终找到了 <a href="https://www.brevo.com/" target="_blank" rel="noopener noreferrer" class="">Brevo</a> 这个服务，提供 HTTP 接口的同时每天限额还很高，解决了我的燃眉之急。</p>
<p>发送的邮件我也特地设计了配色和 CSS，希望收到的人不会觉得太丑陋。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="邮件的大致样式" src="https://sqybi.com/assets/images/email-template-f40c807b75b6ddde563784fca3e5417b.webp" width="648" height="580" data-zoomable="" class="img_ev3q"><div class="img-caption">邮件的大致样式</div></div><p></p>
<p>因为时间原因，暂时所有的邮件内容除了评论以外都是英文的。我会在后面找时间为邮件也增加 i18n 的处理逻辑，关于什么是 i18n，可以参见 <a href="https://sqybi.com/blog/adding-i18n-for-a-docusaurus-site/" target="_blank" rel="noopener noreferrer" class="">为 Docusaurus 站点添加 i18n：LLM 的正确打开方式
</a> 中的介绍。技术上来说已经确认可行了，不过需要的改动还是不小的。</p>
<p><strong>这里再唠叨一次，我非常建议所有人在评论的时候都填写一下自己的邮箱，因为有人评论你的时候能够收到邮件，还是蛮关键的一件事。</strong></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="评论列表区域">评论列表区域<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E8%AF%84%E8%AE%BA%E5%88%97%E8%A1%A8%E5%8C%BA%E5%9F%9F" class="hash-link" aria-label="评论列表区域的直接链接" title="评论列表区域的直接链接" translate="no">​</a></h3>
<p>在发表评论区域的上方，就是评论列表区域了。</p>
<p>评论列表大概长这个样子，如果这篇文章的评论能够多一些的话，也可以直接拉到下面看。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="评论列表" src="https://sqybi.com/assets/images/comment-list-292626c7e43f6d9fbd4ac9fd91c845d2.webp" width="746" height="902" data-zoomable="" class="img_ev3q"><div class="img-caption">评论列表</div></div><p></p>
<p>可以看到几个关键的点：</p>
<ul>
<li class="">评论列表可以嵌套。</li>
<li class="">评论的右侧有回复评论的按钮。</li>
<li class="">当评论层级达到一定深度的时候，回复评论的按钮会消失。</li>
</ul>
<p>以及有一些图中看不到的信息，首先是回复评论的按钮当鼠标指到对应评论范围的时候（不一定要在按钮上），颜色会加深，以提示可以回复评论。我觉得这个交互有助于增加回复评论的意愿，不过也只是猜测。</p>
<p>限制回复评论层级也是有原因的，主要是考虑到嵌套太深的话会影响界面展示。不过后来测试的时候发现忘了考虑移动端，最后几层还是会出框。现在再改动层级限制问题比较多，可能会考虑后续在移动端减小头像大小和缩进，以便于显示更多内容。</p>
<p>此外，在首次加载页面和发表新评论后刷新评论内容的时候，都会有一个小的加载动画。这几年的技术发展还是很有用的，这个动画（以及网页上绝大部分能看到的各种各样的动画）是纯粹使用 CSS 实现的，并不需要上传 GIF 图片。不过一个没解决的小问题是这个动画会比加载早一点点完成，这是因为我还没有找到 React 中某个 DOM 元素渲染完成后的事件，所以对于评论区这样比较大的 DOM，如果渲染速度慢了，看起来就是加载动画先消失了。</p>
<p>添加这个动画的初衷还是避免读者觉得评论区“卡了”，发表评论时的动画也是如此。用动画解决卡顿也算是业界这么多年经久不衰的一剂灵丹妙药了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="单条评论">单条评论<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E5%8D%95%E6%9D%A1%E8%AF%84%E8%AE%BA" class="hash-link" aria-label="单条评论的直接链接" title="单条评论的直接链接" translate="no">​</a></h3>
<p>进一步看每一条评论的内容，由以下几个部分组成：</p>
<ul>
<li class="">用户的头像。</li>
<li class="">用户的昵称，填写了网站的用户则会获得一个可以跳转的链接。</li>
<li class="">评论的发表时间。</li>
<li class="">评论的内容。</li>
</ul>
<p>其中头像是 Gravatar 的，前面已经提到过。其它的显示包括位置，也都经过了精细的调整。</p>
<p>评论的内容是用 HTML 的方式呈现的，整个评论系统的收取和发送都是在 Cloudflare Worker 上实现的，发送评论的过程中 Worker 会将 Markdown 转化为 HTML 存进数据库，在评论展示的时候使用。</p>
<p>此外，鼠标指到评论区域的时候，还会有一个不太明显的发光效果。这个单纯是我自己觉得好看随手搞的，因为怕过于花哨了所以没敢做得太明显，我自己还是比较满意的。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="深色模式适配">深色模式适配<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E6%B7%B1%E8%89%B2%E6%A8%A1%E5%BC%8F%E9%80%82%E9%85%8D" class="hash-link" aria-label="深色模式适配的直接链接" title="深色模式适配的直接链接" translate="no">​</a></h3>
<p>除了上面的基本功能以外，我还为整个评论系统进行了完整的深色模式适配。</p>
<p>一开始我其实还想着能不能复用一些变量，但是后来就放弃了。如果你看了我的源码，就会发现基本上是“哪里不行改哪里”，颜色不对的就加一个 <code>[data-theme="dark"]</code> 来打补丁。</p>
<p>聊到这里又不得不说一下业界发展的情况，CSS 选择器的功能迭代其实在各种框架的多配色、多平台、多语言适配中起到了很大作用。如果没有属性选择，可能这些功能的实现也都会复杂很多。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="i18n-适配">i18n 适配<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#i18n-%E9%80%82%E9%85%8D" class="hash-link" aria-label="i18n 适配的直接链接" title="i18n 适配的直接链接" translate="no">​</a></h3>
<p>最后要提一下的是，作为一个支持 i18n 的网站（再次提示：不了解的读者可以看 <a href="https://sqybi.com/blog/adding-i18n-for-a-docusaurus-site/" target="_blank" rel="noopener noreferrer" class="">为 Docusaurus 站点添加 i18n：LLM 的正确打开方式
</a> 这篇文章），这次的评论功能也进行了 i18n 的适配。网页右上角的下拉菜单可以选择语言，切换到英文就能看到效果。</p>
<p>这个过程中我发现了一个以前没发现的技巧，之前我只会用 Docusaurus 的 <code>&lt;Translate&gt;</code> 来配置多语言，这几天发现原来还有一个配套的 <code>translate()</code> 函数可以用于组件属性之类不能使用 DOM 元素的地方。之前可能有一些其它的页面实现的时候因为这个原因漏掉了一些翻译，后面如果发现的话我再补上吧。</p>
<p>还剩下一个小问题是我选择的这个编辑器组件本身的 tooltip 只有英文，这个我实在是改不了了，将就着用吧。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="背后的技术选型">背后的技术选型<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E8%83%8C%E5%90%8E%E7%9A%84%E6%8A%80%E6%9C%AF%E9%80%89%E5%9E%8B" class="hash-link" aria-label="背后的技术选型的直接链接" title="背后的技术选型的直接链接" translate="no">​</a></h2>
<p>以产品经理的角度聊了系统的设计之后，接下来聊点技术的东西，也就是各种组件的选型。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="后端服务">后端服务<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E5%90%8E%E7%AB%AF%E6%9C%8D%E5%8A%A1" class="hash-link" aria-label="后端服务的直接链接" title="后端服务的直接链接" translate="no">​</a></h3>
<p>因为 Docusaurus 是一个纯前端的框架，所以实现评论系统必然要有一套后端的服务。</p>
<p>熟悉我的人应该在文章开头就能猜到，我是用了 Cloudflare Worker 搭建这套服务的。下面聊一下更细节的选型。</p>
<p>这套服务的代码我也开源了，可以在 <a href="https://github.com/sqybi/blog-comment-service/" target="_blank" rel="noopener noreferrer" class="">sqybi/blog-comment-service</a> 看到。代码暂时还没有 refactor，挤在一个文件里，看着可能有些费劲。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="数据库">数据库<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E6%95%B0%E6%8D%AE%E5%BA%93" class="hash-link" aria-label="数据库的直接链接" title="数据库的直接链接" translate="no">​</a></h4>
<p>这套评论服务使用了 Cloudflare D1 作为后端数据库。</p>
<p>相比 KV 数据库，还是 SQL 更适合存储评论这种完全结构化的数据。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="邮件发送">邮件发送<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E9%82%AE%E4%BB%B6%E5%8F%91%E9%80%81" class="hash-link" aria-label="邮件发送的直接链接" title="邮件发送的直接链接" translate="no">​</a></h4>
<p>首先，我使用了 Cloudflare Worker Queue 将邮件发送的步骤和评论发送拆分开，避免因为邮件服务问题导致评论无法发送的情况。</p>
<p>需要注意的是，很早的时候我认为 Cloudflare 的 Queue 是一个类似于 Kafka 的消息队列。但是后来用了一下才发现，这个 Queue 其实是一个高延迟的队列，主要目的是让 Worker 能够尽快返回，把一些耗时的任务放在另一个 Worker 进程里执行。同时，Queue 也提供了一些 batch 和重试之类的功能，方便批量处理请求。</p>
<p>接下来，邮件的发送用到了 Brevo 这个服务。前面也简单介绍过了，这算是一个很好用的邮件发送服务，而且对于我这种发送量很少的个人用户是免费的，甚至不用绑定信用卡。服务本身的 API 和管理界面也都做得很不错，好评。据说 Brevo 的前身叫 Sendinblue，不知道有没有用过的小伙伴。</p>
<p>我其实在发现 Cloudflare 无法完成邮件发送的时候，首先尝试的是 AWS 的邮件服务。可惜的是，AWS 需要验证电话，但是我又接不到他们打来的电话，怀疑是最近电诈太多统一屏蔽了。不过也算是因祸得福，以我的了解，AWS 的服务多少应该还是要收一些钱的，限制也会更多。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="cors">CORS<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#cors" class="hash-link" aria-label="CORS的直接链接" title="CORS的直接链接" translate="no">​</a></h4>
<p>因为现代浏览器的一些安全性更新，现在如果不处理 CORS 的话，基本是没有办法应对这种跨域接口调用的。</p>
<p>好在 CORS 的处理并不难，只需要在发送请求端带上 <code>Origin</code> 标头，同时在接收端判断是否允许跨域，并对于允许的情况带上 <code>Access-Control-Allow-Origin</code> 标头就可以了。</p>
<p>另外因为浏览器通常都会提前发送 <code>OPTIONS</code> 请求来缓存 CORS 信息，所以对于这类请求也需要额外处理一下，一样是返回 <code>Access-Control-Allow-Origin</code> 标头就行。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="cloudflare-wrangler">Cloudflare Wrangler<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#cloudflare-wrangler" class="hash-link" aria-label="Cloudflare Wrangler的直接链接" title="Cloudflare Wrangler的直接链接" translate="no">​</a></h4>
<p>这次开发 Cloudflare Worker 之前，我已经积攒了一些经验，所以也顺便整理了一下本地的配置，现在能够比较轻松地使用 Wrangler 进行调试和部署了。</p>
<p>整体的配置方案是：</p>
<ul>
<li class="">维护一个 <code>wrangler.toml</code> 的模板。</li>
<li class="">在本地添加两个 <code>.gitignore</code> 文件，分别是 prod / staging 环境的 <code>wrangler.toml</code>；并尽量把所有有区别的配置（连接到的 Cloudflare 服务、各种 token、服务名称）都在这个文件里区分。</li>
<li class="">使用 Wrangler 命令行的 <code>-c</code> 参数加载不同文件来区分环境。</li>
<li class="">使用 Wrangler 命令行生成 <code>worker-configuration.d.ts</code> 文件，并也一并加入到 <code>.gitignore</code> 中，避免把环境变量的值不小心带到 Github 上。</li>
</ul>
<p>这样，基本就可以通过下面的几个命令来完成大部分开发中需要的操作了：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">npx wrangler types -c wranger-${env}.toml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">npx wrangler dev -c wranger-${env}.toml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">npx wrangler deploy -c wranger-${env}.toml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">npx wrangler tail -c wranger-${env}.toml</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="前端实现">前端实现<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E5%89%8D%E7%AB%AF%E5%AE%9E%E7%8E%B0" class="hash-link" aria-label="前端实现的直接链接" title="前端实现的直接链接" translate="no">​</a></h3>
<p>前端因为本身是在开发一个 Docusaurus Component，所以基本就是 React 开发，没有后端那么多可讲的细节。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="使用-chatgpt-协助开发">使用 ChatGPT 协助开发<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E4%BD%BF%E7%94%A8-chatgpt-%E5%8D%8F%E5%8A%A9%E5%BC%80%E5%8F%91" class="hash-link" aria-label="使用 ChatGPT 协助开发的直接链接" title="使用 ChatGPT 协助开发的直接链接" translate="no">​</a></h4>
<p>和之前一样，因为开发中需要编写大量 CSS，所以我还是会让 ChatGPT 来帮助我生成 CSS 并进行一些最初的设计。</p>
<p>在使用 ChatGPT 的过程中，我通常会遵循以下的方式：</p>
<ul>
<li class="">尽量将任务拆解：例如如果我想实现一个酷炫的功能，我会考虑把功能拆解之后逐步扔给 ChatGPT。例如，先实现最基本的 HTML 结构，让后设计元素之间的关系让 ChatGPT 生成基础 CSS，自行修改配色等细节后再找 ChatGPT 生成一些自己不好写的部分譬如动画效果。</li>
<li class="">不要过于相信 LLM：尽可能不要把已有的代码都扔给 ChatGPT 让他重写，或者直接实现完整功能（“生成一个网站”是行不通的，因为开发者自己都描述不清里面的需求细节）。更有效率的方式是用语言描述最小功能之后，学习一下生成的代码是怎么实现的，并转写到自己的项目里，这样也有助于找到 ChatGPT 写出的 bug。</li>
<li class="">帮忙排查错误：当遇到一个复杂的报错时，把报错内容整个扔进去让 ChatGPT 翻译反而是效率很高的。我的本职工作会大量编写 C++ 代码，这时让 ChatGPT 帮我查 gcc / clang 的报错，效率提升尤为明显。</li>
<li class="">小众软件库相关的回答容易出现幻觉：例如 Docusaurus / Cloudflare Worker 这种使用人数并没有那么多的软件，实际上 ChatGPT 的回答经常出现幻觉。在提出问题的时候就要有一个最基本的判断，例如一个 Python 语法的问题大概率会得到对的答案，但是一个 Docusaurus 下如何实现某功能的问题则需要搜索引擎协助的二次确认，或者干脆自己写一段代码验证一下。</li>
<li class="">同时使用不同的 LLM：除了 ChatGPT，我也会同时打开一些免费的 LLM 服务，例如 <a href="https://kimi.moonshot.cn/" target="_blank" rel="noopener noreferrer" class="">Kimi</a> 和 <a href="https://www.doubao.com/chat/" target="_blank" rel="noopener noreferrer" class="">豆包</a> 进行协助。现在很多国产服务都是支持在线搜索的，对于比较新的技术，准确性会高一些。多个服务之间的结果，也可以用来进行对比。上面提到的这两个服务的开发者里都有我的前同事在，同时也都还蛮好用的，这里给他们打一个小广告。</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="css-踩坑">CSS 踩坑<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#css-%E8%B8%A9%E5%9D%91" class="hash-link" aria-label="CSS 踩坑的直接链接" title="CSS 踩坑的直接链接" translate="no">​</a></h4>
<p>实现过程中，遇到问题比较多的就是 CSS 了。</p>
<p>大部分问题最后都解决了，一个完全没有解决的问题是 Docusaurus 站点主题配置的 <code>custom.css</code> 中无法引入本站图片，即使只填写了路径，也会被解析为一个 Javascript object，从而导致最终静态网站编译生成的 CSS 中这个路径变为 <code>[Object object]</code> 无法读取。</p>
<p>我倾向于认为这是一个 Docusaurus 设计的问题，暂时能想到的方案就是使用带上域名的完整路径（并没有测试过，猜测可行，有人测试了的话可以在下面留言）。但是这个方案实在是太 hacky 了，希望 Docusaurus 能早点修复这个问题。</p>
<p>另外一个问题是，使用 <code>import styles from './index.module.css'</code> 在 js 文件中导入 stylesheet 的时候，出现过某些 CSS <code>@keyframes</code> 动画无法正常加载的情况。、</p>
<p>但是后来重新实现发布评论动画的时候，却发现 <code>@keyframes</code> 动画又可用了。或许是当初的写法出了什么差错吧，当时的代码也已经删了，这估计会成为一个未解之谜了。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="通过-dotenv-加载本地配置">通过 dotenv 加载本地配置<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E9%80%9A%E8%BF%87-dotenv-%E5%8A%A0%E8%BD%BD%E6%9C%AC%E5%9C%B0%E9%85%8D%E7%BD%AE" class="hash-link" aria-label="通过 dotenv 加载本地配置的直接链接" title="通过 dotenv 加载本地配置的直接链接" translate="no">​</a></h4>
<p>Cloudflare 是可以直接集成 Docusaurus 部署的，整个编译过程都会发生在云端，只需要把代码传到 Github 就可以了。</p>
<p>在这个过程中，Cloudflare 还可以配置一些编译时的环境变量。而 Docusaurus 则支持在 <code>docusaurus.config.js</code> 中通过 <code>process.env</code> 将环境变量加载到 <code>siteConfig</code> 中，并在需要的时候通过下面的方式调用：</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token literal-property property" style="color:#36acaa">siteConfig</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> customFields </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useDocusaurusContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>但是本地启动 dev 环境的时候，这些环境变量是不存在的。这时就需要安装 <code>dotenv-cli</code> 软件包：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">npm install --save-dev dotenv-cli</span><br></span></code></pre></div></div>
<p>然后在根目录下编写一个 <code>.env</code> 文件存储环境变量，并改动 <code>package.json</code>，在启动本地环境的时候带上 <code>dotenv</code> 命令：</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token property" style="color:#36acaa">"scripts"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"docusaurus"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"dotenv docusaurus"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"start"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"dotenv docusaurus start"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"build"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"dotenv docusaurus build"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><br></span></code></pre></div></div>
<p>当然一些本地的 Node 脚本也可以这么搞，比如我本地调用 ChatGPT 进行 i18n 翻译的脚本也是用 dotenv 启动的。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="其它改动">其它改动<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E5%85%B6%E5%AE%83%E6%94%B9%E5%8A%A8" class="hash-link" aria-label="其它改动的直接链接" title="其它改动的直接链接" translate="no">​</a></h2>
<p>除了评论系统本身，还有一些其它小的改动也一并合入了，这里都简单介绍一下。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="调整字体加载">调整字体加载<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E8%B0%83%E6%95%B4%E5%AD%97%E4%BD%93%E5%8A%A0%E8%BD%BD" class="hash-link" aria-label="调整字体加载的直接链接" title="调整字体加载的直接链接" translate="no">​</a></h3>
<p>在配置了网络字体之后，经常会出现页面刚打开的时候是默认字体，过了一会儿突然切换到正确的网络字体的情况。</p>
<p>这个实际上是由字体配置的 CSS 文件中 <code>font-display</code> 控制的。我将之前的 <code>font-display: swap</code> 修改为了 <code>font-display: fallback</code>，观感应该好了一些。</p>
<p>关于这个配置的细节，我在这里不赘述了，可以参考 <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display" target="_blank" rel="noopener noreferrer" class="">mdn web docs 的文档</a>。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="后续可以做的改进">后续可以做的改进<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E5%90%8E%E7%BB%AD%E5%8F%AF%E4%BB%A5%E5%81%9A%E7%9A%84%E6%94%B9%E8%BF%9B" class="hash-link" aria-label="后续可以做的改进的直接链接" title="后续可以做的改进的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="导入-giscus-历史评论">导入 Giscus 历史评论<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E5%AF%BC%E5%85%A5-giscus-%E5%8E%86%E5%8F%B2%E8%AF%84%E8%AE%BA" class="hash-link" aria-label="导入 Giscus 历史评论的直接链接" title="导入 Giscus 历史评论的直接链接" translate="no">​</a></h3>
<p>后面可能会找个时间把之前的历史评论都导入进来，毕竟之前还是有一些文章评论蛮多的。</p>
<p>这个和新评论互不影响，这点不需要担心。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="给每条评论提供可跳转的-url">给每条评论提供可跳转的 URL<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E7%BB%99%E6%AF%8F%E6%9D%A1%E8%AF%84%E8%AE%BA%E6%8F%90%E4%BE%9B%E5%8F%AF%E8%B7%B3%E8%BD%AC%E7%9A%84-url" class="hash-link" aria-label="给每条评论提供可跳转的 URL的直接链接" title="给每条评论提供可跳转的 URL的直接链接" translate="no">​</a></h3>
<p>这个功能不太复杂，但是背后的一个复杂功能是给邮件内也加上能够跳转到这条评论的链接。</p>
<p>邮件的跳转功能则这个涉及到数据库的改动和 i18n 的适配，所以现在这一版没有上线这个功能，等后续一起实现。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="支持给文章点表情">支持给文章点表情<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E6%94%AF%E6%8C%81%E7%BB%99%E6%96%87%E7%AB%A0%E7%82%B9%E8%A1%A8%E6%83%85" class="hash-link" aria-label="支持给文章点表情的直接链接" title="支持给文章点表情的直接链接" translate="no">​</a></h3>
<p>这个其实是 Giscus 之前提供的功能，感觉还是蛮有趣的。</p>
<p>不过最近使用这个功能的人也不多，优先级不会排得很高。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="前文提到过的内容">前文提到过的内容<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E5%89%8D%E6%96%87%E6%8F%90%E5%88%B0%E8%BF%87%E7%9A%84%E5%86%85%E5%AE%B9" class="hash-link" aria-label="前文提到过的内容的直接链接" title="前文提到过的内容的直接链接" translate="no">​</a></h3>
<p>前面的文章中已经提到了一些需要进行的改进：</p>
<ul>
<li class="">邮件内容支持 i18n。</li>
<li class="">编辑器的 blockquote 显示问题。</li>
<li class="">以更清晰的方式显示正在回复哪个评论。</li>
<li class="">刷新页面不丢失编辑中的评论内容。</li>
<li class="">适配移动端显示。</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="写在最后">写在最后<a href="https://sqybi.com/blog/make-docusaurus-better-comment-system-launched/#%E5%86%99%E5%9C%A8%E6%9C%80%E5%90%8E" class="hash-link" aria-label="写在最后的直接链接" title="写在最后的直接链接" translate="no">​</a></h2>
<p>其实该写的都写完啦，已经没有什么好写的了。</p>
<p>都看到这儿了，你还不试着发一个评论吗！</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 计算机技术</category>
            <category>分类 | 碎碎念</category>
        </item>
        <item>
            <title><![CDATA[Docusaurus 的近期更新]]></title>
            <link>https://sqybi.com/blog/recent-updates-of-docusaurus/</link>
            <guid>https://sqybi.com/blog/recent-updates-of-docusaurus/</guid>
            <pubDate>Fri, 06 Sep 2024 00:10:00 GMT</pubDate>
            <description><![CDATA[一段时间没有更新博客，前几天更新了一篇文章顺便升级了 Docusaurus 的版本。]]></description>
            <content:encoded><![CDATA[<p>一段时间没有更新博客，前几天更新了一篇文章顺便升级了 Docusaurus 的版本。</p>
<p>解决了一些兼容性问题之后，感觉好像有哪里不一样了，就仔细阅读了一下 Docusaurus 的更新日志，发现他们最近还真的更新了不少实用的功能。</p>
<p>在对着这些功能一一改动之后，我决定简短地总结一下这些升级以及 <a href="https://sqybi.com/" target="_blank" rel="noopener noreferrer" class="">SQYBI.com</a> 上的对应修改。</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>其它改动</div><div class="admonitionContent_BuS1"><p>除了 Docusaurus 相关的改动之外，我还对博客进行了一系列的微调。</p><p>其中最明显的当属博客浅色模式背景配色的改动，以及整个博客字体的改动了。</p><p>现在博客使用 <code>Noto Serif SC</code> 作为默认正文和标题字体，<code>Courier Prime</code> 作为等宽字体。前者直接使用会有一些渲染问题，我参考了 <a href="https://onojyun.com/" target="_blank" rel="noopener noreferrer" class="">MÖBIUS 莫比乌斯</a> 这个博客的 CSS 进行了一些调整，之后显示效果好了不少。</p><p>其它的小改动比如 header / footer 的调整和 blockquote 的样式调整等，这里就不再赘述。ChatGPT 真的是写 CSS 的神器啊。</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="作者相关改动">作者相关改动<a href="https://sqybi.com/blog/recent-updates-of-docusaurus/#%E4%BD%9C%E8%80%85%E7%9B%B8%E5%85%B3%E6%94%B9%E5%8A%A8" class="hash-link" aria-label="作者相关改动的直接链接" title="作者相关改动的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="作者个人页面和全部作者页面">作者个人页面和全部作者页面<a href="https://sqybi.com/blog/recent-updates-of-docusaurus/#%E4%BD%9C%E8%80%85%E4%B8%AA%E4%BA%BA%E9%A1%B5%E9%9D%A2%E5%92%8C%E5%85%A8%E9%83%A8%E4%BD%9C%E8%80%85%E9%A1%B5%E9%9D%A2" class="hash-link" aria-label="作者个人页面和全部作者页面的直接链接" title="作者个人页面和全部作者页面的直接链接" translate="no">​</a></h3>
<blockquote>
<p>改动版本：<a href="https://docusaurus.io/blog/releases/3.5#blog-authors-pages" target="_blank" rel="noopener noreferrer" class="">Docusaurus 3.5</a></p>
</blockquote>
<p>这个应该是最明显的改动，在现在这一页的上方就可以看到我的名字可以点击了。</p>
<p>现在暂时只有我一个作者，不过 Docusaurus 本身的设计就是支持多作者的，我也不排斥有其他作者一起来写作。如果你有投稿的意愿，可以通过这个网站上任何可以联系到我的方式联系我。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="社交媒体链接">社交媒体链接<a href="https://sqybi.com/blog/recent-updates-of-docusaurus/#%E7%A4%BE%E4%BA%A4%E5%AA%92%E4%BD%93%E9%93%BE%E6%8E%A5" class="hash-link" aria-label="社交媒体链接的直接链接" title="社交媒体链接的直接链接" translate="no">​</a></h3>
<blockquote>
<p>改动版本：<a href="https://docusaurus.io/blog/releases/3.5#blog-social-icons" target="_blank" rel="noopener noreferrer" class="">Docusaurus 3.5</a></p>
</blockquote>
<p>和上面的改动类似，我的名字下面现在也多出了一排小图标。</p>
<p>暂时只有有限的几个网站能够自动适配图标，不知道后面会不会再更新自定义图标的功能。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="标签相关改动">标签相关改动<a href="https://sqybi.com/blog/recent-updates-of-docusaurus/#%E6%A0%87%E7%AD%BE%E7%9B%B8%E5%85%B3%E6%94%B9%E5%8A%A8" class="hash-link" aria-label="标签相关改动的直接链接" title="标签相关改动的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="为标签添加描述信息">为标签添加描述信息<a href="https://sqybi.com/blog/recent-updates-of-docusaurus/#%E4%B8%BA%E6%A0%87%E7%AD%BE%E6%B7%BB%E5%8A%A0%E6%8F%8F%E8%BF%B0%E4%BF%A1%E6%81%AF" class="hash-link" aria-label="为标签添加描述信息的直接链接" title="为标签添加描述信息的直接链接" translate="no">​</a></h3>
<blockquote>
<p>改动版本：<a href="https://docusaurus.io/blog/releases/3.4#tags-files" target="_blank" rel="noopener noreferrer" class="">Docusaurus 3.4</a></p>
</blockquote>
<p>这个改动的最大作用就是：可以把标签的代号、URL 和显示文字分开，且显示文字可以支持 <a class="" href="https://sqybi.com/blog/adding-i18n-for-a-docusaurus-site/">i18n</a> 了。</p>
<p>我也重新整理了一下我的所有标签并进行了分类，这样找特定系列的文章应该也会变得更简单一些。</p>
<p>后面有时间的话可能会把“所有文章”页面的 CSS 再调整一下，尽可能贴近 Docusaurus 本身的标签样式。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="汇总的标签页面">汇总的标签页面<a href="https://sqybi.com/blog/recent-updates-of-docusaurus/#%E6%B1%87%E6%80%BB%E7%9A%84%E6%A0%87%E7%AD%BE%E9%A1%B5%E9%9D%A2" class="hash-link" aria-label="汇总的标签页面的直接链接" title="汇总的标签页面的直接链接" translate="no">​</a></h3>
<blockquote>
<p>改动版本：<a href="https://docusaurus.io/blog/releases/3.4#tags-files" target="_blank" rel="noopener noreferrer" class="">Docusaurus 3.4</a></p>
</blockquote>
<p>因为上一个改动，Docusaurus 也添加了一个包含 <a href="https://sqybi.com/blog/tags/" target="_blank" rel="noopener noreferrer" class="">所有标签</a> 的汇总页面。</p>
<p>因为汇总得还挺不错，我把这个页面的链接放在了顶部导航栏里，替代了原先的文章分类下拉框。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="其它页面改��动">其它页面改动<a href="https://sqybi.com/blog/recent-updates-of-docusaurus/#%E5%85%B6%E5%AE%83%E9%A1%B5%E9%9D%A2%E6%94%B9%E5%8A%A8" class="hash-link" aria-label="其它页面改动的直接链接" title="其它页面改动的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="更好看的-rss-页面">更好看的 RSS 页面<a href="https://sqybi.com/blog/recent-updates-of-docusaurus/#%E6%9B%B4%E5%A5%BD%E7%9C%8B%E7%9A%84-rss-%E9%A1%B5%E9%9D%A2" class="hash-link" aria-label="更好看的 RSS 页面的直接链接" title="更好看的 RSS 页面的直接链接" translate="no">​</a></h3>
<blockquote>
<p>改动版本：<a href="https://docusaurus.io/blog/releases/3.5#blog-feeds-styling" target="_blank" rel="noopener noreferrer" class="">Docusaurus 3.5</a></p>
</blockquote>
<p>RSS / Atom 页面现在支持 XSLT 描述文件了！</p>
<p>简单来说，这个文件的作用就是可以把原先看起来就像一坨代码的 XML 文件以人类更可读的形式展示出来。Docusaurus 考虑到这群懒人应该都不愿意自己写 XSLT 文件，所以贴心的准备了一个默认的，只需要添加配置 <code>xslt: true</code> 就可以生效。</p>
<p>我已经打开了这个配置，大家可以自己看一下 <a href="https://sqybi.com/blog/rss.xml" target="_blank" rel="noopener noreferrer" class="">RSS 页面</a> 的展示效果（顺便订阅一下哦！）。</p>
<blockquote>
<p>一个小的发现：Docusaurus 的文档里把 xslt 文件的扩展名不小心写成了 xls，看来是 Excel 用太多了，哈哈哈！</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="博客边栏支持以年份分组">博客边栏支持以年份分组<a href="https://sqybi.com/blog/recent-updates-of-docusaurus/#%E5%8D%9A%E5%AE%A2%E8%BE%B9%E6%A0%8F%E6%94%AF%E6%8C%81%E4%BB%A5%E5%B9%B4%E4%BB%BD%E5%88%86%E7%BB%84" class="hash-link" aria-label="博客边栏支持以年份分组的直接链接" title="博客边栏支持以年份分组的直接链接" translate="no">​</a></h3>
<blockquote>
<p>改动版本：<a href="https://docusaurus.io/blog/releases/3.5#blog-sidebar-grouping" target="_blank" rel="noopener noreferrer" class="">Docusaurus 3.5</a></p>
</blockquote>
<p>这个改动还挺明显的，不过我一度以为自己曾经实现了这个功能，还在 <a href="https://t.me/sqybi_channel" target="_blank" rel="noopener noreferrer" class="">Telegram channel</a> 里吐槽了一下。</p>
<p>后来仔细检查了一下，我实现的其实是 <a class="" href="https://sqybi.com/archive/">所有文章</a> 页面，逻辑是类似的所以记错了。</p>
<p>希望哪天 Docusaurus 把这个页面也做了吧，省得每次更新都要提心吊胆，生怕哪个 breaking change 让这个功能失效了。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="小功能更新">小功能更新<a href="https://sqybi.com/blog/recent-updates-of-docusaurus/#%E5%B0%8F%E5%8A%9F%E8%83%BD%E6%9B%B4%E6%96%B0" class="hash-link" aria-label="小功能更新的直接链接" title="小功能更新的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="hash-router-模式">Hash Router 模式<a href="https://sqybi.com/blog/recent-updates-of-docusaurus/#hash-router-%E6%A8%A1%E5%BC%8F" class="hash-link" aria-label="Hash Router 模式的直接链接" title="Hash Router 模式的直接链接" translate="no">​</a></h3>
<blockquote>
<p>改动版本：<a href="https://docusaurus.io/blog/releases/3.4#hash-router---experimental" target="_blank" rel="noopener noreferrer" class="">Docusaurus 3.4</a></p>
</blockquote>
<p>这个就是 URL 里带 <code>#</code> 的功能，也就是现在前端框架都支持的单页面应用。</p>
<p>如果希望用压缩包发布博客的话，这个功能可以允许用户简单的在本地打开一个 html 文件就能获得博客的全部功能（实际上是使用 JavaScript 实现各种跳转）。但是因为 hash router 并不能视为一个单独的页面，从而不能被缓存，历史跳转和 URL 直接访问也会有各种各样的问题。对于大部分在线应用，使用单页面模式都不一定是一个好的选择。</p>
<p>这个问题当年在前司用 Vue 写抽奖系统的时候就踩过一次坑，后来用 React 写数据分析系统的时候果断避开了。Docusaurus 官方也贴心地说明了不要在在线环境中使用这个模式。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="为-localstorage-的键值添加前缀">为 localStorage 的键值添加前缀<a href="https://sqybi.com/blog/recent-updates-of-docusaurus/#%E4%B8%BA-localstorage-%E7%9A%84%E9%94%AE%E5%80%BC%E6%B7%BB%E5%8A%A0%E5%89%8D%E7%BC%80" class="hash-link" aria-label="为 localStorage 的键值添加前缀的直接链接" title="为 localStorage 的键值添加前缀的直接链接" translate="no">​</a></h3>
<blockquote>
<p>改动版本：<a href="https://docusaurus.io/blog/releases/3.4#site-storage---experimental" target="_blank" rel="noopener noreferrer" class="">Docusaurus 3.4</a></p>
</blockquote>
<p>TL;DR: Docusaurus 存储在 Chrome localStorage 里面的数据在一个 URL 可能指向多个网站的时候会在网站间产生冲突，所以他们给这些数据的 key 加了前缀。</p>
<p>这个问题可能在本地调试多个 Docusaurus 站点的时候会比较明显，毕竟可能同样是 <code>http://localhost:3000</code>，每次启动本地服务器都是不同的网站。</p>
<p>这还是一个实验性功能，我也没有这样的需求，所以现在这个网站还没有开启它。</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 计算机技术</category>
            <category>分类 | 碎碎念</category>
        </item>
        <item>
            <title><![CDATA[成为优秀的程序员（02）：管理的目的]]></title>
            <link>https://sqybi.com/blog/becoming-an-brilliant-programmer-02/</link>
            <guid>https://sqybi.com/blog/becoming-an-brilliant-programmer-02/</guid>
            <pubDate>Mon, 02 Sep 2024 00:30:00 GMT</pubDate>
            <description><![CDATA[如果需要查看系列中的其它文章，请使用 tag 跳转到文章目录界面：#becoming-an-brilliant-programmer。]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>如果需要查看系列中的其它文章，请使用 tag 跳转到文章目录界面：<a class="" href="https://sqybi.com/blog/tags/becoming-an-brilliant-programmer/">#becoming-an-brilliant-programmer</a>。</p>
</blockquote>
<p>感谢 <a href="https://github.com/MD-20880" target="_blank" rel="noopener noreferrer" class="">MD-20880</a> 的催更，这一次更新就来继续写这个系列吧。</p>
<p>其实我这篇文章已经写了好几个月了，但是需要工作的时候，精力被占用得真的很严重。这导致我每次有空续写的时候都和上一次间隔一两个礼拜以上，即使已经提前写好了大纲，还是要花很多时间重新读一次以前写的内容才能和过去的自己接续起来。</p>
<p>痛定思痛，在好几个月都没办法出一篇更新的情况下，我决定把这篇文章拆成几篇更短的文章来发。这样一方面我手里能有更多的存货，另一方面也可以给内容分一个章节，方便快速回忆起之前写了什么。</p>
<p>第一篇文章，先讲讲为什么我会选择“管理”作为这几篇文章的主题。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为什么要聊管理">为什么要聊管理<a href="https://sqybi.com/blog/becoming-an-brilliant-programmer-02/#%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E8%81%8A%E7%AE%A1%E7%90%86" class="hash-link" aria-label="为什么要聊管理的直接链接" title="为什么要聊管理的直接链接" translate="no">​</a></h2>
<p>在一个主题是“程序员”的系列中，第二篇文章就讲到“管理”这个话题，乍看是蛮奇怪的。但我认为，对于一个优秀的程序员来说，管理是终其一生的职业生涯中始终无法避开的话题。</p>
<p>作为一个坦诚的人，我也不得不说，这么早讲到管理，也有一些我个人的私心在里面。有看了最近几篇文章的读者可能发现了，我最近刚刚换了一个新工作，从原先被迫担任的管理岗切换到了一个类似于 IC 的岗位。</p>
<p>意料之外的是，即使在这样一个看似和管理无关的岗位上，原先管理岗的经验也给了我很大帮助；另一方面，因为不再实际进行管理工作，我其实很担心几年之后，我会将之前的这些经验逐渐淡忘。</p>
<p>所以我希望把自己的经验尽早分享出来，这样也能作为一个给自己的大纲，在今后随时回顾。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="逃不开的管理">逃不开的管理<a href="https://sqybi.com/blog/becoming-an-brilliant-programmer-02/#%E9%80%83%E4%B8%8D%E5%BC%80%E7%9A%84%E7%AE%A1%E7%90%86" class="hash-link" aria-label="逃不开的管理的直接链接" title="逃不开的管理的直接链接" translate="no">​</a></h2>
<p>大部分“普通”的程序员，职业路径基本都是走向管理岗，带领一个几十、几百甚至几千人的团队，这也是最世俗的躲避 35 岁危机的方式。虽然我自己并没有选择这条路，但是我并不认为这是一种不好的选择， 反而是适合更多人的选择。</p>
<p>而部分程序员，则可能会选择 IC 路线。IC 即 Individual Contributer，通常在大一些的公司里，总能在附近的几个组找到一些 IC。简单来说，可以认为 IC 是有很强技术能力、能独立负责一些大型的项目，但是又不负责人员实际管理的一种更技术的方向。</p>
<p>选择了 IC 路线，并不意味着要和管理完全隔绝。诚然，IC 通常在公司中有着更高的自由度，负责的工作也更贴近技术。但是一个只知道写代码的 IC，通常不太可能是一个最优秀的 IC。</p>
<p>事实上，绝大部分的软件项目，最终都还是为了产品目标服务的。这也是<a class="" href="https://sqybi.com/blog/becoming-an-brilliant-programmer-01/">上一篇文章</a> 中将软件行业描述得如此摇摇欲坠，但软件行业依旧稳定存在的原因：只要能完成主要的产品目标，一切屎山都是可以被容忍的（直到产品目标都完不成了为止，也就是屎山崩塌的那一刻）。所以，当一个人完全不了解组织是如何运转的时候，他也就很难参与到这个组织的工作中；同时，了解产品的最好途径就是每一个已经了解这个产品的人。与世隔绝的 IC 或许可以独立完成一个不错的项目，但是绝对没有办法解决超出个人资源极限的问题。</p>
<p>更进一步，如果我不仅仅满足于当一个 IC，而是希望做一个独立程序员，自己开发自己的软件，我是不是就能摆脱管理的困境，完全随心所欲地开发了呢？</p>
<p>事实上，我认为任何一个独立程序员，都需要比在公司打工的程序员更懂得管理。一方面，独立程序员意味着你要自己完成原先公司中可能十几个岗位合作完成的工作，和人打交道是不可避免的。另一方面，即使仅仅限于软件上，任何一个独立开发过软件项目的人大概都能感受到，一个人写代码更容易写出难以维护的东西。如果要避免这个问题，那么你就必须先学会如何自己管理自己，而这其实是比在公司里管理一个小组更进阶的工作。</p>
<p>当然，或许每个程序员都听说过一些“上古神犇”的传说，在这些传说里他们一个人开发了一整套软件，完成了一个团队都无法完成的工作。</p>
<p>诚然，这样的程序员是存在的。但我们也不得不承认，这样的人凤毛麟角，而他们写出的软件，通常也都有着大众视角中各种各样的“缺点”——正因为他们在开发过程中能够决定过多的事情，这些软件与其说是一些工具，不如说是这些大师的艺术作品。</p>
<p>因为这一系列文章的受众毕竟还是和我一样普通甚至刚入行的程序员，参考这些大师的例子是没有必要的。我相信他们在我这个年龄的时候，甚至更年轻的时候，也不需要我这样的浅薄建议。我们不妨放下身段，以更世俗的眼光审慎地看一看自己真正需要的东西是什么。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="管理带来了什么">管理带来了什么<a href="https://sqybi.com/blog/becoming-an-brilliant-programmer-02/#%E7%AE%A1%E7%90%86%E5%B8%A6%E6%9D%A5%E4%BA%86%E4%BB%80%E4%B9%88" class="hash-link" aria-label="管理带来了什么的直接链接" title="管理带来了什么的直接链接" translate="no">​</a></h2>
<p>看到这里，或许你认同了管理能力对于程序员是必须的，亦或你还不认同这个观点。</p>
<p>没有关系，我们可以换一个角度考虑：管理究竟给软件开发带来了什么？</p>
<p>事实上，这个问题在上一篇文章已经得到了一些解答：</p>
<blockquote>
<p>好消息是，程序员（以及所有相关的职业，恕后文不一一列举）学会了<strong>通过抽象来隔离理解成本</strong>。</p>
</blockquote>
<p>说起管理，包括我在内的绝大多数程序员脑海中想象到的一定是当老板，带团队。但为什么我们需要“团队”，它是为什么产生的？</p>
<p>当软件的规模发展到一定程度的时候，他一定会超出个人的开发和维护能力上限。这可能是因为软件功能过多，来不及全部完成；也可能是因为软件开发的时长拖得过久，以至于一些早期的代码和设计已经被忘记；说到底还是时间的问题。</p>
<p>人类就是这样，一辈子都在和时间做斗争，但是最终还是会带着不甘输给时间。</p>
<p>而解决这些问题的方式，正如上一篇文章所讲，就是合理的抽象。但当我们做出了抽象设计以后，下一个问题就随之出现，也是上一篇文章着重提到过的事情：</p>
<blockquote>
<p>一方面清楚地知道进一步抽象会导致程序员们越来越少地<strong>理解</strong>其它抽象层，一方面又期望程序员们更多地<strong>理解</strong>其它抽象层——这就是今天软件行业的困境。</p>
</blockquote>
<p>对，就是“理解”。对系统进行抽象之后，我们将问题从理解整个系统转化为了理解抽象。这减少了“理解”本身的成本，但是带来了“如何理解”的额外成本。</p>
<p>说到底，管理本身就是一种维护“如何理解抽象”的工作。让每个人精确地理解自己最需要理解的那部分抽象，才能让这个系统运转得更高效和顺畅。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="下集预告">下集预告<a href="https://sqybi.com/blog/becoming-an-brilliant-programmer-02/#%E4%B8%8B%E9%9B%86%E9%A2%84%E5%91%8A" class="hash-link" aria-label="下集预告的直接链接" title="下集预告的直接链接" translate="no">​</a></h2>
<p>在下一篇文章中，我会介绍以多年的个人经验总结出的两种管理模式，以及它们的异同。</p>
<p>不过我最近其实刚刚接受了一个采访，但是最终出的稿件实在是有点不知所云，和我想表达的内容完全没有关联，这让我有点想把采访时的回答整理一下发出来。在更新下一篇这个系列之前，我可能会插入一篇或者几篇这个采访中的内容总结出来的文章。</p>
<p>又或者，马上到十一假期了，这个假期我会和几个朋友一起去青甘环线走一圈（Exun：6），所以下一次的更新可能是旅游日记也说不定？</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 计算机技术</category>
            <category>系列 | 成为优秀的程序员</category>
        </item>
        <item>
            <title><![CDATA[适配 macOS 系统的机械键盘]]></title>
            <link>https://sqybi.com/blog/mechanical-keyboards-compatible-with-macos/</link>
            <guid>https://sqybi.com/blog/mechanical-keyboards-compatible-with-macos/</guid>
            <pubDate>Thu, 30 May 2024 23:00:00 GMT</pubDate>
            <description><![CDATA[事先声明：本文不含广告，但是我还挺想有朝一日能拿到广告费的。]]></description>
            <content:encoded><![CDATA[<p>事先声明：本文不含广告，但是我还挺想有朝一日能拿到广告费的。</p>
<p>大概一个月之前，我刚刚从之前工作了七年多的公司离职，换到了一个新的行业，开始新的工作。</p>
<p>正因为这样，最近各种事情也都在刚刚上手的阶段，需要学习的东西很多。作为一个假装成 E 人的 I 人，社交压力也是不小的。加之生活里好多之前的同事朋友们都想和我聊聊，自己也在找房，所以确实没什么时间更新博客，就连四月上旬去日本的照片到现在为止也只<a href="https://flickr.com/photos/sqybi/" target="_blank" rel="noopener noreferrer" class="">修了几张</a>。</p>
<p>一转眼就已经是 3 开头的日期了，为了避免五月份开空窗，我还是决定水一篇文章。</p>
<p>（既然你已经点进来了，我就不得不诚挚地告诉你：如果你没有遇到和我一样的问题，那么这篇文章真的很水。）</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="苹果好人坏">苹果好，人坏<a href="https://sqybi.com/blog/mechanical-keyboards-compatible-with-macos/#%E8%8B%B9%E6%9E%9C%E5%A5%BD%E4%BA%BA%E5%9D%8F" class="hash-link" aria-label="苹果好，人坏的直接链接" title="苹果好，人坏的直接链接" translate="no">​</a></h2>
<p>因为毕业就去了微软，所以其实我一开始在工作中接触的编程环境就是纯纯的 Windows + Visual Studio。而作为一个竞赛生，Linux 自然也是很早就玩过的。但直到入职谷歌以后，我才第一次拿到了一台 MacBook，也是第一次用上了 macOS 系统。</p>
<p>不得不说，其实当年的 macOS 还真挺适合程序员的：不像那时的 Windows 一样连命令行用起来都费劲，也不像那时的 Linux 一样只要用上了 X 就能遇到一万个 bug。更别提那时的 Windows 连 Powershell 都没有搞好，而 Linux 发行版即使不用图形界面，一样会碰到各种令人头疼的问题——如果有当年用 Arch Linux 的朋友一定会记得它所谓的滚动更新，实则如果几个月不更新突然更新了一次，等待你的大概率就是重装了。</p>
<p>反观 macOS 系统，一方面有着还算稳定的 GUI 体验，另一方面也有 shell 可以用，至少跑个 git 跑个 SSH 不成什么问题。作为一个开发终端，这真是再合适不过了。</p>
<p>花开两朵，各表一枝。除了电脑，键盘也是程序员工作的重要组成部分，我自己也早早地拥有了几把机械键盘。不过那个时候机械键盘的市场还不太成熟，市面上好用的的机械键盘还是以 Cherry 和 FILCO 为主，所以当初也没怎么考虑过 Mac 和 Windows 快捷键区别的问题。虽然体感上确实不好用，但反正都是凑合用呗。</p>
<p>而这个时候，互联网上对苹果产品普遍贴的标签还是：封闭，但好用。那时还在世的乔布斯，也正是最被神化的时候。加之前面说的，Windows 和 Linux 确实在某些方面还不太给力，所以大部分人也都很随波逐流。macOS 即使不好用也不是苹果的问题，肯定是“我”的问题。<strong>苹果好，人坏！</strong></p>
<p>后来离开了谷歌，新公司的开发机和线上环境都是 Ubuntu 系统。而那几年正好也是 Ubuntu 的桌面环境发力的日子，在工作和生活的压力下，失去了很多业余时间地我，也就顺理成章地抛弃了之前那些 geek 的坚持，转投当年最看不起的 Ubuntu 系统——你还别说，用着还真挺舒服。虽然小问题很多，但是相比前几年已经是很能用的状态了。</p>
<p>再后来，因为转到管理岗，所以我在公司的开发机和笔记本又装回了 Windows 系统。而这时 Windows 开始推出 WSL = Windows Subsystem Linux，不得不说这个东西真的把 Windows 变成了一个开箱即用的开发环境，是这几年 Windows 让我最爽的一次改动了。</p>
<p>慢慢地，或许是因为和政府部门跟国企对接导致打开 Word 的次数逐渐增多，我在公司打开 Linux 的次数逐渐减少。而在家里，自从电脑换了主板之后 Linux 没有网卡驱动开始，我也就再也没有重新打开过它，所有 coding 都直接用 VSCode 和 WSL 下的 SSH，连接到家里的另一台 Linux 服务器完成。但不管是 Linux 还是 Windows，不得不说它们的使用体验还是很一致的，切换也很丝滑，偶尔因为什么原因切回 Linux 也不会用着不顺手。</p>
<p>接下来的几年里，时间就像停滞了一样。每天都在做着差不多的事，也没有什么热情再去折腾和尝试不同的操作系统。直到最近，我终于结束了这份持续时间长到我从来都没有想象过的工作，来到了一家新的公司，开启了一段新的人生，也又一次拿到了一台 MacBook。</p>
<p>而这七年间，机械键盘的市场也发生了翻天覆地的变化。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="苹果坏键盘也坏">苹果坏，键盘也坏<a href="https://sqybi.com/blog/mechanical-keyboards-compatible-with-macos/#%E8%8B%B9%E6%9E%9C%E5%9D%8F%E9%94%AE%E7%9B%98%E4%B9%9F%E5%9D%8F" class="hash-link" aria-label="苹果坏，键盘也坏的直接链接" title="苹果坏，键盘也坏的直接链接" translate="no">​</a></h2>
<p>要说最近几年的机械键盘市场，最明显的转变就是：Cherry 和 FILCO 两个老牌厂商不行了，国产机械键盘厂商在压低价格的同时，把机械键盘玩出了花，也越来越模糊了客制化键盘这个小圈子和量产键盘之间的界限。</p>
<p>之前奉 Cherry 的青轴茶轴红轴为圭臬的人们，也开始发现原来键盘的轴体可以更加好用，更加好听，甚至更加好看。而各种新的配列设计，新的键帽材质，各种个性化的设计，也无一不在吸引着更多机械键盘的新老玩家入坑回坑。更重要的是，这一切都比之前还要便宜得多。</p>
<p>当然，Cherry 的几款键盘依旧在高端领域有着一席之地，但早已不是当初一手遮天的状态了。</p>
<p>而这也像苹果公司在这几年的变化：人们慢慢发现，即使是苹果的产品，也远没有达到完美，甚至问题很多。但在走下神坛的同时，它也凭借着自己的特点和优势，一直在市场上安居一隅。</p>
<p>回到正题，现在我的状态就是：I have a MacBook, I have a keyboard.</p>
<p>当我把它们插到一起的时候——</p>
<p>干，明明在系统里切换了 F 区键位的功能，默认为 F1-F12 而不是多媒体键了，甚至已经在笔记本键盘上生效了，可我的外接键盘怎么还是反的啊！</p>
<p>我当时使用的键盘是 VGN S99 阿尼亚轴，无论从外观还是轴体上，我都还挺喜欢这块键盘的，而这块键盘自己也宣称“支持 macOS”。但作为程序员，每次 F 区的按键都要加上 Fn 一起按，实在是没法忍受。</p>
<p>四处求索，我终于在 V2EX 上看到了这样的解答：苹果的 F 区和功能键甚至 Fn 键的软件触发方式确实和 Windows 键盘不太一样，但这并不是导致 F 区不能互换的原因；真实原因是只有官方认证的键盘支持 F 区键位互换的功能，其他键盘的 code 被苹果屏蔽了，而有些键盘则可以通过模拟官方键盘的 code 来达到触发换位的效果。</p>
<p>虽然我也没有验证这个说法的真假，但是苹果对官方键盘和第三方键盘有区别对待看起来是坐实了的。虽然苹果坏，但是手头的键盘也坏了啊！</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="寻找合适的键盘">寻找合适的键盘<a href="https://sqybi.com/blog/mechanical-keyboards-compatible-with-macos/#%E5%AF%BB%E6%89%BE%E5%90%88%E9%80%82%E7%9A%84%E9%94%AE%E7%9B%98" class="hash-link" aria-label="寻找合适的键盘的直接链接" title="寻找合适的键盘的直接链接" translate="no">​</a></h2>
<p>最开始的时候，我还抱着一丝希望，想用 Karabiner-Elements 这个据说在 Mac 上万能的改键软件来拯救手里的键盘。</p>
<p>但是不知道是键盘的问题还是软件的问题，我发现确实部分键位是可以通过这个软件互换的，准确地说是 F6 - F12。但是 F1 - F5 的键位，却根本没有办法找到对应的触发按键配置。</p>
<p>因为工作也挺忙的，能折腾的时间并不多，而每天都要把手粘在 Fn 上，却是实实在在的效率损失。思前想后，还是决定干脆用公司入职发放的 Productivity Boost 报销额度，给自己换一块新的键盘，也算是正确使用方式了吧。</p>
<p>最开始的时候，有考虑过购买客制化键盘。咨询了一下身边的朋友，就发现了几个和我的需求冲突很大的问题：</p>
<ul>
<li class="">因为需要报销，所以必然要找可以开发票的地方购买。但是客制化键盘的官方发售途径通常都会很快被抢光，越是有名且稳定的键盘型号越是如此，这些品控和手感上确定没有问题的键盘，完全没有办法以能开出发票的形式买到。</li>
<li class="">而那些能买到现货的键盘，则大部分都是一些名不见经传的品牌和型号。而且绝大部分客制化键盘都是售出不退的，万一买到一块不喜欢的键盘，金钱花费还是其次，时间成本才是更大的问题：这意味着可能又要一两个礼拜没有合适的键盘用了。</li>
<li class="">虽然大部分客制化键盘看起来都支持 QMK / VIA，而从网上的信息来看，QMK / VIA 也是肯定能完成 Mac 下 F 区改键的，但是很多客制化键盘的售前咨询几乎等于零。万一买到一块不支持的键盘，基本就是买了一块废铁了——或者说是废铝。</li>
<li class="">客制化键盘大部分都需要手动组装，甚至有一些还需要焊接，但是产品界面通常不会明确的写出组装方式。对于没有从零开始组装过客制化键盘的我来说，在急着用上的情况下，花这么多时间研究也不太值得。</li>
</ul>
<p>综合来看，客制化键盘相比一个生产力工具，更像是一个玩具。如果闲下来了玩玩自然是好的，但是想要即插即用，恐怕不太合适。</p>
<p>最终，我还是把目光投向了市场上的一些特殊品类：可以一定程度上客制化的量产键盘。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="我的解决方案nuphy-halo96">我的解决方案：NuPhy Halo96<a href="https://sqybi.com/blog/mechanical-keyboards-compatible-with-macos/#%E6%88%91%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88nuphy-halo96" class="hash-link" aria-label="我的解决方案：NuPhy Halo96的直接链接" title="我的解决方案：NuPhy Halo96的直接链接" translate="no">​</a></h2>
<p>首先重复一次，这不是广告，这不是广告。</p>
<p>我并没有花很多时间调研这个市场，所以可能还会有一些比这个键盘更好的选择。或者说，本来选键盘就是一个相当因人而异的事情，每个人都有自己的喜好，十年前那个只要退烧就是 FILCO 和 Cherry 的市场才不太正常。</p>
<p>我之所以分享这个键盘，也只是想给和我遇到了同样问题的朋友一个快速的解决方案，至少也是一个解决的方向，不用花太多时间去自己查找。虽然这个博客也没啥人评论，但是我也很欢迎有不同方案的朋友来分享一下你们的键盘，有机会我也会买来试一试。</p>
<p>先说重点：NuPhy 的 Air 系列和 Halo 系列产品，都是可以满足上述 F 区键位互换要求的。</p>
<p>而 Air 系列的优点在于它是支持 QMK / VIA 的，也就是可以更灵活的改键。但是对于我来说缺点在于，它是一块矮轴键盘——我的手指力气还是有点大的，提前触底恐怕手会吃不消。</p>
<p>反观 Halo 系列，购买的过程就体现出这种量产键盘的优势了。我简单咨询了一下客服，而客服非常专业地表示这款键盘虽然使用的是 NuPhy 自己的改键软件，但是本身就是可以完美适配 macOS 的，F 区互换也一定没问题。而且作为一个量产产品，它还有一个客制化键盘从来都没有的优势：七天无理由退货！客服甚至明确表示，如果不放心的话可以先买回去用用，万一不行还可以退回来，有运费险呢。</p>
<p>最终，我选择了 Halo 系列下自己最习惯的 96% 配列，也就是牺牲一部分 Insert 区的功能键但保留小键盘的配列。而轴体上我其实是不小心选错了，买了冷翠蔷薇轴。这是一款段落轴，而我其实从阿米洛的静电容机械轴开始就退烧了段落轴，一直都是更喜欢线性轴的。</p>
<p>键盘到手之后，第一件事就是试试 F 区，结果也非常完美。只要在系统里打开更换 F 区功能的选项，这块键盘也就随之换了过来。</p>
<p>但是用了几分钟，我就发现了轴体的不对劲，也是这个时候才发现自己选错了轴。而这款冷翠蔷薇轴……怎么说呢，即使在线性轴里，在我看来也可以算得上是“垃圾”的级别了。段落触发非常早，几乎就在按下的一瞬间。而只要你的按键过程不是 100% 直上直下的，那么就很大概率会在下落的时候被卡一下。在我还没有熟悉这块键盘的时候，感觉至少有 5% 左右的几率在按键时会触底失败而没有触发按键。</p>
<p>而更加难受的是，这块键盘除了空格以外，即使是功能键也使用了这款轴体，这就导致类似于 Cmd + Opt + X 这种组合键的触发失败几率大大升高。当然，这块键盘的空格键手感是相当不错的，这点倒是可以夸一夸。</p>
<p>不过这个时候，就体现出这种披着客制化键盘外皮的量产键盘带来的优势了。这块键盘和很多现在的国产量产键盘一样，都是可以换轴的！</p>
<p>而在我写下这篇文章的时候，新的轴体和键帽已经在路上了，我也终于即将结束这长达一个月的忍受，用上舒服的键盘和键位了。</p>
<p>至于之前的 VGN S99 阿尼亚轴键盘——不得不说阿尼亚轴实在太舒服了，所以我已经拿回家插在我的 Windows 系统上，替代掉了家里的 SKN 青龙 4.0。</p>
<p>而拆下来的青龙，除了准备打游戏时换上以外，我也有点想换给我家里那台服务器做被用键盘，而服务器上插着的那块阿米洛森灵草木绿轴，就只好找机会出掉。</p>
<p>以我通常的操作，这块阿米洛的键盘大概会在某个熟人或者公司二手群里被我以低于闲鱼的价格出掉。虽然我确实也没有在博客上卖东西的打算，不过如果你真的是一个能看完这么无聊文章的人，又恰好是我认识的熟人，同时也想要这块键盘，不如就偷偷在评论里或者私下敲我一下。因为这也是一种缘分，所以说不定你受键盘之灵祝福，能拿到更低的价格呢。</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 碎碎念</category>
        </item>
        <item>
            <title><![CDATA[小米 14 Ultra 摄影相关的高强度使用体验总结]]></title>
            <link>https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/</link>
            <guid>https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/</guid>
            <pubDate>Sun, 14 Apr 2024 22:00:00 GMT</pubDate>
            <description><![CDATA[在一个多月之前，我入手了小米 14 Ultra（和它的摄影手柄套装），替换掉了手里的小米 12 Pro。]]></description>
            <content:encoded><![CDATA[<p>在一个多月之前，我入手了小米 14 Ultra（和它的摄影手柄套装），替换掉了手里的小米 12 Pro。</p>
<p>一方面，我之前的手机性能着实差了一些，一些你们都懂的游戏掉帧严重，特别是在同时还打开了微信视频的情况下更是如此，是时候更新换代了。</p>
<p>另一方面，上一代小米 13 Ultra 专注于摄影的思路着实有点打动我，不过我当时也看到了这台手机设计上存在的一些问题，所以没有入手。而这次的发布会上，能够感觉到之前的这些问题特别是重心问题在 14 Ultra 上已经有了很大改善。</p>
<p>此外，我最近也是越来越体会到旅游时并非每一天每一刻都适合随身携带相机。而现在的手机摄影已经相当成熟，可以作为非正式出片时相机的良好补充。这让我有越来越强烈的需求，想要持有一款影像素质更强的手机。</p>
<p>所有这些原因叠加在一起，我决定首发购入小米 14 Ultra。恰逢最近有一些工作上的变动，正好有了一个接近两周的假期可以去日本旅游，我也在这个过程中深度体验了这款手机的优缺点。</p>
<p>总的来说，这款手机的优点颇多，基本上和各类软文或者非软文的评测一样，无论是大光圈、大底带来的暗光表现，还是徕卡影调带来的一键出片效果（调教得真的很棒！），以及视频拍摄上的种种优化，只要是用过这款手机的人基本都会认同。</p>
<p>所以，接下来的文章可能会主要集中在手机的部分小缺点上。这并非意味着它不是一款出色的手机，但这款手机过于专注于特定的用途，以至于它并不适合所有人，或者说甚至不适合大多数人。如果你是它的目标用户，那么这些缺点多多少少都是可以忍受的；但如果你不是它的目标用户，那么这些缺点的任何一个都有可能成为在使用体验上压倒你的最后一棵稻草。</p>
<p>适合的才是最好的。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="在小米-14-系列中做出选择">在小米 14 系列中做出选择<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E5%9C%A8%E5%B0%8F%E7%B1%B3-14-%E7%B3%BB%E5%88%97%E4%B8%AD%E5%81%9A%E5%87%BA%E9%80%89%E6%8B%A9" class="hash-link" aria-label="在小米 14 系列中做出选择的直接链接" title="在小米 14 系列中做出选择的直接链接" translate="no">​</a></h2>
<p>首先要提的是，选择小米系列而不是同样专注于影像旗舰的 OPPO / vivo，肯定是有我多年都在使用小米的原因所在——迁移数据毕竟是很痛苦的事情。</p>
<p>但是前几年经历了把数据和应用迁移到 iPhone 又迁移回来，我依旧还在使用小米手机，自然也是因为它的产品定位和我足够契合：不一定有特别的亮点，但一定是短板足够长的水桶。</p>
<p>所以这里我们不会聊品牌之间的选择，而是更主要聊一下我为什么在小米的三台新机型中选择了 14 Ultra，而非 14 或 14 Pro。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="小米-14小屏机的旗舰">小米 14，小屏机的旗舰<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E5%B0%8F%E7%B1%B3-14%E5%B0%8F%E5%B1%8F%E6%9C%BA%E7%9A%84%E6%97%97%E8%88%B0" class="hash-link" aria-label="小米 14，小屏机的旗舰的直接链接" title="小米 14，小屏机的旗舰的直接链接" translate="no">​</a></h3>
<p>首先说一下小米 14 这台小屏机。在小屏机这个相对小众的市场上，小米可谓杀出了一条血路。这次的小米 14 从各种配置和设计上，在保证了整体小巧的情况下，可以说和 14 Pro 不相上下，我甚至差一点就没等到 14 Ultra 发布，而是直接入手了这台机器；当然最后还是忍住了。</p>
<p>我这次一起出行的朋友中，就有一位使用小米 14 作为主力机的摄影爱好者。整体来看，虽然小米 14 的主摄没有一英寸底，但是实际夜景表现也并没有相差太多。而长焦段的 JN1 传感器和 14 Ultra 长焦使用的 IMX858 其实并没有可以明确体验到的差别，我们这两台手机的长焦端成像效果至少在手机屏幕上看起来半斤八两。</p>
<p>小米 14（也包括 14 Pro）在旅行摄影上的唯一不足，可能就是缺少一个 100mm 以上焦段的长焦了。但其实如果只是发发朋友圈，75mm 左右焦段的 3x 长焦加上裁切，也足以应付绝大部分情况。</p>
<p>所以<strong>如果不是强烈需要将手机作为相机的代替，那么小米 14 将是我最推荐的日常机，没有之一</strong>。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="小米-14-pro大屏真的是优势吗">小米 14 Pro，大屏真的是优势吗<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E5%B0%8F%E7%B1%B3-14-pro%E5%A4%A7%E5%B1%8F%E7%9C%9F%E7%9A%84%E6%98%AF%E4%BC%98%E5%8A%BF%E5%90%97" class="hash-link" aria-label="小米 14 Pro，大屏真的是优势吗的直接链接" title="小米 14 Pro，大屏真的是优势吗的直接链接" translate="no">​</a></h3>
<p>而说到小米 14 Pro，高情商的说法是，14 Pro 拥有和 14 几乎一样的配置和性能，是提供给非小屏爱好者的选择。低情商的说法嘛，那就是 14 Pro 作为一个大屏机，几乎没有什么能和 14 拉开差距的配置。</p>
<p>甚至写到这里的时候，我都不知道这台机器还有什么可以说的优点。</p>
<p>反正我肯定是更心动小屏的，所以见仁见智吧。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="小米-14-ultra差异化和泛用性">小米 14 Ultra，差异化和泛用性<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E5%B0%8F%E7%B1%B3-14-ultra%E5%B7%AE%E5%BC%82%E5%8C%96%E5%92%8C%E6%B3%9B%E7%94%A8%E6%80%A7" class="hash-link" aria-label="小米 14 Ultra，差异化和泛用性的直接链接" title="小米 14 Ultra，差异化和泛用性的直接链接" translate="no">​</a></h3>
<p>和 14 Pro 不同，14 Ultra 则是做出了足够的差异化。一方面，几颗镜头更大的光圈和主摄的一英寸大底，虽说绝大多数场景下的拍摄体验上并不一定能带来肉眼可见的提升，但至少从参数上给人一种“我拍的照片更好了”的感觉。另一方面，增加的 5x 长焦提供了旅行中常用的最长焦段视角和压缩感，而稍微更广一些的广角端……我自己比较菜，是不怎么知道如何使用广角端的，但是广角这东西确实每一毫米都有它的作用，所以应该有人可以无视这颗广角令人发指的畸变把它用好吧。</p>
<p>14 Ultra 相比 13 Ultra 的一个重要优化是修改了之前头重脚轻的重心设计。我虽然没有购买 13 Ultra，但是也去小米之家摸过不少次，只能说但凡还想日常把手机当一个手机来使用的话，就绝对不应该入手 13 Ultra。而 14 Ultra 的改动则令人欣喜：虽然摄像头模组依旧巨大，但是现在手机整体的重心合理，甚至镜头下方能够成为一个很好的手指支撑点。</p>
<p>当然作为一个纯粹的手机，我认为 14 Ultra 大镜头模组导致的问题依旧存在，例如整体重量依旧很重、容易摸脏镜头，横握的时候非常难受等等。我也不会推荐购买这台手机之后，把它纯粹地当作一个手机使用。不过相比 13 Ultra，这一代现在至少已经是能用的程度了。</p>
<p>如果说还有什么令我浑身难受的缺点，那或许就是这套镜头模组防抖系统的晃动问题。虽然心里知道这是正常的，也知道实际使用上不会有问题，但这套防抖的晃动幅度还是让人难以习惯，反正我是真的没有见过第二台防抖系统有这么大晃动噪音的手机或者相机了。</p>
<p>说得夸张一点，如果你在自习室里摇晃手机，我很怀疑旁边的同学会因为防抖系统产生的咔哒声把你轰出去。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="如何在三款手机中进行选择">如何在三款手机中进行选择<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E5%A6%82%E4%BD%95%E5%9C%A8%E4%B8%89%E6%AC%BE%E6%89%8B%E6%9C%BA%E4%B8%AD%E8%BF%9B%E8%A1%8C%E9%80%89%E6%8B%A9" class="hash-link" aria-label="如何在三款手机中进行选择的直接链接" title="如何在三款手机中进行选择的直接链接" translate="no">​</a></h3>
<p>所以总的来说，我认为在这三台手机之间选择，只需要遵循如下方案：</p>
<ol>
<li class="">首先确认你是不是一个需要手机作为相机在某些场景下替代的摄影爱好者，而非只想用手机记录下生活中的某些画面。如果你的目的是使用手机替代相机的话，那就可以考虑 14 Ultra；但如果不是，那么我觉得购入 14 Ultra 的意义不大。</li>
<li class="">当你是一个小屏爱好者的时候，优先考虑 14。或者说，你都是小屏爱好者了，还有什么理由不选择 14 呢？</li>
<li class="">如果你不喜欢小屏，但也不会拿手机当相机重度使用的时候，可以考虑 14 Pro。</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="摄影手柄体验">摄影手柄体验<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E6%91%84%E5%BD%B1%E6%89%8B%E6%9F%84%E4%BD%93%E9%AA%8C" class="hash-link" aria-label="摄影手柄体验的直接链接" title="摄影手柄体验的直接链接" translate="no">​</a></h2>
<p>不得不说，这次的摄影手柄还是很吸引眼球的。可实际体验下来，我觉得摄影手柄并没有想象中那么好用。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="摄影手柄的最大优点">摄影手柄的最大优点<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E6%91%84%E5%BD%B1%E6%89%8B%E6%9F%84%E7%9A%84%E6%9C%80%E5%A4%A7%E4%BC%98%E7%82%B9" class="hash-link" aria-label="摄影手柄的最大优点的直接链接" title="摄影手柄的最大优点的直接链接" translate="no">​</a></h3>
<p>首先是优点，调节拨轮和拨杆真的很爽！我使用的配置是调节拨轮用来调节 EV，而调节拨杆则是配置成了分段调节镜头倍率。也就是说拨动拨杆的时候，焦段会在 0.5x、1x、2x、3.2x 和 5x 间调节，而非无级调节，这也符合我使用变焦镜头的习惯，大部分场景下只固定在若干个焦距上，如果要裁切的话后期回来再说。我个人比较推荐无论是相机还是手机，在入门阶段都尽可能地这样使用变焦镜头，以快速熟悉各个焦段的画面范围、压缩感和距离感，为过渡到定焦头打好基础。</p>
<p>但是仔细想想，这一定程度上也是因为小米的相机软件界面调整 EV 和焦距的操作并不舒适。特别是在这一代的徕卡调色下，正确调整 EV 是拍摄时的重中之重，而 EV 的调整竟然要手动在一个远离快门的位置点击 + 拖动，甚至如果要退出调整的话还需要第二次点击！</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="快门按钮不如点击屏幕">快门按钮不如点击屏幕<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E5%BF%AB%E9%97%A8%E6%8C%89%E9%92%AE%E4%B8%8D%E5%A6%82%E7%82%B9%E5%87%BB%E5%B1%8F%E5%B9%95" class="hash-link" aria-label="快门按钮不如点击屏幕的直接链接" title="快门按钮不如点击屏幕的直接链接" translate="no">​</a></h3>
<p>手柄的快门按钮，则是我使用下来体验最差的功能。</p>
<p>键程长，触发力度大，左手本来为了避免挡住镜头就要虚握，而手柄本身的仿皮材质很滑，这一系列原因导致按快门的过程几乎一定会导致相机向下移动一小段距离，偏离一开始的构图。</p>
<p>也正是因为如此，在使用手柄的时候，我几乎还是会点击屏幕来触发快门。这可以说是这款手柄最糟糕的一个设计了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="手柄设计中的其它亮点">手柄设计中的其它亮点<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E6%89%8B%E6%9F%84%E8%AE%BE%E8%AE%A1%E4%B8%AD%E7%9A%84%E5%85%B6%E5%AE%83%E4%BA%AE%E7%82%B9" class="hash-link" aria-label="手柄设计中的其它亮点的直接链接" title="手柄设计中的其它亮点的直接链接" translate="no">​</a></h3>
<p>除了按钮和拨杆以外，这款手柄的设计还是有一些其它亮点的。</p>
<p>首先这款手柄是搭配了一个专门的仿皮手机壳使用的，这款手机壳背后有一个镂空的小洞，用来适配手柄锁死的卡扣。而这个洞的位置，恰好可以露出手机背板上的小米 logo——相信所有第一次装上这个手机壳的同学，看到这个小洞的时候都会会心一笑。</p>
<p>另外，这款手机壳背后的摄像机模组周围，有一个可以拆卸的金属环。这个金属环除了可以换成其它颜色（我购买的白色手机壳，自带了银色和金色的环），最主要的一个功能是可以更换成滤镜转接环，直接转接相机滤镜！虽然我一次也没有用上过，但是这应该就属于“我可以不用但你最好能有”的功能了吧。再退一步，就算真的不用，至少能换成金色金属环也是炫耀感满满的。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="一贯糟糕的品控">一贯糟糕的品控<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E4%B8%80%E8%B4%AF%E7%B3%9F%E7%B3%95%E7%9A%84%E5%93%81%E6%8E%A7" class="hash-link" aria-label="一贯糟糕的品控的直接链接" title="一贯糟糕的品控的直接链接" translate="no">​</a></h3>
<p>说完功能设计上的特点，就不得不聊一聊这款手柄的糟糕品控了。首批品控不行，也是很多小米供应链产品的通病。</p>
<p>我是和手机一起购入的手柄，所以拿到的应该也是最早的那一批次产品。结果在使用过程中，就遇到了各种各样的品控问题。</p>
<p>首先是一个没那么多人提到的问题，那就是上面提到的可拆卸金属环在拆卸的时候非常紧。这款金属环的拆装方式有点类似于相机镜头：有一个解锁按钮，在按下的状态可以旋转金属环将其拆下；而安装的时候则是旋转到按钮位置就可以咔哒一声卡死。</p>
<p>而我遇到的问题简单来说，就是这个按钮的固定装置过紧了。当手机壳装在手机上的时候，因为本身和手机之间有一定的缝隙，所以即便用再大的力气按这个按钮，手机壳本身的变形也会导致没有办法按到底，从而根本没办法解锁金属环！而拆下手机壳之后，也需要用另一个手指顶着按钮后面，同时用很大的力气按住按钮，才能拧下金属环。</p>
<p>我也看到一些网上的评论提到他们的金属环遇到了相反的品控问题，就是太松了导致没有拆卸就会有一定的晃动。小米啊，你可长点心吧……</p>
<p>第二个问题就是很多评测中都提到的电池充电逻辑问题了：摄影手柄会优先给手机充电，这就导致手机电量不足 80% 的时候，摄影手柄会持续给手机充电直到自己的电量耗尽。而手柄并没有预留另一块电池给自己的正常功能，从而会发现出去拍了没多一会儿，手柄就失灵了。</p>
<p>据说这个问题在新的固件中有所改善，前几天固件刚刚推送了。而因为后面的文章中会提到的一些原因，我没能在这次的旅行中体验到这个问题是否已经解决，只能等后续的机会了。</p>
<p>第三个问题则是断连，这个问题也有很多人报过了，我也是万万没想到 Type-C 口的连接竟然也有断连问题。使用中需要通过重新插拔手柄解决，且似乎有少量几率需要多次插拔，不知道是不是我使用的姿势问题。因为手柄本身有一个卡扣（也不知道有卡扣怎么还断连？），每次插拔要解锁再锁上，还是蛮麻烦的。</p>
<p>第四个问题是最致命的问题，也是导致我这次旅行没能带上手柄的关键原因：在放置了一个礼拜没使用之后，手柄直接充不进去电了！</p>
<p>我在即将出发的时候才发现了这个问题，不光是手柄本体无法充电，将手柄连接手机的时候，手柄和手机都没有办法进入充电状态。</p>
<p>正因为如此，我在临出发前的那个晚上匆忙申请了小米的售后，并把手柄留在了家里让老婆帮我交给快递员。因为实在是太突然了，所以我甚至没来得及找到全部配件（指包装盒和另外的两个金属环），只留下了手机壳和手柄本体。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="令人惊喜的售后维修">令人惊喜的售后维修<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E4%BB%A4%E4%BA%BA%E6%83%8A%E5%96%9C%E7%9A%84%E5%94%AE%E5%90%8E%E7%BB%B4%E4%BF%AE" class="hash-link" aria-label="令人惊喜的售后维修的直接链接" title="令人惊喜的售后维修的直接链接" translate="no">​</a></h3>
<p>这个问题固然是令人烦恼的，但可能是小米也知道自己的手柄出了品控问题，所以维修的过程十分简单明了：直接给我寄了一套新的手柄套装回来。</p>
<p>我对这个维修结果还是很满意的，唯一可惜的是：早知道就不把配套手机壳还回去了，这个手机壳单卖也要 200 块钱呢。</p>
<p>这个新的手柄至少到现在为止还没有过断连。但是正如上文所说，我暂时也没有特别多的机会测试这个手柄的续航表现和稳定性，只能等待下次出门的机会了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="最佳的第三方配件">最佳的第三方配件<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E6%9C%80%E4%BD%B3%E7%9A%84%E7%AC%AC%E4%B8%89%E6%96%B9%E9%85%8D%E4%BB%B6" class="hash-link" aria-label="最佳的第三方配件的直接链接" title="最佳的第三方配件的直接链接" translate="no">​</a></h3>
<p>或许你已经看过<a href="https://www.bilibili.com/video/BV19Z421h7rA/" target="_blank" rel="noopener noreferrer" class="">一些视频</a>，说小米 14 Ultra 的摄影套装后盖可以完美适配银鹭八宝粥的盖子。</p>
<p>我实际体验了一下，不仅仅是银鹭八宝粥，娃哈哈八宝粥的盖子也能完美适配！而且银鹭八宝粥的盖子是黑色的，而娃哈哈恰好是白色的，完美地对应上了摄影套装的两种颜色。</p>
<p>而使用了一段时间之后，不得不说这个严丝合缝的程度远远比品控出现问题的金属环好太多了，甚至到了我有一段时间每见到一个人都要把手机连着八宝粥盖子交给他把玩一番的程度。</p>
<p>这才是小米 14 Ultra 的最佳第三方配件啊！</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="摄影体验">摄影体验<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E6%91%84%E5%BD%B1%E4%BD%93%E9%AA%8C" class="hash-link" aria-label="摄影体验的直接链接" title="摄影体验的直接链接" translate="no">​</a></h2>
<p>聊完这些杂七杂八的，终于要开始聊摄影体验了。</p>
<p>经过这一个多月的体验，我现在使用这台手机的方式已经基本固定下来了：使用默认拍照模式，选择合适的焦段，构图，略微调整 EV，偶尔根据情况选择焦点，拍照。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="过于复杂的专业模式和不够复杂的默认模式">过于复杂的专业模式和不够复杂的默认模式<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E8%BF%87%E4%BA%8E%E5%A4%8D%E6%9D%82%E7%9A%84%E4%B8%93%E4%B8%9A%E6%A8%A1%E5%BC%8F%E5%92%8C%E4%B8%8D%E5%A4%9F%E5%A4%8D%E6%9D%82%E7%9A%84%E9%BB%98%E8%AE%A4%E6%A8%A1%E5%BC%8F" class="hash-link" aria-label="过于复杂的专业模式和不够复杂的默认模式的直接链接" title="过于复杂的专业模式和不够复杂的默认模式的直接链接" translate="no">​</a></h3>
<p>因为 JPEG 的后期空间确实不大，所以我一开始也尝试过使用专业模式拍摄，并储存 UltraRAW 图片。但是用过几次之后，我发现即使有摄影手柄，手机上实际可以使用的拨轮和拨杆数量还是太少了。而对于每个参数都需要精细调整的专业模式（基本等同于相机的 M 模式），在手机上操作的复杂度实在太高。</p>
<p>另外，我为了尝试 UltraRAW 也曾经把一张照片放到 Lightroom 里做了后期，结果发现自己后期的效果和当时直拍的徕卡影调几乎一模一样——可以说是我现在的后期技术还不错，和徕卡影调的效果不相上下；反过来也可以说徕卡影调和我的思路很一致，基本上就可以直接拿来用了。</p>
<p>所以后来我也开始放弃抵抗，直接使用默认模式拍照，除了 EV 以外基本什么都不调整，结果反而拍得更舒服了。有很多没有思考时间的抓拍场景都能拍下不错的照片，同时也能将更多的精力专注在如何构图上。同时，专业模式没有办法自动附加水印，可能也是我不想使用它的原因之一。</p>
<p>下面就是一张我在公交车上使用默认模式抓拍到的照片。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="一张抓拍的照片" src="https://sqybi.com/assets/images/candid_photograph-5d9dfea3d04cbddba93abffeca1af9d1.jpg" width="1080" height="1606" data-zoomable="" class="img_ev3q"><div class="img-caption">一张抓拍的照片</div></div><p></p>
<p>当然反过来说，只需要调整 EV，也就意味着 EV 调整才是拍摄中的重中之重。你要根据照片希望体现的影调和照片中的高光与暗部表现，来决定提升或降低几档 EV。但毕竟需要调整地只有一个参数，所以已经是很容易上手的了。</p>
<p>此外，我还是希望小米可以在后续的固件迭代中，将直方图和斑马纹下放到默认模式。毕竟在手机屏幕上顶着大太阳看过曝和曝光不足的地方，有时候还是过于困难了一些。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="徕卡影调的暗部问题">徕卡影调的暗部问题<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E5%BE%95%E5%8D%A1%E5%BD%B1%E8%B0%83%E7%9A%84%E6%9A%97%E9%83%A8%E9%97%AE%E9%A2%98" class="hash-link" aria-label="徕卡影调的暗部问题的直接链接" title="徕卡影调的暗部问题的直接链接" translate="no">​</a></h3>
<p>徕卡影调的调色方案，在我看来是在拉高对比度，压低高光且压低大部分颜色饱和度的同时，保留了红橙色调的饱和度。</p>
<p>这自然不是完美的，比如在一些光比很大的场景中，暗部经常会过黑。虽然导入到电脑上放大后发现真正黑成一坨的情况并不多见，但在手机屏幕上有的时候看起来还是很难受的。此外，有一些场景下高光部分恰好是红色的话，会导致对比度进一步拉大，从而暗部可能真的会过暗。</p>
<p>当然，如果是大逆光的话，也一样会出现类似的情况。不过本来逆光拍摄又想保留暗部就是不太正确的做法，更多情况下使用相机拍摄也一样要堆栈，放到手机上主体面积比较小的话很难触发 HDR，这里就不展开说了。</p>
<p>一个红色高光导致暗部过暗的例子可以见下面这张照片。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="红色高光导致暗部过暗" src="https://sqybi.com/assets/images/red_highlight-ce39940f86a710d76e045574cfaa691f.jpg" width="1080" height="1607" data-zoomable="" class="img_ev3q"><div class="img-caption">红色高光导致暗部过暗</div></div><p></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="主摄不如长焦畸变和光圈的分析">主摄不如长焦？畸变和光圈的分析<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E4%B8%BB%E6%91%84%E4%B8%8D%E5%A6%82%E9%95%BF%E7%84%A6%E7%95%B8%E5%8F%98%E5%92%8C%E5%85%89%E5%9C%88%E7%9A%84%E5%88%86%E6%9E%90" class="hash-link" aria-label="主摄不如长焦？畸变和光圈的分析的直接链接" title="主摄不如长焦？畸变和光圈的分析的直接链接" translate="no">​</a></h3>
<p>在这两周的拍摄过程之中，我还可以发现一个趋势：1x 主摄使用越来越少，3.2x 长焦使用越来越多。主摄裁切的 2x 和 5x 的长焦通常会作为补充，而 0.5x 的广角几乎没有使用过。</p>
<p>这个焦段的使用结果自然有我自己拍摄习惯的问题，比如我用 24-70 的镜头时大部分时间也是锁在 70mm 端的，偶尔用一用 35mm，24mm 也不太常用。但是在使用上，我觉得这次 1 英寸大底的主摄和 0.5x 广角镜头是存在一定问题的。</p>
<p>首先，即使是主摄镜头，畸变也过于严重。而 0.5x 广角镜头的畸变更是惨不忍睹，我甚至找了半天都没能找到一个样张。我不确定是不是受限于硬件大小，所有手机的广角头都是这样，但实际上这确实让它的可用性大打折扣。</p>
<p>其次，因为这次 3.2x 镜头的光圈给的足够大，IMX858 的性能也足够好，或许还有这次整体影调偏低调的缘故，这一切都导致夜景的拍摄中大底主摄不是必需品。很多时候只要光线没有暗到一定程度，3.2x 镜头的拍摄效果一样很好，例如下面的这张照片。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="3.2x 镜头的暗光效果" src="https://sqybi.com/assets/images/75mm_at_night-6346da34b67dc6720391b6fb4cfb6dd8.jpg" width="1080" height="1606" data-zoomable="" class="img_ev3q"><div class="img-caption">3.2x 镜头的暗光效果</div></div><p></p>
<p>作为一个对比，5x 镜头就远没有那么优秀。例如下面这张照片的自动快门速度就来到了 1/8s，从而导致整张照片都拍糊了。如果 3.2x 镜头也是这个进光量，恐怕夜景就只能靠主摄了，这个长焦大光圈可能也是 14 Ultra 相比 14 为数不多的显著优势吧。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="5x 镜头的暗光效果" src="https://sqybi.com/assets/images/120mm_at_night-c53aa970f3fa8d2b1a090a4dc6b77031.jpg" width="1080" height="1606" data-zoomable="" class="img_ev3q"><div class="img-caption">5x 镜头的暗光效果</div></div><p></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="过慢的快门速度">过慢的快门速度<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E8%BF%87%E6%85%A2%E7%9A%84%E5%BF%AB%E9%97%A8%E9%80%9F%E5%BA%A6" class="hash-link" aria-label="过慢的快门速度的直接链接" title="过慢的快门速度的直接链接" translate="no">​</a></h3>
<p>再回到上面这张照片。仔细看一下水印中的参数就会发现，这张照片暴露了小米 14 Ultra 反复出现的一个问题：不知道是不是因为高感的效果实在不好，当感光度来到 1000 左右的时候，手机的算法宁可拉长曝光时间，也不愿意再提高一些感光度。</p>
<p>有过一定经验的拍摄者都知道，在手持的情况下，与其为了减少噪点降低 ISO 延长快门速度，还不如降低快门速度到安全范围内，然后拉高 ISO。毕竟无论什么时候，拍到都比拍好更重要，而一张糊了的图片是完全不能用的，也就等同于没有拍到。（如果你不知道，可以关注我的<a class="" href="https://sqybi.com/blog/tags/from-taking-pictures-to-photography/">从拍照到摄影</a>系列文章。现在还在连载中，后面会提到这些知识点的。）</p>
<p>如果以后有机会，我可能会开专业模式尝试一下暗光下高感的效果，看看这只是相机参数策略的失误，还是真的有其必然原因。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="其它细节使用体验">其它细节使用体验<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E5%85%B6%E5%AE%83%E7%BB%86%E8%8A%82%E4%BD%BF%E7%94%A8%E4%BD%93%E9%AA%8C" class="hash-link" aria-label="其它细节使用体验的直接链接" title="其它细节使用体验的直接链接" translate="no">​</a></h2>
<p>除了上述摄影方面的体验之外，我也尝试记录了这段时间的一些其它使用体验。</p>
<p>其中某些众所周知的问题，例如防抖系统的晃动噪声问题已经在上文中提过了，这里就不再赘述。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="摔狠狠地摔">摔！狠狠地摔！<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E6%91%94%E7%8B%A0%E7%8B%A0%E5%9C%B0%E6%91%94" class="hash-link" aria-label="摔！狠狠地摔！的直接链接" title="摔！狠狠地摔！的直接链接" translate="no">​</a></h3>
<p>手机在旅行中总是免不了一些磕磕碰碰。无论是因为放进口袋的时候放歪了，还是抬手的时候碰到了旁边的人，总之我的手机在这两周的旅程中从差不多胸部到腰部的高度跌落了三四次。</p>
<p>不过就像大部分跌落测试中展现的那样（而且我的手机并不是裸奔，还有手机壳和原厂膜的保护），无论是屏幕还是镜头，在这几次跌落中都没有任何的损伤。想起当时被我随随便便摔碎屏幕的小米 10 系列，只能说曲面屏除了帅以外没有任何优势，微曲才是正解啊！</p>
<p>可惜的是，这几次跌落导致我的原厂屏幕膜有一些挫伤和气泡，同时原厂的透明手机壳也产生了一点裂纹。这几天可能就要换新的贴膜和手机壳了，但是我并没有接到广告 :P</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="品控又是品控">品控，又是品控<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E5%93%81%E6%8E%A7%E5%8F%88%E6%98%AF%E5%93%81%E6%8E%A7" class="hash-link" aria-label="品控，又是品控的直接链接" title="品控，又是品控的直接链接" translate="no">​</a></h3>
<p>除了手柄之外，手机上我也遇到了一点疑似品控问题的小问题。</p>
<p>这次小米 14 Ultra 的音量和电源按键手感是相当不错的，按下的时候有非常明显“咔哒”的段落感。</p>
<p>但是在我来到日本的第二天，我的电源按钮按下时突然变成了很肉的手感，这时我甚至还没有摔过这台手机。</p>
<p>上一次遇到类似的问题是在飞智的黑武士 3 手柄上，这款手柄的 START 按键也出现了失去段落感的问题。我怀疑可能是内部的硅胶从某个特殊的角度卡住了，但是也并不知道怎么解决。</p>
<p>幸运的是，在即将离开日本的时候，这台手机的电源按钮突然自己恢复正常了。虽然后续还是会非常偶然地出现一些奇怪的手感变化，比如能感觉到按下的时候有一个左右的位移，不过也算是基本可用了。不然这种小问题，真是让人觉得送修不值得，不修恶心人，令人进退不得。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="照片后期编辑的问题">照片后期编辑的问题<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E7%85%A7%E7%89%87%E5%90%8E%E6%9C%9F%E7%BC%96%E8%BE%91%E7%9A%84%E9%97%AE%E9%A2%98" class="hash-link" aria-label="照片后期编辑的问题的直接链接" title="照片后期编辑的问题的直接链接" translate="no">​</a></h3>
<p>因为我现在的拍照基本都是使用普通模式的 JPEG 直出，所以导入到 Lightroom 做后期就显得不是那么必要了。同时小米的相册 app 也提供了足够好的编辑功能，基本上可以满足绝大部分后期编辑的需求。</p>
<p>只不过在使用的过程中，我还是遇到了一些软件交互设计上不太舒服的地方。</p>
<p>首当其冲的问题是，对于一张照片，在进行了一次编辑后，会以编辑时间作为文件名保存一个新文件。虽然相册中似乎是按照拍摄时间排序的，所以依旧会看到编辑后的照片和拍摄时的照片排列在一起，但拷贝到 NAS 或者电脑硬盘之后，就很难根据文件名区分哪张照片是由哪张照片编辑得到的了。而且编辑后的照片并不会有特殊的文件名，看起来就像直接拍摄的照片一样，这真的很诡异。</p>
<p>其次也是一个编辑后保存的问题。通常在编辑一张直接拍摄的<strong>带水印的</strong>照片时，小米的相册 app 会自动移除水印部分，把照片本身展示在界面中编辑，并在编辑后根据设置重新加上水印。可此时如果希望再次编辑这张带水印的<strong>编辑后的</strong>照片，就会发现水印也成为了照片的一部分被编辑，所有裁剪、调整亮度、调整颜色的功能，也都会作用在水印上。此时，就只能手动裁剪掉水印部分，或者重新编辑原始照片来解决，但无论那种方法都很麻烦。</p>
<p>再接下来还是一个水印相关的问题。简单来说，拍摄时生成的水印与二次编辑后的水印，字体和间距是不完全一致的。我也不知道怎么解释这个问题……</p>
<p>最后，我还比较偶然地遇到了几次定位不准确的问题。我在京都、神户等地区拍摄的一系列照片中，竟然混入了几张定位是东京的照片——然而我的这次旅行目的地是日本关西，根本就没有去过东京。</p>
<p>这些大大小小的问题看似都不那么关键，我也不确定小米什么时候能在系统更新中修复它们。希望有朝一日这些问题真的能被解决吧。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="其它杂七杂八的体验">其它杂七杂八的体验<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E5%85%B6%E5%AE%83%E6%9D%82%E4%B8%83%E6%9D%82%E5%85%AB%E7%9A%84%E4%BD%93%E9%AA%8C" class="hash-link" aria-label="其它杂七杂八的体验的直接链接" title="其它杂七杂八的体验的直接链接" translate="no">​</a></h2>
<p>除了上述摄影相关的体验以外，还有一些不知道该归到什么类别中，和摄影没有直接关系的体验，就统一写到文章的最后吧。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="无线充电支架">无线充电支架<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#%E6%97%A0%E7%BA%BF%E5%85%85%E7%94%B5%E6%94%AF%E6%9E%B6" class="hash-link" aria-label="无线充电支架的直接链接" title="无线充电支架的直接链接" translate="no">​</a></h3>
<p>我是在小米之家线下购买这台手机的，所以拿到了一张几百元的优惠券，可以用于购买店内任何小米产品。</p>
<p>思考了一下之后，我决定购买了和手机同时上市的新款无线快充支架。</p>
<p>不得不说，这款支架还是给了我一些惊喜的。我一直以来都有在电脑上使用 <a href="https://github.com/beancount/beancount" target="_blank" rel="noopener noreferrer" class="">Beancount</a> 记账的习惯，之前我都是用 MIUI+ 投屏到电脑上对账的。但是偶尔的高延迟加上很多场景无法呼出输入法，以及一些需要指纹识别和禁止投屏的场景（财务相关的软件尤其多），还是会带来很多不便，让我不得不频繁抓起手机。</p>
<p>但是有了这款支架以后，配合新系统的眼部追踪功能，几乎可以在我记账的过程中全程维持只要我看向手机，手机屏幕就会自动点亮。同时，支架的角度也很适合不取下的情况下输入一些简单的文字，或者进行一些简单的点击和翻页操作。</p>
<p>不过考虑到场景受限，以及这款无线充电支架本身的价格，我并不推荐任何人在没有需求和没有优惠的情况下购买它。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="miui">MIUI+<a href="https://sqybi.com/blog/xiaomi-14-ultra-photography-experience-summary/#miui" class="hash-link" aria-label="MIUI+的直接链接" title="MIUI+的直接链接" translate="no">​</a></h3>
<p>前面既然提到了 MIUI+，也顺便提一下小米 14 Ultra 在 MIUI+ 上的体验。</p>
<p>小米迟迟不肯将 MIUI+ 开放给小米笔记本外的 PC 系统，一直是受人诟病的一个问题。好在还是有一些方法搞到 MIUI+ 安装包的，所以我也一直用着它的投屏功能。</p>
<p>但是从 12 Pro 更换为 14 Ultra 之后，之前的 MIUI+ 突然就不能使用了，连接时手机上会提示“当前电脑应用版本过低”。这个情况一直持续到我去日本旅游，我也是对它毫无办法。</p>
<p>好在旅游回来之后，我打开电脑就发现 MIUI+ 应用内推送了新版本更新。升级了新版本之后，虽然扫码连接的时候还是会有上述报错，但手机上是可以成功弹出连接提示的，且确认连接之后所有的功能都能够正常使用。</p>
<p>唯一还存在的问题是，如果从电脑端 MIUI+ 上选择在线的手机主动连接，手机上无法正常弹出提示。也就是说，每次连接都需要使用手机重新扫描电脑上的二维码才可以。但是这都是小问题了，能用比什么都好。</p>
<p>希望有朝一日，小米可以把这个好用的多端互联功能公开出来，下放到所有品牌的 Windows PC 上吧。</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 摄影</category>
        </item>
        <item>
            <title><![CDATA[索尼相机的终极伴侣：Monitor+]]></title>
            <link>https://sqybi.com/blog/ultimate-companion-for-sony-cameras-monitor-plus/</link>
            <guid>https://sqybi.com/blog/ultimate-companion-for-sony-cameras-monitor-plus/</guid>
            <pubDate>Thu, 07 Mar 2024 23:59:00 GMT</pubDate>
            <description><![CDATA[这，是用来连接索尼相机的软件。]]></description>
            <content:encoded><![CDATA[<p>这，是用来连接索尼相机的软件。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="Creators&amp;#39; App" src="data:image/png;base64,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" width="100" height="100" data-zoomable="" class="img_ev3q"><div class="img-caption">Creators&amp;#39; App</div></div><p></p>
<p>这，也是用来连接索尼相机的软件。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="Imaging Edge Mobile" src="data:image/png;base64,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" width="100" height="100" data-zoomable="" class="img_ev3q"><div class="img-caption">Imaging Edge Mobile</div></div><p></p>
<p>这，还是用来连接索尼相机的软件。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="Play Memories Home" src="data:image/png;base64,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n6VmWarf1vKk0cXQe2YZvf1aL180oqjRpKEmNL+lFwh/kRhl+Lxrvj+gYfh0Hq+kpMQrOgbf/e533377bRwSVgwzwcbtt9+O93ePMlkxavfeey8XcUvS+O1vf8uhCy+80Nt3ekj+4x//IEVAL72iw0DG4O5rr73W0tLiFWWgV69eDz744ObNm1euXLlmzRqa8eUvfzmTXrNmzeJeX/rSl+bMmYObJDDxuXHjxptvvpmx/9znPuc2ntM3bNhw//33H0uv6dOn/+tf/+KoW3PdunXIOU31DitK586dX3zxxX/+859cDVnlFg8//DD9gLtitvz3v/+F917VVOi//vrrqcOluCAd+Ic//IEp4R1OYfjw4Uxs7kirqLlly5Zf//rXnKgNyck3CgsdPjlCZae+B7SlRU4XdfK+o1cyiYAiFKBQVVO+ymFVVEGuzFaZbLYj9TLcrBimaliqz1SzhJKja3mG3tWvFPuSAdNXbBlFwigWerGid1UG+9t+ofTewFMwY9hobm52S47FgAEDGhoa/vjHP/74xz/GUNN9v/jFL+655x736KZNmxj1q666CslxS1z06dMHL8XF6VOvKIV33nmnrKxs2rRpbYaW6MwnI3fsvIdwL7/88oIFC7gXt37ssccY7wceeODb3/427XfrMOojR4784he/+Jvf/Gb79u333Xffc889RyL8q1/9itEiV0As2XjkkUeQljvuuOPnP/95JmmYHn/9618nT578yiuv/OQnP3niiSfQj4ceeoi5gVq7dZAfBO/cc8+lMBAI/PKXvyTVwGBRAclB5zJF7oc//OHvf/97LgKfaAyz8Qtf+MJf/vKXdC/169ePFsJRSEmmwjXpKK9JX+7R16wqE8Fmh0zJhIzHRCRkB1tEa7MdaLCb6uymWmejud7ZbqwRzXWipdYKHLQad5v1m6zaleahfyVLn0rufqD1lVvrfja57ifj6u4bWX//8PoHRjU8PLrx8TGNT40r/f7QrZf22fbZPtsn99o5qffuab33Xtj3z/0cNpw6CgsLw+FwPI69Owpjx46tqqrCJYwZM4ZdJh/zHhpBJrcCoHeys7PdbWRp2LBhxNC6ujp3/tEXf/vb32zbJg9w67i46aabiLYMvzv2NADGwAyGAWbEYrGLLrrIrQmIxXv37t22bRsh484776QmougdUxTyVpR13rx5br/TBqjG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" width="200" height="46" data-zoomable="" class="img_ev3q"><div class="img-caption">Play Memories Home</div></div><p></p>
<p>索尼在历史上推出过很多不同版本的应用和软件，甚至不同的软件可能只能适配不同的相机。例如我手里的 A7M4 和 α6000，就需要分别使用不同的 app 和手机连接，想用 Imaging Edge 连接 A7M4 是行不通的。</p>
<p>而即便有这么多看起来为每款相机“量身定做”的软件，在使用的过程中还是会遇到各种各样的问题。断连和速度慢都是小事，即便是 2021 年发售的 A7M4，甚至都会出现相机和手机 app 连接必须经过第三方 WiFi 的设计。</p>
<p>而相机本身是没有浏览器界面的，这导致如果你的 WiFi 需要额外的网页登陆验证（很多酒店 WiFi 都是这样的），那么你就失去了把相机上照片传到手机上的机会……吗？并不是！</p>
<p>今天要介绍的就是这样一款 app：<a href="https://monitorplus.cc/" target="_blank" rel="noopener noreferrer" class="">Monitor+</a>。它不光可以解决上面这个棘手的问题，甚至可以把你的手机转换为一块实时监视屏和远程快门线，我的很多延时摄影照片（例如<a href="https://flickr.com/photos/sqybi/53275915787/in/album-72177720315126633/" target="_blank" rel="noopener noreferrer" class="">这张</a>）都是用这款 app 拍摄的。</p>
<p>这款 app 也不仅仅支持索尼的相机，大部分主流品牌的相机都可以与它连接。而图片传输和基础的远程监看、快门触发功能，全都是免费的！</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="相片传输功能">相片传输功能<a href="https://sqybi.com/blog/ultimate-companion-for-sony-cameras-monitor-plus/#%E7%9B%B8%E7%89%87%E4%BC%A0%E8%BE%93%E5%8A%9F%E8%83%BD" class="hash-link" aria-label="相片传输功能的直接链接" title="相片传输功能的直接链接" translate="no">​</a></h2>
<p>出门在外，自然希望除了拍摄一些好照片以外，也能快速挑选出一部分在手机和 pad 上简单修图之后，发一个美美的朋友圈。</p>
<p>但如果你使用的是索尼相机，就会遇到上述无法连接酒店 WiFi 问题。总不能为了传几张照片，就换一个酒店吧？</p>
<p>如果你恰好有另一个手机或者一个同行的朋友，或许开一个手机热点是解决方案之一。但事实上，索尼相机本身的硬件设计上并不是不能直接和手机通讯。其实，它们之间甚至可以使用 5G 频段的高速 WiFi 通讯。</p>
<p>这时，如果你安装了 Monitor+ 这款 app，并按照指引连接到你的相机（只需要在相机上打开 WiFi），就可以打开一个选择照片的页面，并筛选一些照片传输到手机上。</p>
<p>对，就是这么简单。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="实时监看和拍摄功能">实时监看和拍摄功能<a href="https://sqybi.com/blog/ultimate-companion-for-sony-cameras-monitor-plus/#%E5%AE%9E%E6%97%B6%E7%9B%91%E7%9C%8B%E5%92%8C%E6%8B%8D%E6%91%84%E5%8A%9F%E8%83%BD" class="hash-link" aria-label="实时监看和拍摄功能的直接链接" title="实时监看和拍摄功能的直接链接" translate="no">​</a></h2>
<p>除了照片传输以外，实时监看和远程拍摄也是这款 app 很重要的功能。</p>
<p>对于免费版，基础的监看和远程快门功能都是可用的。除此之外，app 还开放了部分参数的调整功能给免费版，甚至连直方图功能也是免费版包括的，在通常的情况下也相当够用。</p>
<p>简单来说，只要你在拍摄的时候不需要离开你的相机，那么免费版完全可以满足全部拍摄需求，帮你剩下一条快门线的钱：大不了就回相机上调整嘛。</p>
<p>可能唯一要注意的是，为了保证实时监看的低延迟，需要确保手机是通过 5G 频段的 WiFi 连接到相机的——只要在相机上打开对应开关就可以了，app 中有对应的操作提示。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="其他收费功能">其他收费功能<a href="https://sqybi.com/blog/ultimate-companion-for-sony-cameras-monitor-plus/#%E5%85%B6%E4%BB%96%E6%94%B6%E8%B4%B9%E5%8A%9F%E8%83%BD" class="hash-link" aria-label="其他收费功能的直接链接" title="其他收费功能的直接链接" translate="no">​</a></h2>
<p>除了基础的免费功能以外，如果你愿意付费，那么软件也提供了大量好用的功能，包括但不限于：</p>
<ul>
<li class="">触摸选择焦点</li>
<li class="">RGB 直方图</li>
<li class="">峰值对焦</li>
<li class="">斑马线</li>
<li class="">套用 LUT</li>
</ul>
<p>还有一些功能例如“跟焦”“翻转”“遮罩”，我也不确定软件是怎么实现的，这里就不多介绍了。</p>
<p>什么外接屏幕，什么图传，在业余场景下统统不需要了。</p>
<p>我现在最后悔的事情，可能就是当初买了一块冷靴安装的外置屏幕，结果到现在一次都没有用过了吧。</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 摄影</category>
            <category>内容 | 软件推荐</category>
        </item>
        <item>
            <title><![CDATA[解决 Openwrt 上 HomeProxy 插件不支持 Hysteria2 Port Hopping 的问题]]></title>
            <link>https://sqybi.com/blog/solving-the-issue-openwrt-homeproxy-hysteria2-port-hopping/</link>
            <guid>https://sqybi.com/blog/solving-the-issue-openwrt-homeproxy-hysteria2-port-hopping/</guid>
            <pubDate>Tue, 05 Mar 2024 21:00:00 GMT</pubDate>
            <description><![CDATA[随手记录一些比较短的问题解决方案：]]></description>
            <content:encoded><![CDATA[<p>随手记录一些比较短的问题解决方案：</p>
<p>Openwrt 上 HomeProxy 的 sing-box 不支持 Hysteria2 port hopping？不如自己来 hop 吧！</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="背景">背景<a href="https://sqybi.com/blog/solving-the-issue-openwrt-homeproxy-hysteria2-port-hopping/#%E8%83%8C%E6%99%AF" class="hash-link" aria-label="背景的直接链接" title="背景的直接链接" translate="no">​</a></h2>
<p>Hysteria2 是一种基于 UDP 的代理方案。</p>
<p>因为国内运营商大多对 UDP 的流量进行了管控（UDP QoS），所以如果长期连接某个特定的端口发送大量 UDP 包，很容易导致后续到这个端口的 UDP 包都会被运营商直接丢弃。</p>
<p>Hysteria 的客户端自带了 port hopping 功能，即可以输入一个或多个端口段，由客户端自行在一定时间之后重新连接一个新的端口。</p>
<p>但我在使用的 OpenWrt (ImmortalWrt) 中 HomeProxy 插件是基于 sing-box 的，可惜的是 sing-box 并没有支持 Hysteria2 协议的 port hopping 特性，且根据 issues 中的讨论，今后也没有支持的打算。</p>
<p>我们只好自己动手丰衣足食，写一段自动更换端口的脚本。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="服务端配置">服务端配置<a href="https://sqybi.com/blog/solving-the-issue-openwrt-homeproxy-hysteria2-port-hopping/#%E6%9C%8D%E5%8A%A1%E7%AB%AF%E9%85%8D%E7%BD%AE" class="hash-link" aria-label="服务端配置的直接链接" title="服务端配置的直接链接" translate="no">​</a></h2>
<p>根据 <a href="https://v2.hysteria.network/docs/advanced/Port-Hopping/#server" target="_blank" rel="noopener noreferrer" class="">Hysteria2 官方文档</a> 中的说明，即使是官方服务端也是不支持配置多端口监听的。这是因为 <code>iptables</code> / <code>nftables</code> 可以简单地通过配置 DNAT 完成同样的功能。</p>
<p>其中<code>iptables</code> 配置如下，如果你的服务端系统已经升级到了 <code>nftables</code> 也可以自行查阅上述文档中的配置方法：</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">iptables -t nat -A PREROUTING -i eth0 -p udp --dport 20000:29999 -j DNAT --to-destination :443</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ip6tables -t nat -A PREROUTING -i eth0 -p udp --dport 20000:29999 -j DNAT --to-destination :443</span><br></span></code></pre></div></div>
<p>这里的 <code>20000</code> - <code>29999</code> 是 port hopping 功能监听的端口段，后续客户端配置需要对应这一段端口号；<code>443</code> 是 Hysteria2 自身监听的端口。</p>
<p>同时，需要注意 <code>iptables</code> 的配置会在重启后失效，可以使用 <code>netfilter-persistent</code> 来持久化配置。</p>
<p>首先安装 <code>netfilter-persistent</code>：</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">apt install iptables-persistent</span><br></span></code></pre></div></div>
<p>理论上如果在安装之前你已经完成了 <code>iptables</code> 配置，那么对应的配置文件就已经被持久化且保存在 <code>/etc/iptables/rules.v4</code> 和 <code>/etc/iptables/rules.v6</code> 中了。</p>
<p>如果没有也没关系，可以执行 <code>iptables-save &gt; /etc/iptables/rules.v4</code> 和 <code>iptables-save &gt; /etc/iptables/rules.v6</code> 手动保存。每次重启的时候，<code>systemctl</code> 的服务 <code>netfilter-persistent.service</code> 都会自动加载这些配置。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="客户端配置">客户端配置<a href="https://sqybi.com/blog/solving-the-issue-openwrt-homeproxy-hysteria2-port-hopping/#%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%85%8D%E7%BD%AE" class="hash-link" aria-label="客户端配置的直接链接" title="客户端配置的直接链接" translate="no">​</a></h2>
<p>客户端则要麻烦一些，推荐使用下列脚本自动执行端口更换操作，模仿 port hopping 的效果。</p>
<p>脚本的开始首先配置了对应服务器配置的端口信息，其中 <code>PORT_STARTING</code> 为起始端口，<code>PORT_RANGE</code> 为端口段的长度。</p>
<p>接下来会尝试最多五次通过 <code>curl google.com</code> 检查网络可达性，注意 HomeProxy 是没有代理 ICMP 协议的，所以这里不要使用 <code>ping</code>，否则可能会失败。</p>
<p>如果五次中有任何一次成功，则意味着端口依然可用，直接退出脚本；如果五次全部失败，则认为端口已经不可用，需要更换端口。</p>
<p>更换端口的方式则是通过 <code>uci</code> 直接修改 OpenWrt 前端 Luci 的配置，同时在修改后适时地重启 <code>homeproxy</code> 服务。</p>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>更新提醒：2024-03-13</div><div class="admonitionContent_BuS1"><p>因为之前的脚本在 OpenWrt 的 sh 中执行，会导致部分语法不支持，所以我更新了脚本内容。</p><p>新的脚本通过测试已经确认可以成功执行。</p></div></div>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">#!/usr/bin/env sh</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">PORT_STARTING=20000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">PORT_RANGE=10000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">MAX_FAILURE_ATTEMPTS_BEFORE_HOPPING=5</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">CURL_TIMEOUT_IN_SECONDS=3</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NETWORK_TEST_URL=http://www.google.com/generate_204</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">LOG_FILE=/var/log/hopping.log</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NODE_NAME=my_hysteria_node</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">failure_count=0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">for i in $(seq 1 ${MAX_FAILURE_ATTEMPTS_BEFORE_HOPPING}); do</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    curl -m ${CURL_TIMEOUT_IN_SECONDS} ${NETWORK_TEST_URL} &amp;&gt; /dev/null</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    if [ $? -eq 0 ]; then</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        echo "Network check successful."</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        break</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    else</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        let failure_count=${failure_count}+1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        echo "Network check failed. Total failures: ${failure_count}"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    fi</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    sleep 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">done</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">if [ "${failure_count}" -ge ${MAX_FAILURE_ATTEMPTS_BEFORE_HOPPING} ]; then</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    new_port=$((RANDOM % ${PORT_RANGE} + ${PORT_STARTING}))</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    echo `date "+%Y-%m-%d %H:%M:%S"` &gt;&gt;${LOG_FILE}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    echo "${failure_count} consecutive ping failures. Try hopping to port ${new_port}." &gt;&gt;${LOG_FILE}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    uci set homeproxy.config.main_node=nil</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    uci commit homeproxy</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    /etc/init.d/homeproxy restart</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    sleep 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    uci set homeproxy.${NODE_NAME}.port=${new_port}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    uci set homeproxy.config.main_node=${NODE_NAME}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    uci commit homeproxy</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    /etc/init.d/homeproxy restart</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    echo "Switched to port ${new_port}" &gt;&gt;${LOG_FILE}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    echo "" &gt;&gt;${LOG_FILE}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">else</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    echo "Network is OK. Total failures: ${failure_count}"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">fi</span><br></span></code></pre></div></div>
<p>这里之所以要先检查网络可用性，是因为这个更换端口服务等于重新启动 HomeProxy 和 sing-box，这意味着它不像 Hysteria 官方客户端实现的 port hopping 一样可以保持连接不断开，而是要断开所有网络连接并重连。如果过于频繁地执行这个操作，反而可能导致网络特别是长连接的不稳定。</p>
<p>这里的网络检查是为了能够只在网络已经断开的情况下通过换端口的方式恢复，当然你也可以修改这部分脚本来执行你自己的检查策略。</p>
<p>最后，将上面的脚本存入文件，例如 <code>/root/port_hopping.sh</code>，并添加可执行权限：</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">chmod +x /root/port_hopping.sh</span><br></span></code></pre></div></div>
<p>然后通过 crontab 定期执行：</p>
<div class="language-crontab codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-crontab codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">* * * * * /root/port_hopping.sh</span><br></span></code></pre></div></div>
<p>大功告成！</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 计算机技术</category>
        </item>
        <item>
            <title><![CDATA[成为优秀的程序员（01）：理解“不理解”]]></title>
            <link>https://sqybi.com/blog/becoming-an-brilliant-programmer-01/</link>
            <guid>https://sqybi.com/blog/becoming-an-brilliant-programmer-01/</guid>
            <pubDate>Mon, 04 Mar 2024 23:00:00 GMT</pubDate>
            <description><![CDATA[如果需要查看系列中的其它文章，请使用 tag 跳转到文章目录界面：#becoming-an-brilliant-programmer。]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>如果需要查看系列中的其它文章，请使用 tag 跳转到文章目录界面：<a class="" href="https://sqybi.com/blog/tags/becoming-an-brilliant-programmer/">#becoming-an-brilliant-programmer</a>。</p>
</blockquote>
<p>没错，我又要开新的坑了。</p>
<p>想想从 2013 年前开始工作，到现在已经有 11 个年头，年假也终于到了 10 天，可喜可贺可喜可贺。</p>
<p>这 11 个年头里，自己算是踩了不少坑。回想起当年，经常会遇到各种迷茫的时刻：为什么我做不好？我到底是强还是弱？所谓的“职业发展规划”到底是什么？等等诸如此类的问题随着各种各样在象牙塔中未曾想象过的变化一起，接踵而至。</p>
<p>而当我试图去模仿那些“成功”的人时，我会发现他们的所谓成功经历根本无法套用在自己身上，从而陷入越来越深的自我怀疑：是不是我自己真的太菜了，所以才不能像他们一样？</p>
<p>直至今日，我依旧觉得这些“成功”是无法复制的。值得欣慰的是，在我自己越来越少地被称作“小朋友”的同时，我也看到小朋友们对这一点的理解越来越深。</p>
<p>同样，我也不认为我的这一系列文章真的能帮助所有人成为优秀的程序员，这只不过是一个噱头罢了。或者再进一步，我这种没人看的博客甚至也不需要什么噱头，这只是因为文章必须要有一个标题，所以我就起了一个标题而已。这些内容与其说是一种指引，不如说是单纯的感悟。如果你也同意一个人的自我是由他过去的所有人生经历所构成的，那么你应该很容易理解这一点。</p>
<p>之所以最终还是起了这样一个标题，其中包含了一些我自己的私心。在我最迷茫的时候，多次幻想着能够有一个人告诉我他在面临类似的情况时是怎么做的。而每次突破了人生的一个难关以后，也都多多少少会有“原来事情不像我想象的那么难，如果当初能有人提点我一下就好了”的想法。</p>
<p>好在这种事情发生得越多，我就越能体会到这样的机遇是多么可遇而不可求。我也看到有很多真的高尚的人，会用自己的时间和金钱去了解和帮助一个群体，例如我的学弟 icedream61（他的 Bilibili 空间：<a href="https://space.bilibili.com/269924695" target="_blank" rel="noopener noreferrer" class="">冰梦</a>）。他就是用了几年的时间了解和调研一些二三本和专科学生的实际情况，希望能够借此帮助他们理解导致他们没有成为所谓的“好学生”或找到所谓“好工作”的社会性原因，从而走出结构性失业的困境。比起我闲暇时间写写博客，这才是真正的引路人。但即使如此，可以看到他的这些工作也并不会覆盖好比十年前的我这样的群体，而像他这样的人也少之又少。是的，<strong>可遇而不可求</strong>。</p>
<p>所以我想，就算我并没有这么高尚的理想，也没有这种坚持下去的韧性，但至少分享自己的知识和认知总是一个好事。特别是对于我们跟着互联网一起成长起来的这一代人，更是从小的时候就打下了这样的烙印。</p>
<p>简而言之，因为这一系列的经历，我会将一些想聊的事情拆成若干不是很长的文章发出来。现在这个系列是和程序员这个职业这份工作相关的，不过会探讨到很多对人生的思考；后面应该也会聊到一些单纯和人生相关的内容，这部分或许会起名叫“成为优秀的人”吧。</p>
<p>那就让我们开始今天的闲聊吧。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="由不理解导致的崩溃">由不理解导致的崩溃<a href="https://sqybi.com/blog/becoming-an-brilliant-programmer-01/#%E7%94%B1%E4%B8%8D%E7%90%86%E8%A7%A3%E5%AF%BC%E8%87%B4%E7%9A%84%E5%B4%A9%E6%BA%83" class="hash-link" aria-label="由不理解导致的崩溃的直接链接" title="由不理解导致的崩溃的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="由不理解构成的世界">由不理解构成的世界<a href="https://sqybi.com/blog/becoming-an-brilliant-programmer-01/#%E7%94%B1%E4%B8%8D%E7%90%86%E8%A7%A3%E6%9E%84%E6%88%90%E7%9A%84%E4%B8%96%E7%95%8C" class="hash-link" aria-label="由不理解构成的世界的直接链接" title="由不理解构成的世界的直接链接" translate="no">​</a></h3>
<p>我认为直到今天，我依旧是一个不容易理解其他人类的人。我很羡慕那些很容易共情的人，而且一直很好奇他们是怎么做到的——甚至有些执拗的认为他们可能也并不能理解他人，仅仅是表现得这样罢了。</p>
<p>而不幸的是，这个世界就是由千千万万像我一样的人类组成的。男人是这样，女人也是这样；大人是这样，孩子也是这样（或许好一些？）；PM 是这样，测试是这样，程序员更加是这样。</p>
<p>而这个世界，或者说得小一点，你能看到的任何涉及到人与人之间合作的事情，都是在这么一种混乱的底层运行逻辑下进行的。这也是《人月传说》中关于人月不成线性关系这一表象的深层原理：沟通成本不可忽略。而如果你进一步去思考这件事，会得到一个更恐怖的结论：当任何软件开发项目达到一定的级别后，它一定会崩溃。（当然不限于软件开发，不过这个文章只讨论到这一特定范围。）</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="好消息和坏消息">好消息和坏消息<a href="https://sqybi.com/blog/becoming-an-brilliant-programmer-01/#%E5%A5%BD%E6%B6%88%E6%81%AF%E5%92%8C%E5%9D%8F%E6%B6%88%E6%81%AF" class="hash-link" aria-label="好消息和坏消息的直接链接" title="好消息和坏消息的直接链接" translate="no">​</a></h3>
<p>好消息是，程序员（以及所有相关的职业，恕后文不一一列举）学会了通过抽象来隔离理解成本。</p>
<p>例如你使用 GCC 或 Clang 编译你的 C++ 代码时，并不需要真的理解它们的实现原理和底层设计——你只需要了解它们的接口就可以了。开发 GCC 的团队和你所在的用 C++ 写一些（至少看起来是）垃圾代码的团队，绝大部分情况下都没有任何交集。能参与到编译器开发，或者甚至给它们提过有效 issue 的人，可能都屈指可数，至少不会包括绝大部分平凡的程序员。</p>
<p>但基于抽象的方式，我们都可以使用这些世界上最优秀的工具，正常完成自己一亩三分地里的工作。</p>
<p>不幸的是，坏消息甚至更坏一些：可能现在的世界上没有人能知道，基于抽象的软件开发到底走到什么地步才会崩溃。</p>
<p>如果对前端开发了解的话可能会感受到，现在的前端开发领域已经先一步走在过度抽象的路上。各种基于抽象的框架层出不穷，但是同一个功能可能被几十上百个不同的框架实现；即使其中只有三四个是你听过的，可能也足够复杂了。加上各种新框架的迭代和旧框架的分支，框架的持续学习成本越来越不能为人们所接受。</p>
<p>而放眼到整个编程领域，这个趋势也依旧值得探讨。在人们讨论什么是优秀程序员的时候，他们通常期望这个真空中的球形程序员除了能够使用各类工具，也能够深入理解原理，而且是越深入越好——最好能从沙子怎么变成芯片上的逻辑门讲起。但随着计算机这几十年来突飞猛进的发展，以及基于抽象的这套理论，“术业有专攻”反而成为了大家的共识。</p>
<p>一方面清楚地知道进一步抽象会导致程序员们越来越少地理解其它抽象层，一方面又期望程序员们更多地理解其它抽象层——这就是今天软件行业的困境。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="或许也不是问题">或许也不是问题<a href="https://sqybi.com/blog/becoming-an-brilliant-programmer-01/#%E6%88%96%E8%AE%B8%E4%B9%9F%E4%B8%8D%E6%98%AF%E9%97%AE%E9%A2%98" class="hash-link" aria-label="或许也不是问题的直接链接" title="或许也不是问题的直接链接" translate="no">​</a></h3>
<p>困境？我觉得我需要立刻撤回我刚刚的话。因为事情可能并没有严重到这个程度，是我夸大其词了。</p>
<p>仔细想想，其实这个复杂化的过程在科学界更早就发生了。现在的科学领域远比单一的软件工程行业复杂成百上千倍，但同样是基于抽象和分工的做法依旧可行。科学家们只去了解和自己的领域紧密相关的知识，同时在一些通识上选择相信共识的观点，并跟随最新的研究成果不断更新与补充。</p>
<p>这么看来，软件行业似乎不会崩溃。好耶——</p>
<p>……也没那么好。这可能意味着你需要被迫理解这千疮百孔的现状，并试图去适应它们。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="稳定的自我认知">稳定的自我认知<a href="https://sqybi.com/blog/becoming-an-brilliant-programmer-01/#%E7%A8%B3%E5%AE%9A%E7%9A%84%E8%87%AA%E6%88%91%E8%AE%A4%E7%9F%A5" class="hash-link" aria-label="稳定的自我认知的直接链接" title="稳定的自我认知的直接链接" translate="no">​</a></h2>
<p>（宇宙级叠甲声明：基于某些信仰的原因，或许 TeX 除外；但以我的水平不足以理解它的完美，所以它也是不完美的。）</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="不要相信任何软件是完美的">不要相信任何软件是完美的<a href="https://sqybi.com/blog/becoming-an-brilliant-programmer-01/#%E4%B8%8D%E8%A6%81%E7%9B%B8%E4%BF%A1%E4%BB%BB%E4%BD%95%E8%BD%AF%E4%BB%B6%E6%98%AF%E5%AE%8C%E7%BE%8E%E7%9A%84" class="hash-link" aria-label="不要相信任何软件是完美的的直接链接" title="不要相信任何软件是完美的的直接链接" translate="no">​</a></h3>
<p>在早先的这些年，我从工作中学到的最重要一点就是：不要在不了解一个软件之前，就擅自认为它是完美的或高大上的。这其实涉及到了一个人对自己的了解和认知自我的稳定性，不知道经历了多少次同样的场景之后，我才慢慢明白了这条道理。</p>
<p>面对一个赫赫有名的软件、工具或者框架，需要基于它进行二次开发的时候，我总是不知道如何下手。我也许能够快速地梳理出一些基本的原理，但它们通常会简单到令我担心：大概是我的想法错了，由这个世界上最优秀的一批人（当然，就像四大天王有五个，通常“最优秀的一批人”也会有很多批）开发出的软件，怎么可能这么简单？</p>
<p>于是我就会开始陷入一种深深的焦虑情绪中，期望有人能站出来告诉我就是这样或者不是这样。但正如上面所说，通常这个人是不会出现的。而这种焦虑会进一步裹挟一个人，让他后面的动作变得畏首畏尾。</p>
<p>而我最终解决了这个问题，或者说部分解决了这个问题，其实是靠着对自我的了解越来越清晰达到的。当你经历过足够多的同样场景时，你就会慢慢锚定自己的位置。你会发现这些看似优秀的人其实写出的工具并不是哪里都很完美，他们自然有许多开创性甚至难以匹敌的工作，但从绝大部分角度来看，他们写的软件也不过是借用了前人的经验，很多地方和我们的想法是一致的。</p>
<p>或者说，他们在构建自己的抽象层时，其实也要基于大量其他人的抽象层开发。一个优秀的软件，其优秀之处不在于它自己重新发明了所有的抽象层，而是在已有的抽象层上做出了前人没有做到过的事情。</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>备注</div><div class="admonitionContent_BuS1"><p>需要再重申的是：这仅仅是我自己遇到的问题。如果你没有遇到过这样的问题，我在为你庆幸的同时也真心地感到羡慕。</p><p>但还是那句话，我也不期望我的这篇文章能帮助到世界上的所有人。如果一个人恰好有和我一样的问题，而我的文字又能在他理解这些问题的道路上协助他稍微地前进一小步，那就已经很好了。</p><p>即使没有这种情况发生，也没有什么关系。毕竟退一万步讲，这一系列文章只是我的闲聊，为了满足我自己的表达欲罢了。</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="用尝试替代思考">用尝试替代思考<a href="https://sqybi.com/blog/becoming-an-brilliant-programmer-01/#%E7%94%A8%E5%B0%9D%E8%AF%95%E6%9B%BF%E4%BB%A3%E6%80%9D%E8%80%83" class="hash-link" aria-label="用尝试替代思考的直接链接" title="用尝试替代思考的直接链接" translate="no">​</a></h3>
<p>虽然我现在的自我认知已经能够一定程度解决这个问题，但这并不代表一个类似的人看了上面的文字就能达到同样的自我认知。相反，作为一个精神内耗其实还挺严重的人，我很理解这种内耗是不能由简单的几句话转变的。</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>备注</div><div class="admonitionContent_BuS1"><p>通常在互联网上会基于 MBTI 对人的分类把我这类人称作 I 人，我不认可这个分类方式，但是认可这种简单有效的分类方法。）</p></div></div>
<p>毕竟，人的这种固有思维只能由自己新的人生经历来修正，而如果没有遇到机缘巧合，新的经历大多数情况下只能靠自己的行为转变带来。请允许我不厌其烦地提示：大前提是你也同意“一个人的自我是由他过去的所有人生经历所构成的”这个观点。</p>
<p>就像《化物语》中所说的：人只能自己救自己，谁也没有办法拯救别人。（人は一人で胜手に助かるだけ。谁かが谁かを助けることなどできない。）</p>
<p>不过列举这句话只是处于我个人的喜好，过于相信自己的认知范围内文化作品的高大上也是我们这一代程序员身上常见的现象，也请读者们见谅。事实上，哲学家们早就洞见了这个道理。无论是黑格尔的辩证法中对于事物发展的理解，还是斯多葛学派对于理性的思考，无一不在体现这个观点。</p>
<p>而改变自我行为最好的方式，其实就在一句大家耳熟能详的古话中。</p>
<p>学而不思则罔，思而不学则殆。</p>
<p>这里的“学”可以是进一步地学习了解，但也需要包括实践。与其为了一些事情的正确与否原地踌躇不前，不如先接受自己的认知。如果这个认知有错误，那么总有一天它会被修正。</p>
<p>其实这也是小时候每个人都听过的道理：失败是成功之母。只不过之前的我，只是简单地把它理解为“即使失败了也要努力才会成功”。现在想想，或许更重要的道理是：每个人都必然会遇到失败，而且会持续地失败。</p>
<p>就像永远都不完美的那些软件一样。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="不理解但是理解">不理解，但是理解<a href="https://sqybi.com/blog/becoming-an-brilliant-programmer-01/#%E4%B8%8D%E7%90%86%E8%A7%A3%E4%BD%86%E6%98%AF%E7%90%86%E8%A7%A3" class="hash-link" aria-label="不理解，但是理解的直接链接" title="不理解，但是理解�的直接链接" translate="no">​</a></h2>
<p>很幸运第一次尝试顺着“不理解”这个话题，边思考边写下这些文字，就能顺畅地结束在另我自己很满意的地方。</p>
<p>虽然上面没有具体讨论到接下来要提到的这个观点，仅仅是触及了一点点，但我还是想夹带一些私货。我认为《EVA》中把人与人之间的隔阂比作 AT Field，真的是一个再精妙不过的比喻。如果你过于相信他人，完全卸下你和他人之间的隔离，那么就会失去自我；而当你完全不相信他人的时候，你的自我也不再有意义。</p>
<p>有趣的是，这两种看似背道而驰的状态通常不是独立出现的，而是一起出现。同时，你还需要在这两种状态间找到一个平衡，才能在保持自我的情况下在世界上存活下去。</p>
<p>因为我不认为我的读者全部了解《EVA》，所以也不打算接着这个话题展开过多讨论。但无论如何，当一个人能够一边作为不理解这个世界的一员，一边理解自己和所有人类对这个世界的不理解时，这个人才能真的开始理解这个世界。</p>
<p>我一开始其实想将文章的标题叫做“屎上雕花”，这是由我司前 CTO 提出的一个描述软件工程状态的词汇。后来想想，这种表述方式虽然足够准确，但还是过于戏虐了。而且这个词被提出的时候，多少带着一些负面的含义。但我这篇文章的观点，更多地是认为这是一种应当被接受的常态——虽然我这些年的工作内容（特别是 CI/CD 和工程化相关）就是为了尽可能消除这种情况，但我还是要接受这个情况的普遍性这一客观事实。</p>
<p>毕竟，理解这种不理解导致的不完美，也是迈向完美过程中的一环。</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 计算机技术</category>
            <category>系列 | 成为优秀的程序员</category>
        </item>
        <item>
            <title><![CDATA[从拍照到摄影（02）：相机的其它基础参数和进阶影响]]></title>
            <link>https://sqybi.com/blog/from-taking-pictures-to-photography-02/</link>
            <guid>https://sqybi.com/blog/from-taking-pictures-to-photography-02/</guid>
            <pubDate>Sun, 03 Mar 2024 20:00:00 GMT</pubDate>
            <description><![CDATA[如果需要查看系列中的其它文章，请使用 tag 跳转到文章目录界面：#from-taking-pictures-to-photography。]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>如果需要查看系列中的其它文章，请使用 tag 跳转到文章目录界面：<a class="" href="https://sqybi.com/blog/tags/from-taking-pictures-to-photography/">#from-taking-pictures-to-photography</a>。</p>
</blockquote>
<p>这篇文章我们接着介绍上一篇文章中遗留的几个相机基础参数。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="数码相机的其它基础参数">数码相机的其它基础参数<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-02/#%E6%95%B0%E7%A0%81%E7%9B%B8%E6%9C%BA%E7%9A%84%E5%85%B6%E5%AE%83%E5%9F%BA%E7%A1%80%E5%8F%82%E6%95%B0" class="hash-link" aria-label="数码相机的其它基础参数的直接链接" title="数码相机的其它基础参数的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="焦距">焦距<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-02/#%E7%84%A6%E8%B7%9D" class="hash-link" aria-label="焦距的直接链接" title="焦距的直接链接" translate="no">​</a></h3>
<p>相信即使对摄影知识没有太多了解的读者，也听说过“广角”“长焦”等词汇——毕竟现在的手机特别是高端手机，越来越像专业摄影设备，导致这些词语也越来越多地出现在我们的生活中。</p>
<p>作为最基础的知识，焦距主要影响的还是同样拍摄距离下，拍摄主体在画面中的大小。通常来说，焦距越长，数值越大，也就是越靠近“长焦”端，主体在画面中越大；反之焦距越短，数值越小，也就是越靠近“广角”端，主体在画面中越小，画面中容纳的内容也越少。</p>
<p>例如，一张靠近广角端的照片可能是这样的：</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="广角端照片，使用手机拍摄" src="https://sqybi.com/assets/images/wideangle-fbba73a418f8ee06b85b331e0fd8d0b0.jpg" width="1024" height="768" data-zoomable="" class="img_ev3q"><div class="img-caption">广角端照片，使用手机拍摄</div></div><p></p>
<p>同一张照片，如果用长焦端对准后面的建筑拍摄，则可能是这样的（这里为了演示使用了画幅裁切来表示，不是真正的长焦端拍摄，但是效果类似）：</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="长焦端照片，使用手机拍摄后裁切" src="https://sqybi.com/assets/images/telephoto-1923fad3bae9dae7e13585c076572ba5.jpg" width="1024" height="768" data-zoomable="" class="img_ev3q"><div class="img-caption">长焦端照片，使用手机拍摄后裁切</div></div><p></p>
<p>这个对比应该足够大家理解广角和长焦的区别了。</p>
<p>而对于光线，通常光圈不变的情况下，镜头焦距和进光量是不存在相关性的。也就是同光圈下不同焦距的镜头，进光量几乎一样。</p>
<p>单纯使用相机的话，只要记住这个结论就可以了。如果你好奇这是为什么：因为实际上光圈值等于焦距和入瞳直径的比值。也就是在光圈值的定义中，已经消除了焦距对进光量的影响。具体原理可以参考：<a href="https://zhuanlan.zhihu.com/p/38354785" target="_blank" rel="noopener noreferrer" class="">镜头焦距和光圈与进光量的关系</a>。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="环境光强度">环境光强度<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-02/#%E7%8E%AF%E5%A2%83%E5%85%89%E5%BC%BA%E5%BA%A6" class="hash-link" aria-label="环境光强度的直接链接" title="环境光强度的直接链接" translate="no">​</a></h3>
<p>可能大家看到这个标题会疑惑，环境光的强度明明和相机本身没有关系，为什么会作为相机的参数之一列出呢？</p>
<p>这里更准确的名称可能是“相机测量到的环境光强度”。一方面，这和相机的传感器接收光线的能力有关，例如传感器像素的设计、传感器的大小、传感器滤光片和镜头的镀膜等，都会导致同样的光线下不同相机接收到的光线量不同；另一方面，这和相机计算光线强度的方式，也就是测光方式有关——毕竟相机只能知道每个像素接收到了多少光线，但整个画面的光线强度并不一定是这些像素的平均值。</p>
<p>当然，最简单的测光方式就是直接把所有像素取一个平均——这一般被称作平均测光。而一些更特殊的测光方式，例如点测光和中心测光，则受你手动指定的对焦点或画面中心的光线强度影响更大。</p>
<p>好在现在的相机通常默认的测光模式（例如“多重测光”或“评价测光”）都是比较复杂的，能够通过一定的算法将图片分区后再加权得出相对准确的环境光亮度，这已经足够绝大部分场景使用了。作为初学者没有必要详细追究具体的测光原理，只需要知道部分特殊情况下可能需要改变测光方式让相机检测到的环境光强度更准确——例如拍摄在一个纯黑的背景中晃动的烛光，或许选择烛光进行点测光是更好的做法。</p>
<p>除去测光以外，还需要了解的是环境光本身就是决定照片好坏的关键因素之一！除了影棚这种特殊场景，大部分情况下闪光灯和补光灯都只能起到辅助作用，而找到方向、强度、颜色都合适的环境光，就很容易拍出好的照片。</p>
<p>所以即使在日常生活中没有携带专业拍摄设备的时候，也多观察身边物体的光影，判断哪些光影是“好看”的，这样可以逐渐积累对光线的敏感度，对摄影技术的提升非常有帮助。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="曝光补偿">曝光补偿<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-02/#%E6%9B%9D%E5%85%89%E8%A1%A5%E5%81%BF" class="hash-link" aria-label="曝光补偿的直接链接" title="曝光补偿的直接链接" translate="no">​</a></h3>
<p>前面提到了环境光强度，但是并没有指出相机是如何使用它的。</p>
<p>在刚刚接触数码相机的时候，最令我迷惑的功能就是“曝光补偿”了，没有之一。因为这个功能的名字其实和它的功能本身并不符合：它并不能对曝光和画面的亮度做任何的补偿，实际上只是一个自动或非全手动模式下，通过调整某些参数（快门、光圈、ISO 等）来达到指定画面亮度的功能。</p>
<p>所以，曝光补偿更合适的名字可能是“画面预期亮度”（自动模式下）或“当前画面亮度”（手动模式下）——也就是上一节中提到的通过测光模式测出的亮度。当然为了能够适应大部分摄影设备，这里我也就不再造词了，后面的文章中还是会规规矩矩地写作“曝光补偿”。</p>
<p>通常曝光补偿的值由 EV 表示。当曝光补偿为 0 EV 时，意味着当前的光线强度处于最亮的白色和最暗的黑色中间的位置（但这不代表接收到了 50% 的光线，而是约 18% 的光线，影调部分会详细介绍）。</p>
<p>还记得前面的文章中提到的“档位”的知识吗？每当曝光补偿的值 +1，就意味着光线强度增加了一档。这可能是快门时间延长一倍、ISO 增加一倍，也可能是光圈值缩小到原来的 1/1.4（光圈值的计算方式请温习：<a class="" href="https://sqybi.com/blog/from-taking-pictures-to-photography-01/#%E4%B8%8D%E5%A5%BD%E8%AE%A1%E7%AE%97%E6%A1%A3%E4%BD%8D%E5%B8%AE%E5%BF%99">从拍照到摄影（01）：相机的基础参数</a>）。同理，如果曝光补偿的值 -1，则意味着光线强度降低了一档。简而言之，EV 变化 1 就意味着整体照片亮度也随之变为之前的 2 倍或 1/2。</p>
<p>因为 2 倍的变化过于剧烈，所以通常相机的 EV 变化最小档位是 1/3。每增加 1/3 EV，光线强度则会变为原先的 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mrow><mn>1</mn><mi mathvariant="normal">/</mi><mn>3</mn></mrow></msup><mo>≈</mo><mn>1.26</mn></mrow><annotation encoding="application/x-tex">2^{1/3} \approx 1.26</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.888em"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em"><span style="top:-3.063em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1/3</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:0.6444em"></span><span class="mord">1.26</span></span></span></span> 倍。而增加三个 1/3 EV 也就是 1 EV 之后，光线强度也就自然变成了 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>1.26</mn><mn>3</mn></msup><mo>≈</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">1.26^3 \approx 2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8141em"></span><span class="mord">1.2</span><span class="mord"><span class="mord">6</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em"><span style="top:-3.063em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:0.6444em"></span><span class="mord">2</span></span></span></span> 倍。当然这里甚至连这个结论都不需要记住，只要知道调整 EV 能改变亮度就足够了。</p>
<p>但是这里需要再次强调：相机是通过调整自动模式下的参数来适配 EV 的。</p>
<p>例如某个场景下，使用相机的光圈优先模式，光圈被固定在 f/2.8，ISO 被手动设置为 ISO 100。此时，唯一可以调整的参数就是快门速度。假设 -1 EV 时快门的速度为 1/100s，此时你觉得亮度太低，需要 +2 EV 的曝光补偿，把画面亮度变为 1 EV——没问题，相机会通过将你的快门变慢 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mn>2</mn></msup><mo>=</mo><mn>4</mn></mrow><annotation encoding="application/x-tex">2^2 = 4</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8141em"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em"><span style="top:-3.063em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:0.6444em"></span><span class="mord">4</span></span></span></span> 倍达到了 1 EV 的效果，此时的快门变为 1/25s。</p>
<p>但是这不是没有代价的。因为快门太慢，所以如果相机不在三脚架上或手不够稳，你会发现画面“糊”了。这时，更好的方法是不要单纯依赖曝光补偿的调整，而是手动增加 ISO 来保证足够快的快门。虽然更高的 ISO 可能带来更多噪点，但是要知道这些噪点都是一定程度上可以通过后期处理去掉的。而且即使不能去掉，“拍到”也永远比“拍好”重要。噪点多的照片可能只是看起来不那么干净，而一张糊了的照片是根本没有办法使用的。</p>
<p>综上所述，等到后面了解互易律之后，我推荐所有使用数码相机的初学者在摄影早期都尽量多地使用手动模式并手动固定 ISO，而非光圈优先和快门优先模式，甚至是全自动模式。在这种模式下，对曝光补偿值的调整是无效的（因为没有可以自动调整的参数）。但是相机会通过 EV 值的方式输出当前的测光结果，可以作为对画面亮度的参考。</p>
<p>这可能在早期会花费你更多的时间调整相机参数，甚至错过一些决定性瞬间。但我个人认为这是值得的，因为你会非常迅速地了解各个参数在不同场景下的作用。当你很清楚不同场景下哪些参数是可以调整而哪些参数是不能的时候，你就可以使用上述几种其它模式，从而达到更快抓拍的效果了。我也会在后续的文章中详细介绍这几种模式的使用场景。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="画幅">画幅<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-02/#%E7%94%BB%E5%B9%85" class="hash-link" aria-label="画幅的直接链接" title="画幅的直接链接" translate="no">​</a></h3>
<p>通常来说，作为摄影新手，你手里应该很大概率只有一台相机，而且很可能是全画幅或 APS-C 规格的残幅相机。</p>
<p>我比较推荐你等到同时拥有全画幅和残幅两台相机的时候，再详细了解画幅的作用。这里，我只列出一些关于画幅最基础的知识：</p>
<ul>
<li class="">可以简单地理解为小画幅等于对大画幅的传感器裁切，例如 APS-C 画幅就是从全画幅相机中裁切出约 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mn>1</mn><mi mathvariant="normal">/</mi><mn>1.5</mn><msup><mo stretchy="false">)</mo><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">(1/1.5)^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em"></span><span class="mopen">(</span><span class="mord">1/1.5</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em"><span style="top:-3.063em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span> 或 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mn>1</mn><mi mathvariant="normal">/</mi><mn>1.6</mn><msup><mo stretchy="false">)</mo><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">(1/1.6)^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em"></span><span class="mopen">(</span><span class="mord">1/1.6</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em"><span style="top:-3.063em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span> 面积的一部分（其中 1.5 / 1.6 为对角线长度比值；之所以有不同系数，是因为不同厂商的 APS-C 画幅传感器大小可能有些许区别）。</li>
<li class="">在上文“焦距”部分的例子中，可以看出裁切基本等于改变焦距。
<ul>
<li class="">裁切图片画面和裁切传感器其实没有太大区别，所以全画幅相机通常也可以通过裁切一部分传感器能接收到的画面来模拟残幅相机。</li>
<li class="">但是事实上通过裁切得到的焦距和原生的焦距是有区别的，裁切只能影响画面中物体的大小，但是不能影响已经拍摄到画面的景深和透视。关于景深和畸变是什么，后面的文章中会介绍。</li>
</ul>
</li>
<li class="">因为一些历史原因，镜头的焦距等参数都以全画幅相机为基础定义。而为了便于理解，残幅相机都会给自己的镜头标注两个焦距参数：（原始）焦距和等效焦距。其中等效焦距表示“残幅相机裁切后，物体的大小等效于全画幅下多少焦距的镜头拍摄的物体大小”，而焦距参数则表示镜头本身的焦距。
<ul>
<li class="">等效焦距只影响物体在最终画面中的大小。</li>
<li class="">焦距影响实际的虚化效果和透视效果，后文会介绍虚化和透视的详细内容。</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="小结">小结<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-02/#%E5%B0%8F%E7%BB%93" class="hash-link" aria-label="小结的直接链接" title="小结的直接链接" translate="no">​</a></h2>
<p>在这篇文章中，你已经学到了：</p>
<ul>
<li class="">焦距越靠近长焦端，数值越大，焦距越长，物体在画面中显得越大，画面容纳的内容越少，也就是通常所说的“拍得远”。</li>
<li class="">焦距越靠近广角端，数值越小，焦距越短，物体在画面中显得越小，画面容纳的内容越多，也就是通常所说的“拍得广”。</li>
<li class="">环境光是摄影中很重要的因素，会直接影响照片的好坏。</li>
<li class="">相机可以通过测光来得到环境光强度，现代相机的默认测光模式已经可以适应绝大部分场景。</li>
<li class="">曝光补偿并不是一种“补偿”，而是通过调节配置为自动的参数达到提升相机亮度的效果。</li>
<li class="">曝光补偿的值每 +1 EV，意味着画面亮度变为原来的 2 倍，也等效于某个参数变为原来的 2 倍（但相机可能会通过调整多个参数来达到一样的效果）。</li>
<li class="">曝光补偿的调整是有代价的，例如过慢的快门可能会导致画面糊掉；新手在早期推荐使用包括手动 ISO 在内的全手动模式，此时曝光补偿是失效的，但可以参考相机测出的 EV 值判断画面亮度。</li>
<li class="">残幅相机的镜头参数中，等效焦距只影响物体在画面中的大小，而焦距会影响虚化和透视的效果；因为某些历史原因，这些大小和效果都是以全画幅相机作为基础比较的。</li>
</ul>
<p>在接下来的一篇文章中，你即将学到：</p>
<ul>
<li class="">焦距和光圈如何影响景深</li>
<li class="">焦距如何影响透视和畸变</li>
<li class="">焦距如何影响手持时的稳定性</li>
<li class="">原生感光度和双原生感光度</li>
</ul>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 摄影</category>
            <category>系列 | 从拍照到摄影</category>
        </item>
        <item>
            <title><![CDATA[从拍照到摄影（01）：相机的基础参数]]></title>
            <link>https://sqybi.com/blog/from-taking-pictures-to-photography-01/</link>
            <guid>https://sqybi.com/blog/from-taking-pictures-to-photography-01/</guid>
            <pubDate>Tue, 09 Jan 2024 01:00:00 GMT</pubDate>
            <description><![CDATA[如果需要查看系列中的其它文章，请使用 tag 跳转到文章目录界面：#from-taking-pictures-to-photography。]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>如果需要查看系列中的其它文章，请使用 tag 跳转到文章目录界面：<a class="" href="https://sqybi.com/blog/tags/from-taking-pictures-to-photography/">#from-taking-pictures-to-photography</a>。</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="从拍照开始到拍照结束">从拍照开始到拍照结束<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-01/#%E4%BB%8E%E6%8B%8D%E7%85%A7%E5%BC%80%E5%A7%8B%E5%88%B0%E6%8B%8D%E7%85%A7%E7%BB%93%E6%9D%9F" class="hash-link" aria-label="从拍照开始到拍照结束的直接链接" title="从拍照开始到拍照结束的直接链接" translate="no">​</a></h2>
<p>拥有自己的第一台卡片相机 Nikon COOLPIX S200，还是我上中学时候的事情。</p>
<p>很多人在给摄影新手建议的时候都会说，设备不重要，不要想着一下子成为摄影师，多拍照，多拍自然就会了。我曾经也是相信这句话的。</p>
<p>于是在那个互联网上还并没有那么容易寻找到知识的年代，我拿着相机到处拍照，到处尝试，不可谓没有把“多拍”做到极致。但是随之而来的，并不是什么成长，而是进一步的迷茫。</p>
<p>我的身边没有多少会摄影的人，我不知道什么才是美的照片，只会一遍一遍重复着歪歪扭扭的奇怪构图；我的身边也没有多少懂相机的人，于是我对胶片相机的了解仅限于胶卷暴露在太阳光下会废掉，也一直以为数码相机拍夜景的时候有花花绿绿的噪点是我自己的问题；我不知道什么是三脚架，也不知道什么是光圈快门 ISO，用了一圈相机的各种模式之后还是换回了自动。</p>
<p>就这样，这台相机在陪伴了我一整个中学之后，终于在手机拍照的效果逐渐赶上它之后，在大学时把它放回了家里。我对“摄影”的尝试从“拍照”开始，到“拍照”也就结束了。</p>
<p>而若干年后开始工作，我又重新用工资给自己买了一台微单相机，索尼的一代神机 α6000。这时候的互联网上已经有了大量良莠不齐的知识，凭借着摸索我选购了第一款便宜的定焦头，也尝试着用光圈优先模式拍照片。但即便如此，我还是带着很多无法解答的疑惑，比如为什么有了大光圈还需要用小光圈，再比如变焦镜头除了贵还有什么别的缺点。</p>
<p>陷入了和之前一样的困境，自然也有一样的结果。一段时间之后这台相机也被我封进了箱子，甚至前几年拿出来的时候自带的狗头已经因为内部的塑料组件老化无法对焦了。</p>
<p>直到前几年，我终于看到了一篇由 Sean Ning 编写的文章，<a href="https://www.ashweb.org/wp-content/uploads/2019/12/%E6%91%84%E5%BD%B1%E7%AC%94%E8%AE%B0_%E6%91%84%E5%BD%B1%E5%85%B6%E5%AE%9E%E4%B8%8D%E9%9A%BE%E5%AD%A6.pdf" target="_blank" rel="noopener noreferrer" class="">《摄影笔记：摄影其实不难学》</a>。可惜的是我寻找了很久都没有找到这个作者的信息，有一个网站疑似是这位作者的博客，但是我也没有找到实际的证据，这里就不放出来了。</p>
<p>这篇文章甚至是 2010 年前后就写成的，同时很明显是一个 Word 导出的 PDF，满满的年代感。虽然年代久远，但是这篇文章的内容却一点都不过时。它从技术的角度切入，先是介绍了相机中许多重要的参数和它们之间的联系，然后循序渐进地引出“影调”这一摄影中的关键概念，接下来进一步延伸到了摄影的本质“突出主题”，之后一路聊到一些基础摄影类型需要考虑的重点要素。</p>
<p>这可能和大部分小红书上“如何构图”或 B 站“如何调色”的文章视频都不一样，它其实全程都没有过多提及摄影的艺术性。相反，这可能是一篇非常“程序员”的文章——我从中看到的都是技术，而且非常受益。</p>
<p>我的这一系列文章，其实就是对这篇<a href="https://www.ashweb.org/wp-content/uploads/2019/12/%E6%91%84%E5%BD%B1%E7%AC%94%E8%AE%B0_%E6%91%84%E5%BD%B1%E5%85%B6%E5%AE%9E%E4%B8%8D%E9%9A%BE%E5%AD%A6.pdf" target="_blank" rel="noopener noreferrer" class="">《摄影笔记：摄影其实不难学》</a>的拙略模仿和简要总结。即使你愿意阅读我的文章，我也推荐你有空的时候去点击前面这个链接，下载 PDF 到本地，然后慢慢地把它读一遍。虽然老法师们可能会嗤之以鼻，但是作为新手一定会受益匪浅——摄影是一个满足自身远远比取悦他人更重要的爱好，何必把老法师们的屁话当真呢？</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="相机的工作原理">相机的工作原理<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-01/#%E7%9B%B8%E6%9C%BA%E7%9A%84%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86" class="hash-link" aria-label="相机的工作原理的直接链接" title="相机的工作原理的直接链接" translate="no">​</a></h2>
<p>随便搜索一下，都能发现很多介绍数码相机原理的文章和视频。</p>
<p>通常来说，它们会先将数码相机分门别类地区分为单反、无反（也就是微单）等类型，然后再分门别类地讲解它们各自的原理，甚至还会画几张光路图。更复杂的文章可能还会额外介绍一下手机和一些特殊相机（双反、旁轴）的技术设计。</p>
<p>但是我不打算写得那么复杂，而是会列出以下几个重要的点：</p>
<ol>
<li class="">当前市面上能买到的数码相机绝大部分都是无反相机，而索尼的“微单”也是无反相机的一种，“微单”是它注册的商标，所以别人不能用。</li>
<li class="">无论是上述哪种相机，甚至是胶片机或手机，本质上都是让光通过镜头中的一系列玻璃和镜面发生各种折射和反射后，投射在固定大小的感光元件上。</li>
<li class="">现在市面上能买到的数码相机和手机绝大部分感光元件也都是 CMOS，除非你为了“复古”特地去买 CCD 相机（不推荐），它的感光元件自然是 CCD；胶片机的感光元件则就是胶片上面的一小格，而拍立得的感光元件就是拍立得的相纸本身，这应该很好理解。</li>
<li class="">单反和无反（微单）的最大区别在于你是如何实时看到感光元件上投射的影像的，通常来说分为直接读取感光元件的信息和通过光路把光一分为二两种方式，现在的大部分数码相机，包括无反相机和手机，都采用的是前一种模式。</li>
<li class="">在真正拍照的时候，相机会先挡住所有射向感光元件的光线，然后短暂地让光线通过一小段时间，并将这一小段时间内感光元件感知到的光线变成照片。这段时间也叫做“快门速度”。</li>
</ol>
<p>而其中最重要的就是第二条。即使其它的内容你一点都看不懂，也只需要知道相机本身就是把光通过各种折射反射投到感光元件上，然后通过感光元件收集一小段时间的光线，最终生成照片的设备就可以了。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="数码相机的基础参数">数码相机的基础参数<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-01/#%E6%95%B0%E7%A0%81%E7%9B%B8%E6%9C%BA%E7%9A%84%E5%9F%BA%E7%A1%80%E5%8F%82%E6%95%B0" class="hash-link" aria-label="数码相机的基础参数的直接链接" title="数码相机的基础参数的直接链接" translate="no">​</a></h2>
<p>任何数码相机，或者说数码摄影摄像设备，都离不开一些最基础的参数。</p>
<p>前面反复说过，相机就是一种光的折射反射+感光元件生成照片的设备。所以可以看到，相机的主要参数中几乎所有参数都和“光”相关，可以用于调整光的特性；而部分参数和“感光元件”相关，可以调整感光元件的特性。</p>
<p>接下来我会介绍若干相机的参数，它们一般来说分为两类，一类和最终的进光量是线性关系，即参数数值变化 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em"></span><span class="mord mathnormal">x</span></span></span></span> 倍，进光量也变化 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em"></span><span class="mord mathnormal">x</span></span></span></span> 倍。而另一类则和进光量是平方关系，即参数数值变化 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em"></span><span class="mord mathnormal">x</span></span></span></span> 倍，进光量会变化 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>x</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">x^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8141em"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em"><span style="top:-3.063em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span> 倍。你可能一开始没有办法记住全部的参数类型，但是没有关系，参数数量不多，你会在自己拍照的过程中慢慢熟悉并记住它们的。而最终熟练记住它们则很重要，因为你在手动模式下需要通过反向调整其中的两个参数达到进光量不变，但参数产生变化的结果，以实现某些特定的风格化目标。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="影响进光的两大要素快门光圈">影响进光的两大要素：快门、光圈<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-01/#%E5%BD%B1%E5%93%8D%E8%BF%9B%E5%85%89%E7%9A%84%E4%B8%A4%E5%A4%A7%E8%A6%81%E7%B4%A0%E5%BF%AB%E9%97%A8%E5%85%89%E5%9C%88" class="hash-link" aria-label="影响进光的两大要素：快门、光圈的直接链接" title="影响进光的两大要素：快门、光圈的直接链接" translate="no">​</a></h3>
<p>通常来说，最常见的直接通过进光量影响照片光影的要素，就是快门和光圈两个参数了。</p>
<p>快门是最直接的参数，也称作“快门速度”，直接以一个时间表示，如 1/100 秒。前面就提到了，其实这就是拍照时感光元件实际接收光线的时间。在这个时间之前和之后，感光元件都会被封在一个不漏光的黑盒子里。</p>
<p>那么很明显，快门的时间越长，照片的进光量就越大，而且它们显然是线性关系（感光 2 秒的进光量是 1 秒的 2 倍）。</p>
<p>光圈就是直接控制了进光孔的大小，越大的光圈进光量就越大，越小的光圈进光量则越小。但是光圈是一个最特殊的参数（我向你保证后面不会有这样的参数了，所以请务必记住！）：光圈的数值越小，则进光量越大！</p>
<p>这是因为光圈本身的定义，其实是一个类似于孔径倒数的东西。这里我可以贴一些文章比如<a href="https://zhuanlan.zhihu.com/p/24048647" target="_blank" rel="noopener noreferrer" class="">等效光圈，是耶？非耶？</a>，但是我真心不推荐新手现在就去阅读这部分内容。</p>
<p>我再保证一次：这是唯一一个数值越小进光量越大的参数，早期只需要记住就可以了。</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>扩展阅读</div><div class="admonitionContent_BuS1"><p>当然如果你已经熟练掌握了基础概念，那么可以读一下上面的文章了解光圈和光通量的关系，有助于理解“为什么大画幅相机虚化更好”等问题。</p></div></div>
<p>同时，因为光圈倒数本身和孔径线性相关，而进光量和面积线性相关，所以很明显光圈和进光量输于前面提到的平方关系。</p>
<p>总结下来，就是光圈<strong>数值</strong>变为原先的 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mi mathvariant="normal">/</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">1/x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord">1/</span><span class="mord mathnormal">x</span></span></span></span> 倍时，进光量会变为原先的 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>x</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">x^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8141em"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em"><span style="top:-3.063em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span>。例如如果我当前的光圈是 F2，如果我希望进光量变为原先的 2 倍，那么光圈应该调整到 F1.4（因为 1.4 的平方约等于 2）。顺便你应该已经看到了，光圈的表示方法是 F 后面加一个数字，如 F1.4、F2、F2.0 都是正确的写法。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="不好计算档位帮忙">不好计算？档位帮忙！<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-01/#%E4%B8%8D%E5%A5%BD%E8%AE%A1%E7%AE%97%E6%A1%A3%E4%BD%8D%E5%B8%AE%E5%BF%99" class="hash-link" aria-label="不好计算？档位帮忙！的直接链接" title="不好计算？档位帮忙！的直接链接" translate="no">​</a></h3>
<p>因为复杂的数值确实不好计算，所以通常相机的各种参数都不是无极调节，而是以档位来调整的。</p>
<p>比如在调节光圈时，可选的档位一般是 F1.4、F2.0、F2.8、F4.0、F5.6、F8.0……可以看到每两个数字之间都是约 1.4 倍的关系。根据前面的公式，每一档都比前一档少 2 倍的进光量。</p>
<p>而快门则可能支持更精细一些的调节，除了 1/100、1/200、1/400……等同样是 2 倍进度的档位以外，还可能有一些 1/3 倍甚至更精细的档位。但快门速度相比之下更好计算，所以这也不是什么太大的问题。</p>
<p>通常情况下，只要记住光圈每档之间是 2 倍进光量的区别就可以了。把前面的各种公式都忘掉吧，每当你调高一档光圈（比如从 F4 调整到 F2.8）时，记得把快门或后面介绍的其它参数对应调低为原先的 1/2（比如从 1/100s 调整为 1/200s）才能保证总进光量的一致就可以了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="感光度噪声和噪点">感光度、噪声和噪点<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-01/#%E6%84%9F%E5%85%89%E5%BA%A6%E5%99%AA%E5%A3%B0%E5%92%8C%E5%99%AA%E7%82%B9" class="hash-link" aria-label="感光度、噪声和噪点的直接链接" title="感光度、噪声和噪点的直接链接" translate="no">​</a></h3>
<p>感光度是一种比较特殊的参数。它本身代表了感光元件（CMOS 或胶片）对光的敏感程度，对光越敏感则意味着生成同样亮度的照片所需要的光越少。感光度的数值通常用 ISO 表示，例如 ISO 100、ISO 200、ISO 3600 等。</p>
<p>从结果上来说，感光度的调整和快门一样，也和最终照片的亮度成线性关系。但这里我不能将其解释为“进光量”，因为实际上在光线投到感光元件上的那一刻，进光量就已经被确定且无法修改了。但是，它确实在进光量因为各种客观事实无法调整的情况下，达到了类似提升进光量的效果，我们称之为提升感光量。</p>
<p>但是如果感光度这么好用，为什么我们不直接把感光度拉到最高呢？</p>
<p>这是因为我们的现实世界中，其实都是多多少少存在着各种噪声的。通常来讲，温度越高则粒子的随机运动越活跃，噪声也就越大。但除非温度能达到绝对零度，否则噪声客观上一直都是存在的。如果感光元件感知到了过高的噪声，体现在照片上就是花花绿绿的噪点。</p>
<p>噪声本身的大小只和温度与干扰时长有关，和相机的光学参数比如光圈是没有直接关系的。也就是说，假设我们现在用 100 的进光量拍摄，产生了 1 的噪声；然后我们通过增大光圈的方式将进光量调整到了 200，此时的噪声仍然是 1。</p>
<p>但是当我们不是增大光圈，而是增大曝光时间（调整快门速度）时，进光量就会和噪声成正比增加。例如我通过增加一倍快门时间的方式调整进光量到 200，此时的噪声大致就会增加到 2。不过因为噪声是随机的，所以增加的这一倍噪声不一定会和原先的噪声叠加在一起，所以观感上来说通常只要曝光时间不是太长，都还可以接受。当然如果是夜晚长时曝光（例如 10 秒或 30 秒甚至更长）的照片，也是要一定程度考虑噪点影响的。</p>
<p>而感光度则更加糟糕一些。在提高感光度时，其实是提高了这段时间之内元件对光线的敏感程度——这不仅包括射入的光线，也是提高了噪声。更糟糕的是，因为时间并没有拉长，所以这等同于原先的噪声在自己的位置直接被扩大了若干倍。</p>
<p>还是举上面的例子，通过从 ISO 100 增加到 ISO 200 来提高感光度，虽然照片的感光量增加到了 200，但此时噪声也增加到了 2，且相当于原地叠加了两次，理论上效果会比增加快门时间更差。</p>
<p>所以，如果不是必须的话，我们应该将感光度设置为可以设置的最低值，有的相机是 ISO 100，有的相机是 ISO 50……是这样吗？不是的！</p>
<p>首先，即使你希望设置在最低感光度，也尽量不要使用 ISO 50 的档位。至少在 2024 年的今天，我浅薄的见识中所了解的相机，通常的正常最低档位也是 ISO 100。而 ISO 50 更像是通过电子增益达到的一个特殊 ISO，实际感光效果可能还不如 ISO 100 好，在日常能够见到的拍摄场景中通常没有意义。</p>
<p>其次，现在的相机传感器在去除噪声这方面做了很多工作。即使是直出（指相机直接生成，没有经过电脑或手机上的后期处理）的照片，在 ISO 3200 甚至 ISO 6400 的感光度下，噪点通常也不会太影响照片本身。此外，因为 AI 技术的普及，所以 Photoshop 等后期软件中通常可以有效地消除噪点。即使你的原片噪点看起来比较严重，也可以后期处理到可用的状态，所以 ISO 12800 甚至更高的感光度在极度弱光且没有办法固定相机的环境中也不是完全不能使用，毕竟能拍到永远比拍好更重要。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="小结">小结<a href="https://sqybi.com/blog/from-taking-pictures-to-photography-01/#%E5%B0%8F%E7%BB%93" class="hash-link" aria-label="小结的直接链接" title="小结的直接链接" translate="no">​</a></h2>
<p>本来打算把所有参数都介绍完的，但是写起来才发现实在太长了，所以部分参数放到了下一期。</p>
<p>在这篇文章中，你已经学到了：</p>
<ul>
<li class="">相机本身就是把光通过各种折射反射投到感光元件上，然后通过感光元件收集一小段时间的光线，最终生成照片的设备。</li>
<li class="">快门是最简单的参数，写法类似于 1/100 秒或 1/100s，它和进光量成线性关系，2 倍的快门对应 2 倍的进光量和感光量。</li>
<li class="">光圈是最特殊的参数，写法类似于 F1.4，它的<strong>倒数</strong>和进光量成<strong>平方</strong>关系，约 1.4 倍的光圈对应 1/2 的进光量和感光量。</li>
<li class="">感光度和快门的效果类似，写法类似于 ISO 1600，但是它不影响进光量，只和最终的感光量成线性关系，2 倍的感光度对应 2 倍的感光量。</li>
<li class="">相片的噪点是不可避免的，且和快门时间与感光度相关，和光圈无关，感光度越高、快门时间越长，则噪点越明显。</li>
<li class="">通常相机的大部分感光度都是可用的，噪点一般很少，即使有噪点也可以通过后期处理进行一定程度的去除，但是不要使用 ISO 50 这个特殊感光度。</li>
</ul>
<p>在接下来的一篇文章中，你即将学到：</p>
<ul>
<li class="">相机的焦距是什么</li>
<li class="">环境光亮度的测量和作用</li>
<li class="">曝光补偿的含义和作用</li>
<li class="">不同画幅对镜头焦距参数的影响</li>
</ul>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 摄影</category>
            <category>系列 | 从拍照到摄影</category>
        </item>
        <item>
            <title><![CDATA[2024 新年快乐！]]></title>
            <link>https://sqybi.com/blog/happy-new-year-2024/</link>
            <guid>https://sqybi.com/blog/happy-new-year-2024/</guid>
            <pubDate>Sun, 31 Dec 2023 23:59:00 GMT</pubDate>
            <description><![CDATA[虽然一下子就是大半个月没有更新，但在这个时间还是让我先说一句，新年快乐！]]></description>
            <content:encoded><![CDATA[<p>虽然一下子就是大半个月没有更新，但在这个时间还是让我先说一句，新年快乐！</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="忙碌-2023">忙碌 2023<a href="https://sqybi.com/blog/happy-new-year-2024/#%E5%BF%99%E7%A2%8C-2023" class="hash-link" aria-label="忙碌 2023的直接链接" title="忙碌 2023的直接链接" translate="no">​</a></h2>
<p>前段时间，工作突然变得非常地忙。不光忙，而且心累。</p>
<p>而雪上加霜的是，或许是因为精神和身体的压力都有点大，身体出现了一些以前从来都没有出现过的疲劳症状，甚至有一天开完最后一个会，直接在会议室里瘫在椅子上起不来了。</p>
<p>可能是受到前段时间家里的猫咪“虽然”突然心脏病去世的影响，保险起见，我还是去做了一些心脏的检查。好消息是整体查下来没有什么太大的问题，坏消息是各种检查一轮一轮持续了很久，加上就诊的时间，让为数不多的休息时间变得更加紧张。</p>
<p>同时，工作上除了本来就有的七八个项目以外，又突然插进来了一个新的高优项目，甚至为了这个项目还临时跑了两三趟上海，很多时间都花在了路上。好在虽然在高铁上还要开会，但是几次回程都是飞机，可以在飞机上休息一下。</p>
<p>当然最近一小段时间其实压力稍微小了那么一点点点点，但是因为出差很多，所以前段时间也刚买了一台 ROG Ally 掌机——于是最近沉迷掌机上打游戏特别是 AVG 游戏，顺便还带着老婆看了<a href="https://www.bilibili.com/video/BV18E411q7yz/" target="_blank" rel="noopener noreferrer" class="">命运石之门的游戏录屏</a>。
再加上一段时间不写东西产生的惰性，最终还是没有抽出时间来更新博客。</p>
<p>顺带一提，第一次带着 Ally 坐飞机，身边座位的小姐姐就掏出了她的 Steam Deck，然后开始拉着我聊起了游戏掌机。这大概是我有印象的第一次在外面被完全不认识的人搭讪吧……当然也没有加微信之类的情节，聊完大家就各玩各的了，下了飞机的第一时间也跟老婆报备过了，大家不用担心。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="生活-2022">生活 2022<a href="https://sqybi.com/blog/happy-new-year-2024/#%E7%94%9F%E6%B4%BB-2022" class="hash-link" aria-label="生活 2022的直接链接" title="生活 2022的直接链接" translate="no">​</a></h2>
<p>如果说这一年和 2022 年相比的最大变化，那可能是生活的心态上确实调整得好了一些。</p>
<p>换做 2022 年，在这样的工作压力之下，我周末和工作日晚上不会有任何精力想要出门。但是这次，至少我还能在休息的时候选择出门见见多年未见刚刚回国的朋友，或者顶着这么多年来最大的一场雪出去吃个火锅烧烤。</p>
<p>以后有机会的话可以慢慢写一系列博客讲一讲心态的转变是怎么发生的。这里简短截说，和<a href="https://www.bilibili.com/video/BV13p4y1R75B/" target="_blank" rel="noopener noreferrer" class="">可妈最近的视频</a>里面讲得有点像：年过三十，终于理解生活不止是单一维度的，终于可以从生活中找到生存的目的。</p>
<p>做出这样的转变，或许是因为今年读了一些马克思恩格斯，或许是疫情之后的环境开始促进大家反思，也或许只是因为年龄到了。但不管怎样，能从死胡同中走出来是好事，希望身边还在这个死胡同里的同学早日找到出口，大家一起迈入下一个人生的死胡同。</p>
<p>可惜的是虽然前段时间已经开始每天运动了，但最近时间实在太少，所以运动和博客更新一样没能坚持下来。该理解的都理解了，可生活和工作，还是真的很难放在天平的两边称量。</p>
<p>美好的愿景，只能放到明年了。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="�愿景-2024">愿景 2024<a href="https://sqybi.com/blog/happy-new-year-2024/#%E6%84%BF%E6%99%AF-2024" class="hash-link" aria-label="愿景 2024的直接链接" title="愿景 2024的直接链接" translate="no">​</a></h2>
<p>中学和大学还在写博客的时候，每年都会写一个明年的 Todo-list，然后一个都打不上勾。</p>
<p>而现在，即使对明年要做的事情依旧有一些规划，也不会再以这种形式列出来了。与其有一大堆具体但无法完成的目标，不如有一个大致的方向。</p>
<p>我的方向则会是：更好地生活。</p>
<p>更好地理解什么是生活，更好地尝试如何生活，更好地平衡工作和生活。</p>
<p>或许会和今年一样做出一些大的转变也说不定？</p>
<p>不必着急，明年的这个时候，一切都会见分晓。</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 碎碎念</category>
        </item>
        <item>
            <title><![CDATA[沉浸式翻译：优秀的浏览器翻译插件]]></title>
            <link>https://sqybi.com/blog/immersive-translate/</link>
            <guid>https://sqybi.com/blog/immersive-translate/</guid>
            <pubDate>Sun, 10 Dec 2023 00:30:00 GMT</pubDate>
            <description><![CDATA[最近状态不好，挑一些简单的 topic 来写吧。]]></description>
            <content:encoded><![CDATA[<p>最近状态不好，挑一些简单的 topic 来写吧。</p>
<p>这里推荐一个浏览器插件：沉浸式翻译。可以说它满足了我对一个翻译插件的几乎全部设想，除了缺少 OCR 功能，以及某些特殊的 PDF 文档无法翻译以外，几乎所有工作生活中的主要需求它都能够满足，保留原文的翻译方式也是遥遥领先。再加上可以灵活接入各类翻译接口（软件的接入功能本身是免费的哦！），可以说这是我迄今为止遇到过的最有用的一款浏览器插件，没有之一。</p>
<p>它的官网在 <a href="https://immersivetranslate.com/" target="_blank" rel="noopener noreferrer" class="">这里</a>，大家也可以去自行了解一二。</p>
<p>至于我有多推荐这款插件，可能从我工作 Slack 的签名就可以看出来：</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="“每个人都应该拥有的 Chrome 插件”" src="https://sqybi.com/assets/images/slack-0f4cfa1b6e1192209129d1a6c232201d.png" width="338" height="85" data-zoomable="" class="img_ev3q"><div class="img-caption">“每个人都应该拥有的 Chrome 插件”</div></div><p></p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>关于拖更</div><div class="admonitionContent_BuS1"><p>一周多没有更新了，不是因为三分钟热度，也不是因为没有东西可以写，只是因为过去的这一周真的精疲力尽。</p><p>不知道是身体原因还是过于累心，最近几周一直在持续胸痛，伴随着左肩的放射性疼痛、晚上大量出虚汗，严重的时候甚至会半夜惊醒，睡眠质量也很差。做了一个 24 小时心电图之后本来想着这周事情太多等周末再去找医生，结果周四开完下班前最后一个会，整个人突然瘫在椅子上动弹不得——实在不敢拖了，于是周五上午强行请了个假去看病。</p><p>好消息是，24 小时心电图没有什么异常；坏消息是医生也很难保证没有问题，所以还是开了一个冠状动脉钙化 CT。</p><p>而周五下午继续超负荷工作到晚上，也终于能喘息一下了。整个周六都感觉还是没缓过来，直到现在才好了一点，来随便写点简单的东西。</p><p>这个状态下别说写博客了，连日常的家务都没法完成。我一方面希望自己的身体别出问题，另一方面其实也有点期待最终还是查出一些小病，说不定还能多一些休息的时间……</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="保留原文的翻译方式">保留原文的翻译方式<a href="https://sqybi.com/blog/immersive-translate/#%E4%BF%9D%E7%95%99%E5%8E%9F%E6%96%87%E7%9A%84%E7%BF%BB%E8%AF%91%E6%96%B9%E5%BC%8F" class="hash-link" aria-label="保留原文的翻译方式的直接链接" title="保留原文的翻译方式的直接链接" translate="no">​</a></h2>
<p>这款插件最重要的功能，就是保留原文的网页翻译方式。</p>
<p>话不多说，让我们用一张图片来看一下翻译的效果。网页来自 <a href="https://google.github.io/styleguide/cppguide.html" target="_blank" rel="noopener noreferrer" class="">Google C++ Style Guide</a>，翻译接口使用了谷歌翻译。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="Google C++ Style Guide 的翻译结果" src="https://sqybi.com/assets/images/example_google_style_guide-8dbb80ee1ddb67fb6f6125bf2b0fb8d6.png" width="1072" height="1283" data-zoomable="" class="img_ev3q"><div class="img-caption">Google C++ Style Guide 的翻译结果</div></div><p></p>
<p>可以看到相比直接替换网页内容的方式，这种翻译方案可以让我们更有效地将译文和原文进行对比。这在翻译技术文档的时候非常有用，可以避免某些单词被错误地翻译为了非专业语境下的形式，比如 string 和 thread 这类单词。</p>
<p>同时，即使对于日常翻译，在翻译接口并不百分百可靠的情况下，这也可以让我们通过快速查阅原文的方式理解部分“翻译腔”很重的译文。</p>
<p>通过 F12 简单检查了一下它的实现方案，看起来这个插件会通过在每一个块中加入行内标签 <code>&lt;font&gt;</code> 来达到插入译文的效果。其中还有一些微妙的技巧，比如对于较短的 <code>&lt;h&gt;</code> 标签，插件并不会在 <code>&lt;font&gt;</code> 中插入 <code>&lt;br&gt;</code>；但对于较长的段落，则会在 <code>&lt;font&gt;</code> 的一开始插入一个 <code>&lt;br&gt;</code> 来达到换行的效果。截图中的“Background 背景”和后续的文字，就分别属于这两种情况。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="多种多样的翻译接口支持">多种多样的翻译接口支持<a href="https://sqybi.com/blog/immersive-translate/#%E5%A4%9A%E7%A7%8D%E5%A4%9A%E6%A0%B7%E7%9A%84%E7%BF%BB%E8%AF%91%E6%8E%A5%E5%8F%A3%E6%94%AF%E6%8C%81" class="hash-link" aria-label="多种多样的翻译接口支持的直接链接" title="多种多样的翻译接口支持的直接链接" translate="no">​</a></h2>
<p>这个插件的另一个优秀之处在于，支持市面上你能想到的几乎所有翻译接口，包括 DeepL 和 OpenAI 的收费接口。当然了，虽然接入本身是免费的，但是接口还是要你自己花钱买的——当然也有更好的方案，后面会提到。</p>
<p>而迄今为止最优秀的全文翻译接口，我认为非 ChatGPT 莫属。看过我前几篇文章的小伙伴都应该知道，我的博客就是使用 ChatGPT 完成 <a class="" href="https://sqybi.com/blog/adding-i18n-for-a-docusaurus-site/">i18n</a> 翻译的。没看过也没关系，你现在就可以在右上角切换语言试试。</p>
<p>可以说 ChatGPT 的翻译结果，绝大部分情况下都不输于人类翻译——至少比我自己翻译得要好。更有甚者，我发现之前的博客中我在中文版里写的一些错字，ChatGPT 都可以在翻译时帮助我纠正。</p>
<p>沉浸式翻译在对于 OpenAI API 的支持上也是做到了最大的开放性，除了最基础的模型选择，它还提供了包括 prompt 定制、切换不同第三方服务（例如 Azure 这种直接提供 ChatGPT API 的厂商，或者 Moonshot 这种模拟了 ChatGPT 接口的厂商）、限制请求速率等各类配置项。</p>
<p>当然如果全部情况都使用 ChatGPT 翻译的话，除了价格可能有点吃不消以外，本身翻译的速度受限于接口调用频率和返回速度限制，也不能特别令人满意。所以我个人的做法是日常使用谷歌翻译，在某些比较难翻译的小段文字部分切换到 ChatGPT 接口。因为插件本身做了很好的优化，所以只会翻译当前网页显示位置附近的文字，不必担心一个长文档会全部被翻译一遍。</p>
<p>可能唯一可惜的是，在我尝试使用 Moonshot 的接口进行翻译时，即使请求速率限制到了一秒一次，实际的请求次数还是会超过这个数字，导致必定会触发速率限制，无法完成翻译，所以没法白嫖这部分免费额度啦。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="本地文档翻译功能">本地文档翻译功能<a href="https://sqybi.com/blog/immersive-translate/#%E6%9C%AC%E5%9C%B0%E6%96%87%E6%A1%A3%E7%BF%BB%E8%AF%91%E5%8A%9F%E8%83%BD" class="hash-link" aria-label="本地文档翻译功能的直接链接" title="本地文档翻译功能的直接链接" translate="no">​</a></h2>
<p>除了能够翻译网页以外，这个插件还有着同样优秀的本地文档对比翻译功能。</p>
<p>关于它支持的翻译方式，可以从插件菜单中看到：</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="支持的各类本地文档翻译" src="https://sqybi.com/assets/images/local_documents-2c33d974d27d5158ded65e37b2170ad2.png" width="181" height="222" data-zoomable="" class="img_ev3q"><div class="img-caption">支持的各类本地文档翻译</div></div><p></p>
<p>这里电子书和字幕文件的翻译都不太常用，而 HTML / txt 的翻译又有太多替代手段，所以 PDF 翻译是我最常用的一个功能。</p>
<p>这里还是用一个例子来展示翻译的效果，原文来自 <a href="https://cdn.openai.com/papers/gpt-4.pdf" target="_blank" rel="noopener noreferrer" class="">OpenAI 关于 GPT-4 的论文</a>：</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="翻译 GPT-4 论文" src="https://sqybi.com/assets/images/pdf_translation_gpt_4-9e9c9b8f07876c745f72c2f977db8c2f.png" width="1920" height="1283" data-zoomable="" class="img_ev3q"><div class="img-caption">翻译 GPT-4 论文</div></div><p></p>
<p>可以看到不管是正常的论文文本，还是侧面的 arXiv 信息，插件都能够正确翻译。其实我之前还用它翻译过一些 Intel / AMD 关于 CPU 介绍的幻灯片 PDF，效果也相当不错。可惜家里的电脑上没有这个文档，没法展示出来了。</p>
<p>这个功能唯一比较坑人的可能是它打开文件的方式是右上角那一堆小按钮里，“打印”按钮左侧的那个相比“打开”更像“分享”的按钮。有不少被我推荐这个插件的人，都问过我如何打开本地 PDF 文件。不过其实第一次打开这个功能时下面文档的指引有提到这件事情，大家还是太粗心了。</p>
<p>另外，对于一些特殊的 PDF 甚至一些 DVI 文件，这个插件可能就没有办法处理了。我写邮件反馈过这个问题，得到的答案是确实不支持。这类文件的特点是你直接复制内容的话会复制出一串乱码……我虽然用过一段时间 LaTeX，但其实对这些输出的格式也不是那么地了解，可能确实很难支持吧。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="可持续的盈利方式">可持续的盈利方式<a href="https://sqybi.com/blog/immersive-translate/#%E5%8F%AF%E6%8C%81%E7%BB%AD%E7%9A%84%E7%9B%88%E5%88%A9%E6%96%B9%E5%BC%8F" class="hash-link" aria-label="可持续的盈利方式的直接链接" title="可持续的盈利方式的直接链接" translate="no">​</a></h2>
<p>对于类似这样的优秀开源插件，我通常都会有两个有些矛盾的担忧：一是作者没有足够的收入能不能持续维护下去，二是作者会不会为了收入慢慢将插件的部分关键功能开源。</p>
<p>好在沉浸式翻译插件一定程度上为自己定义了一个看起来很不错的盈利模式。对于没有自己购买 ChatGPT 和 DeepL 接口的用户，如果购买了它们的会员，可以直接使用插件服务器提供的后台接口调用 ChatGPT 或 DeepL 进行翻译。插件的会员费和直接购买 DeepL Pro 会员基本持平，而 ChatGPT 则因为是按量请求所以不好计算。</p>
<p>插件本身因为会承接大量翻译请求，所以实际上其中重复的请求也很多。插件服务器通过缓存这些请求，来达到减少实际接口调用的效果，从而赚取其中的差价。</p>
<p>总所周知，DeepL 和 ChatGPT 接口与会员的购买，在国内是一件并不太简单的事情。对于的确有需求的用户，直接购买这个插件的会员，确实能省下不少事情，也算是一种双赢吧。</p>
<p>对于这种能产生 <a href="https://en.wikipedia.org/wiki/Pareto_efficiency" target="_blank" rel="noopener noreferrer" class="">帕累托改进</a> 的工具，我向来都是很喜欢的。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="彩蛋">彩蛋<a href="https://sqybi.com/blog/immersive-translate/#%E5%BD%A9%E8%9B%8B" class="hash-link" aria-label="彩蛋的直接链接" title="彩蛋的直接链接" translate="no">​</a></h2>
<p>除了上面介绍的主要功能之外，这个插件还有丰富的配置选项，其中很大一部分都能根据用户的需求改进翻译体验，非常值得一试。</p>
<p>一个小彩蛋是，这个软件的 <a href="https://immersivetranslate.com/" target="_blank" rel="noopener noreferrer" class="">主页</a> 和 SQYBI.com 一样，也是使用 Docusaurus 搭建的。证据就在网页的 meta 信息里。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="找到你了！" src="https://sqybi.com/assets/images/using_docusaurus-a6bb4ae84c690b2d6654be111b157179.png" width="483" height="132" data-zoomable="" class="img_ev3q"><div class="img-caption">找到你了！</div></div><p></p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 计算机技术</category>
            <category>内容 | 软件推荐</category>
        </item>
        <item>
            <title><![CDATA[为什么 Linksys VELOP 路由器不适合旁路网关]]></title>
            <link>https://sqybi.com/blog/linksys-velop-and-bypass-gateway/</link>
            <guid>https://sqybi.com/blog/linksys-velop-and-bypass-gateway/</guid>
            <pubDate>Fri, 01 Dec 2023 23:00:00 GMT</pubDate>
            <description><![CDATA[TL;DR: 在一个有旁路由的网络环境中使用 Linksys VELOP 路由器作为主路由，可能会导致旁路由搭建困难或损失网络性能，请优先考虑其它路由器。更新：网件 Netgear 的也不行，安心用小米吧。]]></description>
            <content:encoded><![CDATA[<p>TL;DR: 在一个有旁路由的网络环境中使用 Linksys VELOP 路由器作为主路由，可能会导致旁路由搭建困难或损失网络性能，请优先考虑其它路由器。更新：网件 Netgear 的也不行，安心用小米吧。</p>
<div class="theme-admonition theme-admonition-danger admonition_xJq3 alert alert--danger"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>听我一言</div><div class="admonitionContent_BuS1"><p>不要折腾网络，会变得不幸。</p></div></div>
<p>前几天因为忍受不了华硕路由器无线 Mesh 的频繁断连，我准备把家里的无线 Mesh 网络整体升级一波。在经过一些简单的调研之后，我选择了口碑是“功能和可定制性少，但是稳定”的 Linksys VELOP 系列路由器，型号是 MX4200。</p>
<p>在配置好几台路由器的无线 Mesh 网络之后，我开始尝试向路由器接入旁路由。</p>
<p>因为之前的华硕路由器本身就接入了一个旁路由，所以我想当然地以为只要同样简单配置一下就可以搞定了。</p>
<p>结果实际情况和想象中大相径庭，各种问题陆陆续续地打了我的脸。不光是简单配置一下解决不了问题，即使我最终梳理清楚了所有问题，最终还是发现只能用一个不太完美的方案完成旁路由的接入。</p>
<p>这也是为什么我一上来就给了结论：Linksys VELOP 不适合作为旁路由网络环境中的主路由。</p>
<p>下面我会仔细分析一下接入过程中遇到的所有问题和它们的原因，以及临时解决方案和它的原理。</p>
<p>文章比较长，技术名词也比较多。如果一口气读完有困难的话，可以考虑分段阅读。当然假使你真的一口气读完了，也请务必通过评论告诉我——我会敬你是条汉子的，或者是条妹子也行。</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>Linksys 神奇的起名方案</div><div class="admonitionContent_BuS1"><p>Linksys 路由器的起名逻辑是这样的：</p><ul>
<li class="">MX4200 是三频路由器，三个频段的总带宽有 4200M，所以叫做 MX4200。</li>
<li class="">购买两个 MX4200 的套装时，因为里面有两个带宽是 4200M 的路由器，所以总带宽是 8400M（注：实际上带宽不能这么计算！），这个套装就叫 MX8400。</li>
<li class="">同理，三个 MX4200 的套装就叫 MX12600。</li>
</ul><p>第一条还情有可原，毕竟很多路由器也都会用类似的方式标识型号。但是后面两条，对于不懂的人来说，实在是有点过于难以理解了。</p></div></div>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>旁路由？旁路网关？</div><div class="admonitionContent_BuS1"><p>所谓旁路由，看起来更正确的说法应该是“旁路网关”，因为大部分情况下这台设备并不承担很多路由功能，而是作为默认网关使用以达到全局流量转发和分流的目的。旁路由的出现主要是因为国内特殊的网络环境对“全局代理”的需求，国外很少会在家庭网络中部署这样的网络架构，所以这个名词几乎只会在国内被使用，也很难找到对应的英文概念。</p><p>我自己并没有什么命名洁癖，所以这篇文章里还是会使用“旁路由”这个更广为人知的名字。</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="无线-mesh-技术和旁路由">无线 Mesh 技术和旁路由<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E6%97%A0%E7%BA%BF-mesh-%E6%8A%80%E6%9C%AF%E5%92%8C%E6%97%81%E8%B7%AF%E7%94%B1" class="hash-link" aria-label="无线 Mesh 技术和旁路由的直接链接" title="无线 Mesh 技术和旁路由的直接链接" translate="no">​</a></h2>
<p>在开始回顾网络部署的过程之前，先简单介绍一下后面会频繁提到的一些技术名词。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="简单的家庭网络结构">简单的家庭网络结构<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E7%AE%80%E5%8D%95%E7%9A%84%E5%AE%B6%E5%BA%AD%E7%BD%91%E7%BB%9C%E7%BB%93%E6%9E%84" class="hash-link" aria-label="简单的家庭网络结构的直接链接" title="简单的家庭网络结构的直接链接" translate="no">​</a></h3>
<p>在常见的家庭网络环境中，一般只会存在一台路由器，或者带有路由器功能的光猫。当同时有路由器和光猫的时候，我们也会考虑将其中的一个置为桥接模式，这样依旧还是只有一个设备在发挥路由器的功能。</p>
<p>我们的个人电脑和手机平板等设备则会直接通过网线或 WiFi 接入路由器，或者经过若干二层交换机后通过网线接入路由器。这里我就不展开介绍二层和三层设备的区别了，总之可以认为这样一种简单的网络环境下，所有设备等同于直接接入了这台路由器。</p>
<p>而这样简单的网络结构在一些复杂的需求下，也会遇到各式各样的瓶颈。对于中国大陆的家用网络而言，最常碰到的两个问题应该就是 WiFi 信号覆盖不全和不能全局代理。</p>
<p>Mesh 技术和旁路由，就是为了解决这两个问题而产生的。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="无线-mesh">无线 Mesh<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E6%97%A0%E7%BA%BF-mesh" class="hash-link" aria-label="无线 Mesh的直接链接" title="无线 Mesh的直接链接" translate="no">​</a></h3>
<p>首先说一下无线 Mesh，这是一种为了解决 WiFi 信号覆盖甚至有线信号覆盖问题而产生的技术。</p>
<p>其实在无线 Mesh 出现之前，就有很多类似的技术能够解决这类问题。例如家庭和办公室使用比较多的，其实是 AC + AP 的技术：在墙内预埋网线，通过网线将很多 AP 连接到同一个 AC。可以认为 AP 这时是 AC 的扩展，可以将 AC 设备的网络以 WiFi 的方式扩展到它们所在的位置，避免了一个 AC 或路由器设备不能覆盖全屋无线信号的情况。同时，AC + AP 方案会通过一系列协议处理信号切换的问题，也就是在移动设备从一台 AP 的信号范围移入另一台 AP 的信号范围时，它可以在合适的时机通知设备切换连接信号发射源，并通过各种手段保证切换的无感，例如你正在打的游戏理论上在这个切换过程中也不会掉线。</p>
<p>但是对于出租屋这类场景，显然预埋网线是不太现实的。即使可以走明线，无论是从走线难度、美观度，还是从搬家时拆卸重装的复杂度来看，这也都不是一个很好的选择。</p>
<p>而无线 Mesh 技术恰好可以解决这个问题：它可以通过无线信号连接多个路由器，使得它们之间不再需要通过网线通信的情况下也能达到 AC + AP 的效果，也就是把之前预埋的网线用无线代替了。更进一步，各家的无线 Mesh 技术也有不同的优化，有一些甚至可以保证不再依赖一个中心结点（也就是之前的 AC），即使任何一台 Mesh 设备挂了，只要剩下设备之间的网络信号足够好，依旧可以组成一个无线 Mesh 网络。</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>无线 Mesh 技术的混乱命名</div><div class="admonitionContent_BuS1"><p>每个品牌也都会给自己的无线 Mesh 技术起一些奇奇怪怪的名字，比如本文中提到的 VELOP，就是 Linksys 的无线 Mesh 技术代号。再例如，华硕的技术叫做 AiMesh，TP-Link 的叫做“易展”（国外版本叫 Deco Mesh，但是并不和国内通用），小米则相对低调地叫“小米自研 Mesh”。</p><p>Linksys 的命名在各家的命名中尤其混乱，例如它们的 Atlas 路由器其实也是类似的无线 Mesh 技术，但这款路由器的名称却没有 VELOP 的名字——不过它们把这款路由器使用的 Linksys Intelligent Mesh 技术改名叫做 Velop Intelligent Mesh 了，也算是保留了这个品牌形象吧。（来源：<a href="https://www.hkepc.com/20766/VELOP_%E6%94%B9%E5%90%8D%E5%8F%88%E8%AE%8A%E7%B4%B0%E5%92%97__Linksys_Atlas_Pro_6_Mesh_Wi-Fi_%E7%B3%BB%E7%B5%B1" target="_blank" rel="noopener noreferrer" class="">VELOP 改名又變細咗 !? Linksys Atlas Pro 6 Mesh Wi-Fi 系統</a>）。</p></div></div>
<p>总之，部署了无线 Mesh 网络之后，可以认为无线信号就被简单地扩展到了更广的范围。而用户也不需要关心具体接入到了哪个无线信号，反正都可以看作直接接入了路由器的无线网卡。</p>
<p>一个更特殊的用法是：使用 Mesh 路由器扩展网络，之后将扩展的路由器 LAN 口接到电脑上。这样设置的网络中，电脑虽然看起来是通过扩展路由器的网线接入，但实际上数据是通过无线 Mesh 传输的，所以其实这台电脑也是接入了主路由器的无线网卡——很重要，一会儿要考。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="早期的全局代理方案">早期的全局代理方案<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E6%97%A9%E6%9C%9F%E7%9A%84%E5%85%A8%E5%B1%80%E4%BB%A3%E7%90%86%E6%96%B9%E6%A1%88" class="hash-link" aria-label="早期的全局代理方案的直接链接" title="早期的全局代理方案的直接链接" translate="no">​</a></h3>
<p>让我们暂且抛开刚刚介绍的的无线 Mesh，旁路由是一个和它没有直接关系的技术。这个技术的作用简单来说就是为网络接入第二个网关，通过将终端设备（电脑、手机、平板等等）的默认网关指向旁路由设备，达到所有网络流量都先经过旁路由设备处理，再转发给主路由，最终发送到互联网的效果。</p>
<p>而想要知道为什么会出现这种技术，还要从早期的全局代理方案说起。</p>
<p>众所周知，在搭建代理服务器的过程中，代理软件通常可以处理当前设备上的部分或所有流量，通过分流的方式让其中一部分流量发送到代理服务器，而另一部分流量走正常途径发出。如果想要把一个设备的代理软件分享给另一个设备，通常要通过局域网 SOCKS 代理之类的形式。</p>
<p>SOCKS 代理能用是能用，但是一个一个设置起来很麻烦。而且碰到一些不支持 SOCKS 代理或者不方便设置 SOCKS 代理的软件，事情就会更加复杂。</p>
<p>但是换一种想法，在上面提到的网络结构中，局域网的所有流量不是都会经过主路由器吗。而代理软件通常可以代理本机的所有流量，那只要我让代理软件跑在主路由器上，不就可以直接在路由器上代理所有流量并分流了吗？</p>
<p>幸运的是，绝大部分路由器的底层系统其实都是 UNIX 内核，把 Linux 上的代理软件迁移到上面不算难事。特别是有一些路由器厂商比如华硕，对这个方面也比较开放，默认提供了 SSH 功能，甚至允许更新自定义固件。</p>
<p>所以，可以看到早期的全局代理很多时候都会依赖魔改的华硕固件，甚至直接在支持的路由器上刷 OpenWrt 这种开源路由器系统来实现。</p>
<p>但是慢慢地，大家发现这种方案有时不太能满足需求。一方面，魔改系统的稳定性不一定有原版系统那么高，万一出现问题的话，整个家中的网络都会瘫痪；另一方面，这样魔改对主路由的性能要求很高，而高性能路由器毕竟也会伴随着比较高的价格。</p>
<p>为了解决上面的问题，新的方案就陆续被提出。</p>
<p>一类方案考虑直接用一台普通的 ARM / x86 设备加上开源路由器系统，在设备本身不支持路由的情况下，从软件层面实现路由功能，也被称之为“软路由”。但是这个方案只能一定程度解决价格和性能的问题，并不能很好地解决稳定性问题，甚至为了在软件模拟下也有足够的性能，反而会引入能耗之类的新问题。</p>
<p>而另一个方案则对设备的功能做了拆分，将一个低价的 ARM 设备接入网络，在这个设备上安装代理软件，并让流出的网络流量都先通过这个设备。这样主路由设备就只需要支持正常的路由器功能，而不需要支持全局代理了。</p>
<p>这个额外的设备，就是我们常说的“旁路由”。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="全局代理的改进方案旁路由">全局代理的改进方案：旁路由<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E5%85%A8%E5%B1%80%E4%BB%A3%E7%90%86%E7%9A%84%E6%94%B9%E8%BF%9B%E6%96%B9%E6%A1%88%E6%97%81%E8%B7%AF%E7%94%B1" class="hash-link" aria-label="全局代理的改进方案：旁路由的直接链接" title="全局代理的改进方案：旁路由的直接链接" translate="no">​</a></h3>
<p>说到这里，相比大家也都明白为什么我一开始说这台设备更应该被称作“旁路网关”了。</p>
<p>实际上，这个新增加的设备并不需要任何路由功能（或者更严谨一些，可能在一些场景下有一点点的路由功能，一般是 NAT）。它的作用是将流经的数据一部分分流到代理服务器，一部分直接传出，所有流量都会流经它的默认网关。与其说它在做的事情是路由，其实更像是一个独立的网关，唯一特殊的是它的流量来源和出口都是同一台设备，也就是主路由。</p>
<p>这样做带来的好处是显而易见的：主路由此时只需要支持一个正常路由器应该有的功能就可以了，绝大部分路由器的原版系统都可以支持这个场景，主路由稳定性会大大提升，对主路由的性能需求也会大幅下降。</p>
<p>而更进一步，当旁路由出现问题的时候，我们也只需要将它从网络上直接拔掉，再把网络中所有机器的默认网关从旁路由修改回主路由，这个网络就依然可以正常使用除了全局代理以外的所有其它功能。</p>
<p>因为有 DHCP 技术的存在，修改默认网关这件事通常也很简单，那就是直接在主路由的 DHCP 设置中修改一下默认网关地址。DHCP 服务会自动将这个默认网关下发给网络中的所有设备，不需要一台一台去设置。有些人希望指定家中的某几台设备走代理，对于他们来说这个配置是不必要的。但是我并不希望给家里几十台 IoT 设备和老婆的每个电子产品都配置一遍网关地址，所以我很需要这个能够自动下发默认网关的功能。</p>
<p>总结一下，按照上面的配置方式，在旁路由正常的时候，网络环境是这样的：</p>
<!-- -->
<p>而当旁路由失效的时候，我们只需要改成这样就可以上网：</p>
<!-- -->
<p>看起来一切都很美好……吗？</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="稳定或者死板">稳定，或者死板<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E7%A8%B3%E5%AE%9A%E6%88%96%E8%80%85%E6%AD%BB%E6%9D%BF" class="hash-link" aria-label="稳定，或者死板的直接链接" title="稳定，或者死板的直接链接" translate="no">​</a></h2>
<p>在购买 Linksys 的路由器之前，我就听说过他们的路由器以稳定著称。这不仅体现在很久都不更新一次的固件上，也体现在 Linksys 的固件几乎不支持任何 SSH 之类的扩展功能，前端界面的可配置项也很有限。当然或许也正是因为这样，这款路由器才能有如此的稳定性。</p>
<p>而当时的我正身受华硕路由器 AiMesh 不稳定的问题困扰，我的某两台华硕路由器之间的连接有时会从 5G 掉到 2.5G，有时甚至会直接断连，要重启两台路由器才能解决。</p>
<p>这种情况下，我自然很愿意牺牲一些扩展性，来换取路由器本身的稳定性。毕竟看起来需要扩展的功能都可以在旁路由上实现，主路由就不需要那么灵活了。</p>
<p>但直到开始部署路由器的时候，我才发现了情况有些不对。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="dhcp-无法修改默认网关">DHCP 无法修改默认网关<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#dhcp-%E6%97%A0%E6%B3%95%E4%BF%AE%E6%94%B9%E9%BB%98%E8%AE%A4%E7%BD%91%E5%85%B3" class="hash-link" aria-label="DHCP 无法修改默认网关的直接链接" title="DHCP 无法修改默认网关的直接链接" translate="no">​</a></h3>
<p>通常来说，将主路由配置好之后，我们只需要做这么几件事：</p>
<ol>
<li class="">把旁路由接入主路由的 LAN 口；</li>
<li class="">为旁路由设备固定一个 IP；</li>
<li class="">把主路由 DHCP 的默认网关地址改为刚刚固定的旁路由 IP；</li>
<li class="">重新连接各种设备或重启路由，使得设备可以重新从 DHCP 获取网关信息。</li>
</ol>
<p>但当我进行到第三步的时候，我惊讶地发现，Linksys 的 DHCP 配置页面上竟然没有配置默认网关地址的地方！</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="Linksys 配置页面" src="https://sqybi.com/assets/images/linksys-config-page-2e093b107ffee2bcd472127fdeab9a3b.png" width="846" height="457" data-zoomable="" class="img_ev3q"><div class="img-caption">Linksys 配置页面</div></div><p></p>
<p>我带着满脑子的“不可能”，开始到处查阅资料。但是查的资料越多，我就越感觉情况不对。</p>
<p>不管是中文网页还是英文网页，都能看到一些类似的问题。但是所有问题的结果，都指向了同一个答案：Linksys 根本不支持在 DHCP 中设置自身 IP 以外的网关。</p>
<p>甚至有人提到他去问了客服，但是客服也在答非所问，回答一直都是可以通过修改路由器本身的 IP 来更改默认网关地址，本质上还是只能将地址指向主路由。</p>
<p>我自己也抱着最后一丝希望问了一下 GPT，结果 GPT 倒是很笃定：抱歉，就是没有这个设置！</p>
<p>连这样常用的配置都没有，这已经不是单纯的稳定，更可以说是一种死板了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="我旁路由也是可以-dhcp-哒">我旁路由也是可以 DHCP 哒！<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E6%88%91%E6%97%81%E8%B7%AF%E7%94%B1%E4%B9%9F%E6%98%AF%E5%8F%AF%E4%BB%A5-dhcp-%E5%93%92" class="hash-link" aria-label="我旁路由也是可以 DHCP 哒！的直接链接" title="我旁路由也是可以 DHCP 哒！的直接链接" translate="no">​</a></h3>
<p>多处查找未果后，我也基本放弃了在 Linksys 的系统中修改 DHCP 默认网关配置的可能性。虽然不知道禁止修改默认网关能不能真的提升路由器的稳定性，但至少我先提前支付了稳定的代价。</p>
<p>不过没有关系，虽然主路由的 DHCP 缺斤短两，但我们还有旁路由。</p>
<p>理论上来说，因为我的旁路由也安装了 OpenWrt 系统而非普通 Linux，所以系统中已经自带了一个 DHCP 服务器。只要关闭主路由的 DHCP 服务，并在旁路由开启服务，也可以达到完全一样的效果。</p>
<p>之所以没有一开始就使用这个方案，主要还是因为这个方案在旁路由出现问题的时候，切换成本稍微大一些：原先只需要修改一个默认网关，现在还需要重新开启主路由的 DHCP 服务。另外，因为同一个网络里同时存在两个 DHCP 服务器会产生冲突，所以在恢复旁路由的时候，也需要先关闭主路由的 DHCP 服务，再开启旁路由的 DHCP 服务才可以。</p>
<p>但是在没有选择的情况下，其实这个方案也麻烦不了多少。于是我快速进行了一些配置，调整到了旁路由 DHCP 的方案。</p>
<p>全部配置完成后，我在自己的电脑上测试了一下，无论是网络访问还是代理都工作得很正常。我以为所有事情都已经做完了，于是告诉老婆网可以用了，然后——</p>
<p>原神，启动！</p>
<p>结果游戏还没加载完，就收到了老婆的投诉。</p>
<p>家里除了我这台电脑之外所有的终端设备，似乎都没有网络了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ipv4-和-ipv6">IPv4 和 IPv6<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#ipv4-%E5%92%8C-ipv6" class="hash-link" aria-label="IPv4 和 IPv6的直接链接" title="IPv4 和 IPv6的直接链接" translate="no">​</a></h3>
<p>这里需要介绍一个背景，那就是老婆那台台式机的网络接入。因为这台台式机在书房，而屋子的结构不太方便走线，所以我采用的组网方式是在屋里放置了一个 Mesh 节点，并将这台台式机用有线的方式连入了这个节点的 LAN 口。</p>
<p>简单画一下，网络结构大概是这样的：</p>
<!-- -->
<p>一开始我还以为是 WiFi 设置的问题，但听说这台台式机也不能连网了，这问题就变得很诡异了。</p>
<p>虽然接入了一台 Mesh 设备，但是电脑本身还是用有线的方式和设备相连的，而 Mesh 协议也只是走了 WiFi 的通道，本身的连接并不会受 WiFi 的影响。更何况，看起来不能访问的只有互联网，局域网还是可以访问——也就是说，Mesh 的通路本身是没有问题的。</p>
<p>之前配置网络的时候我曾经遇到过旁路由上的 DNS 在某些设备，特别是 Windows 上通过 IPv6 连接时，可能会出现 IPv6 DNS 地址获取错误的情况。所以我当时也是不慌的：不管怎么样，先把 IPv6 关了试一下。</p>
<p>但是不试不知道，一试吓一跳：原来上次配置网络的时候我已经把网卡的 IPv6 协议关上了，也就是说，现在无法访问互联网的问题是出现在纯 IPv4 网络下的。</p>
<p>更诡异的是，当我打开 IPv6 协议之后，很多网站又突然可以访问了。虽然有一些应用依旧有问题，比如 QQ 还是不能登录，但这样推测很大概率是 IPv4 的网络出现了问题，而 QQ 这些应用只能走 IPv4，所以才不能使用。</p>
<p>其实到这里我是放心了一些的，毕竟相比复杂的 IPv6，IPv4 相对来说还是我熟悉的领域。上网搜一搜，总能找到一些答案的嘛。</p>
<p>原神，关闭。</p>
<p>Google，启动！</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="突如其来的解决方案">突如其来的解决方案<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E7%AA%81%E5%A6%82%E5%85%B6%E6%9D%A5%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88" class="hash-link" aria-label="突如其来的解决方案的直接链接" title="突如其来的解决方案的直接链接" translate="no">​</a></h2>
<p>经过一番搜索，我发现这个问题比想象中的更加复杂。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="知其然不知其所以然">知其然不知其所以然<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E7%9F%A5%E5%85%B6%E7%84%B6%E4%B8%8D%E7%9F%A5%E5%85%B6%E6%89%80%E4%BB%A5%E7%84%B6" class="hash-link" aria-label="知其然不知其所以然的直接链接" title="知其然不知其所以然的直接链接" translate="no">​</a></h3>
<p>网上有不少人遇到了类似的问题，但是大部分场景都不和我这个场景完全一样。同时，可能是关注 IPv6 的人比较少，我也并没有看到过汇报 IPv6 可用但 IPv4 可用的情况。</p>
<p>不过我还是发现了一些端倪，一些讨论中经常会提到，在接入了旁路由之后，出现了有线上网可用，但是 WiFi 不可用的场景。</p>
<p>如果忽略我老婆的那台通过 Mesh 有线连接的电脑，那么其它的设备正好体现出上述的这种特性。</p>
<p>考虑到电脑通过有线连接到 Mesh 节点应该也不是一种很常见的网络结构，所以很可能这就是同一个问题。而部分问题下面也给出了解决方案，只需要在旁路由中设置一下 iptables：</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">iptables -t nat -I POSTROUTING -j MASQUERADE</span><br></span></code></pre></div></div>
<p>就可以让所有设备正常上网了！</p>
<p>而我尝试了一下这个方案，发现确实可以解决问题。不光是所有的无线设备，此时就连我老婆那台电脑，都可以正常上网了。</p>
<p>虽然问题暂时是解决了，但是作为一个程序员，显然不能满意这样一个答案。既不知道发生了什么，也不知道这个改动有没有副作用。</p>
<p>好在因为之前研究过 <a href="https://github.com/Tilerphy/ps4broadcast/" target="_blank" rel="noopener noreferrer" class="">ps4broadcast</a> 这个项目，也进行过一些二次开发，所以我对 iptables 还是有一些了解的。很显然，上面的命令是尝试在旁路由上进行 DNAT 地址转换。</p>
<p>通常来说，因为路由器的 IPv4 子网地址是私有地址，所以路由器必然会在私网地址和公网地址之间进行一次 NAT 转换。既然主路由已经有了这个功能，为什么需要在旁路由上再进行一次 DNAT，才能正常访问网络呢？</p>
<p>更进一步讲，如果是主路由的 NAT 转换出了问题，那为什么有线网络不会受到影响，单单是无线网络和 Mesh 受到了影响呢？WiFi 的连接和 Mesh 的连接，它们之间又有什么共同之处？</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="间章iptables">间章：iptables<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E9%97%B4%E7%AB%A0iptables" class="hash-link" aria-label="间章：iptables的直接链接" title="间章：iptables的直接链接" translate="no">​</a></h3>
<p>在继续讲故事之前，为了让你们能够听懂我在说什么，这里也讲一下 iptables 是什么。</p>
<p>有一些网络经验的小伙伴都能说出，iptables，不就是 Linux 的防火墙吗？</p>
<p>对，也不对。</p>
<p>iptables 的功能看起来是对于所有流经内核的网络包，指定一些规则进行过滤和修改，之后再将网络包发出。将这样的功能称作“防火墙”，似乎也没什么不妥，甚至连 <a href="https://www.netfilter.org/" target="_blank" rel="noopener noreferrer" class="">netfilter</a> 项目的主页都是这样写的：</p>
<blockquote>
<p>iptables is a generic <strong>firewalling software</strong> that allows you to define rulesets. Each rule within an IP table consists of a number of classifiers (iptables matches) and one connected action (iptables target).</p>
</blockquote>
<p>等一下，为什么 iptables 的介绍在一个叫“netfilter”的网站上？</p>
<p>这就是“也不对”的部分了：事实上，真正执行这些规则的，是 Linux 内核中一个叫做 netfilter 的框架。上面的网站上也有介绍：</p>
<blockquote>
<p>The netfilter hooks are a framework inside the Linux kernel that allows kernel modules to register callback functions at different locations of the Linux network stack. The registered callback function is then called back for every packet that traverses the respective hook within the Linux network stack.</p>
</blockquote>
<p>所以打一个比方，iptables 就像是 netfilter 框架的一个前端工具，用于更简便地配置防火墙的条目。</p>
<p>不过对于大多数用户来说，倒也没有必要区分得这么清楚。知道 iptables 可以配置 Linux 内核的防火墙，已经足够理解大部分内容了。</p>
<p>而这里的“防火墙”，其实也不能单纯当作杀毒软件中的防火墙来理解。很多杀毒软件的防火墙只能控制数据包的通过与否，而 iptables 不仅可以控制数据包的通过，还可以修改 IP 协议数据包头部的内容。</p>
<p>而这，也就是 iptables 可以实现 NAT 的原理。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="间章nat">间章：NAT<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E9%97%B4%E7%AB%A0nat" class="hash-link" aria-label="间章：NAT的直接链接" title="间章：NAT的直接链接" translate="no">​</a></h3>
<p>讲到实现 NAT，就不得不说一下 NAT 是什么。这里跳过 TCP/IP 四层模型和 OSI 七层模型的基础知识，因为它们不太会影响后续的理解。想仔细理解的同学，请自行翻出《计算机网络》开始恶补。</p>
<p>根据 <a href="https://en.wikipedia.org/wiki/IPv4_header" target="_blank" rel="noopener noreferrer" class="">IPv4 Header</a> 中的介绍，IP 数据包的头部包含了一些路由和数据传输过程中需要的信息。而为了理解 NAT，我们需要关注的是“Source IP Address”和“Destination IP Address”两条信息，下面简称为 saddr / daddr。</p>
<p>从 IP 层的数据传输角度，一个数据包从一个内网地址的机器发送到互联网，通常经历了这样几个流程：</p>
<ol>
<li class="">从内网机器发送到默认网关，也就是路由器。此时数据包的包头中，saddr 地址是内网机器的地址，而 daddr 则是公网的目标地址。</li>
<li class="">默认网关也就是路由器收到数据包后，需要判断它将要发到的地址，并对应进行转发。这里先考虑没有旁路由的简单网络环境，此时默认网关发现目标地址是互联网上的地址，于是需要将数据包转发给互联网上的下一级路由器，这个路由器会通过你的运营商网线和若干交换机，与你的路由器相连。</li>
<li class="">之后经过互联网上路由器的多次转发，这个数据包到达了服务器。而服务器大概率也要给你一个回复，此时它会使用原先数据包中的 saddr 作为回复数据包的 daddr，并通过互联网上的路由器传回你的路由器。</li>
<li class="">你的路由器再根据 daddr 的信息，将响应发回给你的内网机器。这样，就完成了一次通信。</li>
</ol>
<p>完美吗？并不是，只要有一些网络常识的小伙伴都能看出来，这里有一个非常明显的问题。</p>
<p>在 IPv4 协议中，内网机器的地址通常是一个私有地址，也就是 <code>192.168.1.123</code> 这样的地址（当然也有一些其它的地址段，这里用最常见的 C 类地址举例）。而私有地址的特点就是：你家的局域网是这个地址，我家的局域网也是这个地址。稍微搞过家里的网络就会知道，大部分路由器的默认地址都是一样的 <code>192.168.0.1</code> 或者 <code>192.168.1.1</code>，并不会因为放在不同的屋子里而有所区别。</p>
<p>如果 saddr 的地址是 <code>192.168.1.123</code>，在上述步骤中的第一和第二步都是没有任何问题的。但是到了第三步的时候，服务器会将收到数据包的 saddr 作为回复数据包的 daddr，再发出去的时候问题就来了：互联网上的路由器根本不认识这个地址是谁家的 <code>192.168.1.123</code>！</p>
<!-- -->
<p>这样的话，这个数据包，你显然就收不到了。</p>
<p>对于 IPv6，因为地址空间非常充足，所以采取了一种很奢侈的办法：别用私有地址了，所有的地址都是公有地址，地址全部是唯一的，这样我不就能通过地址直接找到设备了吗。</p>
<p>但是对于 IPv4，私有地址的划分本来就是因为公有地址不够用了，让我给每个人分一个公有地址，臣妾做不到啊。于是，就只能用 NAT 这样的办法，来解决数据如何传回来的问题。</p>
<p>NAT，全称是“Network Address Translation”，网络地址转换。它的功能和名称基本一致，就是一个把公有地址和私有地址（其实也包括私有地址之间，原理是类似的，这里不展开说了）来回转换的技术。</p>
<p>回顾一下上述的四个步骤，第三步中因为操作完全在服务器端，所以使用 saddr 作为回复的 daddr 这件事是不能更改的。那么如果我们想让 daddr 能够正确地指向家里路由器的公网地址，就只能提前修改 saddr 了。</p>
<p>而路由器的 NAT 正是在第二步的时候，提前替换 saddr 为公网地址。这样，服务器端就可以在回复的时候，填写正确的 daddr 了，如下：</p>
<!-- -->
<p>但这里也引入了一个新的问题，那就是回程时的 daddr 变成了一个固定的公网地址。那么假设内网中还有另外一台机器，我们怎么区分应该将回复转发给哪台机器呢？</p>
<p>好在除了 IP 地址，数据头中还有很多其它可以使用的信息，例如端口。路由器可以将自己向外发送请求时的端口绑定到发送时的内网 IP，这样等到数据包从同一个端口回来的时候，路由器就可以查询当时发送的内网 IP 地址，并正确转发回这台机器了。</p>
<p>将发送请求和收取回复这两个步骤拆分开的话，我们将前者称作 SNAT，即 Source Network Address Translation；而后者称作 DNAT，即 Destination Network Address Translation。这两个名字也与实际的过程吻合：SNAT 修改了 source address，而 DNAT 修改（判断）了 destination address。</p>
<!-- -->
<p>不过可能是为了简洁，我们通常说的 SNAT，指的其实是先进行 SNAT 后进行 DNAT 的整个过程。</p>
<p>与之相对的，DNAT 则是先进行 DNAT 后进行 SNAT，也就是外部地址通过公网请求你的路由器，由你的路由器转发到内网机器上的过程。配置过路由器的同学一定见过类似的功能，它的名字叫做“端口转发”。不过这个功能和这篇文章无关，这里就不展开说了。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="打破砂锅问到底">打破砂锅问到底<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E6%89%93%E7%A0%B4%E7%A0%82%E9%94%85%E9%97%AE%E5%88%B0%E5%BA%95" class="hash-link" aria-label="打破砂锅问到底的直接链接" title="打破砂锅问到底的直接链接" translate="no">​</a></h2>
<p>书接上文，现在的情况是有线网络和 IPv6 没有受到影响，仅仅在通过无线网络传输数据且协议为 IPv4 的情况下，才会出现问题。而且，解决问题的方式竟然是在旁路由上再做一次 NAT。</p>
<p>至此，我的判断是大概率主路由的 NAT 功能出现了问题。这是因为 IPv6 网络并不需要纯内网地址，所有地址都是可以路由的公网地址，所以不需要 NAT 的 IPv6 没有受到影响；而接入旁路由之前网络连接是正常的，有理由相信这应该是网络结构的变化导致 NAT 出现了一些问题。</p>
<p>带着 NAT、无线网络、旁路由这些关键词，我又进行了新一轮的搜索。</p>
<p>功夫不负有心人，终于在 <a href="https://cloud.tencent.com/developer/article/2036952" target="_blank" rel="noopener noreferrer" class="">关于旁路由设置后，主路由WIFI无法上网的问题</a> 这篇文章中，我找到了关于所有问题的解答。作为这篇超长文章的最后一部分，请允许我再花一些时间，把这些解答和分析用我的方式转述给大家。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="网桥和-iptables">网桥和 iptables<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E7%BD%91%E6%A1%A5%E5%92%8C-iptables" class="hash-link" aria-label="网桥和 iptables的直接链接" title="网桥和 iptables的直接链接" translate="no">​</a></h3>
<p>文章中给出了这样一个关键信息：对于 Redmi AX5 路由器，有线网口和无线网口之间是有一个虚拟网桥的，且某个内核变量的设置导致了虚拟网桥上的流量会交由 iptables 处理。</p>
<p>为了避免文章过于冗长，这里就不再展开解释网桥的概念了。你可以简单认为是为了让路由器上不同的网口能够互相传输数据，需要像搭桥一样将它们接在一起。</p>
<p>对于不同有线网口的数据传输，路由器本身可以通过内部的交换机芯片，直接在硬件上传输数据。这个时候，路由器的操作系统内核是看不到这些数据的。</p>
<p>但是对于有线网口和无线网口之间的数据，因为底层协议不同，所以必须要交给 CPU 进行一些数据转换。此时，路由器的软件内核就会处理这些数据。</p>
<p>通常情况下，内核也只是简单处理一下数据格式转换，再转发数据到对应网口就结束了。好巧不巧，Redmi AX5 路由器在某些特定状态下可能会开启这样一个 <code>sysctl</code> 配置：</p>
<div class="language-ini codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ini codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">net.bridge.bridge-nf-call-iptables = 1</span><br></span></code></pre></div></div>
<p>而这个配置的含义就是，让刚刚提到的这些通过网桥跨网口传输的数据，全部走一遍 iptables 防火墙。</p>
<p>我们都知道（不知道也没关系），iptables / netfilter 是具有状态机制的防火墙。它的状态机制实现导致了，如果是被它判定成属于同一个 stream 的数据包，在首次通过 nat 表进行了 NAT 转换后，无论转换结果如何，后续的包都会使用同样的转换方案。</p>
<p>关于如何判定成同一个 stream，这里也不需要更详细地了解。但显而易见，如果一个数据包原封不动地经过 iptables 两次，那它一定会被判定为同一个 stream。</p>
<p>而如果这个包第一次被 NAT 规则判定为不需要进行转换，那么第二次通过的时候，就不会再判定一次，而是直接不进行转换发出。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="网络结构带来的巧合">网络结构带来的巧合<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E7%BD%91%E7%BB%9C%E7%BB%93%E6%9E%84%E5%B8%A6%E6%9D%A5%E7%9A%84%E5%B7%A7%E5%90%88" class="hash-link" aria-label="网络结构带来的巧合的直接链接" title="网络结构带来的巧合的直接链接" translate="no">​</a></h3>
<p>知道了上面的信息，让我们回顾一下 NAT 部分提到的网络结构（简化了端口部分）：</p>
<!-- -->
<p>如果我们在这个网络结构中加入旁路由，那么数据传输的前几步就会变成这样：</p>
<!-- -->
<p>可以看到，因为内网机器的网关设置为旁路由，所以数据包首次经过主路由的时候，会被转发旁路由上。此时，因为旁路由的 IP 也是一个内网地址，所以主路由判定不需要进行 NAT。</p>
<p>如果内网机器与旁路由都是通过有线网络和主路由连接的，那么这个数据包不会被主路由的 iptables 处理，也就没有任何问题。但是当内网机器是通过无线网络连接到主路由（包括 Mesh 连接）时，问题就出现了：iptables 处理了这个数据包，虽然正确转发给了旁路由，但它也记住了一件事情：这个数据包是不需要做 NAT 的。</p>
<p>再继续看几步，就会发现问题所在：</p>
<!-- -->
<p>因为旁路由的网关是主路由，所以在处理了这个数据包之后，旁路由会再次将这个数据包扔回给主路由。本来主路由发现这个数据包这次要发向外网了，是应该对它进行一次 NAT 转换的。可因为状态机制的存在，此时主路由会以为这个数据包是之前 stream 的一部分，是一个不需要转换的数据包——于是主路由没有修改 saddr，就把这个数据包发给了互联网（上图中的第四步 <code>!!!</code> 部分）。</p>
<p>接下来的事情就和 NAT 章节里没有 NAT 的场景完全一致了：服务器受到数据包后，将数据包的 saddr 作为回复数据包的 daddr 发出。但此时因为 daddr 是一个内网地址，所以互联网上的服务器一脸懵逼，不知道应该把数据包发给谁，只能丢掉数据包（上图中的第五步 <code>???</code> 部分）。而路由器和内网机器，也永远都不会收到这个回复了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="怎么又是-dhcp-哒">怎么又是 DHCP 哒！<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E6%80%8E%E4%B9%88%E5%8F%88%E6%98%AF-dhcp-%E5%93%92" class="hash-link" aria-label="怎么又是 DHCP 哒！的直接链接" title="怎么又是 DHCP 哒！的直接链接" translate="no">​</a></h3>
<p>路由器真的这么傻，以至于连这种场景都解决不了吗？当然不是，实际上只要不让网桥上的流量被 iptables 处理，NAT 的结果就不会被缓存，就能够解决刚刚的问题。</p>
<p>在上面的文章中，作者其实也分析了 Redmi AX5 路由器是如何处理这种情况的。</p>
<p>总结起来，小米的路由器其实进行了一些检查，在 DHCP 的 DNS 或网关中至少有一个配置项的 IP 不是路由器自身的 IP 时，会通过 sysctl 关闭使用 iptables 处理网桥流量的这个功能。</p>
<p>这里会出现 DHCP 看起来很突兀，但仔细想想其实很合理：刚刚的功能很显然是为了优化 NAT 性能，减少 NAT 判断的；但是在有旁路网关（请允许我这里暂时不使用“旁路由”这个词，毕竟这里需要的确实是网关）的时候，这个功能很显然会出现问题。而 DHCP 的这两个配置，将部分网络流量指向了路由器之外的 IP，基本也就意味着网络中存在一个其它旁路网关，且到达这个旁路网关的流量一定会被路由器转发。</p>
<p>所以小米的路由器其实很巧妙地规避了这个问题：只要正常开启 DHCP 服务，并正确配置默认网关，所有流量就都可以被正常 NAT。</p>
<p>即使有其它原因导致不能在小米路由器上开启 DHCP 服务或调整这个设置也没关系，我们还有一个最终方案，那就是 SSH 连到路由器上，直接修改处理对应逻辑的脚本。虽然这样会影响一些稳定性，但至少能够解决问题。</p>
<p>现在 Linksys 路由器上表现出的现象，和 Redmi AX5 上的现象出奇地一致。虽然我没有实际抓包，但是基本也可以笃定，这里遇到的就是这个问题。</p>
<p>既然小米路由器有这个判断逻辑，那我们或许有理由相信，Linksys 的路由器也可以这样设置。</p>
<p>是这样吗？</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="似乎不行">似乎……不行？<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E4%BC%BC%E4%B9%8E%E4%B8%8D%E8%A1%8C" class="hash-link" aria-label="似乎……不行？的直接链接" title="似乎……不行？的直接链接" translate="no">​</a></h3>
<p>说到这里可能大家已经把前面的内容差不多忘光了，请允许我提醒一下：在文章的最开始，我就介绍了 Linksys 路由器的一个最大的问题：DHCP 服务器不能设置默认网关！</p>
<p>这个问题导致了在我配置的网络环境中，主路由器是没有开启 DHCP 功能也不能开启 DHCP 功能的，开启它会导致没有办法自动设置默认网关为旁路由。而这个功能，也因此被迫转移到了旁路由上开启。</p>
<p>之前这个问题可能还只是一个小事，最多导致我们的网络结构变更稍微麻烦一点。但现在它却变成了一个非常致命的问题，让我们直接失去了通过修改 DHCP 配置正确设置 NAT 的这个方案。</p>
<p>也就是说，无论 Linksys 的路由器有没有上述判断逻辑，现在 DHCP 都开不起来，也就无从验证和解决了。</p>
<p>而 Redmi AX5 上的终极方案，也就是直接 SSH 改代码的方案，这里也没有办法使用。正如上面说过的，可能是处于稳定性的考虑，Linksys 的路由器甚至没有开放 SSH 端口，也没有在界面上暴露任何相关的配置。</p>
<p>看起来这条路已经走到了死胡同，但稍微回顾一下，就会发现刚刚我们似乎已经在旁路由上通过修改 iptables 配置解决过这个问题了。那么当时的方案是怎么解决问题的，又有什么副作用呢？</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="旁路由-nat-是如何解决问题的">旁路由 NAT 是如何解决问题的<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E6%97%81%E8%B7%AF%E7%94%B1-nat-%E6%98%AF%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3%E9%97%AE%E9%A2%98%E7%9A%84" class="hash-link" aria-label="旁路由 NAT 是如何解决问题的的直接链接" title="旁路由 NAT 是如何解决问题的的直接链接" translate="no">​</a></h3>
<p>刚刚有解释过，旁路由的那条 iptables 命令：</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">iptables -t nat -I POSTROUTING -j MASQUERADE</span><br></span></code></pre></div></div>
<p>实际上就是一条 SNAT 的规则。<code>nat</code> 和 <code>POSTROUTING</code> 涉及到 iptables 的表和链的实现，暂且不表，简单理解成一个过滤器就行；而这里的 <code>-j MASQUERADE</code> 其实和 <code>-j SNAT</code> 基本是同样的功能，就是对数据包进行 SNAT 转换，区别在于 <code>-j SNAT</code> 需要手动指定一个地址，而 <code>-j MASQUERADE</code> 则会自动获取网卡的地址进行转换。</p>
<p>而设置了这条规则之后，所有数据包中的 saddr，就会从原先的内网机器 IP，变为旁路由的 IP。这样主路由就不会将这个修改后的数据包看作刚刚那个数据包 stream 的一部分，而是会当作一个新的数据包，重新在主路由上做一次 NAT，也就规避了缺少一次 NAT 的问题。</p>
<p>而服务器发送回复数据包的时候，因为主路由记录的原始数据包是由旁路由发出的，所以回复的数据包也会被转发到旁路由。而旁路由的 iptables 因为设置了 <code>MASQUERADE</code> 规则，所以也会和主路由一样记录一个对应关系，并再次将主路由发过来的这个数据包转发给刚刚的内网机器。这样，就打通了全部的通路，内网机器也能够收到正确的数据包了。</p>
<p>此时的数据流大概是这样：</p>
<!-- -->
<p>这大概是文章里最复杂的一个图了，希望你能看懂。不过看不懂也没关系，总之就是出去的时候数据包经历了 内网机器 --&gt; 主路由 --&gt; 从路由 --&gt; 主路由 --&gt; 服务器的过程，而回复的数据包则反过来走了一次全程。</p>
<p>这个解决方案中，旁路由终于有了一些名副其实的作用：它完整地执行了主路由和内网机器之间的 NAT 转换，除了和主路由在同一个内网以及所有流量经过主路由以外，其它的部分表现得就像一个挂在主路由下面的二级路由一样。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="旁路由-nat-的副作用">旁路由 NAT 的副作用<a href="https://sqybi.com/blog/linksys-velop-and-bypass-gateway/#%E6%97%81%E8%B7%AF%E7%94%B1-nat-%E7%9A%84%E5%89%AF%E4%BD%9C%E7%94%A8" class="hash-link" aria-label="旁路由 NAT 的副作用的直接链接" title="旁路由 NAT 的副作用��的直接链接" translate="no">​</a></h3>
<p>问题解决了，但这并不是最好的方案。</p>
<p>正如上面所说，回复的数据包是反过来走了一次全程的。</p>
<p>对于通过代理软件代理的流量，因为本身就相当于旁路由重新发出了一个请求，所以其实不会受 SNAT 与否的影响，总会走完这整条路经。但是对于普通的非代理流量，我们更期望的是在回程时直接从主路由转发到内网机器，而不是再经过一次旁路由，平白无故地多出两次数据包转发的开销。</p>
<p>而本来禁止网桥数据包通过 iptables 的方案，是能做到这一点的。但因为 Linksys 的功能过于保守，我们恐怕没有任何办法可以实现这个方案了。</p>
<p>最终，我在完成了上面所有这些内容的验证之后，还是选择了退货。本来想直接换成小米的路由器，但是想了想还是下单了几台网件的路由器，准备趁着这个机会试一试不同品牌的情况，多踩一踩坑。</p>
<p>毕竟对于爱折腾的人来说，踩坑的经历，其实才是生活中最有趣的那部分。</p>
<div class="theme-admonition theme-admonition-danger admonition_xJq3 alert alert--danger"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>但还是请听我一言</div><div class="admonitionContent_BuS1"><p>不要折腾网络，会变得不幸。</p></div></div>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 计算机技术</category>
        </item>
        <item>
            <title><![CDATA[带着路书去旅行]]></title>
            <link>https://sqybi.com/blog/traveling-with-a-travel-map/</link>
            <guid>https://sqybi.com/blog/traveling-with-a-travel-map/</guid>
            <pubDate>Tue, 28 Nov 2023 20:30:00 GMT</pubDate>
            <description><![CDATA[每次出门旅行之前，我们必然都会进行一些旅行规划。]]></description>
            <content:encoded><![CDATA[<p>每次出门旅行之前，我们必然都会进行一些旅行规划。</p>
<p>对于我来说，旅行规划中最重要的一环，就是准备一份旅行的路书，里面包括了各种旅行的路线和时间安排。</p>
<p>除非体力不允许，通常来说我们的旅行都会按照路书上记载的大体方向进行，当然也会根据实际情况有各式各样的微调。而无论是希望方便地查看后续路线，记录已经走过的景点，还是随时微调路线，一个好用的路书软件自然必不可少。</p>
<p>我希望在这篇文章中根据自己的经验，推荐一些国内外旅行时好用的路书软件。希望它们在大家的下一次旅行规划中能够有所帮助。</p>
<p>这里先给出一个我推荐的软件和简单的关键词总结，但是我相信大部分读者应该更关心我在体验它们的过程中都遇到了什么。</p>

























<table><thead><tr><th style="text-align:left">软件</th><th style="text-align:left">适用范围</th><th style="text-align:left">优缺点</th></tr></thead><tbody><tr><td style="text-align:left">Google My Maps</td><td style="text-align:left">国外旅行</td><td style="text-align:left">优秀的基础功能；几乎没有额外功能，手机端易用性一般</td></tr><tr><td style="text-align:left">高德路书</td><td style="text-align:left">国内旅行</td><td style="text-align:left">够用的基础功能，认真的产品和开发团队；功能略显简陋，缺少步行导航</td></tr><tr><td style="text-align:left">exping</td><td style="text-align:left">国内旅行</td><td style="text-align:left">优秀的基础和附加功能，社区等额外功能不会强行引流，手机端极其好用；网页端体验较差，问题很多</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="什么是路书">什么是路书<a href="https://sqybi.com/blog/traveling-with-a-travel-map/#%E4%BB%80%E4%B9%88%E6%98%AF%E8%B7%AF%E4%B9%A6" class="hash-link" aria-label="什么是路书的直接链接" title="什么是路书的直接链接" translate="no">​</a></h2>
<p>“路书”是一个很神奇的词。在中文互联网语境中，这个词似乎能广泛地被人接受，且在不同场景下自然地代表了不同的含义。但是在英文语境中，这个词会在不同场合对应到完全不同的英文单词。</p>
<p>我并不是很熟悉这个词具体的来源，所以本来不应该班门弄斧的。但是为了对后面要聊的概念进行一些基本的解释，我也只能根据我自己掌握的知识和搜索的结果来推测这个词的来源了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="拉力赛或许是起源pacenotes-和-roadbook">拉力赛或许是起源：Pacenotes 和 Roadbook<a href="https://sqybi.com/blog/traveling-with-a-travel-map/#%E6%8B%89%E5%8A%9B%E8%B5%9B%E6%88%96%E8%AE%B8%E6%98%AF%E8%B5%B7%E6%BA%90pacenotes-%E5%92%8C-roadbook" class="hash-link" aria-label="拉力赛或许是起源：Pacenotes 和 Roadbook的直接链接" title="拉力赛或许是起源：Pacenotes 和 Roadbook的直接链接" translate="no">​</a></h3>
<p>不知道有多少人和我一样——我自己第一次听说“路书”这个词，是在拉力赛中。</p>
<p>当年人们的主要娱乐活动还是电视节目，我家自然也不例外。在 CCTV-5 转播的达喀尔拉力赛中，我第一次知道了这种赛车比赛原来还需要一个领航员，对着一份叫做“路书”的东西告诉车手应该怎么开。</p>
<p>简单来说，车手在正式比赛之前一般都会把路线开上两次。第一次用于记录路书，第二次用于和领航员核对路书并进行修正（来源：<a href="https://www.zhihu.com/question/24806202/answer/379193213" target="_blank" rel="noopener noreferrer" class="">拉力赛车手和领航员是如何配合的？</a>）。而这里路书的叫法，似乎有 <a href="https://en.wikipedia.org/wiki/Pacenotes" target="_blank" rel="noopener noreferrer" class="">pacenotes</a> 和 <a href="https://en.wikipedia.org/wiki/Roadbook" target="_blank" rel="noopener noreferrer" class="">roadbook</a> 两种。</p>
<p>关于两个单词的用法，一说是官方的全程路书叫 roadbook，领航员的赛段路书叫 pacenotes；另一说是两者没有什么太大区别。我并非要进行拉力赛的入门介绍，也没有这个能力，所以这里也就不展开讨论了。</p>
<p>其实不光是拉力赛，其它赛车比赛也可能有领航员和路书。大部分情况下，路书至少承担了标记各种地形和弯道的作用。特别是在很长的路线中，车手的记忆力不足以支持他们像 F1 跑圈那样可以记住所有路线中的弯道和特殊地形特点，这时允许一个领航员使用路书进行提醒，车手就可以更专注于驾驶技巧，这是可以增加比赛观赏性的。</p>
<p>而对于野外定向拉力赛，路书还有一个额外的功能，那就是配合导航信息（电子罗盘）进行定位和导航，避免“开错路”的尴尬局面。可不要认为这是闹着玩的——野外特别是沙漠中的救援不会像公路上那么及时，甚至对于部分比赛（比如达喀尔拉力赛），路线可能还会穿越战争中遗留的雷区，万一走错了可是要踩地雷的。</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>电子路书</div><div class="admonitionContent_BuS1"><p>记得当年看比赛的时候，领航员或者手里会拿着一个本子，写着手记的路书；或者会打印一份长长的纸条。</p><p>但是这次我搜索资料的时候，发现路书似乎也电子化了，和电子罗盘导航系统合并在了一起。不过很久不开比赛了，我也不确定这个技术是不是已经广泛地被使用，或者说还有很多车手和领航员依旧坚持使用自己更习惯的传统路书？</p><p>不知道评论里有没有了解拉力赛的同学可以帮忙解惑。</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="自行车骑行的路书cue-sheet">自行车骑行的路书：Cue Sheet<a href="https://sqybi.com/blog/traveling-with-a-travel-map/#%E8%87%AA%E8%A1%8C%E8%BD%A6%E9%AA%91%E8%A1%8C%E7%9A%84%E8%B7%AF%E4%B9%A6cue-sheet" class="hash-link" aria-label="自行车骑行的路书：Cue Sheet的直接链接" title="自行车骑行的路书：Cue Sheet的直接链接" translate="no">​</a></h3>
<p>近些年来，自行车公路和越野骑行已经从一个小众运动，慢慢壮大并进入人们的视野。自行车骑行需要的“路书”，是圈子里常见的讨论内容。</p>
<p>而当我使用 bicycle + pacenotes 作为关键词搜索的时候，却发现并不能找到什么有用的信息。经过一番搜索，我发现似乎自行车领域使用的“路书”应该叫做 cue sheet，例如 <a href="https://lifeisabeautifuldetail.com/blog/cue-sheets" target="_blank" rel="noopener noreferrer" class="">Just The Tip: Cue Sheets</a> 和 <a href="https://www.ridestudiocafe.com/connect-communicate/clinics/how-to-read-a-cue-sheet" target="_blank" rel="noopener noreferrer" class="">How to Read a Cue Sheet</a> 所提到的。</p>
<p>而自行车比赛和赛车的最大区别就在于，自行车比赛是不可能有领航员的，所以也很难通过选手自己勘察路线记录路书。取而代之的是对于类似环法这种大型的比赛，会由官方统一发布路书。</p>
<p>而受限于自行车的结构，这种路书也都不会很大，通常是一些小纸条，可以直接贴在车把上。</p>
<p>对于骑行爱好者，应该也有不少人在规划路线的时候会准备一个类似的路书。所以在中文语境中搜索“路书软件”的时候，你会发现有很多路书软件其实是为了自行车骑行准备的。虽然也有类似的功能，但是相比旅游中看重的各类观光景点的信息和交通信息，这类软件可能更关注于公路和地标的数据收集。同时，它们普遍还会整合一些计速、配速之类的功能，这也是旅行中用不到的。</p>
<p>后面也会提到，在寻找合适的旅行路书软件时，这部分软件反而是最大的干扰项。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="旅行路书travel-map">旅行路书：Travel Map<a href="https://sqybi.com/blog/traveling-with-a-travel-map/#%E6%97%85%E8%A1%8C%E8%B7%AF%E4%B9%A6travel-map" class="hash-link" aria-label="旅行路书：Travel Map的直接链接" title="旅行路书：Travel Map的直接链接" translate="no">​</a></h3>
<p>我有足够的信心认为旅行中的“路书”这个词，是借鉴了上述两个“路书”而产生的。</p>
<p>同样地，我也只能通过搜索来尝试找到正确的英文关键词。经过一番折腾，我找到了一个可能正确的词汇：travel map。</p>
<p>相比上述偏专业性的路书，旅行的路书更加贴近实际。相比使用一些专业标记法来记录路线的细节，旅行路书一般更关注的点有：</p>
<ul>
<li class="">景点的信息记录和攻略</li>
<li class="">基于多种交通形式的路线规划</li>
<li class="">交通时间计算</li>
<li class="">其它个性化定制和功能整合，如票务服务、机酒推荐和预订、租车服务等</li>
</ul>
<p>而考虑到我个人的需求，我在这篇文章中会主要关注景点标记、路线规划、交通方式选择、时间计算这几个功能，以及尽可能完善的备注功能（包括景点和路线的备注）。我认为这些功能已经足够我完成一份完整的旅行规划了，其它的整合服务应该由更专业的软件实现。</p>
<p>关于这件事你可以有自己的想法，但这不会影响我接下来的推荐都是基于上面这些原则的。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="旅行路书的工具推荐">旅行路书的工具推荐<a href="https://sqybi.com/blog/traveling-with-a-travel-map/#%E6%97%85%E8%A1%8C%E8%B7%AF%E4%B9%A6%E7%9A%84%E5%B7%A5%E5%85%B7%E6%8E%A8%E8%8D%90" class="hash-link" aria-label="旅行路书的工具推荐的直接链接" title="旅行路书的工具推荐的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="google-my-maps-国外旅行的首选">Google My Maps 国外旅行的首选<a href="https://sqybi.com/blog/traveling-with-a-travel-map/#google-my-maps-%E5%9B%BD%E5%A4%96%E6%97%85%E8%A1%8C%E7%9A%84%E9%A6%96%E9%80%89" class="hash-link" aria-label="Google My Maps 国外旅行的首选的直接链接" title="Google My Maps 国外旅行的首选的直接链接" translate="no">​</a></h3>
<p>说到 Google Map，在国外旅行过的朋友应该都不陌生。</p>
<p>除了中国大陆这片比较特殊的土地，Google Map 在绝大部分国家和地区都有着非常不错的覆盖。同时，Google Map 的产品功能也像 Google 的大部分产品一样优秀，在日本换乘地铁的时候帮了我不小的忙——虽说最后我还是错误地坐上了一班去机场的快车，并因为身上并没有现金而尴尬地被带到了下车站的警卫室补刷了卡，只能说日本地铁的复杂程度是真的没救了。</p>
<p>但是这里提到的 Google My Maps 则并不是 Google Map，而是 Google 的另一个产品。你可以通过 <a href="https://www.google.com/maps/d/" target="_blank" rel="noopener noreferrer" class="">Google My Maps</a> 访问到它。</p>
<p>这个工具似乎并不是为路书而生的，它更像是一个 Google 内部通用的地图编辑器，被公开释放了出来。这个工具提供了一些看起来相当基础的功能：</p>
<ul>
<li class="">添加图层</li>
<li class="">添加位置点，并修改位置点的颜色等属性</li>
<li class="">添加位置之间的路线，包括直线和各种交通方式的规划路线</li>
<li class="">以各种格式导入和导处图层数据</li>
<li class="">多用户协作编辑</li>
</ul>
<p>虽然只有这些功能，但 Google My Maps 可以说是将这些功能做到了极致。没有任何花里胡哨的附加功能，反而让这个产品在旅行路书这件事情上极其好用：为旅程分段建立图层，在图层上标记你要去的所有地点，在地点之间连线，为它们写上一些备注——好了，你已经获得了一份足够可用的路书。</p>
<p>或者说，不光是路书，只要你自己足够 geeky，就很难不被这么一个简单但有用的产品打动。在我进入自动驾驶行业的这七年，我看到无数开发者将 Google My Maps 当作 KML（这也是一种 Google 定义的地理数据格式）或其它格式的地理数据编辑器。不得不说，在通用的场景下，这绝对比大部分我们内部开发的编辑器要好用。</p>
<p>唯一比较明显的缺点，可能是它的手机端依赖 Google Map，且入口极深，手机端的操作也很难说得上好用，比较适合只用来查看地图。</p>
<p>因为我的国外旅行大多都是和几个在 Google 就职的朋友一起进行的，所以也没有再考虑过其它工具了。不过在搜索的过程中，我也看到了一些其它的在线工具，例如 <a href="https://travelmap.net/" target="_blank" rel="noopener noreferrer" class="">TravelMap</a>。至少从 <a href="https://clem.travelmap.net/cycling-around-australia" target="_blank" rel="noopener noreferrer" class="">它的 Demo</a> 来看，这个工具还是蛮好用的，说不定下次出行的时候可以试一下。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="被旅行社占据的国内路书市场">被旅行社占据的国内路书市场<a href="https://sqybi.com/blog/traveling-with-a-travel-map/#%E8%A2%AB%E6%97%85%E8%A1%8C%E7%A4%BE%E5%8D%A0%E6%8D%AE%E7%9A%84%E5%9B%BD%E5%86%85%E8%B7%AF%E4%B9%A6%E5%B8%82%E5%9C%BA" class="hash-link" aria-label="被旅行社占据的国内路书市场的直接链接" title="被旅行社占据的国内路书市场的直接链接" translate="no">​</a></h3>
<p>可能是因为中国人没有旅行前编写路书规划的习惯，也可能是自驾游市场在这一代年轻人才刚刚兴起，寻找国内路书产品的过程可谓举步维艰。</p>
<p>在国内，你可以看到很多打着“路书”旗号的产品。但是每当点进这些产品，你都会发现它们的首页挂着“定制师”“营销”“旅行社”的产品，或者是为开车自驾游、骑行等场景极端定制化的产品。</p>
<p>在这些产品中，后者因为定制化过于深入而很难适配各类旅行需求。而前者虽然一定程度上可以进行路线规划，但使用一段时间就会发现它们都有着比较一致的问题，例如只包含热门景点、按照 to B 的模式收费、更关注于如何向客户介绍景点而非规划路线等。</p>
<p>至少在我的实际体验中，我觉得这些路书软件都远远没有达到“可用”的级别。此时，我将目光重新投向了国内的地图软件，试图找到一个包含类似于 Google My Maps 功能的国内地图软件。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="擦身而过的高德路书">擦身而过的高德路书<a href="https://sqybi.com/blog/traveling-with-a-travel-map/#%E6%93%A6%E8%BA%AB%E8%80%8C%E8%BF%87%E7%9A%84%E9%AB%98%E5%BE%B7%E8%B7%AF%E4%B9%A6" class="hash-link" aria-label="擦身而过的高德路书的直接链接" title="擦身而过的高德路书的直接链接" translate="no">​</a></h3>
<p>国内几款主要的地图软件中，有很多都有自定义地图的功能（找不到的可以去对应的云平台找一找）。但是绝大部分的此类功能都限制颇多，且更倾向于制作定制化地图而非规划路线，在一些关键功能例如导航上总会有所缺失。同时，因为很多类似功能其实都是云平台的一部分，所以在出门使用的时候也没有很好的手机应用支持。</p>
<p>好在查找的过程中，我发现高德地图在它的网页版上有一个名字就叫“路书”的功能：</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="高德地图的路书功能" src="https://sqybi.com/assets/images/amap-travel-map-b952e56b3e9d3ff4bc298cb46914890f.png" width="797" height="497" data-zoomable="" class="img_ev3q"><div class="img-caption">高德地图的路书功能</div></div><p></p>
<p>而这个功能也正如它的名字，的的确确是单纯的路书。除了不支持步行导航，其它的基本功能已经几乎齐全了，我甚至在旅行开始之前已经用它创建了一份完整的路书。</p>
<p></p><div class="img-container"><img decoding="async" loading="lazy" alt="旅行前创建的路书" src="https://sqybi.com/assets/images/travel-map-before-trip-c9a5c7e838bd301e40fc311a7f5509e6.png" width="433" height="617" data-zoomable="" class="img_ev3q"><div class="img-caption">旅行前创建的路书</div></div><p></p>
<p>但是就当我准备再微调一下这份路书，为里面的地点根据分类标上不同的颜色时，我突然发现自己遇到了一个非常诡异的 bug。在调整了某些地点的颜色或者图标后，整个路书的地图页面都会开始自动抽搐，且所有在页面上的操作都会没有响应。</p>
<p>简单地打开控制台 debug 了一下，我将问题定位到了路线的显示上。进一步排查之后，我发现了复现问题的方法：只要创建两个非常近的地点，在它们之间连一条路线，使得路线的驾车时间小于 1 分钟，这个问题就会出现。而且出现问题的时候，从这条路线开始，后续所有路线的预期时间都不会再显示。这也进一步印证了我的猜测，就是显示预期时间的时候出现了问题。</p>
<p>继续排查，可以发现出现问题的代码中检查了一个接口返回的预期时间，并基于“分”这个字进行了分割。那么问题的 root cause 就显而易见了：这个接口返回小于一分钟的时间时，很可能单位是“秒”而不是“分”。这时前端没有正确处理这个返回值，所以会导致某个代码直接进入死循环，地图开始无限缩放，且占用前端线程（虽然 JavaScript 没有线程吧，但大概就是这个意思）导致所有操作失效。</p>
<p>问题是发现了，但我自己也没办法修复啊。只好点开界面右上角的“反馈”按钮，想碰碰运气。</p>
<p>好消息是，这个反馈功能并不是那种自动回复的机器人，而是直接打开了 <a href="https://lbsbbs.amap.com/forum.php?mod=forumdisplay&amp;fid=60" target="_blank" rel="noopener noreferrer" class="">一个论坛</a>；坏消息是，这个论坛最新的帖子已经是 2018 年的了，看起来已经很久没有人维护了。</p>
<p>不过当我继续顺藤摸瓜下去的时候，发现了 <a href="https://lbsbbs.amap.com/forum.php?mod=viewthread&amp;tid=46620&amp;extra=page%3D1" target="_blank" rel="noopener noreferrer" class="">这样一个帖子</a>：</p>
<blockquote>
<p>亲爱的高德开发者论坛用户您好：</p>
<p>自2018年10月18日起，高德开发者论坛除车机板块外，其他板块将停止发帖与维护，如您有使用问题请&nbsp;<a href="https://lbs.amap.com/dev/ticket/type" target="_blank" rel="noopener noreferrer" class="">提交工单</a>&nbsp;联系我们，感谢您的理解。</p>
<p>感谢您对高德开发者论坛的关注，祝您生活愉快。</p>
</blockquote>
<p>只要有地方提工单那就好说，于是我点开链接，提了一个工单，详细描述了上面发生的问题。</p>
<p>结果客服的回复倒是很快，告诉我工单已经转给了工程师。但是坏消息是，我是十一出行之前使用的这个路书功能，但他们的工程师要等到十一假期结束之后才能给我反馈。</p>
<p>这期间也有高德的产品经理和我联络。首先是第一个产品经理表示虽然我的工单提在了开放平台，但是路书其实是 app 的功能，需要转到 app 那边。后面 app 的产品经理也和我取得了联系，但是也表示要十一之后才能安排 debug 和修复。</p>
<p>已经规划了出门旅游的我自然是等不了的，只能寻找下一个替代品了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="好用但不完全好用的-exping">好用但不完全好用的 exping<a href="https://sqybi.com/blog/traveling-with-a-travel-map/#%E5%A5%BD%E7%94%A8%E4%BD%86%E4%B8%8D%E5%AE%8C%E5%85%A8%E5%A5%BD%E7%94%A8%E7%9A%84-exping" class="hash-link" aria-label="好用但不完全好用的 exping的直接链接" title="好用但不完全好用的 exping的直接链接" translate="no">​</a></h3>
<p>几经周折，我从少数派上的 <a href="https://sspai.com/post/73855" target="_blank" rel="noopener noreferrer" class="">一篇文章</a> 中发现了一款国产路书产品 <a href="https://exping.world/" target="_blank" rel="noopener noreferrer" class="">exping</a>。</p>
<p>这款产品可以说是我使用下来最好用的路书产品了。除了上面提到过很多次的基本功能以外，它至少还提供这样一些额外的功能：</p>
<ul>
<li class="">协作编辑</li>
<li class="">Emoji 自定义图标</li>
<li class="">按日期和路线的分组</li>
<li class="">Emoji 打卡</li>
<li class="">地点评分</li>
<li class="">社区</li>
</ul>
<p>此外，因为我是在今年十一期间使用的，所以还有一些后来推出但我还没有用过的功能，比如自由绘制两点间的路线。</p>
<p>虽然我前面一直强调 Google My Maps 的优势在于没有添加很多花里胡哨的功能，但 exping 的这些功能其实并没有引起我的反感。究其原因，可能是因为他们的产品设计真的很克制——比如我并不关心社区功能，而这个产品也能做到在我使用的过程中，几乎不会强制插入任何社区功能的入口。</p>
<p>而这个产品因为一开始就是一个手机端产品，所以它们的手机应用交互也是相当好用的。旅行的过程中，免不了要因为各种原因修改一些原先制定的规划，而这次十一的旅行，我顺畅地在 exping 的手机 app 中完成了大量的修改，甚至可以一边走一边改（如果你也想这么做，请务必注意交通安全！），丝毫不感到费力。</p>
<p>虽然有着这么多优点，但这个产品还是存在它自己的问题的。</p>
<p>最明显的问题，就是它的免费版本功能限制过多。虽然我自己是愿意为优秀产品付费的类型，但是不得不说在试用的过程中，诸如分组数量上限这样的限制，属实让我用得不太开心。我不确定有多少人能为了一次旅行开通一个月的付费会员，虽说价格不贵，但是我很担忧国人的付费习惯能否支撑起这个软件的收入。</p>
<p>我自己大概会在每次旅行需要使用它的时候都开一个月会员，算是最低程度地支持一下吧。</p>
<p>另外一个比较难以忍受的问题，就是这个软件的网页版过于简陋了，bug 也太多了。</p>
<p>例如分组显示的逻辑，在手机上和网页版就很不一致，甚至网页版自己似乎都很不一致。举个例子，看起来路线分组是和日期绑定的，但是网页端的 UI 又会将所有路线分组和所有日期平铺地展示出来，且不显示它们之间的联系——这使得网页端对分组和日期的增删操作都存在非常大的困难。</p>
<p>当然，在我开始使用这个软件的时候，网页端应该也是刚刚上线不久。我也能看到网页端上有一个比较详尽的问卷，在调查各种使用中可能出现的问题，所以对这点我也暂时是可以容忍的。</p>
<p>但整个路书都用手机端完成，体验确实不太好。希望下次出行之前，这些问题都可以被解决吧。</p>
<p>最后，我其实对这个产品的社区功能抱有一些怀疑的态度。在用户量如此至少的情况下，社区中很难出现高质量的路书，所以我不是很能理解这个时间点推出社区功能的必要性。不过看在开发者对这个功能的入口如此克制的情况下，我就暂且当作是他们一个小小的试验吧。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="后日谈高德路书的-bug-修复">后日谈：高德路书的 bug 修复<a href="https://sqybi.com/blog/traveling-with-a-travel-map/#%E5%90%8E%E6%97%A5%E8%B0%88%E9%AB%98%E5%BE%B7%E8%B7%AF%E4%B9%A6%E7%9A%84-bug-%E4%BF%AE%E5%A4%8D" class="hash-link" aria-label="后日谈：高德路书的 bug 修复的直接链接" title="后日谈：高德路书的 bug 修复的直接链接" translate="no">​</a></h2>
<p>在我的旅行即将结束的时候，高德的程序员也回来上班了。</p>
<p>不考虑我已经给出了详细的复现手段，甚至帮他们定位了代码错误位置这些背景情况，总之他们还算比较快的定位了这个问题，并在大概几周之后通知我已经完成了修复上线。我也验证了一下，发现问题确实不存在了。</p>
<p>其实对于这个结果我还是蛮惊讶的，毕竟从论坛来看这已经是一个过气的产品了，而这么基础的 bug 一直没有人提出，也很可能是因为这个产品真的没有什么用户。</p>
<p>通常来说这样的问题随便打发一下用户或者慢慢排期修也是 OK 的，我甚至在他们沟通的时候感觉这些程序员和产品经理已经很不了解路书产品了，他们甚至不知道产品的入口在哪里。但是他们还是认真地记录了问题并完成了修复，这里也感谢这个过程中认真参与的产品经理和程序员。</p>
<p>下次有机会的话，我会再试一次用这个产品规划我完整的旅行——虽然可能它只会被 exping 这类创业公司的产品落下得越来越远，但那也是公司决策的问题了。</p>
<p>认真的人值得认真的对待。</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 碎碎念</category>
            <category>内容 | 软件推荐</category>
        </item>
        <item>
            <title><![CDATA[摄影故事：母亲、孩子、尾迹]]></title>
            <link>https://sqybi.com/blog/photography-story-mother-son-and-wake/</link>
            <guid>https://sqybi.com/blog/photography-story-mother-son-and-wake/</guid>
            <pubDate>Sun, 26 Nov 2023 00:30:00 GMT</pubDate>
            <description><![CDATA[背景故事]]></description>
            <content:encoded><![CDATA[<p><a href="https://www.flickr.com/photos/sqybi/53277433710/in/dateposted/" target="_blank" rel="noopener noreferrer" data-flickr-embed="true" data-header="true" data-footer="true" title="海滩上的小朋友" class=""><img decoding="async" loading="lazy" src="https://live.staticflickr.com/65535/53277433710_bbb579288a_k.jpg" width="2048" height="1365" alt="海滩上的小朋友" class="img_ev3q"></a><script async="" src="//embedr.flickr.com/assets/client-code.js" charset="utf-8"></script></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="背景故事">背景故事<a href="https://sqybi.com/blog/photography-story-mother-son-and-wake/#%E8%83%8C%E6%99%AF%E6%95%85%E4%BA%8B" class="hash-link" aria-label="背景故事的直接链接" title="背景故事的直接链接" translate="no">​</a></h2>
<p>这是一张在泉州旅游时，于泉州海滩上拍下的照片。</p>
<p>拍摄的时候我自己其实处于比较放松的状态，所以只是随便拍一拍海面，也没有想过可以出片。但是恰好在拍摄海面上开过的游艇留下的尾迹时，一对母子出现在了镜头里。</p>
<p>母子中的小朋友就像海滩上大部分小朋友一样，用自己的脚探索着这片对他来说很新鲜的沙滩。而母亲也和大部分母亲一样，默默在身后守护着他。</p>
<p>这个场景比较打动我的是这一幕中背景的尾迹和前景的母子形成的呼应。母亲在守护着孩子的这一个刹那，也会守护着他今后的人生。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="后期思路">后期思路<a href="https://sqybi.com/blog/photography-story-mother-son-and-wake/#%E5%90%8E%E6%9C%9F%E6%80%9D%E8%B7%AF" class="hash-link" aria-label="后期思路的直接链接" title="后期思路的直接链接" translate="no">​</a></h2>
<p>这张照片因为几乎是抓拍，所以整体构图其实有些杂乱。之所以选择这张来讲解，也并不是因为这张照片拍得多好，而是因为对我来说这个画面非常有趣。</p>
<p>为了解决构图的问题，我首先进行了不小的裁剪。因为背景的人太多了，所以需要尽可能把主体之外的部分，也就是尾迹和母子之外的部分裁切掉，并大概保留了 1:2:2 的天空、海洋和沙滩。</p>
<p>但是仅仅进行裁剪，背景的人物还是过多了。这本身是一个硬伤没有太好的办法，所以我选择了降低这对母子之外画面中人物的对比度。但可惜的是，这对母子的服装本身也不鲜艳，所以最终的效果只能说有用，但不能说很好。另外，海洋和沙滩交界的部分也是这样调整的副作用，好在这部分对比度变化还是符合画面逻辑的，并不是非常突兀。</p>
<p>其余的部分就是对画面整体进行简单的调色，沙滩部分基本保留了原始的颜色，海洋和天空整体有一些调整，以尽量和沙滩部分区分开。同时，对海上的船只也稍微降低了一些对比度，避免船上的红色过于喧宾夺主。</p>]]></content:encoded>
            <author>contact@sqybi.com (sqybi)</author>
            <category>分类 | 摄影</category>
        </item>
    </channel>
</rss>