玉、凿与匠人

玉、凿与匠人

长久以来,围绕虚拟歌姬的争论似乎总是在两端之间拉扯:她到底是工具,还是偶像?

“工具论”者强调她的声库本质:她是软件,是数据,是创作流程中被操作的对象。

“偶像论”者强调她超越声库的那部分:她有名字,有形象,有人格,有千千万万人赋予她的情感。两方各执一词,争论往复。

但我一直觉得这个问题的提法本身就有些不对。

如果虚拟歌姬是”工具”,那么 Vocaloid 是什么?Ace Studio 是什么?SynthV 是什么?这些才是你在创作时打开、操作、关闭的软件——如果它们不叫工具,什么才叫工具?

工具一词在讨论中被用得太宽泛了,宽泛到把本应区分的东西混在了一起。

昨天,ilem 在一些想法中重申了他的立场:洛天依是声库,也只是声库。他的逻辑很清晰——只有当她确定地是一件工具的时候,创作者对作品的完整所有权才能成立,”调教”这道工序才能被承认为一项有意义的劳动。这个论述自洽且有力,他说出了许多创作者心里有但从未成文的东西。

然而我想指出的不是他说错了什么,而是他和所有参与这场争论的人一样,也许被一个过于粗糙的二分法框住了。”是工具还是偶像”这个问题,预设了只有这两个选项。但如果我们跳出这个框架,把创作过程拆得更细一些,也许会看到一种不同的图景。

我想提出一个三分法:料、具、人

一、料:歌姬是玉

先说”料”。

“工具”这个词暗含着一种完全的可替换性:锤子坏了换一把锤子,功能不变。但你把一首歌的人声从一位歌姬换成另一位,整件作品的质感就变了。这不是好与坏的差别,而是气质的差别。这说明歌姬参与了作品本身的物质构成,她不只是实现意图的手段。

与其说她是工具,不如说她是被雕琢的玉石。

每一款玉都有自己的质地:和田玉温润内敛,翡翠通透张扬,黑曜石冷峻深沉。不同的歌姬也是如此,每个音源的音色里天然带着某种情绪的倾向,她不是中性的白纸,而是有纹理、有硬度、有光泽的质料。你用同一首曲子交给不同的歌姬,出来的不只是音色的差异,而是整首歌的情绪走向、气质氛围都会随之改变。这不是”换了一把锤子”能解释的,这是换了一块玉。

但玉不会自己变成作品。

一块玉放在那里,它有自己的纹理和色泽,却没有主体性,没有意志,不会自己决定要成为什么形状。它只是在那里,带着自己的特质,等待被读懂。

玉雕中有一个俏色的说法:雕刻师顺着玉石天然的颜色分布来构思题材,让瑕疵变成巧思,让纹理成为表达的一部分。好的虚拟歌姬创作也是如此,创作者不是在强迫她表达任何东西,而是在读懂她的质地之后,顺着她的纹理走,找到最适合她的表达方式,然后把自己的情感注入其中。这种关系不是”使用”,而更接近于一种对话,尽管对话的另一端并没有意识。

而这种质地也不完全是天生的。

一位歌姬刚发布时,她带着的东西各不相同。有些拥有完整的形象、配色乃至人设故事——这些视觉与叙事的元素,在第一首作品诞生之前就已经为这块玉镀上了一层底色。有些只有一个名字和一副嗓音,气质几乎全靠后续的作品去慢慢定义。还有一些连形象也没有——比如那些只作为声音存在的字母人——反而因为少了视觉预设,留出了更纯粹的想象空间,纹理完全从声音本身生长出来,有着别样的韵味。

但无论起点如何,歌姬出厂时的纹理都只是一个开始。真正让它丰富起来的,是随后一首又一首作品的积累。创作者们从不同的角度去雕刻她,让听众知道了这块玉可以这么雕、也可以那么雕。那些经典作品沉淀下来的基调,逐渐汇聚成了人们对这位歌姬的情感认知:她”适合”什么样的歌,她”擅长”什么样的表达。这种认知反过来又影响着后来的创作者,他们带着这些前理解去打开软件,去与这块玉对话。

玉的质感,某种意义上,是被历代匠人一起养出来的。

那么所谓的”偶像”属性呢?在这个框架里,它其实是可以被解释的:当一块玉被足够多的匠人雕刻过、被足够多的人欣赏过,人们开始对这块玉产生情感:不是对某一件作品,而是对玉本身。这种情感是真实的,也是可以理解的。但它不改变一个基本事实:玉本身是没有灵魂的。人们爱的,是历代匠人留在这块玉上的痕迹的总和。

二、具:软件是凿子

再说”具”。

如果歌姬是玉,那么 Vocaloid、Ace Studio、Synth V、UTAU——这些具体的软件才是真正意义上的工具。

它们是凿子、是砂轮、是抛光机。它们决定的是你用什么方式、以什么精度去雕琢这块玉。手凿费力但可以精准到每一刀的力度与角度,电凿省力但需要控制,数控设备可以快速成型但手感会减弱。

工具是可替换的——这正是”工具”一词应有的含义。换一把凿子不会改变玉的质地,只会改变你雕刻的方式和效率。你用 Vocaloid 还是 Ace Studio 来调同一位歌姬,出来的声音会有差异,但那是工艺的差异,不是质料的差异。歌姬还是那位歌姬,玉还是那块玉。

工具的进化本身是自然的。从 Vocaloid 到 Ace Studio,自动性越来越强,操作门槛越来越低,更多人得以参与到创作中来——这就像从手凿进化到电凿。创作者省下的体力可以投入到更高层次的思考中,作品的可能性空间也随之扩展。这是好事。

但这里有一条需要被辨认的边界线。

工具应当跟随使用者的意图行事。

当电凿仍然需要你握着、引导着、决定每一刀落在哪里的时候,它就是工具,不管它多省力、多高效。手凿和电凿的区别是效率的区别,不是主体性的区别。握着电凿的人仍然是那个在做判断的人:这一刀深还是浅,这条线走还是不走,这个细节留还是不留。

但如果有一天,凿子开始自己判断这块玉应该雕成什么,开始替你决定走刀的方向和深度,它就不再是工具了。

这正是当下部分 AI 创作工具令人不安的地方。像 Suno 这样的歌声生成模型,它也自称工具,但它做的事情远不止执行意图:你给它一个prompt,它自动生成一段完整的音乐,伴奏混音啥都有了。你不需要判断任何细节,甚至不需要知道有哪些细节可以判断。你要做的,只是听一遍,然后决定”行”或”不行”。这时候你的角色已经从匠人变成了审核者,从创造者变成了甲方。

而最微妙的是,这种转变是舒适的。AI 给出的结果往往”听起来没问题”,甚至”听起来很好”。你很难指出它具体哪里不对,因为它的每一个局部处理都是在统计意义上,最优化的选择。但正是这种面面俱到的合理,抹去了某种本该存在的东西,那种只有当一个具体的人在做具体的判断时,才会出现的偏向、执拗和个人印记,以及长尾的无法被捕获的可能性。

主体性不是被夺走的,是被舒适地、不知不觉地让渡的。

更进一步地,工具的进化还带来了一些更复杂的效应。新一代的 AI 调校确实提高了创作的下限,以前需要大量经验才能做到”不难听”的事情,现在软件可以自动帮你处理。这意味着更多人可以参与创作,全体创作者投入到虚拟歌姬创作中的总精力可能反而是增加的。

但同时,每个创作者在每首作品上做出的主动判断,有可能减少了。减少了多少需要自己决定的环节,就减少了多少个人特色得以显影的机会。总量可能在增长,但每一份的浓度可能在被稀释。

当然,这并不意味着旧的工具就应该被抛弃,也不意味着新的工具就必然是坏的。一个创作者完全可以自己去选择在哪些环节交给 AI 处理、在哪些环节自己把控,只要他心里清楚地知道自己在做什么,知道哪里是他的判断、哪里是机器的判断。

关键不在于工具先进与否,而在于:你是在用它,还是它在引导你?

三、人:灵魂的注入者

最后说”人”。

真正让一件作品苏醒的,从来不是玉本身,也不是凿子本身,而是那个握着凿子、读着玉纹、把自己的情感和审美一刀一刀刻进去的人。

这是整个三分框架中最重要、也最容易被忽视的一个部分。

打开声库软件的时候,调教师面对的是操作界面。从这个界面出发,去思考一首歌应该怎么唱,去调整每一个参数、每一段气息的处理方式,这是一段切实的、可被感知的创作劳动。它和编曲、作词、混音一样,需要审美,需要判断,需要经验的积累,也需要时间的投入。

这道工序通常被叫作”调教”。这个名字本身就很有意味,它暗示着一种驯化、一种引导,也暗示着被引导的对象本身并不具备自主性。这和前面的框架是一致的:玉不会自己变成作品,是匠人把它变成作品。

正因为玉本身没有灵魂,创作者才可以无负担地倾注自己的灵魂。这一点ilem在他的文章中说得很透彻:”只有对无灵魂的事物,我才可以倾注我的灵魂。对木偶提线才是表演,对活人提线则是霸凌和犯罪。”面对的是无生命无意识的质料,”注入”这个行为才成立,创作者对作品才拥有完整的、不需分割的所有权。

但这里面藏着一种深刻的脆弱性。

当人们的认知中,歌姬不是玉而是歌手的时候,当人们说”洛天依唱了一首好歌”而不是”某个创作者使用天依做了个好作品”的时候,创作者的劳动就变得不可见了。人们看见的是台前那个光鲜的角色,看不见幕后那个调了几十个小时参数的人。

ilem 在文中描述了这种拉扯:”我付出的一半灵魂被押在她的舞台上拿不回来。”这不是矫情,这是一个真实的困境:你把心血注入了一个没有生命的容器,但所有人都以为那个容器本身就是活的。你的灵魂没有离去,但在旁人眼中,它已经变成了”别人”的一部分。

这是一种来自认知层面的威胁:歌姬作为”玉”,被当成了”人”。

而来自工具层面的威胁则是另一种形态。当 AI 工具接管了”这首歌该怎么唱”的判断时,创作者的劳动不是变得不可见,而是变得不必要。不是你的功劳被别人领走了,而是这份功劳从根本上不再需要你来建立。

两种威胁的形态不同,但受害的是同一个角色:那个本应站在作品核心的、真实存在的创作者。

所以三分法的意义,说到底不只是在理论上把概念拆清楚,而是在为创作者争取一种应得的可见性。把歌姬从”工具”的框架中拆出来、还原为”质料”,不是为了抬高她的地位,恰恰相反,是为了指出:她是材料,不是作者。真正的作者一直是人。把软件还原为”工具”、把 AI 的角色限定在”辅助”,同样不是拒绝进步,而是坚持一个底线:做判断的应当是人,不是凿子。

结语

所以,”虚拟歌姬是工具还是偶像”,这个问题也许从一开始就问错了。

她不是工具。工具是软件,是那些你打开、操作、关闭的程序。她也不是偶像,至少,不是那种拥有自主意识和独立人格的存在。

她是玉。

有着自己的纹理和倾向,有着被历代创作者共同养出来的气质,在那里安静地等待,等一个懂她的人,拿起趁手的凿子,把灵魂一刀一刀地刻进去。

料、具、人。三者缺一不可,但不应混为一谈。拆开来看,许多纠结也许就不再是纠结了。

Disclaimer: 由Claude进行总结润色

在 iOS 上为网站添加 PWA 支持

最初的方案

之前一直在用这个方法来手动给网站添加 PWA 支持:
https://notes.alinpanaitiu.com/Install-any-website-as-PWA-on-iOS

遇到的问题

但是呢,在 NotebookLM (https://notebooklm.google) 上这个方式就失效了 😭

问题的根源在于:

The method doesn’t work on websites with a more restrictive Content Security Policy because the manifest has to be fetched from an external host (api.lowtechguys.com in this case).

简单来说,就是这个网站的内容安全策略比较严格,不允许从外部主机获取 manifest 文件。

寻找替代方案

虽然之前设置过 MITM,但实在不想通过这么暴力的方法来修改了,还折腾。于是尝试找替代方案。

突然想起来 WebClip 似乎也可以用来强制 PWA!于是开始尝试创建 WebClip。

探索过程

安装 WebClip 需要描述文件。我记得 LiveContainer (https://github.com/LiveContainer/LiveContainer) 利用了 WebClip 来做快速启动,于是去翻了一圈它的 GitHub。

找到了这个 PR 尝试引入相关功能,通过它比较详细地了解了 WebClip 的相关内容~

解决方案

经过一番搜索,最终找到了全新的工具:

Works Perfectly!

新发现的问题与改进

使用过程中发现了一个缺陷:通过 WebClip 添加的网站只在首页很沉浸,一点击就会出现 Safari 的界面,体验不太好。

为了解决这个问题,我又提交了一个 PR: Add IgnoreManifestScope support for web clips #1

在 WebClip 配置文件中添加了 IgnoreManifestScope 键,并将默认值设置为 true

这样可以让全屏 Web Clip 在导航到外部网站时不显示 Safari UI,实现真正无缝的全屏 Web App 导航体验!

在原作者合并 PR 之前,我已经 self-deploy 了一个版本: https://webclip.180811.xyz

可以直接用起来啦~💕

MongoDB 向 MeiliSearch 同步的踩坑记录

使用 meilisync

感谢yzqzss的大力支持

tl;dr: fork并大改了程序,参见

崩坏的前端

先尝试使用了他的Admin Console,https://github.com/long2ice/meilisync-admin

只有AMD64,没有ARM的镜像。谁还没有x86_64的机器啊,尝试在非数据库的机器上使用。我当时还没意识到从A机拉数据到B机再塞给C机是啥概念,但总之当时犯傻了。

下镜像、运行……等等这个数据库同步的admin为什么还要MySQL和Redis的DBurl啊?不理解但是当时配置了。

随后……

  1. 没有初始账户 ref #7

    解决方案是手动写邮箱密码进数据库,还要手搓 bcrypt hash

  2. 创建MongoDB数据源,报错Unknown option user #11

    原因竟然是,不同数据库在后端配置文件需要的参数不同,网页只按照PostgreSQL的user进行了传参,而且后端没处理直接塞,sync程序原地爆炸。

    使用抓包改包重放解决。

    本来写了fix但发现PostgreSQL的参就是对的,那爱咋咋地吧我感觉我管不了。也应该没人看到这还想用吧……应该吧。

  3. 设置好一切了之后还是跑不起来……后端有如下报错(删除一吨内容):

    2025-04-11 21:38:42.156 | INFO     | uvicorn.protocols.http.httptools_impl:send:496 - 10.0.1.1:64000 - "POST /api/sync HTTP/1.1" 500
    ERROR:    Exception in ASGI application
    Traceback (most recent call last):
      File "/meilisync_admin/meilisync_admin/models.py", line 64, in meili_client
        self.meilisearch.api_url,
        ^^^^^^^^^^^^^^^^^^^^^^^^
    AttributeError: 'QuerySet' object has no attribute 'api_url'

    额……看起来不是简单配置文件的问题了……

于是尝试使用cli,避免是那鬼畜的Admin Console导致的问题以为马上就是终结的开始,原来只是开始的终结。

滞后的docker

找到实际进行同步的程序,https://github.com/long2ice/meilisync

我还是尝试了Docker,毕竟是”Recommended“的方法。但是按照他Readme写的compose,

version: "3"
services:
  meilisync:
    image: long2ice/meilisync
    volumes:
      - ./config.yml:/meilisync/config.yml
    restart: always

拉下来的镜像有问题。

我遇到的是 TypeError: ‘async for’ requires an object with aiter method, got list #94
但对应还有 TypeError: ‘async for’ requires an object with aiter method, got coroutine #76

嗯,得用dev呢。

啊对和上文一样,他MongoDB的user的字段是username,和模板不一样。鬼知道当时我怎么能灵光一现想出是username的。

后面配置文件来回几次之后不想搞docker了,故转为本地cli。

本地Python

本地cli阶段,一切似乎向着好的方向好起来了。

为数不多的几个问题就是,虽然有 pip install meilisync[mongo] for MongoDB,但是只安装这个是不够的。实际运行任何命令都会狠狠的告诉你,缺这缺那。你只能 pip install meilisync[all] for all.

还有小bug要打zsh。

$ pip install meilisync[mongo]
zsh: no matches found: meilisync[mongo]

终于配置好config,一切似乎在向好发展……或者是么?

爆炸的进度

参考 #17 中的回复,当以MongoDB作为数据源时,progress.json 可能不会自动生成,导致一堆一堆的TypeError: meilisync.progress.file.File.set() argument after ** must be a mapping, not NoneType

解决方案,先touch一下progress.json,再写进案例……

{"resume_token": {"_data": "8267FBA647000000022B042C0100296E5A10046F963A9EB7AB4D14B8CF191E8E5E8D67463C6F7065726174696F6E54797065003C696E736572740046646F63756D656E744B65790046645F6964006467FBA6470D168B18625CC73E000004"}}#                                                                                   

狠狠的log

测试没发现大问题之后,改配置文件关了debug,使用nohup运行起来之后我就去干别的事了,直到硬盘告警把我拉回到shell。同步数据库到新地方的确很耗空间,我也准备好了。但我实在没想到是中间的这位硬盘先爆炸了——增速甚至大于Meili数据库的机器——人畜无害的同步器给我摔了6个G的日志到我脸上。

这不可能啊,我明明在配置文件中写了debug=false啊——

tail了一下巨大的log,发现他把每一条同步的内容全纯文本的记录下来了……

其实是默认的插件实例导致的。

在配置文件中存在如下的内容:

debug: false
plugins:
  - meilisync.plugin.Plugin

其中plugin部分实际引用的是 https://github.com/long2ice/meilisync/blob/dev/meilisync/plugin.py

class Plugin:
    is_global = False

    async def pre_event(self, event: Event):
        logger.debug(f"pre_event: {event}, is_global: {self.is_global}")
        return event

    async def post_event(self, event: Event):
        logger.debug(f"post_event: {event}, is_global: {self.is_global}")
        return event

在这个plugin中,不管配置文件中debug的设置为何值,都会写入debug。

解决方案有三种:

  1. 不引用这个plugin

  2. 修改plugin内容

  3. 修改全局的log级别:

    Meilisync使用loguru,参考其文档可以通过设置level实现,再根据其环境变量的相关文档,可以设置LOGURU_LEVEL,可采用值如下表:

    Level name Severity value Logger method
    TRACE 5 logger.trace()
    DEBUG 10 logger.debug()
    INFO 20 logger.info()
    SUCCESS 25 logger.success()
    WARNING 30 logger.warning()
    ERROR 40 logger.error()
    CRITICAL 50 logger.critical()

    然后设置环境变量:

    Unix下:

    export LOGURU_LEVEL=INFO

    Windows下:

    PowerShell

    $env:LOGURU_LEVEL="INFO"

    CMD

    set LOGURU_LEVEL=INFO

后续来看节省了一吨的空间……

在各种debug中,把这个服务从B迁移到了C,也就是Meili Search所在的地方。这在后来被证明提升了非常多的速度。

Index的疑虑

我的数据中有id一项,但实际使用中会冒出各种问题,还是使用_id作为主键。

动手改脚本

矫正了类型

似乎一切正常的运行了一阵子之后,程序自己就死掉了。几次检查之后发现是 TypeError: Object of type ObjectId is not JSON serializable。此时的进度大概都是1,140,000条数据。

同样有GitHub Issue,#16,说是”fixed“。检查了一下本地代码,的确包含了fix的内容。但似乎还有出现在 #102,这次就没有任何回复了。

最难搞的不是修代码,而是让它再出错。由于出错之后进度就g了,每次都是从头开始,而每次跑到错误地方需要20分钟,消耗了几个小时在这个上面……还有,运行期间CPU全都拉满……我还应该庆幸不是用的小服务商机器会被拉闸……

对了,这段时间,用上了sentry.io。很奇怪作者在这个同步工具中特别留了sentry.io的口子,但它真的非常有用。也许作者知道会在各种地方出bug?

本地的修改

于是再实现了一下检测与修复。一开始尝试改造那个plugin,但一开始实在没理顺内容,最后决定硬改源码!添加了额外的类型检查。不想一次次的pip install,直接进site-packages改文件,又快又好。

修复完 ObjectId 不久,看超过半小时都没问题,进度也在一点点的走,正准备去睡觉,结果又有报错,这次是Object of type datetime is not JSON serializable,类似 #31 。同样的,加检查。这次是在5,270,000的位置,大概三分之一。修好之后能接着同步,也过了一半,于是我放心的去睡觉了。

然后早上醒来又是晴天霹雳,在差不多三分之二的时候,就会冒出Client error '408 Request Timeout' for url 'http://127.0.0.1:7700/tasks/xxxx。实在没办法,索引的东西太多太多,算不过来也就越积压越多,直至彻底boom。但不正常的是,这个问题也被修过,在 #13 有提起过,但不知道啥原因,还是爆炸了。此时我检查了一下积压了多少,发现运行一个小时就会积压半个小时……我应该庆幸没有发生Too many open files的问题……

索引慢是没办法的……欸等等,说到底这索引就不应该这么快加才对吧!

延迟的索引

我决定尝试延迟,然后发现可怕的事实:在创建index的时候,meilisync 没有指定任何的字段索引选项。所以文档中的每个字段都会显示并可搜索,这耗费了超级多的资源,也造成可怕的浪费。我们完全没必要一开始就索引全部的内容。相反,我们在从远端同步数据的时候,不应该建立任何的索引,而应该等到直到所有来自源的内容全都都成功被插入了之后,再做索引的处理,而且应该能在config file中指定哪些字段被索引,包括索引的类型(searchable, sortable, filterable, none )

于是写了。目前写了从远端同步数据的时候,不应该建立任何的索引的逻辑,同步速度提升了一万倍。

然后写了在同步完之后通过改setting设置索引的功能,一切看似非常正常,直到一觉睡醒还是没有任何索引。

这不应该啊。检查之后发现,虽然提交了修改索引的任务,但跑到一大半爆炸了:

Index `nmbxd`: internal: MDB_TXN_FULL: Transaction has too many dirty pages - transaction too big.

终于不是meilisync的问题了!

优化的内存

仔细确认之后发现,其实不是跑了几个小时。它跑了几十分钟就transaction too big了,然后缩小batch重试,直到咋都试不出来。

锻炼!

经@yzqzss提醒了最佳实现是先设定attribution,再同步index,遵循最佳实现,但那样的话可能再出现408。要解决408得实现队列,我比较懒不想再写代码了。

随后找了下竟然找到了能减少index时内存占用的flag,参考 https://github.com/meilisearch/meilisearch/issues/3603--experimental-reduce-indexing-memory-usage,的确一用就灵,一次成功。

以及关于更新,运行meilisync refresh即可。

再之后就是写systemd来定时进行同步了,如下。

# /etc/systemd/system/meilisync.timer
[Unit]
Description=Run meilisync refresh nmbxd weekly on Monday at 5 AM

[Timer]
# Run every Monday at 5:00 AM local time
OnCalendar=Mon *-*-* 05:00:00
Persistent=false

[Install]
WantedBy=timers.target
# /etc/systemd/system/meilisync.service
[Unit]
Description=Meilisync Refresh nmbxd
#After=network.target

[Service]
Type=oneshot
WorkingDirectory=/path/to/meilisync/config/
Environment='LOGURU_LEVEL=DEBUG' 
ExecStart=/etc/meilisync/meilisync/bin/meilisync refresh

配置文件/path/to/meilisync/config/config.yml

debug: false
progress:
  type: file
source:
  type: mongo
  host: REDACTED
  port: REDACTED
  username: 'REDACTED'
  password: 'REDACTED'
  database: REDACTED
meilisearch:
  api_url: http://127.0.0.1:REDACTED
  api_key: REDACTED
  insert_size: 10000
  insert_interval: 10
sync:
  - table: REDACTED
    index: REDACTED
    full: true
    pk: _id
    attributes:
      id: [filterable, sortable]
      fid: [filterable]
      img: [filterable]
      ext: [filterable, sortable]
      now: [filterable, sortable]
      name: [searchable]
      title: [searchable]
      content: [searchable]
      parent: [filterable, sortable]
      type: [filterable]
      userid: [filterable]
sentry:
  dsn: ''
  environment: 'production'

电信IPTV和网络复用

本文使用设备为 F4600T 和 SK-WR6640X,其他设备应该也可以参考。

Step 0: 获取光猫超级密码

参考 教程 拿到了光猫的超级密码

Step 1: 获取光猫上 IPTV 接口相关信息

  1. 状态下的状态总览找到iTV的“连接名称”
    首页下的状态总览

  2. 进入网络,进入网络设置 - 网络连接,在连接名称处选中在上面找到了连接名称,记录下VLAN 模式VlanID802.1p 的值,保存备用
    image

Step 2: 设置 VLAN 绑定

在上一步的基础上,点击左侧的VLAN 绑定,进行如下操作:

  1. 选择
  2. 选择插网线的口
  3. 填入上一步获取的 VLAN(也可以随便写,和后续保持一致即可)
  4. 以及对应的 WAN 连接名称
  5. 不要忘了保存

image

Step 3: 设置路由器

路由器接到上一步中选中的网口,比如我这是网口 3。登录,进行配置,我就以我目前这台创维 SK-WR6640X 为例。

选中网络设置,进入 IPTV 配置,启用,模式为桥模式,选中插机顶盒的网口,设置 VLAN 模式VLAN ID802.1p 为上方获取/设置的值,进行确定。

image

重启盒子,即可通过一根和光猫连接的网线,同时完成 IPTV 和上网的功能。

参考连接

选定机型为 SK-WR6640X(实际 30 入手)

集成与外置 FEM 芯片的无线性能对比实测-路由器交流

总结 142 款运营商定制 WiFi6 mesh 路由的配置,供大家参考(有几款可刷 OPENWRT)-无线路由器硬件改造以及故障维修-恩山无线论坛

获取 F600T 光猫超级密码

中兴 F4600T 光猫超级密码获取方法(IOS)

IPTV 相关设置参考

GitHub - ruur/cmcc-iptv: 移动宽带单线复用(INTERNET+IPTV)

布网简单改造——IPTV 与网络单线复用的路由器什么值得买

单线复用,不用设置光猫-iptv 直播源、网络视频直播资源、直播代码-恩山无线论坛

IPTV 单线复用实践及总结 - 知乎

PS

SK-WR6640X 的信号真的很好,30 买到绝对值

How did I built this blog

零:内容框架、托管服务等的选择及必要的准备

内容框架:选择 Hexo

  • 配置较为简单
  • 简洁而快速
  • 是静态内容框架
  • 社区活跃,插件、主题众多

托管服务:选择 Vercel

  • 配置较为省心

  • CI/CD方便

  • 既往使用经验较多

可以从官网注册。

包管理器:选择 pnpm

  • 节约磁盘空间

  • 安装速度快

  • 各系统间表现稳定

安装可以参考官方教程

存储处;选择 GitHub

  • 与 Vercel 深度结合
  • 使用场景多样
  • 全球最大

可以从官网注册。

一:使用 Vercel 模板快速创建 Hexo 网站

在 Vercel 创建新项目

前往 Vercel ,新增项目。

image-20220325182649912

前往模板中心寻找模板

image-20220325182905036

选择 Hexo

image-20220325182957226

创建 Git 文件夹

image-20220325183111580

完成

image-20220325183645368

此时已经搭建完成一个基本的 Hexo 站点。

二:配置网站

本地安装依赖

之前本地已经安装了 pnpm,故直接运行

pnpm install

结果为

image-20220325201839522

升级 Hexo 版本

观察发现 Hexo 有新稳定版本6.1.0,故升级。

pnpm update ----latest

image-20220325202013959

在本地运行 hexo 服务

image-20220325202058110

此时发现有warn,故修改warn处,顺便配置文件进行了 本地化 修改:

image-20220325203724428

此时网页效果为:

image-20220325202141659

选用 YUN 主题

此时感觉网页效果不佳,准备安装并使用 Hexo-Theme-Yun 主题。

pnpm install hexo-theme-yun@latest --save
hexo config theme yun

image-20220325202453027

image-20220325202524210

配置 YUN theme

在 YUN 主题的配置文件 _config.yun.yml 中做以下配置:

语言设置为中文

language: zh-CN

配置侧边栏社交图标

特别:关于RSS

RSS 是本人的心头爱,肯定要进行配置。配置 RSS 不止需要在 _config.yun.yml 中进行配置,还需要安装 hexo-generator-feed,具体如下:

pnpm install hexo-generator-feed --save

再在_config.yml的末尾加入如下内容作为hexo-generator-feed的配置项:

feed:
  enable: true
  limit: 20
  hub: https://pubsubhubbub.appspot.com/
  content: true
  order_by: -date
  icon: images/avatar.jpg
  autodiscovery: false
  template:

再在 _config.yun.yml 中加入以下配置,完成侧边栏的设置。下面的是当时我实际配置文件。

# 配置侧边栏社交图标
social:
  - name: RSS
    link: /atom.xml
    icon: icon-rss-line
    color: orange
  - name: GitHub
    link: https://github.com/Ovler-Young
    icon: icon-github-line
    color: "#181717"
  - name: E-Mail
    link: mailto:ovlertheyoung@gmail.com
    icon: icon-mail-line
    color: "#8E71C1"
  - name: 网易云音乐
    link: https://music.163.com/#/user/home?id=310842841
    icon: icon-netease-cloud-music-line
    color: "#C10D0C"
  - name: Telegram
    link: https://t.me/Ovler
    icon: icon-telegram-line
    color: "#0088CC"
  - name: Telegram Channel
    link: https://t.me/shengxiaoguan
    icon: icon-telegram-fill
    color: "#0088CC"

配置标语动画

banner:
  enable: true
  title: 
    - Ovler
    -- hexo
  border: true
  cloud:
    enable: true
    color: "white"
  go_down:
    enable: true
    icon: icon-arrow-down-s-line

配置替换鼠标光标

cursor:
  enable: true

配置侧边栏头像

avatar:
  enable: true
  url: /images/avatar.jpg
  rounded: true
  opacity: 1
  mickey_mouse: false
  status:
    enable: true
    emoji: 😀
    message: Hello world!

配置页脚

配置了年份和运行时间

footer:
  since: 2022
  live_time:
    enable: true
    prefix: 本博客已运行
    suffix: (●'◡'●)
    start_time: "2022-03-21T17:05:00"

使用 霞鹜文楷 字体

个人较为喜欢 霞鹜文楷 字体,参考教程后配置。

先安装lxgw-wenkai-webfont字体包:

pnpm install lxgw-wenkai-webfont --save

image-20220327011612735

再在 _config.yun.yml 中加入以下配置,完成霞鹜文楷字体的设置。

font:
  cdn:
    enable: true
    lib:
      - https://cdn.jsdelivr.net/npm/lxgw-wenkai-webfont@latest/style.css
  serif:
    family: "'Songti SC', 'Noto Serif SC', STZhongsong, STKaiti, KaiTi, Roboto, serif"
    weight: 900
  sans_serif:
    family: "'LXGW WenKai', 'PingFang SC', 'Microsoft YaHei', Roboto, Arial, sans-serif"
    weight: 400
  monospace:
    family: "'Source Code Pro', 'Courier New', Courier, Consolas, Monaco, monospace"

配置友链

新建页面:

hexo new page links

image-20220331023933139

根据文档对友链进行配置:

进入 source/links/index.md,设置 links 字段。

  • url: 博客链接
  • avatar: 头像图片链接
  • name: 怎么称呼?
  • blog: 站点名称
  • desc: 一句话描述
  • color: 代表色,默认是灰色 gray

根据文档,我的友链配置为:

---
layout: links
title: Friends
date: 2019-06-21 13:06:06
keywords: 链接
description: 一个emm,咖啡馆?
comments: true
links:
  - url: https://hexo.180811.xyz
    avatar: https://hexo.180811.xyz/images/avatar.jpg
    name: Ovler
    blog: Ovler 的 Hexo
    desc: Feeling tired.
    color: "#a5f4e8" # 代表色
    email: ovlertheyoung@gmail.com
  - url: https://blog.180811.xyz
    avatar: https://hexo.180811.xyz/images/avatar.jpg
    name: Ovler
    blog: Ovler 的 typecho
    desc: 以前的博客站,似乎,好久没更新了
    color: "#df5749" # 代表色
    email: ovlertheyoung@gmail.com
placeholder: 还没想好说些什么 # 默认对友链的描述
tip: 友链加载中~如失败请刷新重试~
---

## 友链

一个emm,咖啡馆?

来坐坐吧!

目前还没啥来加的,大佬们可以通过侧边栏的各种联系方式联系到我来加友链,我会尽快回复的!

目前只有自娱自乐,也希望日后能加多一些。

配置背景

_config.yun.yml 中加入以下配置,完成背景的设置:

bg_image:
  enable: true
  url: https://cdn.jsdelivr.net/gh/Ovler-Young/blog/source/images/2830.png
  dark: https://cdn.jsdelivr.net/gh/Ovler-Young/blog/source/images/2830.png
  opacity: 0.8

注意:这里的图片链接最好是图床等加载较快的图片,太慢的话滑动会闪:(

配置页面

配置链接

参考 https://hexo.io/zh-cn/docs/permalinks 中配置修改

配置搜索

配置搜索需要安装 hexo-generator-search,具体如下:

pnpm install hexo-generator-search --save

image-20220327012220168

再在主题文件_config.yun.yml的末尾加入如下内容作为hexo-generator-feed的配置项:

# 关闭默认的引擎搜索
engine_search:
  enable: false
# 开启本地搜索
local_search:
  enable: true

配置 tags

安装 hexo-generator-tag,具体如下(截图时已安装):

pnpm install hexo-generator-tag --save

image-20220327014615469

参考主题的教程, 有

新建 tags 页面,在博客根目录下输入:

hexo new page tags

修改 source/tags/index.mdFront Matter

---
date: 2017-10-09 19:11:58
comments: false
type: tags
---

_config.yun.yml 中设置:

wordcloud:
enable: true

来使用彩色的词云替代原生的标签云。

配置分类

因为原有配置中已经包含了hexo-generator-tag依赖,配置分类不再需要安装新插件。

新建页面:

hexo new page categories

image-20220331023215967

修改新生成文档的头部信息:

---
title: categories
date: 2022-03-31 02:27:20
comments: false
type: categories
---

处理 warngins

image-20220326235513205

Hexo运行总有好多warning,让我很头疼。于是查阅资料,在这份资料中发现了解决办法。故,在package.json中加入以下内容:

"resolutions": {
  "stylus": "^0.57.0"
}

nib 中的过时package强制解析为新版本。在运行 pnpm install , 更新包及依赖。

顺便,它也干掉了 pnpm install 时报的4个 deprecated warn.

(nib 咋GitHub更新npm不发包呢…)

剩下两个 pnpm install 的 deprecated warn 都是来自 CSS 这个两年没维护的老东西了… 暂时无法处理

旧文章导入

之前已有过一个博客,为typecho搭建,这次也一并迁移过来。

先在本地安装 hexo-migrator-rss 插件:

$ pnpm install hexo-migrator-rss --save
Packages: +56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 529, reused 500, downloaded 27, added 56, done

dependencies:

image-20220331082820673

再运行 hexo migrate rss <source> 命令,我的情况是:

hexo migrate rss https://180811.xyz/index.php/feed/

image-20220331083006026成功导入四篇内容。

再对导入的文章做一遍校对,这里就不再赘述了。

另:还要干啥

  • 补完站点介绍与个人页面

  • 写写怎么搞个 HexoPlusPlus 来管理 Hexo

    UPD: HexoPlusPlus, 它, achieved了……等替代品 Wexagonal 变得可用中…

  • 还有啊,别做鸽子了:(

    不过感谢你们的催更,嘻嘻

  • 绑定网址

  • 为旧文章打 tag

  • 调整配色和背景图片

主要参考资料

https://vercel.com/guides/deploying-hexo-with-vercel

https://pnpm.io/cli/update

https://yun.yunyoujun.cn/guide/

https://www.haoyizebo.com/posts/710984d0/

https://github.com/lxgw/LxgwWenKai/issues/24

https://hexo.io/zh-cn/docs/permalinks

https://hexo.io/zh-cn/docs/migration#RSS