[{"content":"自从 2021 年买了 NAS，就一直想着可以收藏超级多的动漫，搭建成自己的动漫库，即便不能每一部都看完，但也能满足自己的收集癖好，算是实现童年的一个小小梦想。\n经过这么多年的摸索、完善，以及各路开源大佬制作的工具，直到 25 年初的时候算是拼凑出一个自己比较满意的方案了。并且，使用了大半年后也没什么特别想加的，趋于稳定，因此记录下来以免以后忘记。\n我的动漫媒体库的基本遵循以下目标：\n不必收集所有动漫，但自己感兴趣的都有 动漫资源无删减、无圣光，保证原汁原味（官方版本原本就有码的除外） 非新番只收集 BD 资源（至今没有 BD 资源的除外） 尽量使用高质量的压制资源 尽量使用中日字幕，翻译质量优先，其次字幕特效 桌面端、移动端、电视均能有较好的观看体验 可以看弹幕（没弹幕太孤单了 TAT） 半自动化，减少繁琐操作（不全自动是因为番剧特典资源比较混乱，很难做到统一） 以下按正常观看流程顺序来记录。\n准备 在整个流程中我用到的一些工具，类似功能都可以任意替换。\n储存： 群晖 DS220+，双 16T 机械硬盘\n服务： 运行于Docker，使用 Docker-compose 方式安装。\n下载： qbittorrent、115 浏览器\n媒体库： EMBY（Jellyfin 与其类似，可以通用）\n播放器： MPV config、\n插件： uosc_danmaku、Tampermonkey、embyToLocalPlayer\n下载 主要分为新番和旧番，其他还有番剧对应的剧场版，单独的动画电影等。\n以收集有 BD 的旧番为主，新番通常需要等待很长一段时间才会有 BD 资源流出，如果想要追番，只能退而求其次选择稍差一点的资源观看（其实只有与 BD 比较会有较大区别），之后再替换成 BD 版。\n对于我来说，新番一个季度一般只会追 1-2 部非常喜欢的，还不一定能追完。经常想起来要看都已经完结了。\n下载的资源不做任何改动，统一存放在下载目录，满足 BT 做种的需求。 毕竟能得到这些资源也是其他爱好者做种分享，自己也要有分享精神。\n我的媒体库目录结构如下，下载目录要和 NAS 中媒体库文件在同一个分区：\n- NAS - Media # 媒体库分区 - anime - animemovie - movie - tv - hlinks - downloads # 下载的未经过整理的原始文件 - anime # 番剧 - animemovie # 动画电影、剧场版 - movie # 普通电影 - tv # 电视剧 - bangumi # 追番专用，出BD资源后直接删除对应的 - book # 图书、电子书、有声书 - other # 其他不好归类的 - sort # 待整理的资源 - incomplete # qBittorrent的下载缓存 压制组 BD 资源我会优先选择VCB-Studio的作品，每集大小在 700Mb-1.2Gb 左右，并且特典、CD、封面一应俱全，画质上乘，一次性满足了我的大部分需求。\n在 VCB 的《作品项目列表》中搜索想要的番剧，通过公网 BT 或者磁力链接下载。\n比较久远的番可能时间太长没人做种，下载会比较慢。我的解决方法是使用 115 离线下载，只要有人在 115 中上传过，就可以确保满速下载。\n115 必须要开会员才能使用，介意可以等 BT 慢慢下或者去找 PT 站的资源。\n其次我会选择Moozzi2压制的作品，除了没有 CD，其他资源也都齐全，大小和品质都满足我的需求。虽然很多人不喜欢他作品压制后饱和度过高的色彩，但我实际观看下来个人是能接受，感觉还不错，因此作为备用方案。\n新番资源，追求最快我会先选择Ani的作品，等Lolihouse资源出了自动替换，具体如何操作可以看大佬《ANI-RSS：自动追番新姿势！》这篇文章。我自己也会在文章末尾简略写一下，方便回忆。\n目前还在活跃的压制组国内外其实质量都不错，比如 AI-Raws 也是我经常的选择。因为个人喜好不同，纠结的话还是先根据自己的硬盘大小筛选，再都下载一集对比观看，选定一个后再下载就不用纠结了。\n字幕 由于下载的压制组的作品，很多都是不带字幕的，这时候就需要自己去寻找了。\n新番的话比较简单，直接下载喜欢的字幕组的资源观看就行，或者去各个字幕组的资源发布页面下载单独的字幕文件，简介中一般都有写。\nBD 因为会修复 TV 新番中的一些错误，直接使用 TV 版的字幕，可能导致时间轴对不上，这时候就要去Anime 字幕论坛中搜索同好们对好轴的版本，感谢分享的同好们！\n实在找不到，也可以使用Aegisub自己对字幕进行对轴、更改字体等操作。\n因为我最喜欢百合日常类型的番剧，对千夏字幕组情有独钟，如果有的话我会最优先选择。新番其实没有太多字幕可以选择，各个字幕组很少会做同一部动漫，各自有各自的主要制作的类型偏好，在有限的选择里选自己喜欢的就行。\n比较老的番剧的话，诸神字幕组拥有中日双语，质量上乘，用作收藏字幕非常合适，是我的第一选择。\n整理 因为对资源有做种需求（不能修改做种资源的文件名），并且为了适配 EMBY 的媒体库识别和刮削，有特定的命名规则。\n而且动漫资源不像普通影视资源，通常原始文件名称更加复杂，不利于媒体库的识别。因此，非常有必要对资源进行整理，规范名称。这也是我选择手动+半自动整理的原因。\n为什么不用 Moviepliot 等工具管理？\n诸如 Nastool、Moviepliot 等工具，全自动下对于普通影视效果非常好。但是，对动漫的识别经常容易错集漏集（例如动漫第 2 季第 1 集有时候是 01 话，又有时候会被命名为 14 话等等情况），还是得手动编辑匹配名称和偏移量，全自动整理完后文件反而更混乱，还要找出错误的删除，重新手动整理，非常闹心，那不如一开始就手动慢慢整理好。\n硬链接 为了同时满足做种和重命名需求，这时候就需要硬链接了。\n简单来说，每个文件在硬盘中都是固定的一块数据，硬链接就是给这块数据再起了一个名字，两个不同的文件名，指向硬盘上完全相同的一块数据。\n注意： 你无论修改哪个“名字”下的文件，另一个“名字”下的内容也会同步改变，因为它们本来就是同一个文件。删除其中一个“名字”，文件数据并不会消失，只有把所有“名字”都删了，文件才会被真正删除。且必须在同一个盘符中！！！\n好处就是节省了硬盘空间，因为不需要复制，就能让文件出现在多个地方，同时同盘符内可以任意移动。\n先将资源存入预先分类好的下载文件夹中，再硬链接至中转文件夹内。\n- NAS - Media # 媒体库分区 - anime - hlinks # 中转文件夹，整理完后移入↑anime - downloads # 下载的未经过整理的原始文件 - anime - sort # 待整理的资源，整理完后移入↑anime 以下我使用过的部分硬链接工具。\nTorrentHardLinkHelper 很多年以前，U2 大佬千反田える发布的工具，发布地址，依然好用。具体使用方法可以可以参考贴吧教程。\n简单来说，可以对已有文件和种子文件内的内容比对，再硬链接到指定位置。\nHlink 使用的是 Docker 的 Web 端硬链接工具，[官网地址](https://hlink.likun.me/）。\n如何使用 Docker 搭建可以参考我之前这篇文章 《Docker-Compose 的日常使用》。\n创建如下配置文件，设置需要包括和排除的文件类型和文件夹：\n// 重要说明路径地址都请填写 绝对路径！！！！ export default { /** * 源路径与目标路径的映射关系 * 例子: * pathsMapping: { * \u0026#39;/path/to/exampleSource\u0026#39;: \u0026#39;/path/to/exampleDest\u0026#39;, * \u0026#39;/path/to/exampleSource2\u0026#39;: \u0026#39;/path/to/exampleDest2\u0026#39; * } */ pathsMapping: { \u0026#39;/Media/downloads/sort\u0026#39;: \u0026#39;/Media/hlinks/\u0026#39;, }, /** * 需要包含的后缀，如果与exclude同时配置，则取两者的交集 * include 留空表示包含所有文件 * * 后缀不够用? 高阶用法: https://hlink.likun.me/other/v2.html#%E6%96%B0%E5%A2%9E%E5%8A%9F%E8%83%BD */ include: [ \u0026#39;mp4\u0026#39;, \u0026#39;mkv\u0026#39;, \u0026#39;mka\u0026#39;, ], /** * 需要排除的后缀，如果与include同时配置，则取两者的交集 * * 后缀不够用? 高阶用法: https://hlink.likun.me/other/v2.html#%E6%96%B0%E5%A2%9E%E5%8A%9F%E8%83%BD */ exclude: [ \u0026#39;**/CDs/**\u0026#39;, \u0026#39;**/Scans/**\u0026#39;, \u0026#39;ass\u0026#39;, ], /** * @scope 该配置项 hlink 专用 * 是否保持原有目录结构，为false时则只保存一级目录结构 * 可选值: true/false * 例子： * - 源地址目录为：/a * - 目标地址目录为: /d * - 链接的文件地址为 /a/b/c/z/y/mv.mkv； * 如果设置为true 生成的硬链地址为: /d/b/c/z/y/mv.mkv * 如果设置为false 生成的硬链地址为：/d/y/mv.mkv */ keepDirStruct: true, /** * @scope 该配置项 hlink 专用 * 是否打开缓存，为true表示打开 * 可选值: true/false * 打开后，每次硬链后会把对应文件存入缓存，就算下次删除硬链，也不会进行硬链 */ openCache: false, /** * @scope 该配置项 hlink 专用 * 是否为独立文件创建同名文件夹，为true表示创建 * 可选值: true/false */ mkdirIfSingle: true, /** * @scope 该配置项为 hlink prune 命令专用 * 是否删除文件及所在目录，为false只会删除文件 * 可选值: true/false */ deleteDir: false, } 再在任务列表中创建任务，有需要可以设置定时循环。\n脚本 由于总是要打开 web 端运行，感觉还是比较麻烦，所以用 AI 制作了一个脚本方便我自己日常使用。目前自用很舒适，Bug 不清楚，有需要可以去我的 Github参考修改。\n重命名 对文件经过硬链接之后，只要不修改文件内的内容，就可以任意操作而不影响原始文件了。因此可以随意重命名，以适配 emby。（jellyfin 可以按相同规律。plex 仅可参考，具体还得看官方文档。）\n对于番剧，将命名改成以下格式：\n- 番剧名 (年代) [tmdbid=编号] # 加上编号更利于准确识别，名称和TMDB一致也可以不需要。 - 特典 # 番剧目录下，任意被命名为extras、specials、shorts、scenes、featurettes、behind the scenes、deleted scenes、interviews、trailers、Season 0的文件夹，都会被识别到媒体库的特典文件夹内，对于番剧来说并不友好，因此推荐把真正的特典内容放在Season 0中。 - 季度 # 按Season 1，Season 02等命名文件夹 - 任意名称+季度集数+加后缀.视频格式 # 识别排在文件名最前的季度与集数 另外还有多种命名方式和文件摆放方式，具体可以看emby-tv 命名规则。\n对于动画电影，就相对来说比较简单：\n- 电影名 (年代) [tmdbid=编号] # 加上编号更利于准确识别，名称和TMDB一致也可以不需要。 - 特典 # 统一使用extras文件夹就行 - 电影名 (年代) - 分辨率标识 # 加上分辨率可以应对同一部电影不同分辨率的情况。 其他命名规则，具体可以看emby-movie 命名规则。\n按照上面的原理，以略微复杂的 摇曳百合（究级难整理的得属物语系列了）为案例示范。\n以下是硬链接一次筛选过后的原文件名称（选取代表性的部分）：\n- [VCB-Studio] Yuru Yuri [Ma10p_1080p] - SPs - [VCB-Studio] Yuru Yuri [SP][Ma10p_1080p][x265_flac].mkv - [VCB-Studio] Yuru Yuri [CM01][Ma10p_1080p][x265_flac].mkv - [VCB-Studio] Yuru Yuri [01][Ma10p_1080p][x265_flac].mkv - [VCB-Studio] Yuru Yuri 2 [Ma10p_1080p] - SPs - [VCB-Studio] Yuru Yuri 2 [Art Design01 Akari][Ma10p_1080p][x265_flac].mkv - [VCB-Studio] Yuru Yuri 2 [NCOP01][Ma10p_1080p][x265_flac].mkv - [VCB-Studio] Yuru Yuri 2 [01][Ma10p_1080p][x265_2flac].mkv - [VCB-Studio] Yuru Yuri 3 [Ma10p_1080p] - SPs - [VCB-Studio] Yuru Yuri 3 [PV01][Ma10p_1080p][x265_flac].mkv - [VCB-Studio] Yuru Yuri 3 [01][Ma10p_1080p][x265_2flac].mkv - [VCB-Studio] Yuru Yuri Nachuyachumi! [Ma10p_1080p] - SPs - [VCB-Studio] Yuru Yuri Nachuyachumi!+ [Preview01][Ma10p_1080p][x265_flac].mkv - [VCB-Studio] Yuru Yuri Nachuyachumi! [NCED][Ma10p_1080p][x265_flac].mkv - [VCB-Studio] Yuru Yuri Nachuyachumi! [Ma10p_1080p][x265_flac].mkv - [VCB-Studio] Yuru Yuri Nachuyachumi! [Ma10p_1080p][x265_flac].mka - [VCB-Studio] Yuru Yuri Nachuyachumi!+ [02][Ma10p_1080p][x265_flac].mkv 按照我的习惯，重命名并且分类后为：\n- 摇曳百合 (2011) - CM - season.nfo - 摇曳百合 CM01 - 1080p.mkv - OPED - season.nfo - 摇曳百合♪♪ NCOP01 - 1080p.mkv - PV - season.nfo - 摇曳百合 3☆Hi！ PV01 - 1080p-trailer.mkv - Yokoku - season.nfo - 摇曳百合 夏日时光！+ Preview01 - 1080p.mkv - Season 0 [Airota@VCB-Studio] - 摇曳百合 - S01E01 - 1080p.mkv - 摇曳百合 夏日时光！+ + - S00E03 - 1080p.mkv - 摇曳百合♪♪ - S00E09 - Art Design01 Akari - 1080p.mkv - Season 1 (2011) [Airota@VCB-Studio] - 摇曳百合 - S00E01 - 1080p.mkv - Season 2 (2012) [Airota@VCB-Studio] - 摇曳百合 - S02E01 - 1080p.mkv - Season 3 (2015) [Airota@VCB-Studio] - 摇曳百合 - S03E01 - 1080p.mkv - 摇曳百合 夏日时光！ (2014) [VCB-Studio] - extras - 摇曳百合 夏日时光！ NCED - 1080p.mkv - 摇曳百合 夏日时光！ (2014) - 1080p.mkv - 摇曳百合 夏日时光！ (2014) - 1080p.mka 再把它们分别移动至媒体库：\n- NAS - Media # 媒体库分区 - anime - 摇曳百合 (2011) - animemovie - 摇曳百合 夏日时光！ (2014) [VCB-Studio] 注意： CM、OPED、PV、Yokoku这些带season.nfo的文件夹，其实可以是根据自己需求，任意建立的文件夹。season.nfo是自己建立的文件，通过修改其中的元数据信息，让其在媒体库中以分类文件夹形式显示。\n例如，CM中的 season.nfo 文件为：\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34; standalone=\u0026#34;yes\u0026#34;?\u0026gt; \u0026lt;season\u0026gt; \u0026lt;plot\u0026gt;\u0026lt;![CDATA[电视放送广告]]\u0026gt;\u0026lt;/plot\u0026gt; \u0026lt;outline\u0026gt;\u0026lt;![CDATA[电视放送广告]]\u0026gt;\u0026lt;/outline\u0026gt; \u0026lt;lockdata\u0026gt;true\u0026lt;/lockdata\u0026gt; \u0026lt;dateadded\u0026gt;2025-09-22 16:40:44\u0026lt;/dateadded\u0026gt; \u0026lt;title\u0026gt;广告\u0026lt;/title\u0026gt; \u0026lt;sorttitle\u0026gt;广告\u0026lt;/sorttitle\u0026gt; \u0026lt;seasonnumber\u0026gt;103\u0026lt;/seasonnumber\u0026gt; \u0026lt;/season\u0026gt; 大量的重命名和分类操作也可以用脚本来减轻重复劳动的压力，有需要的话同样可以参考我的 Github。\n媒体库 我使用的是emby（因为很久以前就购买了永久会员），jellyfin 的设置与 emby 几乎相同，plex 没有用过。\n安装 同样是使用 Docker-compose，安装方法参考 《Docker-Compose 的日常使用》。\n我的 yaml 文件配置如下：\n--- services: emby: image: lscr.io/linuxserver/emby:beta container_name: emby environment: # 用户和组ID设置 - PUID=填自己的 - PGID=填自己的 # 时区设置 - TZ=Asia/Shanghai volumes: # 配置目录 - /volume1/docker/emby-beta/library:/config:rw # 媒体库目录 - /volume1/music:/music - /volume2/Media/anime:/anime - /volume2/Media/downloads/Bangumi:/bangumi:rw - /volume2/Media/animemovie:/animemovie:rw ports: # 主要端口（修改为8888） - 8888:8096 # HTTPS端口（可选） - 8920:8920 devices: # Intel硬解设备映射（关键） - /dev/dri:/dev/dri restart: unless-stopped 插件：\nTheMovieDb：官方自带的刮削插件，使用这个足够满足绝大多数需求。 Bangumi Lite：Bangumi 自动点格子，放在/config/plugins中就行。 设置 大部分默认设置即可，我一般只更改以下几项。\n用户 将默认用户更改为管理员用户，设置密码，给最高权限。 新增一个专门看动漫的用户，无密码，有限权限，设置仅可观看动漫相关的媒体库，不允许删除文件等操作。日常观看都用这个用户，防止误操作。 媒体库 建立追番、动漫、剧场版、音乐四个媒体库。\n以动漫媒体库为例进行设置，其他设置大同小异。\n文件夹： 直接填在 docker-compose 中映射好的分类目录/anime，或者其他你自定义的。\n共享网络文件夹： 填 Nas 上文件夹的实际地址，如nfs://ip地址/volume2/Media/anime，需要开启 smb 或者 nfs 功能，我习惯用 nfs 读取。填写这一项可以获取到文件的实际地址，方便用 mpv 等播放器观看时直接打开本地文件，而不是使用流媒体播放。\n实时监视： 手动整理的媒体库，一般不开启，仅在追番媒体库开启。添加新动漫的时候，直接手动扫描一下媒体库就行。开启的话容易在整理还没完成的时候就自动刮削了元数据，生成很多命名不对的文件，导致文件混乱。\nnfo： 开启后会读取文件同目录下的元数据文件信息，之前整理阶段自己制作的season.nfo就是靠这个生效。\n元数据下载器： 勾选后会按顺序获取元数据信息，所谓的刮削就是指这个。由于之前的整理阶段已经针对 TheMovieDb 做好了非常细致的命名，通常只需要选择 TheMovieDb 就行。我勾选 Bangumi 是为了同时获取 Bangumi 番剧的编号，用来自动点格子。\n合集： 这个功能个人认为非常没用，又关不掉，还会如第一张截图所示生成一个普通情况下无法删除的媒体文件夹，逼死强迫症。因此设置成最大。关于如何删除后面再说。\n元数据储存方式： Nfo 勾选，勾选后才会用 nfo 文件的形式储存元数据。\n图像获取器： 我喜欢优先选择 FanArt，FanArt 的海报图片质量通常更加高清，并且更纯粹，没有多余的广告演员等信息在海报上。其次再选择 TheMovieDb。\n保存媒体图片到媒体文件夹中： 勾选。这样今后移动整理删除都更加方便整洁。\n字幕： 相关功能都不开启，对动漫类影视几乎没有任何作用。只对不在意这些，也不想折腾的人有用。自己收藏的影视还是自己找心仪的字幕比较好。\n播放： 默认就行。仅影响 Bangumi 何时判断自动点格子。\n效果 Tips 我遇到的一些问题，以及解决方案。\n主页不好看怎么办？ 使用emby-crx项目，目前适用于 4.8 的正式版 emby，4.9 的测试版自己修改了好几天也无法适配，只能暂时放弃，在找懂代码的朋友修改中。\n以下是我自己用的笨方法：\n在/docker/emby-beta/下创建emby-crx目录。 SSH 管理员模式进入 Nas，进入目录。 cd /volume1/docker/emby-beta/emby-crx 拉取主要使用的这几个文件到目录下，main.js使用的是issues#17： wget https://raw.githubusercontent.com/Nolovenodie/emby-crx/master/static/css/style.css wget https://raw.githubusercontent.com/Nolovenodie/emby-crx/master/static/js/common-utils.js wget https://raw.githubusercontent.com/Nolovenodie/emby-crx/master/static/js/jquery-3.6.0.min.js wget https://raw.githubusercontent.com/Nolovenodie/emby-crx/master/static/js/md5.min.js wget https://raw.githubusercontent.com/mobclix/emby-crx/master/content/main.js 文件夹内新建对应的config.js： class Config{ constructor() { //媒体库id，用逗号分隔。进入媒体库后url里的parentId //this.parentId = \u0026#34;5,21463\u0026#34;; this.parentId = \u0026#34;\u0026#34;; //滚屏间隔 ms this.interval = 8000; //是否开启随机 this.random = true; this.itemQuery={ //返回横幅的最大数量，注意每10个为一轮，一轮不足10个的会被舍弃。例如27则只显示两轮20个 Limit : 20,//(integer) Optional. The maximum number of records to return //一般只需要关注上面几个配置，下面不了解的不需要修改 /*-------------------------------------------------------------------------------------------------------------------------------*/ Recursive : true,//(boolean) When searching within folders, this determines whether or not the search will be recursive. true/false SortOrder : \u0026#34;Descending\u0026#34;,//(string) Sort Order - Ascending,Descending Fields : \u0026#34;ProductionYear\u0026#34;,//(string) Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines EnableUserData : false,//(boolean) Optional, include user data ImageTypeLimit : 1,//(integer) Optional, the max number of images to return, per image type Fields : \u0026#34;ProductionYear\u0026#34;,//(string) Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines IncludeItemTypes : \u0026#34;Movie,Series\u0026#34;,//(string) Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted. ImageTypes : \u0026#34;Backdrop\u0026#34;,//(string) Optional. If specified, results will be filtered based on those containing image types. This allows multiple, comma delimited. EnableImageTypes : \u0026#34;Logo,Backdrop\u0026#34;,//(string) Optional. The image types to include in the output. SortBy : \u0026#34;ProductionYear, PremiereDate, SortName\u0026#34;,//(string) Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime ArtistType : \u0026#34;\u0026#34;,//(string) Artist or AlbumArtist MaxOfficialRating : \u0026#34;\u0026#34;,//(string) Optional filter by maximum official rating (PG, PG-13, TV-MA, etc). HasThemeSong : \u0026#34;\u0026#34;,//(boolean) Optional filter by items with theme songs. HasThemeVideo : \u0026#34;\u0026#34;,//(boolean) Optional filter by items with theme videos. HasSubtitles : \u0026#34;\u0026#34;,//(boolean) Optional filter by items with subtitles. HasSpecialFeature : \u0026#34;\u0026#34;,//(boolean) Optional filter by items with special features. HasTrailer : \u0026#34;\u0026#34;,//(boolean) Optional filter by items with trailers. AdjacentTo : \u0026#34;\u0026#34;,//(string) Optional. Return items that are siblings of a supplied item. MinIndexNumber : \u0026#34;\u0026#34;,//(integer) Optional filter by minimum index number. MaxPlayers : \u0026#34;\u0026#34;,//(integer) Optional filter by minimum number of game players. ParentIndexNumber : \u0026#34;\u0026#34;,//(integer) Optional filter by parent index number. HasParentalRating : \u0026#34;\u0026#34;,//(integer) Optional filter by items that have or do not have a parental rating IsHD : \u0026#34;\u0026#34;,//(boolean) Optional filter by items that are HD or not. LocationTypes : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted. ExcludeLocationTypes : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted. IsMissing : \u0026#34;\u0026#34;,//(boolean) Optional filter by items that are missing episodes or not. IsUnaired : \u0026#34;\u0026#34;,//(boolean) Optional filter by items that are unaired episodes or not. MinCommunityRating : \u0026#34;\u0026#34;,//(number) Optional filter by minimum community rating. MinCriticRating : \u0026#34;\u0026#34;,//(number) Optional filter by minimum critic rating. AiredDuringSeason : \u0026#34;\u0026#34;,//(integer) Gets all episodes that aired during a season, including specials. MinPremiereDate : \u0026#34;\u0026#34;,//(string) Optional. The minimum premiere date. Format = ISO MinDateLastSaved : \u0026#34;\u0026#34;,//(string) Optional. The minimum premiere date. Format = ISO MinDateLastSavedForUser : \u0026#34;\u0026#34;,//(string) Optional. The minimum premiere date. Format = ISO MaxPremiereDate : \u0026#34;\u0026#34;,//(string) Optional. The maximum premiere date. Format = ISO HasOverview : \u0026#34;\u0026#34;,//(boolean) Optional filter by items that have an overview or not. HasImdbId : \u0026#34;\u0026#34;,//(boolean) Optional filter by items that have an imdb id or not. HasTmdbId : \u0026#34;\u0026#34;,//(boolean) Optional filter by items that have a tmdb id or not. HasTvdbId : \u0026#34;\u0026#34;,//(boolean) Optional filter by items that have a tvdb id or not. ExcludeItemIds : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered by exxcluding item ids. This allows multiple, comma delimeted. StartIndex : \u0026#34;\u0026#34;,//(integer) Optional. The record index to start at. All items with a lower index will be dropped from the results. ExcludeItemTypes : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted. AnyProviderIdEquals : \u0026#34;\u0026#34;,//(string) Optional. If specified, result will be filtered to contain only items which match at least one of the specified IDs. Each provider ID must be in the form \u0026#39;prov.id\u0026#39;, e.g. \u0026#39;imdb.tt123456\u0026#39;. This allows multiple, comma delimeted value pairs. Filters : \u0026#34;\u0026#34;,//(string) Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes IsFavorite : \u0026#34;\u0026#34;,//(boolean) Optional filter by items that are marked as favorite, or not. IsMovie : \u0026#34;\u0026#34;,//(boolean) Optional filter for movies. IsSeries : \u0026#34;\u0026#34;,//(boolean) Optional filter for movies. IsNews : \u0026#34;\u0026#34;,//(boolean) Optional filter for news. IsKids : \u0026#34;\u0026#34;,//(boolean) Optional filter for kids. IsSports : \u0026#34;\u0026#34;,//(boolean) Optional filter for sports. MediaTypes : \u0026#34;\u0026#34;,//(string) Optional filter by MediaType. Allows multiple, comma delimited. IsPlayed : \u0026#34;\u0026#34;,//(string) Optional filter by items that are played, or not. Genres : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted. OfficialRatings : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimeted. Tags : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered based on tag. This allows multiple, pipe delimeted. Years : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered based on production year. This allows multiple, comma delimeted. EnableImages : \u0026#34;\u0026#34;,//(boolean) Optional, include image information in output Person : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered to include only those containing the specified person. PersonIds : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered to include only those containing the specified person. PersonTypes : \u0026#34;\u0026#34;,//(string) Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited Studios : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted. StudioIds : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted. Artists : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted. ArtistIds : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted. Albums : \u0026#34;\u0026#34;,//(string) Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimeted. Ids : \u0026#34;\u0026#34;,//(string) Optional. If specific items are needed, specify a list of item id\u0026#39;s to retrieve. This allows multiple, comma delimited. VideoTypes : \u0026#34;\u0026#34;,//(string) Optional filter by VideoType (videofile, dvd, bluray, iso). Allows multiple, comma delimeted. Containers : \u0026#34;\u0026#34;,//(string) Optional filter by Container. Allows multiple, comma delimeted. AudioCodecs : \u0026#34;\u0026#34;,//(string) Optional filter by AudioCodec. Allows multiple, comma delimeted. VideoCodecs : \u0026#34;\u0026#34;,//(string) Optional filter by VideoCodec. Allows multiple, comma delimeted. SubtitleCodecs : \u0026#34;\u0026#34;,//(string) Optional filter by SubtitleCodec. Allows multiple, comma delimeted. Path : \u0026#34;\u0026#34;,//(string) Optional filter by Path. UserId : \u0026#34;\u0026#34;,//(string) User Id MinOfficialRating : \u0026#34;\u0026#34;,//(string) Optional filter by minimum official rating (PG, PG-13, TV-MA, etc). IsLocked : \u0026#34;\u0026#34;,//(string) Optional filter by items that are locked. IsPlaceHolder : \u0026#34;\u0026#34;,//(boolean) Optional filter by items that are placeholders HasOfficialRating : \u0026#34;\u0026#34;,//(boolean) Optional filter by items that have official ratings GroupItemsIntoCollections : \u0026#34;\u0026#34;,//(boolean) Whether or not to hide items behind their boxsets. Is3D : \u0026#34;\u0026#34;,//(boolean) Whether or not to hide items behind their boxsets. SeriesStatus : \u0026#34;\u0026#34;,//(string) Optional filter by Series Status. Allows multiple, comma delimeted. NameStartsWithOrGreater : \u0026#34;\u0026#34;,//(string) Optional filter by items whose name is sorted equally or greater than a given input string. NameStartsWith : \u0026#34;\u0026#34;,//(string) Optional filter by items whose name is sorted equally than a given input string. NameLessThan : \u0026#34;\u0026#34;//(string) Optional filter by items whose name is equally or lesser than a given input string. } Object.getOwnPropertyNames(this.itemQuery).forEach(key =\u0026gt; { if(this.itemQuery[key]==\u0026#34;\u0026#34;){ delete this.itemQuery[key]; } }) this.parentIds = this.parentId.split(\u0026#39;,\u0026#39;); } } 回到上级目录，将容器内index.html文件拷贝出来并且备份： cd ../ # 注意写自己设置的容器名 docker-compose cp emby:/app/emby/system/dashboard-ui/ index.html # emby4.9测试版目录 docker-compose cp emby:/system/dashboard-ui/ index.html # emby4.9测试版目录 在index.html文件的\u0026lt;/head\u0026gt;前插入代码，用于调用js和css，保存： \u0026lt;link rel=\u0026#39;stylesheet\u0026#39; id=\u0026#39;theme-css\u0026#39; href=\u0026#39;emby-crx/style.css\u0026#39; type=\u0026#39;text/css\u0026#39; media=\u0026#39;all\u0026#39;/\u0026gt; \u0026lt;script src=\u0026#34;emby-crx/common-utils.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script src=\u0026#34;emby-crx/jquery-3.6.0.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script src=\u0026#34;emby-crx/md5.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script src=\u0026#34;emby-crx/config.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script src=\u0026#34;emby-crx/main.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; 将文件夹和文件拷贝回容器内： docker-compose cp index.html emby:/app/emby/system/dashboard-ui/ docker-compose cp emby-crx emby:/app/emby/system/dashboard-ui/ 刷新 emby 首页观察效果。 如何使用动态封面图？ 将 Gif 图片保存为 Png 格式上传使用。\n突然冒出的合集无法删除怎么办？ 在首页中，将合集内的剧集选中设置，移出合集。或者在设置-主屏幕中，选择不显示合集。这两种方法可以隐藏主页的合集显示，但媒体库中依然存在。 在config/root/default中找到合集或者collection，删除。重启 emby，有概率可以删除媒体库的合集。 安装StrmAssistant插件，设置中可以选择隐藏合集，同时媒体库中合集点开详细设置会出现移除按钮。 演员栏都是英文名、问号怎么办？ 使用这两个工具都可解决。media_server_tools、StrmAssistant。\n播放 绝大部分情况下都是使用 PC 桌面端播放，目前只有在 PC 上才能流畅使用弹幕功能，而这个功能对我来说太重要了，大家一起看真的不会那么孤单。\n桌面端 折腾版： 使用的是 MPV 播放器，基于大佬的整合包自己再修改一些设置日常使用。Potplayer、VLC、MPC-BE 等等播放器我都使用过，最终因为可高度自定义，还是喜欢 MPV。\n不想折腾： 也可以使用弹弹 play，捐赠会员可以直接调用 mpv 播放且显示弹幕。\n超级懒： 也可以直接使用魔改版的 emby 桌面端，请自己搜索下载。\n配置 快捷键配置，修改input.conf文件，位于/mpv/portable_config/中。整合包已经设置的非常齐全，几乎不需要做任何的修改。最多添加一个一键开关滤镜指定着色器的功能，例如：\nCTRL+0 change-list glsl-shaders add \u0026#34;~~/shaders/Anime4K/glsl/Restore/Anime4K_Restore_GAN_UL.glsl;~~/shaders/Anime4K/glsl/Upscale/Anime4K_Upscale_GAN_x4_UL.glsl;~~/shaders/Anime4K/glsl/Restore/Anime4K_Clamp_Highlights.glsl\u0026#34; #menu: 着色器 \u0026gt;自用4k优化 # 在原有着色器的基础上再添加这些着色器。 功能配置，修改mpv.conf文件，位于/mpv/portable_config/中。\nslang=assfonts,chs,sc,zh-Hans,zh-CN,cht,tc,zh-Hant,zh-HK,zh-TW,chi,zho,zh # 将assfonts的子集化字幕设置为第一优先级 screenshot-format=webp # 截图使用webp格式 screenshot-webp-quality=95 # 截图压缩质量 screenshot-template=\u0026#34;C:/Users/用户名/Pictures/mpv/%{media-title}-%P-%n\u0026#34; # 截图路径 [Anime] profile-desc=自用动画配置 profile-cond=path:find(\u0026#34;Anime\u0026#34;)~=nil or path:find(\u0026#34;anime\u0026#34;)~=nil or path:find(\u0026#34;ANIME\u0026#34;)~=nil or path:find(\u0026#34;Bangumi\u0026#34;)~=nil profile-restore=copy vf-toggle=fps=fps=60/1.001 script-opts-append=\u0026#34;uosc_danmaku-auto_load=yes\u0026#34; # 在条件配置栏添加,在指定关键词路径下播放的文件,锁定所有帧率为60fps,并且自动打开弹幕开关。 弹幕相关设置可以看uosc_danmaku。\nEmby 调用 MPV 使用embyToLocalPlayer安装脚本，开启服务器和本地硬盘模式。 下载embyToLocalPlayer.zip，解压到纯英文路径下，打开embyToLocalPlayer.ini。 设置 mpv.exe 的路径，并选择 mpv 播放器。 开启回传进度。 填写 emby 端的目录前缀，例如我的是nfs://ip地址/volume2/Media/，这就是之前媒体库要设置网络共享文件夹的原因。 填写本地目录前缀，我是直接将Media文件夹映射成了M:盘，填写a= M: 其他根据自己需求设置。 效果 Android 端 目前都无法使用弹幕功能，只能通过将 xml 格式的本地弹幕转换成字幕实现。\nEmby for Android：手机使用，可以自行搜索魔改版，更好用。\nEmby for Android TV：电视使用，可以自行搜索魔改版，更好用。\niOS 端 目前都无法使用弹幕功能，只能通过将 xml 格式的本地弹幕转换成字幕实现。\nInfuse：苹果设备使用，ios 最好用的播放器。缺点是太贵，买断只能使用一个大版本，无法享受后续的更新。\nEmby for iOS：日常使用足够。\n结语 至此，在满足我收集癖和绝大部分需求的情况下，还能更舒服、轻松的观看动漫。\n折腾过后也是满满的成就感！\n","date":"2025-10-08T16:27:20+08:00","image":"https://orinnge.com/posts/anime-video/title_hu_e352d626452b4e38.webp","permalink":"https://orinnge.com/posts/anime-video/","title":"我的动漫媒体库搭建指北"},{"content":"前言 Docker-compose 相比 Docker，简单来说，就是把所有需要配置的信息都填写进一个 yaml 文件里，直接通过 yaml 文件一键配置与构建容器。\n而且一个项目可以同时设置多个容器，省去了重复配置以及重复容器太多造成混乱的烦恼。\n例如，好几个项目需要用到数据库容器，配置多了以后容易分辨不出曾经哪个数据库对应哪个项目。\n目前群晖的Container Manager能支持使用 Docker-compose，将近一年使用下来体验良好。因此，我打算将已有的 Docker 容器，逐步转为 Docker-compose 构建。\n以下记录日常需要用到的操作。\nyaml 配置文件 详细参数可以参考菜鸟教程。\n与 Docker 建立config目录相似，yaml 文件通常存放在想要建立的项目的根目录下：\n- Nas - volume1 - docker - ani-rss - config - compose.yaml 不是必须，仅为了层次条理清晰，方便日后整理备份迁移。\n如果是群晖，直接在项目中选择 yaml 文件构建就行。\n单容器项目 以 emby 为例，官方给的配置如下：\n--- version: \u0026#34;2.3\u0026#34; #这一项原本没有，为了方便讲解加上 services: emby: image: lscr.io/linuxserver/emby:latest container_name: emby environment: - PUID=1000 - PGID=1000 - TZ=Etc/UTC volumes: - /path/to/emby/library:/config - /path/to/tvshows:/data/tvshows - /path/to/movies:/data/movies - /opt/vc/lib:/opt/vc/lib #optional ports: - 8096:8096 - 8920:8920 #optional devices: - /dev/dri:/dev/dri #optional - /dev/vchiq:/dev/vchiq #optional - /dev/video10:/dev/video10 #optional - /dev/video11:/dev/video11 #optional - /dev/video12:/dev/video12 #optional restart: unless-stopped version：指定 Docker-Compose 文件格式版本，有些项目可能需要使用旧版本格式。\nservices：顾名思义，简单来说就是告诉 Docker “我要运行这几个东西，它们各自怎么配置”。\nemby：整个服务的名称，如果不指定容器名,会默认用项目名_服务名_序号当容器名称。\nimage：容器镜像的名称，填写需要拉取的容器镜像。\ncontainer_name：容器名称，必须唯一，docker 命令中用到的容器名就是这里设定的名称，可以自由更改。\nenvironment：配置容器运行需要的环境参数，通常在镜像页面说明文档中会写明各种环境参数的意义，再根据需要选择是否填写。\nvolumes：目录映射，:左边是本地硬盘的路径，:右边是容器内路径。按示例的配置，硬盘中的/path/to/emby/library文件夹就等于容器内/config文件夹。\nports：访问端口，:左边是要映射的端口，:右边是容器的端口。\ndevices：硬件设备映射。\nrestart：重启策略。\n明白了各项配置参数的意义后，以下是我根据自己需求更改的配置：\n--- services: emby: image: lscr.io/linuxserver/emby:beta # 将镜像更换为beta版本 container_name: emby environment: # 用户和组ID设置，关系到容器的权限，需要自己获取，下面是我乱填的 - PUID=8888 - PGID=777 # 时区更改 - TZ=Asia/Shanghai volumes: # 配置目录，设置library文件夹存放emby的配置文件 - /volume1/docker/emby-beta/library:/config # 媒体库目录 - /volume1/music:/music - /volume2/Media/anime:/anime - /volume2/Media/downloads/Bangumi:/bangumi - /volume2/Media/animemovie:/animemovie ports: # 将内网登录端口改为8888 - 8888:8096 # HTTPS端口没动 - 8920:8920 devices: # Intel硬解设备映射，如要开启硬解必须设置 - /dev/dri:/dev/dri # 容器崩溃停止，自动重新启动，不影响手动停止 restart: unless-stopped 注意： /music、/anime、/bangumi、/animemovie路径会被容器当作在不同的分区。如果有硬链接的需求，则需要将映射改为/volume2/Media/downloads/Bangumi:/downloads/bangumi，这样bangumi内的文件可以硬链接至downloads文件夹内。\n多容器项目 以 RSS-Hub 为例，直接将多个容器打包在一个服务内，可以相互有联系：\nservices: rsshub: # two ways to enable puppeteer: # * comment out marked lines, then use this image instead: diygod/rsshub:chromium-bundled # * (consumes more disk space and memory) leave everything unchanged image: diygod/rsshub # or ghcr.io/diygod/rsshub restart: always ports: - \u0026#34;1200:1200\u0026#34; environment: NODE_ENV: production CACHE_TYPE: redis REDIS_URL: \u0026#34;redis://redis:6379/\u0026#34; PUPPETEER_WS_ENDPOINT: \u0026#34;ws://browserless:3000\u0026#34; # marked BILIBILI_COOKIE_你的ID: # 例如想给容器加上bilibili的cookie用于识别，可在环境中加上 healthcheck: test: [\u0026#34;CMD\u0026#34;, \u0026#34;curl\u0026#34;, \u0026#34;-f\u0026#34;, \u0026#34;http://localhost:1200/healthz\u0026#34;] interval: 30s timeout: 10s retries: 3 depends_on: - redis - browserless # marked browserless: # marked image: browserless/chrome # marked restart: always # marked ulimits: # marked core: # marked hard: 0 # marked soft: 0 # marked healthcheck: # marked test: [\u0026#34;CMD\u0026#34;, \u0026#34;curl\u0026#34;, \u0026#34;-f\u0026#34;, \u0026#34;http://localhost:3000/pressure\u0026#34;] # marked interval: 30s # marked timeout: 10s # marked retries: 3 # marked redis: image: redis:alpine restart: always volumes: - redis-data:/data healthcheck: test: [\u0026#34;CMD\u0026#34;, \u0026#34;redis-cli\u0026#34;, \u0026#34;ping\u0026#34;] interval: 30s timeout: 10s retries: 5 start_period: 5s volumes: redis-data: 相关命令 需要开启 SSH 功能。\n登录 登录 SSH 账号：\nssh 用户名@[ip] -p 端口 进入管理员模式：\nsudo -i 退出命令：\nexit 基础命令 构建镜像：\ndocker-compose build 查看运行状态：\ndocker-compose ps 查看日志：\ndocker-compose logs 进入容器：\ndocker-compose exec 容器名 /bin/sh 容器内运行命令：\ndocker-compose exec 删除容器：\ndocker-compose rm 重启项目：\ndocker-compose restart 复制文件：\ndocker-compose cp 文件名.html emby容器名:/app/emby/system/dashboard-ui/ 更新项目 查看当前正在运行的项目：\ndocker-compose ls cd 到需要更新项目的文件夹：\ncd /volume1/docker/项目文件夹 停止项目：\ndocker-compose stop 项目名 更新项目：\ndocker-compose pull 重新启动项目并在后台运行：\ndocker-compose up -d ","date":"2025-09-28T16:58:09+08:00","permalink":"https://orinnge.com/posts/docker-compose-use/","title":"Docker-Compose的日常使用"},{"content":"\r自从上一个教程视频已经过去了一年多，是时候更新一下了（ 才不是因为拖延症）。\n其实是上半年的时候，因为换了素体，身体不再那么与Avatar适配，单纯的的拉长拉短Avatar比例虽然勉强能用，但总不是那么完美，一些小细节总是会出现各种bug。于是去翻了翻官方文档，想看看VRChat游戏中，Avatar校准的基础原理是什么，接着就翻到了这个Kung\u0026rsquo;s guide。\n参考上面的教程，自己适配调试了一段时间，确认各方面没啥问题后录好了素材，但是，因为五月病拖延症犯了，一直拖到了现在。\n教程还是面向萌新，所以讲的比较基础，使用的方法也是尽量无脑傻瓜操作，老手可以参考思路，省流可以直接看 身体比例调整 这一节，非常简单。\n为什么要改 为什么要那么麻烦再去修改呢？如果你在VRChat里使用全身追踪的时候遇到了这些烦恼或者类似的情况，一个符合自己身体比例的Avatar或许可以改善这些情况。\n以下是在仅使用3个tracker的情况下。手臂增加2个tracker可以勉强解决手臂弯曲相关问题，大腿增加两个tracker可以勉强解决膝盖弯曲相关问题（也有可能会更明显）。增加基站优先于增加tracker，多一个基站位置准确性能得到非常大的提升。\n手臂伸不直\n垫脚脚尖部下陷\n站立姿势与现实不符（明明站直了，身体却是弯曲）\n跪姿膝盖悬空\n腿无法伸直（尽管现实中腿已经伸到最直）\n视线高度与现实不一致（手的位置是现实中视线的高度）\n在修改模型之前，对 校准方式 和 锁定方式 最好有一定的了解，方便理解为什么要修改。\n校准方式 这里参考Kung\u0026rsquo;s guide视频。我做了一定的简化和更改，有条件的建议看原视频。\n使用过的应该都知道，在VRChat中，全身追踪和Avatar校准绑定主要是通过 身高校准 和 臂展校准 两种方式。\n那么具体是如何运作的呢？我们以下图为例，前方「粉色」的代表真实的身体，后方「白色」的代表使用的Avatar。\nVRChat是通过缩放Avatar的大小来与真实身体适配，然后与选择的锁定方式匹配上。\n身高模式 先说用的最多，一般情况下也是最好用的身高模式。\n通常情况下，缩放Avatar至真实身高后整体上比较好的适配，但问题多数会出现在手臂的比例不协调上。大多数人会出现比下图中更明显的真实手臂短于或长于Avatar手臂的情况。如果使用的是非正常人体比例的Avatar（比如头部异常大，身材短小），不协调感会更加明显。\n从长期的使用经验下来，手部的校准基本只使用校准时的角度信息，控制器的位置和手部的骨骼是直接绑定到一起的 。\n这就会导致：\n当真实手臂 短于 Avatar手臂时，肘部会一直是弯曲状态，想要伸直非常困难。 当真实手臂 长于 Avatar手臂时，手部运动会有错位，例如手上拿着东西伸直手臂，东西会因为错位而握在手臂的前方。 臂展模式 臂展模式是缩放Avatar至真实臂展后再进行校准，通常在真实身体与Avatar比例不适配的时候不好用，因此使用的人较少。\n由于身高方向的比例不适配造成的影响更加明显，无论是头部的、腿部的偏差都会很明显的造成日常使用时的错位感。相信使用过的人都有明显的体会，比如站立的时候膝盖一直是弯曲状态。\n但是，使用臂展模式可以很更为准确的测量真实身体与Avatar之间的比例关系，之后的测量也会在臂展模式中进行。\n锁定方式 锁定方式有 头部 、 腰部 、 头部和腰部 三种。\n在真实身体比例不适配的情况下多多少少都会有一些问题，只能在其中选一个影响较小的使用。\n腰部锁定 腰部锁定或许是大多数人选择用的方式，看起来似乎有很好的效果，但这其实是最不推荐的锁定方式。\nVRChat会基于腰部tracker位置为中心，对身体进行垂直移动调整。视线高度与真实不在同一水平线上主要也是由于使用的腰部锁定造成。\n视线高度不一致会造成非常明显的低头腿弯曲，抬头掂脚的问题。\n同时由于固定点在腰部，胸部区域旋转的时候容易带动头部一起有轻微的旋转，实际效果并不令人满意。\n头部锁定 头部锁定会以头为中心对身体位置进行垂直调整，能够确保Avatar视线中心和真实视线在同一水平线上。\n通常真实的腿会比Avatar的腿短一些，就会导致足部的tracker被抬高，可以略微放大一些Avatar让tracker在正确的位置，但这又会导致手臂的比例错误。\n跳动的时候有可能腰部和胸部像弹簧。\n不过这也是三种锁定方法里影响最小的选择， 大多数时候应该选择这个 。\n全部锁定 全部锁定是头部tracker和腰部trakcer同时固定住，真实身体和Avatar比例不适配时，会造成身体的弯曲，跳动的时候也可能腰部和胸部像弹簧，因此一般情况下很少人使用。\n但是，真实身体与Avatar身体比例适配的情况下，这种锁定方式是最优的选择，强烈推荐。\n准备阶段 在改自己的Avatar前，最好能够先排除外部环境对全身追踪的影响，以免之后测量真实身体比例的时候出错。\n追踪环境 一个良好的追踪环境在日常游玩的过程中也是非常有必要的，即使不在意身体比例问题，也建议把环境布置好。\n我会以我布置的环境为例子讲解，目前基本能够稳定不丢追运行2个多小时，因为主要用于跳舞，更长时间没有测试过。\n接收器 全身追踪时位置不对，乱漂，首先要考虑的就是接收器的问题，以我的经验来看，基本70%的追踪错误、不稳定的情况都是接收器导致的。\n两个接收器之间 一定不要紧挨着插 ，需要隔开留出足够的空间防止互相干扰。附近的类似耳机、话筒之类的无线接收器建议不插，如果在运行中有概率会干扰导致漂移。\n接收器与tracker之间最好不要有东西阻挡，比如我是把Hub粘在了桌子底下。中间孔位不想浪费，也要插接收器的话，最好使用延长线。如果不在意美观度的话，最优选择是所有接收器都用延长器尽量分散开摆放。\n如果是使用的n7r的sw3、sw4接收器，一定要用固定住防止抖动，并且少配对一个tracker。以我的sw3来说，稍微碰一下就容易出现usb弹出重连的问题（所以买了新的接收器再也没用过sw3了）。\n总之，如果在正常使用的时候突然漂、移动，优先检查接收器问题。\n基站 基站的摆放就可以比较随意了，只需要遵循一个原则： 哪里有照射的死角，就补充照射到哪里。\n不过根据使用经验，可以在以上原则的基础上，尽量的优化的摆放位置。\n以我的房间为例，实际使用面积比较小（图中选中部分是基站的位置），大多数人应该能达到比我更好的使用效果。\n两基站之间形成的矩形长度大约5m，宽度大约1.6m。由于现实中还摆放了椅子等各种杂物，实际使用空间大约是矩形中间的2mx1.6m，应该比很多人的空间都小了。\n只有一个基站：放在自己站立的正前方4m左右，快速转身的动作基本不会丢追。 两个基站：类似我的放置方法（根据实际妥协后），以自身为圆心半径4m左右的对角，有条件的最好是与自身成45度的对角。实际使用可以随意转身。 因为基站的定位非常灵敏，距离太近的话，tracker与基站间形成的角度大，运动情况下，变化的角度也会更大，就更容易抖动。\n高度至少高于自己的身高，2.5-3m更好。基站与人之间不要有床、椅子之类的遮挡， 优先排除遮挡的情况 。\n两个以上基站：以两个基站为基础，多的基站补充照射到死角区域。比如跪坐或者趴着，就可以放一个在地上方便照到脚。 注意基站照射区域的反光：比如门玻璃、白色的柜子、地面瓷砖、计算机屏幕等等。\n安装推荐使用：天地撑（又或者叫衣架立杆，40元左右）、带1/4螺丝的大力夹U型云台（10.5元左右）配合使用，可以有效减少基站运行时本身的震动带来的影响。\n定位器 这里的tracker特指基于基站的光学定位器，惯性定位器原则上可以用，但不推荐。\ntracker的话需要注意的地方不多。如果是n7r的tracker，因为比较小，建议放在不容易被遮挡的部位，不然 非常非常非常 容易丢追。\n腰部tracker：\n固定在前面，定位更准确，但做弯腰动作时，腰部tracker容易丢追。 固定在后面，更方便，各方面影响都小，但不能躺，也更容易抖动。 固定在侧面，挥手的时候非常容易打到。 推荐使用绑带固定在腰后。\n腿部tracker：\n固定在脚背，可以很好的减少跳跃时的抖动，动作更准确。 固定在脚腕，方便，但各方面效果都不如脚背。 如果是Vive的tracker，推荐直接穿合脚的运动鞋，用鞋带给tracker的三个角来个龟甲缚，最稳，脚背和tracker间的空间越小，抖动最小。\n吐槽：花三百元买绑带，真不如30-40买双广场舞鞋，或者100多买双运动鞋，专门室内使用得方便。\n其他不好固定的tracker，推荐穿运动鞋，使用 鞋带 、 tracker软性底座 和 1/4螺丝 将tracker固定在脚背，每次使用直接穿鞋就好，方便快捷。\n如果还有多余的tracker，从提升效果的角度来看，手臂trakcer x 2 \u0026gt; 胸tracker x 1 \u0026gt; 大腿tracker x 2 。\nVR设置 最好尽量减少VR设备和游戏设置对全身追踪的影响。\nHMD（头戴显示器） 以quest2为例，一体机尽量使用原装头戴，使用额头垫起过高的替换头戴（或者怕额头出汗垫了东西）可能会造成识别的游戏区域地面高度不对，最终导致SteamVR以及游戏内地面高度不对。\n如果不是一体机，则没有这个烦恼。 不过地面高度不对，对准确校准也影响不大，可以不用过于在意。\n空间校准 如果是一体机（如pico、quest），想要使用全身追踪必须先进行空间校准，通常使用：\npushrax/OpenVR-SpaceCalibrator，原版校准插件，多年没更新了； ArcticFox8515/OpenVR-SpaceCalibrator，增加自动校准功能； hyblocker/OpenVR-SpaceCalibrator，在上一个的基础上修复了一些Bug，增加了一些功能； Hrenact/OpenVR-SpaceCalibrator-CN，在上一个的基础上进行了汉化。 想要使用自动校准功能，一般是加一个tracker固定在HMD上，将校准对象分别设置为HMD和头上的tracker，使用过程中会持续不断的执行校准，简单方便，能省很多事，每次启动不用重复校准过程。比较推荐使用。\n但是，持续不断的执行校准的方法只是治标不治本，如果环境搭建好了，基本只用每次启动最开始进行一次校准，在不大幅变动所处区域的情况下（频繁出入游戏区，等导致一体机出现识别区域错误的情况），能维持比较久的时间（2个小时以上），也还不错。\n所以，可以参考以下流程，尽可能让空间保持稳定（纯经验之谈）：\n通过串流软件启动SteamVR，打开所有追踪设备，四处走动并晃一晃、甩一甩手柄； 观察手柄和空间的状态，看是否会有突然跳动的情况，如果有，则重启SteamVR（SteamVR就是这样经常抽风，等进游戏才发现空间四处跳动就很折磨了）； 如果没有空间跳动，则先把所有追踪设备打开（因为每开一个，tracker的整体位置都可能会跳动），等待位置稳定; 将index指虎手柄或者用于校准的tracker拿手上，再将一体机手柄置于上方（防止被遮挡，摄像头识别不到），拿稳后720度旋转（可以不用画8，保证全角度被基站照到），一般选slow（手速快可以选fast）；\nVRChat设置 VRChat基于默认设置，动捕与IK选项。\n需要注意的有两个：\n肩宽补偿：开启的话可以减少手臂伸不直的情况。(比如Avatar已经与真实身体匹配后手臂还是伸不直，开启这项一般可以解决) 追踪器运动预测：可以理解为 运动不平滑度 ，默认是0%（最大平滑）， 建议调到90%-100%（相当与不开启） 。这个功能会平滑tracker的运动轨迹，让运动看起来更流畅，但会丢失很多细节导致动作看起来软绵绵的。再者，在第三方视角下，由于网络原因，VRChat本身会强制带有一层平滑过滤，开启后相当与有两层过滤，这也是平常游玩的时候看有些人动作像是基本没怎么动的原因。 身体比例调整 讲了一大堆前置的准备，不仅是方便日常的游玩，也是为了能更准确的测量真实身体在游戏中的比例，方便之后的修改。\n因为是面向新手，我会使用最傻瓜的方法操作，熟手参考流程就行了。\n测量身体比例 使用需要修改的原Avatar，切换的到 臂展模式 ； 调整到合适的手臂长度（图里我调到的是1.85m），使腰部tracker与Avatar腰部接近； 将左、右手柄放在右、左两肩以及右、左两腰，观察位置是否与现实对应； 拍照或截图记录下来手柄和足部tracker与Avatar的相对位置。\n合适的手臂长度：\n如果想要后续操作最简单，调整手臂长度至足部tracker位置与现实中位置一致，后续只需要调整Avatar手臂的长度；\n或者调整手臂长度至手柄位置与现实中位置一致，后续只需要调整Avatar腿的长度，但是缩短退后需要将身体原点重置为0，稍微麻烦一点；\n我选择的是同时调整手臂和腿的长度，因为最复杂，也方便一次演示多种情况，而且对原模型的比例影响最小。\n接下来我会以Chiffon和我自己的身体比例为例，来演示如何修改，两种方法各有各的优点和局限，选择自己喜欢就好（我选择的是都用）。\n方法一：Blender调整 更精准，更彻底，更灵活的调整，同时又相当于有个独属于自己的身体，适合经常改模的小伙伴或者只用一套骨骼适配所有衣服的Avatar。\n之前的教程推荐了使用M3插件。为了更加的对于Blender苦手友好，且M3插件已经转收费，我会关闭它并且全程尽量只使用鼠标操作，确保再小白也能学会。\n顺便再更新一下更傻瓜的Blender和中文安装方法，目前我使用的是最新的长期服务版Blender4.2。\n使用辣椒酱大佬的铁锅炖启动器，可以直接在启动器中选择想要的版本安装。\n在启动器的创意工坊中，可以直接安装中文翻译插件（如果Blender玩的很溜，用的插件很多可以安装独立版，独立版对非常多的插件也有翻译），注意安装后要点击启用插件才会生效。\n不想下启动器，也可以在steam里选择测试版里的长期服务版，就不用经常更新了。\n再安装上Cats-Blender-Plugin-Unofficial，由于原版的长期不更新了，因此这里选的非官方版本的新cats插件，方便导入导出。\n进入Blender，先删除所有场景内默认的组件，防止导出的时候忘记导出不需要的东西，再点击 导入模型 ，导入需要修改的Avatar。\n手臂调整 点击图里右上方的 -Y 切换到正视图，选择 游标 选项，比对之前测量的数据截图，点击 鼠标右键 ，用游标标记位置（这里我只估了个大概位置，没有标得很准确，实际越准越好），然后选中骨骼，进入 姿态模式 。\n在右上角点击骨骼小人， 勾选 显示骨骼叠加层，根据需要调整淡化几何体，方便调整身体时清楚看到骨骼。\n切换到 选择 工具，选中手部根骨骼，在右边栏进入 骨骼菜单 ，在关系选项卡中，将继承缩放设置为 无 。这一步是为了在缩放手臂骨骼的时候，手部骨骼不会跟着一起缩放。之后的足部设置原理相同。\n为什么要不允许手部和足部一起缩放呢？一是因为一起缩放会改变手指和脚趾的长短，看起来会非常畸形；二是因为手和足想要调整到合适的比例比较困难，在3D软件中显示看起来合适的大小实际使用并不合适，一般需要在VR中观察后再根据自己的喜好调整。\n设定好后，切换到 变换 工具，选中上手臂的骨骼，拖动横向的拉杆，调整单一方向上骨骼缩放（我这里是红色的X轴方向，搞不清颜色和方向对应关系可以看右上视角选择的显示），直至标记位置与Avatar握手柄的位置重合。\n由于真实身体的两只手臂很可能长短不一样，推荐使用同样的方法，再对另一只手臂调整。可以避免一只手臂能伸直，另一只手臂伸不直的情况。\n如果是有强迫症，“我必须要两只手一样长！”，可以在关闭另一只手的继承缩放后，选中之前调整的上手臂，点击鼠标 右键-复制姿态 ，再选种对应另一只手的上手臂，点击鼠标 右键-粘贴轴向翻转姿态 ，这样两只手就对称了。\n调整好后，点击cats插件的 Apply as Rest Pose 应用之前修改的变换，手部就算调整完成了。\n腿部调整 接着是调整腿部骨骼，看之前的图片可以明显看到，原Avatar模型的骨骼位置看起来不是很标准，稍微修复一下。\n切换回 选择 工具，选中整个骨骼，进入 编辑模式 ，开启 透视模式 ，由于想把 大腿下端的骨骼节点 移动到 小腿上端的骨骼节点 ，因此先选中 小腿上端的骨骼节点。\n选中后，点击鼠标 右键-吸附-游标到选中项 ，这样游标就吸附过去了。\n再选中 大腿下端的骨骼节点，点击鼠标 右键-吸附-选中项到游标，这样大腿的骨骼位置就调整好了。\n依葫芦画瓢，将其他部位的骨骼也修复好。\n观察腿部骨骼的形状，可以看到膝盖有一点像前弯曲的角度，这是很有必要的，可以更好的识别腿的前后关系，避免一些人体畸形Bug，因此修改的时候有必要保留这个角度。\n其实手臂手肘也需要一些向后弯曲的角度用于识别前后关系，只是需要的角度没膝盖这么大，非常微小，建议Avatar比例全部调整并且测试好后，再手动进入编辑模式添加一点弯曲度。\n再次进入 姿态模式 ，切换到 变换 工具，按之前手臂讲的方法用游标标记好足部tracker的位置（我是穿鞋放在了脚背上）。\n选择 大腿的骨骼，拉动垂直方向上的拉杆缩放，根据标记点找到一个合适的缩放大小（比如我的tracker在脚背，就让标记点刚好在脚背的高度），点开左下角缩放菜单，或者在右边骨骼选项卡中查看并记下缩放的数据（图里只缩放了0.744，我觉得不够所以手动改成了0.78）。\n*为什么一个显示是Z轴，一个显示是Y轴呢？Z轴是相对全局场景空间整体方向上的Z轴，可以在界面正上方坐标轴显示「全局」看到；Y轴是相对选择的骨骼这个个体的坐标轴。因此显示的轴不同。\n按 Ctrl+Z 撤回刚才的变换，将两只脚的小腿和足部骨骼 继承缩放 都设置为 无。\n因为需要保留膝盖的角度，所以需要将坐标轴切换为局部，或者直接在骨骼选项卡中直接输入要缩放的参数。\n用相同的方法将左右大腿、小腿分别缩放好后，应用变换。\n身体细化 可以看到按真实身体修改后的身体比例外观不再如原版那么完美，显的又短又粗（没办法，这就是我），Avatar也悬空了，并不是在标准的原点坐标。接下来就来解决这两个问题。\n进入 姿态模式 ，使用 缩放 工具，选中要缩放的骨骼，按住小方块拖拽调整，直到腿部粗细合适，然后复制到另一条腿，应用变换。\n对应颜色的方块就是锁定对应的轴不变，比如图里是拖拽的绿色方块，代表Y轴，因此可以保证腿Y轴的长度被锁定不变，而只改变红色z轴和蓝色x轴的粗细。可以用这个方法对身体其他各个部位进行调整。\n用上面讲到的方法，调整了大腿、小腿的粗细并复制到另一条腿，对手臂粗细进行了微调，大幅缩减了头的大小。这样Avatar在手脚长度符合真实身体比例的同时，还有比较不错的外观。同时共用同一个骨骼的衣服也按比例缩放好了。\n调整原点 点击 视角球-X 进入侧视图，切换到 选择 工具，选中身体的网格进入 编辑模式-点模式（右边第一个） ，选中身体网格最低的点。\n点击 鼠标右键-游标至选中项 。\n在视图选项卡中，将游标的X坐标和Y坐标都 设置为0 。这样游标的定位点就确定好了。\n回到 物体模式 ，按 A 全选，点击 鼠标右键-设置原点-原点至3D游标 。\n再进入 条目 选项卡，将位置中的Z轴复制下这个数字备用， 再设置为0。通常做到这一步就身体全部都回到原点了。\n旧版本的Blender可能会出现只有身体归零，骨骼没有归零的情况。\n选中骨骼，进入 编辑模式 ，按A全选，使用 移动 工具，随意沿垂直轴拖放移动一下（局部模式显示的是Y轴，全局模式显示的是Z轴），将之前备份的数字复制进去（具体正负需要自己尝试，可能会不一样，通常是负）。\n这样原点也调整好了。\n最终调整 有些Avatar作者可能因为使用软件不同或者使用习惯的原因，导入的FBX数据可能比较奇怪。\n这里回到 物体模式 ，全选所有组件，应用缩放，将XYZ轴的缩放都应用成 1 。（0.01的缩放导入Unity后容易有奇奇怪怪的bug，我也不清楚原理，也会影响Unity里对Avatar的调整）\n全部完成后，确保Blender文件内没有其他不相关的组件，使用Cats插件的导出Avatar，导出为FBX文件。\n用插件导出会默认设定好适应Unity的参数，全部使用默认导出即可。如果弹出警告界面，点击继续导出即可。\n到这一步算是全部做好了，后续如果想直接将FBX导入，一步步添加材质、动态骨骼，可以从16:00开始，看我之前的教程，个人更推荐这样，修改的更彻底，bug更少。\nUnity调整 如果不想重新一步步添加材质，也可以用FBX替换的方法，这在以前的教程中也有演示。\n原理是同名替换原始FBX文件，达到沿用原本设置的目的。这里再在之前的方法再进行一些补充。\n选择到替换好的FBX文件，在骨骼选项中将动作属性修改成 None ，应用后，再修改回 Humanoid ，再次应用。\n这一步的作用是，重置一下动作属性，消除可能会出现的骨骼错位Bug。\n再进入骨骼配置，把一些错误的匹配删除或者替换。\n再在材质界面，把原本的材质添加回材质栏，应用。\n直接替换的FBX通常边界盒会被重置成网格大小，可以使用MA插件来一次性解决，不用一个一个修改。\n选中Avatar，添加 MA Mesh Setting组件 ，将锚点覆盖模式和网格边界覆盖模式都设置为 指定 ，将骨骼中的 Chest 拖入锚点覆盖， Hips 拖入根骨骼，再根据自己需求设置网格的区域大小缩放。\n最后常规的，穿上衣服，再调整视角球位置、测试效果（这两个详细的会在下一节讲到），进游戏观察手脚大小后再按流程调整测试，直到改到满意的状态就行啦！\n方法二：直接Unity调整 想要偷懒，并且对修改的比例精确性没那么在意，可以直接对Unity骨骼进行缩放。\n最大的优点是穿已经适配Avatar的衣服可以一键操作，不用额外的修改。缺点是缩放是全局的，不能按单个骨骼角度缩放。\n比例调整 直接进入Avatar的上臂骨骼，调整 横向Y轴的缩放 ，因为演示为了之后方便计算，我设置的0.68。\n因为在Unity中，对父骨骼的缩放一定是会影响到子骨骼的，因此后续还要按照父骨骼的缩放比例反向调整回来。又因为会影响到子骨骼，反向调整只需调整之前父骨骼的一个次级骨骼就行。例如：缩放了UpperArm，保留LowerArm缩放，后续只需调整Hand就行。\n使用Unity脚本可以做到子骨骼不继承缩放，但对萌新来说太过复杂，所以就不多说了。直接问AI就可以得到对应脚本使用。\n为什么不使用MA插件对骨骼单独进行缩放？一是MA官方也不推荐使用缩放插件对Avatar骨骼缩放，二是缩放并不会带动骨骼节点移动，会导致网格拉扯，并不适用。\n选择到手部的骨骼，Y轴向再放大1.5倍（因为父骨骼的关系缩小了2/3，所以再放大3/2）。\n将其他需要缩放的骨骼按之前的方法都调整好后，选择整体骨骼，垂直方向拖动至与地面平齐（只能目测）。\n一键穿衣 穿与原Avatar适配的衣服只需要在点击衣服 Setup Outfit 后，再选中衣服骨骼，在 将位置与Avatar进行对齐 选项中，只勾选 也对齐缩放 ，执行后就一键适配修改后的Avatar了。\n视角球设定 视角球并不需要完全与Avatar眼球平齐，因为是定位的HMD的位置，可以适当的将视角球相对眼睛前移，可以有更好的校准效果。（或者在校准的时候适当抬头，直到各个tracker与现实位置大致一致）\n测试效果 想要测试在游戏中的效果可以使用官方的 Gesture Manager插件 。在 Options 菜单中可以自由测试动作和表情效果。\n如果出现原本默认隐藏的衣服还是显示出来，是因为原Avatar设置的衣服开关的默认动画覆盖了自己原本的设置，删除动画或者调整为默认关闭就好（建议直接删，调整需要所有相关组件都调整）。 写在最后 现在，就有了一个符合自己真实身体Avatar了！动作不再有偏差，很多以前做不到的动作都可以愉快的显示！\n其实只看调整这一节的话，会发现实际要操作的内容其实非常非常少，原理也非常简单。\n可我竟然恁是从11月下建文档开始，磨磨叽叽写了13000多个字！还写到了12月最后一天！万幸终于是差不多写完了。\n插件地址 启动器使用的是VRChat官方的VCC工具，插件也是直接用订阅地址订阅，下面是并不是都在教程里用到。\nGesture Manager 官方自带添加 Modular Avatar 穿衣 lilToon 着色器 AvatarOptimizer 模型优化 VRC-Avatar-Performance-Tools 贴图优化 参考资料 全身追踪 \u0026mdash; Full-Body Tracking [NEW 2020] VRChat FBT Fixes (Fullbody Avatar Mega-Tutorial) ","date":"2024-12-31T18:06:42+08:00","image":"https://orinnge.com/posts/avatar-fit/title_hu_39959ff18fc91d62.webp","permalink":"https://orinnge.com/posts/avatar-fit/","title":"为VRChat改一个符合自己身体比例的模型"},{"content":"自带插件不能删除 ssh进入服务器，输入（/home/web为安装路径）:\necho \u0026#34;define(\u0026#39;FS_METHOD\u0026#39;, \u0026#39;direct\u0026#39;);\u0026#34; \u0026gt;\u0026gt; /home/web/html/wp-config.php redis报错连接不上 ssh服务器，输入（/home/web为安装路径）：\necho \u0026#34;define(\u0026#39;WP_REDIS_HOST\u0026#39;, \u0026#39;redis\u0026#39;); define(\u0026#39;WP_REDIS_PORT\u0026#39;, \u0026#39;6379\u0026#39;);\u0026#34; \u0026gt;\u0026gt; /home/web/html/wp-config.php 文章页面404 触发原因是固定链接修改后，同时发布文章会显示 wordpress网站发布失败：此响应不是合法的JSON响应\nnginx添加伪静态配置规则，在https，server{ } 大括号里面添加下面的代码：\nlocation / { try_files $uri $uri/ /index.php?$args; } # Add trailing slash to */wp-admin requests. rewrite /wp-admin$ $scheme://$host$uri/ permanent; 主题上传失败 表现为 上传的文件大小超过 php.ini 文件中定义的 upload_max_filesize 值\n先查看下容器信息\ndocker ps -a 进入容器 php：填容器名或者镜像ID 容器\ndocker exec -it php /bin/bash 查询 php.ini 的位置\nphp --ini 如果出现如下显示：\nConfiguration File (php.ini) Path: /usr/local/etc/php Loaded Configuration File: (none) Scan for additional .ini files in: /usr/local/etc/php/conf.d Additional .ini files parsed: /usr/local/etc/php/conf.d/docker-fpm.ini, /usr/local/etc/php/conf.d/docker-php-ext-mysqli.ini, /usr/local/etc/php/conf.d/docker-php-ext-sodium.ini 文件本该出现的位置/usr/local/etc/php显示为 (none) ,表明文件不存在\n输入ls显示路径下只有有如下文件：\nconf.d php.ini-development php.ini-production php.ini-development、php.ini-production为官方提供的参考配置文件，任意复制一份并重命名为 php.ini ：\ncp php.ini-production php.ini 再输入php --ini检查是否生效,出现如下表示生效:\nConfiguration File (php.ini) Path: /usr/local/etc/php Loaded Configuration File: /usr/local/etc/php/php.ini Scan for additional .ini files in: /usr/local/etc/php/conf.d Additional .ini files parsed: /usr/local/etc/php/conf.d/docker-fpm.ini, /usr/local/etc/php/conf.d/docker-php-ext-mysqli.ini, /usr/local/etc/php/conf.d/docker-php-ext-sodium.ini 退出容器：\nexit 将配置文件复制到容器外方便修改，./表示容器外的当前路径：\ndocker cp php:usr/local/etc/php/php.ini ./ 将文件下载到本地，修改如下内容：\npost_max_size = 16M upload_max_filesize = 16M 覆盖容器外的 php.ini ，并复制回容器内：\ndocker cp php.ini php:usr/local/etc/php/php.ini 重启容器\ndocker restart php 刷新下页面，上传主题文件\n缺少一个或多个必须的模组 在 工具-站点健康 里显示\n进入容器 php：填容器名或者镜像ID 容器\ndocker exec -it php /bin/bash 输入php -m，查看当前的扩展模块，不出意外的是没有：\n[PHP Modules] Core ctype curl date dom fileinfo filter hash iconv json libxml mbstring mysqli mysqlnd openssl pcre PDO pdo_sqlite Phar posix random readline Reflection session SimpleXML sodium SPL sqlite3 standard tokenizer xml xmlreader xmlwriter zlib 安装exif、zip扩展 docker-php-ext-install exif docker-php-ext-install zip 安装gd扩展 先安装gd的依赖包，不然装不了gd扩展（php7.4以上的版本）：\napt-get install -y \\ libfreetype6-dev \\ libjpeg62-turbo-dev \\ libpng-dev \\ libwebp-dev \\ zlib1g-dev 添加gd库编译选项：\ndocker-php-ext-configure gd \\ --enable-gd \\ --with-freetype \\ --with-jpeg \\ --with-webp 再安装gd扩展模块:\ndocker-php-ext-install -j$(nproc) gd 安装intl扩展 pecl install imagick \u0026amp;\u0026amp; \\ docker-php-ext-enable imagick 安装imagick扩展 先安装，弹出提示直接回车:\napt-get install -y libmagickwand-dev \\ \u0026amp;\u0026amp; pecl install imagick 再安装imagick扩展模块:\ndocker-php-ext-enable imagick 如果是PHP8.3以上版本：\nERROR: `make INSTALL_ROOT=\u0026#34;/tmp/pear/temp/pear-build-defaultuserl6yASZ/install-imagick-3.7.0\u0026#34; install\u0026#39; failed 这个错误通常是由于 Imagick.stub.php 文件中的预处理条件没有正确关闭。这个问题在 PHP 8.3 上尤为常见。解决需要把PHP换成8.2或以下版本，或者用 develop 分支。\n因为不影响使用，也没查到可以成功使用的 develop 分支方法，所以选择不管imagick扩展。\n检查是否都安装成功 输入php -m检查容器扩展，退出容器\nexit 用上文的方法，修改 php.ini ，将对应插件前的 ; 去掉，没有的添加上：\nextension=gd extension=intl extension=exif extension=zip extension=imagick.so 重启容器\ndocker restart php WordPress无法上传WebP、ico等图片 搜索安装 Enable SVG, WebP, and ICO Upload 插件\n参考资料 快速修改PHP镜像中的php.ini并生效 - wuuconix\u0026rsquo;s blog docker如何修改容器内部文件的方法 - 个人文章 - SegmentFault 思否 docker-docker中如何给PHP安装扩展 - intl - 知乎 如何在docker容器中安装php自带的扩展模块_docker php 安装扩展-CSDN博客 Using Imagick extension with PHP 8.3 on Docker | Orkhan’s Blog ","date":"2024-11-15T14:47:51+08:00","permalink":"https://orinnge.com/posts/wordpress-questions/","title":"WordPress建站初期常见问题"},{"content":"碎碎念 起因是，正在开心研究博客的评论系统的时候，需要保存一个密码，发现Bitwarden却一直在转圈加载。之前因为证书过期也出现这种情况，我没有在意，日常去查看群晖的证书目录、检查acme.sh容器，发现均正常运行。\n思考了一会，又猜测可能是ddns没有正确的更新到域名上去，于是又去域名控制台查看更新情况。\n查询到的值，和搜索自身ip查到值是一样的，这就很令人纳闷了。\n于是我又想，难道因为我用的运营商的DNS，被污染了？于是打算换DNSpod试试。然而，正在我打算换，进入路由器后台的时候，发现\n这是什么奇怪的IP地址？查询后发现IP地址显示的位置距离我十万八千里，于是恍然大悟， 我被偷偷变成内网了！\n这不能忍啊，愤怒的拨打电信10000的客服电话：“您好…”“人工服务”，“业务繁忙…”“人工服务”，“您可以先查流量…”“人工服务”\n客服1\n“家庭网络不可以申请公网ip”\n“我用了几年了，这两天突然这样的” “好的，我帮您设置了，请重新拨号连接”\n“好的，我试试” “请问还有什么能帮到您的，结束后按两个1好评”\n「路由器还在重启拨号中，心想这么干脆，应该没问题吧，给了两个1」 结果还是在内网\n客服2\n“我看已经帮您设置了公网”\n“我这里显示还是在内网中啊？！” “我这里帮您开启公网双zan”\n「没听清zan是什么，也不知道什么是公网双zan，先答应吧」\n“好的，我先重新拨号试试” 在拨号中…“请问还有什么能帮到您的，结束后按两个1好评”\n「还想让她等一下的，话还没说出口已经是两个1的系统提示了」 「这回应该解决了吧，先给两个1吧，顺便查了下公网双z」\n靠联想词搜索，原来是公网双栈，有说法是ipv4和ipv6同时公网，又有说法是ipv4内网、ipv6公网，还有说法是开启了ipv6会让ipv4只有内网。 重新拨号完，依旧是内网ip，开启ipv6，获取不到任何地址，一片空白\n客服3\n“我这里看已经帮您设置了公网双zan”\n“可是我这里ip显示并没有在公网啊？” “这是ipv6的公网，您要开启ipv6”\n“我开启了ipv6，显示一片空白，并且我是想要ipv4的公网，之前一直都有的” 避开ipv4的问题没有回答，“您好，这边帮您切换到了公网单zan，您再拨号试试”\n“好的，我再试试” 在拨号中…“请问还有什么能帮到您的，结束后按两个1好评”，立马又是系统提示音 「这回总该解决了吧，于是又给了两个1」 重新拨号完，这回终于不是内网ip了，是 联机中断！ 重启路由、重启光猫， 联机中断！\n客服4\n“已经帮您设置了公网”\n“这次不是公网，是网都没有了。” “已经帮您上报，给您运维师傅的联系电话，可以打电话联系”\n“好的，谢谢” 「我不忍心还是扣了两个1」 去打了运维的电话，折腾了半天终于电脑拨号恢复了网络，但是依旧连ipv6都没有，因为天很晚了，说要上门查看 两天过去…中途只有回访的电话，没有运维上门的电话\n客服5\n“已经是ipv6的公网单栈，不需要开通的。”\n“什么是公网单栈，什么是公网双栈啊？” “稍等我查一下，不好意思，系统里也没有具体解释” 再打给运维，沟通后说师傅很忙要问问有没有时间，然后直接挂断电话再没有回音。（我寻思原来不是你上门啊？）\n折腾了好几天，PC端拨号也试验过，情况是不仅公网ipv4没有，甚至ipv6都没有，只能怀疑是光猫有问题，运维上门修也联系不上。\n如果半个月内还没有回音，那就去投诉了，给足他们时间，再好说话的脾气也被磨没了，😡\n既然如此，那就只能先想办法没公网的情况下解决问题了\nOpenSSL 由于基本只在家用，所以就在想有没有办法直接给IP地址加上SSL证书，搜索后发现不少人也有类似问题。可以使用OpenSSL制作自签名证书，来给内网加上https。\n前期准备 先去OpenSSL官网下载并安装对应系统的安装包，Light版已经足够大多数人使用。 Windows搜索环境变量→编辑账户的环境变量→在Path中添加OpenSSL安装位置的bin文件夹进入环境变量，例如我添加的路径是C:\\Program Files\\OpenSSL-Win64\\bin，方便随时调用。 在想存放证书文件的文件夹，按Shift+鼠标右键→在此处打开Powershell窗口 制作证书 生成私钥，private可以改成任意名字。\nopenssl genpkey -algorithm RSA -out private.key 使用刚刚生成的私钥，生成证书签名请求（CSR）。\nopenssl req -new -key private.key -out csr.pem 会提示需要提供一些信息，分别是国、省、市、企业、部门、域名、邮件、密码、可选公司，可以随意填写，我只在域名填了Nas的IP地址，其他都是乱写的。\n使用CSR和私钥生成自签名证书，我直接申请了100年。\nopenssl req -x509 -days 36500 -key private.key -in csr.pem -out certificate.crt 这样，证书相关的操作就完成了。\n给Nas内网地址加入证书 我使用的是群晖Nas，所以以群晖为例子来设置，其他Nas应该大同小异。\n进入控制面板-安全性-证书-新增-新增新证书-导入证书，将.key文件加入私钥、.crt文件加入证书，点击确定。\n100年的证书就成功添加上去了，然后点击设置，设定证书的使用范围,我将所有的都改成了自签证书。\n打开浏览器网页，输入https://NasIP地址/ 测试效果，会提示不安全，无所谓，反正是在内网，仍然进入就行了。\n内网Nas通过https成功访问。\nWebUI通过https访问 以Bitwarden为例（因为官方硬性要求WebUI使用https才能使用，如果是安卓客户端，反而可以直接用http登录），如果直接使用https://内网IP:端口的方式会发现无法连接。\n可以进入控制面板-登录门户-高级-反向代理服务器，添加反向代理。 来源是要访问的https端口，目的地是Bitwarden的自己设定的容器端口。\n可以发现主机名不让填IP，然而，其实可以不填，直接确定就好。\n这时输入https://内网IP:1111就能访问http://内网IP:2222的Bitwarden的WebUI界面了。\n拓展 其他部署的项目也都可以用类似方法，比如TinyTinyRSS的订阅链接，必须是https，因此可以给RSSHub也加上证书并反向代理。（然而我直接把TTRSS换成了Miniflux\n再比如Transmission老是要求身份验证，也可以换成https进入。\n甚至有多余闲置的域名的话，可以直接把内网IP地址解析到域名上使用，还挺好用的，哈哈。\n参考资料 bitwarden本地搭建(无需购买SSL证书) - THATO - 博客园 如何使用 OpenSSL 创建自签名证书 - SSL Dragon ","date":"2024-11-15T03:20:32+08:00","permalink":"https://orinnge.com/posts/public-ip/","title":"用了几年的公网ip被偷偷停用了"},{"content":"日常折腾时，受初之音大佬的博客的启发，想着自己也可以搭建一个用来整合知识，这样就不用每过一段时间想更新或重新建立一遍曾经搭建好的东西的时候，再从头开始查找资料，甚至书签里保存的网页资料再也打不开。\n想到就做，查阅各种资料和视频后，综合来看比较推崇的有Wordpress、Typecho、Halo、Hexo、Hugo，这五款博客框架。前三款是动态博客，后两款是静态博客，区别可以参考ʕ•ᴥ•ʔ Bear Blog。由于大佬用的是Typecho，我想玩点不一样的，所以最先的使用目标是用户数最多，教程最丰富的Worpress。\n写在前面，体验过Wordpress、Halo、Hugo后：\n如果你只想写文，前期想尽可能少的折腾，推荐选择动态博客。听说动态博客容易被攻击（例如进你博客就跳转到小黄网之类的），尤其是基于php的，所以说是前期。 在不打算魔改主题的情况下，根据喜欢的主题选择博客框架，不加过多的插件，2核2g的云服务器（通常会选择更小的，我这有点超标了）对于三款来说都是非常流畅，刚需Markdown在Typecho、Halo里选。 如果容易对主题中的小细节抓心挠腮，主题给的自定义设置里又没有可以更改的，会php的大佬推荐选择Wordpress，可以后台直接更改css，php文件并预览效果。 不怕折腾的选择hexo、hugo，有对于非程序员来说，较为易懂的文件格式，并且能修改代码的同时预览效果。 实时预览功能真的非常重要，不然就是修改主题包内的文件，然后频繁的打包上传服务器查看效果再修改，也许有更好的方法，但是我不会，哈哈。 个人推荐就是 优先选主题！优先选主题！优先选主题！ 有个喜欢的主题，什么难处都能克服！\n前期准备 由于动态网站依托于数据库，所以必须先准备好服务器，根据需求选择是否需要域名。\n云服务器 云服务器商可以是，阿里云、腾讯云的轻量应用服务器，比较经济实惠稳定。海外的服务商话，搬瓦工稳定好用，就是贵。双11，黑色星期五之类的节日可能有优惠，可以等这些时间再入手。非活动时间的话按月买更好，因为按年买价格是一样的。\n一般大陆服务器可使用的带宽和流量远远小于其他地区的服务器。但是，延迟的话，我所在的区域是大陆\u0026lt;香港\u0026lt;新加坡\u0026lt;东京、首尔\u0026lt;硅谷。\n镜像可以按需求选已经搭建好一套应用镜像，也可以单独选一个系统镜像，之后可以重置系统更改，这里我选的Ubuntu24.04\n也可以是自家的Nas作为服务器，如果只当笔记本地内网自己看（有公网ip可以绑定域名），那使用Nas最为方便，只需要Docker一键就行。\n域名 购买服务器的商家基本也都有域名，购买也非常简单，不多缀述。国内域名必须实名。推荐使用.COM或者其他顶级域名。\n如果仅自己使用，可以不需要域名，直接通过ip访问云服务器。\n解析域名 如果进入公网，可进入各家的域名控制台，找到对应域名，点击解析\n记录类型A，表示将域名指向一个具体的IPV4地址，也就是云服务器的公网地址 记录类型CNAME，表示将其他域名指向另一个类型，比如想输入blog.xxx.com跳转到xxx.com，就需要用到CNAME 主机记录，填@，表示没有前缀，比如xxx.com;填任意，如blog，表示blog.xxx.com 记录值，A记录填具体的IP地址，也就是云服务器的公网地址，CNAME填指向的域名 TTL，默认就好，越小对变化反应越快，但会影响解析速度 例如，分别添加@和WWW主机记录，分别设置为A和CNAME，值分别填xxx.xxx.xxx.xx和xxx.com，效果就是进入www.xxx.com自动跳转到xxx.com\n配置好后，等待一会便可以通过域名访问你的服务器了。\n备案 网站服务器位于中国大陆的需要实名备案，具体方法云服务商都有，非常简单，只是需要等待一段时间。服务器位于其他地区的则不需要备案，可以直接使用。\nSSH工具 虽然网页控制台也有网页版的SSH工具可以直接进入服务器，但还是更推荐使用本地SSH工具，更加方便。\n我纯外行比较小白，所以看重外观，使用的是Tabby\n创建密钥对 为了更方便也更安全的使用云服务器，可以先在服务器控制台创建密钥对，并妥善保存好自动下载到本地的私钥。\n然后点进服务器，绑定刚刚的密钥。\n新建配置 进入Tabby的配置和连接，点击新建新配置，选择SSH连接 名称分组自定，主机填云服务器的ip，私钥选择刚刚保存的私钥，点击保存\n这样以后每次进入服务器操作，都不用输入密码，还更加安全。\n服务器配置 服务器系统我选的Ubuntu24.04，也可以选择debain12，更加纯净，能输入的命令是一样的。\n配置环境 进入后先更新系统目录，更新系统，安装一些需要的组件\napt update -y \u0026amp;\u0026amp; apt upgrade -y \u0026amp;\u0026amp; apt install -y curl wget sudo socat 安装docker和docker-compose，并赋予权限，可以非常简单的运行各种打包好的容器，小白友好\ncurl -fsSL https://get.docker.com | sh curl -L \u0026#34;https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)\u0026#34; -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose 创建好存放数据的目录，之后备份只需要备份整个web文件夹就行\ncd /home mkdir web cd web mkdir certs 申请证书 为域名申请证书，域名需要有证书才能使用https访问，先安装acme.sh\ncurl https://get.acme.sh | sh 可以为多个域名申请同一个证书并存在同一个路径下，这里是存在/home/web/cert里，acme.sh会自动创建定时任务每60天重新申请一次证书，非常方便，更多用法可以去acme.sh\n~/.acme.sh/acme.sh --register-account -m 你的邮箱 --issue -d 你的域名1号 -d 你的域名2号 -d 你的域名3号 --standalone --key-file /home/web/certs/key.pem --cert-file /home/web/certs/cert.pem --force Wordpress搭建 Wordpress的主题非常多，而且后台使用起来很简单，想要什么功能，插件里一搜基本都有。因为还没有发过大量的文章，用的也是2核2g的云服务器，所以说的占内存、不流畅、卡顿之类的，还没有遇到过。\n但是如果刚需使用Markdown编辑文章，试用了几款插件转换总是会出现各种问题，并不好用，因此才会有下面Halo搭建这一部分。\n创建目录 首先给Wordpress创建目录、给数据库创建目录、创建nginx配置文件、编辑docker-compose，注意要在/home/web路径下操作\ncd /home/web mkdir html mkdir mysql touch nginx.conf nano docker-compose.yml docker-compose配置 将下面的配置信息复制（复制好内容，对着编辑器按鼠标右键就行）进去，按 Ctrl + O 然后按 Enter保存，按 Ctrl + X退出编辑器。也可以在外面编辑好内容通过SFTP替换文件。\n配置来源于kejilion/docker，我结合其他几个配置文件添加了redis，详细说明可以看下方 参考资料 里的原视频，讲解的非常详细，利于小白理解原理，感谢大佬！\ndocker-compose的好处是可以自由组合，整合了Wordpress所需要的所有环境，一键部署。\n为了便于理解，我添加了一些注释，可能会有些不对的地方\nversion: \u0026#39;3.8\u0026#39; services: # 用与反向代理，让网站内容可以通过域名显示 nginx: image: nginx container_name: nginx restart: always ports: - 80:80 - 443:443 volumes: - ./nginx.conf:/etc/nginx/nginx.conf # 映射nginx配置文件 - ./certs:/etc/nginx/certs # 映射证书目录 - ./html:/var/www/html # 映射Wordpress目录 # Wordpress基于php运行 php: image: php:fpm container_name: php restart: always volumes: - ./html:/var/www/html #映射Wordpress目录 # 数据库，动态框架的内容都是在数据库里 mysql: image: mysql container_name: mysql restart: always volumes: - ./mysql:/var/lib/mysql # 映射数据库目录 environment: - MYSQL_ROOT_PASSWORD=xxxxxx # root用户密码，自行填写 - MYSQL_DATABASE=web - MYSQL_USER=xxxx # 数据库用户名，自行填写 - MYSQL_PASSWORD=xxxxxxxx # 数据库密码，自行填写，越复杂越安心 # 内存缓存机制，配合Wordpress内的redis插件，提速网站 redis: image: redis container_name: redis restart: always volumes: - ./redis:/data 安装Wordpress 从官方源下载Wordpress压缩包，安装解压到/home/web/html文件夹内，并删除下载的安装包（可以根据更新情况替换版本号）\ncd /home/web \u0026amp;\u0026amp; wget https://cn.wordpress.org/wordpress-6.6.2-zh_CN.zip \u0026amp;\u0026amp; sudo apt-get install -y unzip \u0026amp;\u0026amp; unzip wordpress-6.6.2-zh_CN.zip -d html \u0026amp;\u0026amp; rm wordpress-6.6.2-zh_CN.zip \u0026amp;\u0026amp; mv /home/web/html/wordpress/* /home/web/html/ 确保进入/home/web目录，安装并启动docker-compose配置的容器\ncd /home/web \u0026amp;\u0026amp; docker-compose up -d 配置运行环境 进入docker容器，给nginx和php容器赋予使用/var/www/html的最高权限\ndocker exec -it nginx chmod -R 777 /var/www/html docker exec -it php chmod -R 777 /var/www/html 进入docker容器，为php安装一些Wordpress需要的扩展\ndocker exec php apt update \u0026amp;\u0026amp; docker exec php apt install -y libmariadb-dev-compat libmariadb-dev libzip-dev docker exec php docker-php-ext-install mysqli 重启php使新配置生效\ndocker restart php 配置nginx 因为之前已经映射了配置文件路径，可以使用Tabby，点击右上角的SFTP，进入/home/web目录下，把nginx.conf下载下来\n配置内容也是基于大佬的kejilion/nginx，根据自己的情况做了一些修改，添加了针对Wordpress的伪静态\nevents { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; client_max_body_size 50m; #限制50m以内文件可上传 # HTTP server server { listen 80; # 监听80端口 server_name xxxxx.com; # 填自己的域名 # HTTP自动跳转到HTTPS，后续根据自己需求，只需要修改HTTPS内的就行 return 301 https://$host$request_uri; } # HTTPS server server { listen 443 ssl; # 监听443端口 server_name xxxxx.com; # 填自己的域名 http2 on; # 启用HTTP2 ssl_certificate /etc/nginx/certs/cert.pem; # 证书的地址 ssl_certificate_key /etc/nginx/certs/key.pem; # 证书的地址 root /var/www/html; # 网页文件的目录 index index.php; #rewrite ^/vip.php(.*)$ /vip.php?s=$1 last; location / { try_files $uri $uri/ /index.php?$args; # 伪静态功能 } # Add trailing slash to */wp-admin requests. rewrite /wp-admin$ $scheme://$host$uri/ permanent; try_files $uri $uri/ =404; # PHP-FPM configuration location ~ \\.php$ { fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } } 配置完后保存文件上传覆盖，再重启一下nginx容器使新配置生效\ndocker restart nginx 登录Wordpress 以上部分完成后，输入自己的域名就可以进入Wordpress后台啦\n数据库名 web 用户名 填在docker-compose中配置的用户名 密码 填在docker-compose中配置的密码 数据库主机 mysql 表前缀 wp_ 之后可以自行探索Wordpress，功能都比较直观，遇到问题可以看我 下一篇文章 ，会分享一些初安装会遇到的常见问题的解决方法。\nHalo搭建 由于不原生支持Markdown，插件也不好用，所以试着转了Halo。总体用下来感觉没啥不好，也挺流畅的。\n我最后没用单纯是因为，喜欢的主题虽然自定义功能很多，但是不能换字体，一些小细节也没法改。需要去压缩包里修改代码然后上传到主题，然后再预览效果，过程过于繁琐。一点微小的改动需要的操作步骤太多了，所以最后放弃了。\n创建目录 首先给Halo创建目录、创建nginx配置文件、编辑docker-compose，注意要在/home/web路径下操作\n由于官方给的配置文件数据库和halo是集成在一起的，就不用单独创建数据库文件夹了\ncd /home/web mkdir halo touch nginx.conf nano docker-compose.yml docker-compose配置 复制下面的内容，按 Ctrl + O 然后按 Enter保存，按 Ctrl + X退出编辑器。也可以在外面编辑好内容通过SFTP替换文件。\n基于官方推荐的配置，这次使用的是postgres数据库，添加了nginx容器，并根据halo的映射目录更改了对应root的目录\nversion: \u0026#34;3\u0026#34; services: halo: image: registry.fit2cloud.com/halo/halo:2.20 restart: on-failure:3 depends_on: halodb: condition: service_healthy networks: halo_network: volumes: - ./halo/halo2:/root/.halo2 ports: - \u0026#34;8090:8090\u0026#34; healthcheck: test: [\u0026#34;CMD\u0026#34;, \u0026#34;curl\u0026#34;, \u0026#34;-f\u0026#34;, \u0026#34;http://localhost:8090/actuator/health/readiness\u0026#34;] interval: 30s timeout: 5s retries: 5 start_period: 30s environment: # JVM 参数，默认为 -Xmx256m -Xms256m，可以根据实际情况做调整，置空表示不添加 JVM 参数 - JVM_OPTS=-Xmx256m -Xms256m command: - --spring.r2dbc.url=r2dbc:pool:postgresql://halodb/halo - --spring.r2dbc.username=halo # PostgreSQL 的密码，请保证与下方 POSTGRES_PASSWORD 的变量值一致。 - --spring.r2dbc.password=填自己设定的密码 - --spring.sql.init.platform=postgresql # 外部访问地址，请根据实际需要修改 - --halo.external-url=http://localhost:8090/ halodb: image: postgres:15.4 restart: on-failure:3 networks: halo_network: volumes: - ./halo/db:/var/lib/postgresql/data healthcheck: test: [ \u0026#34;CMD\u0026#34;, \u0026#34;pg_isready\u0026#34; ] interval: 10s timeout: 5s retries: 5 environment: - POSTGRES_PASSWORD=填上面自己设定的密码 - POSTGRES_USER=halo - POSTGRES_DB=halo - PGUSER=halo nginx: image: nginx container_name: nginx restart: always ports: - 80:80 - 443:443 volumes: - ./nginx.conf:/etc/nginx/nginx.conf - ./certs:/etc/nginx/certs - ./halo:/var/www/halo networks: halo_network: 确保进入/home/web目录，安装并启动docker-compose配置的容器\ncd /home/web \u0026amp;\u0026amp; docker-compose up -d nginx配置 先查询一下容器的内部ip地址，记录下来\nip addr show docker0 因为之前已经映射了配置文件路径，可以使用Tabby，点击右上角的SFTP，进入/home/web目录下，把nginx.conf下载下来\n配置内容基于上面Wordpress的配置修改，用以适配Halo\nevents { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; client_max_body_size 50m; # 上传限制参数50m以内文件可上传 # 将之前查询到的halo容器ip地址替换下面，官方文档里的 upstream halo { server 172.xx.x.x:8090; } # HTTP server server { listen 80; # 监听80端口 server_name 填自己域名; # HTTP自动跳转到HTTPS，后续根据自己需求，只需要修改HTTPS内的就行 return 301 https://$host$request_uri; } # HTTPS server server { listen 443 ssl; # 监听443端口 server_name 填自己域名; http2 on; # 启用http2 ssl_certificate /etc/nginx/certs/cert.pem; # 证书的地址 ssl_certificate_key /etc/nginx/certs/key.pem; # 证书的地址 root /var/www/halo; # 网页文件的目录 # 用来获取Halo内部容器地址，官方文档里的 location / { proxy_pass http://halo; proxy_set_header HOST $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } try_files $uri $uri/ =404; } } 配置完后保存文件上传覆盖，再重启一下nginx容器使新配置生效\ndocker restart nginx 登录Halo 以上部分完成后，输入自己的域名就可以进入Halo后台啦，可以看到Halo甚至比Wordpress简单了很多。\n没有什么需要特别注意的，内容都可以自己设定，先自己探索吧！\n一些总结 备份的话直接备份整个web文件夹就好。\n看着内容不多，实际自己折腾了好几天，主要是不想使用一键包或者面板之类的，想要理解每段代码的原理，花费了比较多的时间。但是弄懂了之后，后期自己修改起来就方便了很多，就比如Halo的nginx配置就是我自己修改的，搭建也更为顺利，中途也没有太多的卡住出现问题。\n体会到了Linux使用代码的方便，操作过一次后，记录下使用的代码，组合成一长串命令，以后再使用就可以复制然后一键执行，非常畅快。\n在这之前只会用群晖的Docker下载使用容器算是比较熟练，感觉自己又变强了一点，开心！\n参考资料 个人博客搭建笔记 - 初之音 一台1H1G的VPS搭建7个网站是种什么样的体验？NGINX MySQL PHP Redis 全面进阶 LDNMP完美版！_哔哩哔哩_bilibili ","date":"2024-11-11T19:08:07+08:00","image":"https://orinnge.com/posts/dynamic-blog-setup/title_hu_7457bf45cacb30d2.webp","permalink":"https://orinnge.com/posts/dynamic-blog-setup/","title":"个人博客搭建（Wordpress、Halo）"},{"content":"普通文字有什么效果呢\n大标题 带序列的呢 这是要被折叠的内容\r中标题 from typing import Iterator # This is an example class Math: @staticmethod def fib(n: int) -\u0026gt; Iterator[int]: \u0026#34;\u0026#34;\u0026#34;Fibonacci series up to n.\u0026#34;\u0026#34;\u0026#34; a, b = 0, 1 while a \u0026lt; n: yield a a, b = b, a + b result = sum(Math.fib(42)) print(f\u0026#34;The answer is {result}\u0026#34;) 小标题 ","date":"2024-11-08T15:30:32+08:00","image":"https://orinnge.com/posts/test/test_hu_304b79dc927bcec5.webp","permalink":"https://orinnge.com/posts/test/","title":"这是一个测试文章"}]