<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/rss.xsl" type="text/xsl"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><generator>Typlog 3.1 (https://typlog.com)</generator><title><![CDATA[Wulu's Blog]]></title><description><![CDATA[盈科而后进。]]></description><link>https://wulu.zone/posts/</link><copyright><![CDATA[Copyright 2021 Wulu's Blog]]></copyright><image><url>https://i.typlog.com/wulu/8359125916_95308.jpg?x-oss-process=style/sl</url><title><![CDATA[Wulu's Blog]]></title><link>https://wulu.zone/posts/</link></image><atom:link href="https://wulu.zone/feed/post.xml" rel="self" type="application/rss+xml"/><atom:link href="https://pubsubhubbub.appspot.com/" rel="hub"/><pubDate>Sun, 08 Mar 2026 11:58:30 +0000</pubDate><item><title><![CDATA[2025 读书总结]]></title><guid>https://wulu.zone/posts/2025-books</guid><link>https://wulu.zone/posts/2025-books</link><description><![CDATA[Wulu 的 2025 读书总结]]></description><pubDate>Sun, 01 Mar 2026 11:56:03 +0000</pubDate><content:encoded><![CDATA[<p>去年只看完了一本书。</p>
<h2>《你当像鸟飞往你的山》</h2>
<div class="block-code"><pre><code>作者：塔拉·韦斯特弗
译者：任爱红
出版社：南海出版公司</code></pre></div>
<p>在看这本书之前，我陆续听说过，但一直没什么兴趣去了解。在我印象中这是一本&quot;励志&quot;书，而我并不喜欢&quot;励志&quot;或&quot;成功学&quot;类的书籍。当时我正在看一些工具书，读得艰难有些疲惫，就想换本有故事性的书来放松一下。</p>
<p>于是，这本书陪我度过了多个通勤和午休前的时间。读完后我发现，虽然作者的故事确实很励志，但这本书想表达的不止于此——它给我带来的更多是关于个体与家庭、个人与信仰关系的思考。</p>
<p>书中最让我印象深刻的，是作者在&quot;回归家庭&quot;和&quot;保持自我&quot;之间的挣扎。也许这两者并非完全对立，但她极端的成长经历把这种冲突逼到了非此即彼的境地。更难的是，&quot;回归&quot;这个选项有着真实的诱惑：回到家庭，回到宗教，仿佛就可以不再烦恼。放弃自己的主体性，不用再为自己负责，上帝会解决一切。那种安稳，并不是没有吸引力的。</p>
<p>这让我想到一个我一直在思考的问题。这种用归属感换取安全感的冲动，在宗教信仰里同样存在——信仰一个至高无上的力量，仿佛生活的问题都能得到解答，仿佛你也能借此拥有某种庇护。这种对外部至高力量的依赖，与作者面临的选择很相似：是选择依赖某个更大的存在来承担自己，还是承担独立思考的重负，以及随之而来的孤独？作者的选择给出了她的答案。</p>
<p>总的来说，我觉得这本书有一种温柔的治愈力量。它没有简单地批判或赞美她的家人，也没有简单地美化自己的选择，而是以真诚的探索和思考，展现了一个人如何在复杂的关系网络中寻找自己的位置。</p>
]]></content:encoded></item><item><title><![CDATA[树莓派5 优化与踩坑]]></title><guid>https://wulu.zone/posts/my-pi5-setup</guid><link>https://wulu.zone/posts/my-pi5-setup</link><pubDate>Sun, 25 Jan 2026 12:24:16 +0000</pubDate><content:encoded><![CDATA[<div class="blockquote"><blockquote><p>本文记录我使用树莓派 5 过程的经验，即是笔记，也是分享。</p>
</blockquote></div>
<h2>优化：增大 swap 分区</h2>
<p>我在我的树莓派 5 4GB 上跑 Docker，部署了多个服务。当加入 Nextcloud 后，系统开始出现明显卡顿，响应速度大幅下降。输入 <code>top</code> 命令发现，内存几乎用满，swap 更是直接 100% 占用：</p>
<div class="block-code"><pre><code>MiB Mem :   4049.9 total,    146.7 free,   3369.8 used,    789.0 buff/c
MiB Swap:    200.0 total,      0.0 free,    200.0 used.    680.1 avail</code></pre></div>
<p>这时我才发现树莓派 5 的 Raspberry Pi OS (Bookworm) 默认仅配置了 200MB swap。这个保守的设置可能是为了照顾使用 SD 卡的用户——毕竟频繁的 swap 读写会严重缩短 SD 卡寿命。</p>
<p>但既然树莓派 5 已经配备了 PCIe 接口，官方也推出了专用的 M.2 HAT+ 和 SSD 套件，如果你和我一样使用 SSD 作为系统盘，完全可以将 swap 调大，充分发挥 SSD 的读写性能和耐用性优势。</p>
<ol>
<li><p>打开配置文件：</p>
<div class="block-code"><pre><code>sudo nano /etc/dphys-swapfile</code></pre></div>
</li>
<li><p>修改 <code>CONF_SWAPSIZE</code>，我的树莓派系统是安装在 SSD 上的，所以 swap 调大点没关系。如果你用的是 SD 卡，建议设置小点，不要超过 1GB，因为频繁的 swap 读写会大幅缩短 SD 卡寿命。</p>
<div class="block-code"><pre><code>CONF_SWAPSIZE=4096  </code></pre></div>
<p>为了设置超过 2GB 的 swap， 还需要修改 <code>CONF_MAXSWAP</code> 调大限制，可以和 <code>CONF_SWAPSIZE</code> 一致，也可以设置的更大一些方便后续调整。</p>
<div class="block-code"><pre><code>CONF_MAXSWAP=4096</code></pre></div>
</li>
<li><p>重启 swap 服务</p>
<div class="block-code"><pre><code>sudo /etc/init.d/dphys-swapfile restart</code></pre></div>
</li>
<li><p>验证</p>
<div class="block-code"><pre><code>free -h</code></pre></div>
</li>
</ol>
<h2>优化：开启 zram</h2>
<div class="blockquote"><blockquote><p>在 AI 的建议下，我还开启了 zram。zram 是一个在内存中创建压缩交换空间的技术。简单来说，它会将不常用的内存页压缩后存储在内存里，通常能达到 2-3 倍的压缩比。对于树莓派这种内存有限的设备来说，zram 是个非常实用的优化手段。</p>
</blockquote></div>
<ol>
<li><p>安装</p>
<div class="block-code"><pre><code>sudo apt update
sudo apt install zram-tools</code></pre></div>
</li>
<li><p>验证</p>
<div class="block-code"><pre><code>cat /proc/swaps</code></pre></div>
<p>可以看到</p>
<div class="block-code"><pre><code>Filename                                Type            Size            Used            Priority
/dev/zram0                              partition       262128          257344          100
/var/swap                               file            4194288         697648          -2</code></pre></div>
</li>
</ol>
<h2>避坑：树莓派 5 PCIe 排线干扰</h2>
<p>如果你使用树莓派 5 搭配 <a href="https://www.raspberrypi.com/products/ssd-kit/">树莓派官方 M.2 套件（HAT+）</a>，建议不要把树莓派直接叠放在路由器上。</p>
<p>之前有段时间，我发现树莓派经常重启，有时甚至直接卡死无响应。最严重的一次，我部署的 Karakeep 书签服务因为底层数据错误导致数据库损坏，数据瞬间全丢，万幸最后从 Meilisearch 中抢救回来了。</p>
<p>排查过程中我尝试了很多方法（包括修改PCIe节能设置等），最后发现罪魁祸首可能是官方 FPC 排线的抗干扰能力不足（虽然官方说是抗干扰的）。后来我将树莓派与路由器物理分离一段距离后，就再也没出现过类似问题。</p>
<p>如果你不需要使用树莓派的 WiFi 功能，也建议关闭。</p>
<h2>参考链接</h2>
<p><a href="https://linuxblog.io/raspberry-pi-performance-add-zram-kernel-parameters/">https://linuxblog.io/raspberry-pi-performance-add-zram-kernel-parameters/</a></p>
<p><a href="https://github.com/geerlingguy/raspberry-pi-pcie-devices/issues/559">https://github.com/geerlingguy/raspberry-pi-pcie-devices/issues/559</a></p>
]]></content:encoded></item><item><title><![CDATA[在 Antigravity 使用 VS Code 应用扩展商店]]></title><guid>https://wulu.zone/posts/Antigravity-VSCode-Marketplace</guid><link>https://wulu.zone/posts/Antigravity-VSCode-Marketplace</link><description><![CDATA[在 Antigravity 使用 VS Code 扩展]]></description><pubDate>Thu, 20 Nov 2025 13:53:39 +0000</pubDate><content:encoded><![CDATA[<p>默认情况下，<a href="https://antigravity.google/">Antigravity</a> 使用 Open VSX 作为扩展市场，因此许多在 Visual Studio Code 中可安装的扩展在 Antigravity 里可能搜不到。如果在从 VS Code 迁移过来，可能会很不习惯。</p>
<p>可以通过下面方式，让 Antigravity 能够使用 VS Code 的应用扩展商店：</p>
<ol>
<li><p>在 Antigravity 的菜单栏中的 “首选项” 中打开 “Antigravity Setting”。</p>
<div style="max-width:400px;width:100%;"><img src="https://i.typlog.com/wulu/8236352575_596753.png" style="width:100%;"></div>

</li>
<li><p>在设置中的 “Editor” 区域，设置以下参数：</p>
<p>Marketplace Item URL</p>
<div class="block-code"><pre><code> https://marketplace.visualstudio.com/items</code></pre></div>
<p>Marketplace Gallery URL</p>
<div class="block-code"><pre><code>https://marketplace.visualstudio.com/_apis/public/gallery</code></pre></div>
<div style="max-width:550px;width:100%;"><img src="https://i.typlog.com/wulu/8236352473_510905.png" style="width:100%;"></div>

</li>
<li><p>重启 Antigravity 即可。</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[树莓派安装 OpenWrt 及扩容教程]]></title><guid>https://wulu.zone/posts/raspberrypi-openwrt</guid><link>https://wulu.zone/posts/raspberrypi-openwrt</link><pubDate>Sat, 27 Sep 2025 04:02:51 +0000</pubDate><content:encoded><![CDATA[<div class="blockquote"><blockquote><p>时隔多年再次重装 OpenWrt，早已忘记当初的安装方法。许多教程已经过时或缺少关键细节，因此记录本文以便日后查阅，也方便有需要的人参考。如有问题，欢迎在评论区讨论。本文仅作为参考，请谨慎操作，数据风险自负。</p>
</blockquote></div>
<p>本文将演示如何在树莓派4B上安装 ImmortalWrt 并进行扩容。</p>
<h2>1. 安装 ImmortalWrt</h2>
<p><a href="https://github.com/immortalwrt/immortalwrt">ImmortalWrt</a> 是 OpenWrt 的一个分支 ，它移植了更多的软件包，支持更广泛的设备，默认优化了配置文件，并为中国大陆用户进行了本地化修改。</p>
<h3>1.1 下载 ImmortalWrt</h3>
<p>前往  <a href="https://firmware-selector.immortalwrt.org/">ImmortalWrt 固件选择工具</a> 下载对应固件：</p>
<p>搜索设备型号，查找对应固件。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8241060128_760046.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1378/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8241060128_760046.png" alt="image.png"loading="lazy" decoding="async" width="1378" height="473" /></picture></figure></div><p>每个设备一般会对应四个固件：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8241060071_323346.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1293/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8241060071_323346.png" alt="image.png"loading="lazy" decoding="async" width="1293" height="829" /></picture></figure></div><ul>
<li><strong>SYSUPGRADE vs. FACTORY:</strong><ul>
<li><strong>FACTORY</strong> 固件是用于<strong>首次安装</strong>ImmortalWrt。</li>
<li><strong>SYSUPGRADE</strong> 固件是用于<strong>升级</strong>已经运行ImmortalWrt的设备，它会保留你的配置。</li>
</ul>
</li>
<li><strong>EXT4 vs. SQUASHFS:</strong><ul>
<li><strong>EXT4</strong> 是一个可读写的日志文件系统，更灵活，可以更方便地修改系统文件。</li>
<li><strong>SQUASHFS</strong> 是一个只读的压缩文件系统，通常与一个小的可写分区（如JFFS2或UBI）结合使用。它在系统稳定性、节省空间和抗意外修改方面有优势。如果系统被破坏，可以更容易地恢复到初始状态。</li>
</ul>
</li>
</ul>
<p>首次安装，选择 FACTORY 版本，树莓派设备推荐使用 EXT4。</p>
<p>下载 FACTORY(EXT4) 的版本。</p>
<h3>1.2 烧录 ImmortalWrt</h3>
<p>利用 <a href="https://rufus.ie/">rufus</a> 工具将上一步得到的 <strong>immortalwrt-[版本号]-bcm27xx-bcm2711-rpi-4-ext4-factory.img.gz</strong> 直接烧录到内存卡，保持 rufus 默认设置即可。</p>
<h2>2. 初始化系统</h2>
<h3>2.1 连接与首次登录</h3>
<p>ImmortalWrt 不再默认创建 Wi-Fi 热点，所以需要通过有线的方式连接到它。</p>
<p>把内存卡插到树莓派中，接通电源。然后用网线连接树莓派和电脑。</p>
<p>在电脑上访问 <code>192.168.1.1</code>。默认账号名为 root，密码为空。</p>
<p>登录后按照提示修改默认密码。</p>
<h3>2.2 配置网络</h3>
<p>进入 “网络” - “接口”，然后编辑默认 lan 接口。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8241059248_764544.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_862/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8241059248_764544.png" alt="image.png"loading="lazy" decoding="async" width="862" height="339" /></picture></figure></div><p>根据实际需求配置网络。</p>
<p>由于我将其作为旁路网关使用，所以设置了静态 IP 地址，并指定了相应的网关和 DNS。且在“DHCP 服务器”界面，勾选“忽略此接口”。</p>
<p>确认无误后，点击“保存并应用”，并强制执行。</p>
<p>然后，就可以用网线将树莓派连接到路由器了。</p>
<h2>3. 扩容分区</h2>
<p>完成后上述步骤后，ImmortalWrt 就能正常使用了。但是默认 ImmortalWrt 只用了 300MB 的储存，并没有用完整张储存卡。所以可用空间很少，并且被浪费。</p>
<p>接下来我们来扩容。</p>
<ol>
<li><p>安装需要用到的工具</p>
<div class="block-code"><pre><code>opkg update  
opkg install fdisk resize2fs losetup</code></pre></div>
</li>
<li><p>查看当前分区状况</p>
<div class="block-code"><pre><code>fdisk -l</code></pre></div>
<p>你会看到类似下面的输出（120GB 的内存卡，只用了 64MB + 300MB）：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8241058525_410655.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_825/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8241058525_410655.png" alt="image.png"loading="lazy" decoding="async" width="825" height="274" /></picture></figure></div></li>
<li><p>重新分区</p>
<p>进入 fdisk 工具：</p>
<div class="block-code"><pre><code>fdisk /dev/mmcblk0</code></pre></div>
<p>输入 <code>p</code>  查看分区表，记住第二分区开始的位置：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8241057747_177615.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_839/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8241057747_177615.png" alt="image.png"loading="lazy" decoding="async" width="839" height="340" /></picture></figure></div><p>输入 <code>d</code> 删除第二个分区：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8241057669_046567.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_824/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8241057669_046567.png" alt="image.png"loading="lazy" decoding="async" width="824" height="118" /></picture></figure></div><p>输入 <code>n</code> 重新创建分区：</p>
<ul>
<li>分区类型：选择 <code>p</code> ，或直接回车使用默认值。</li>
<li>分区序号：选择 <code>2</code> ，或直接回车使用默认值。</li>
<li>起始扇区：输入之前记录的 <code>147456</code>（根据实际情况替换，使用原起始扇区）。</li>
<li>结束扇区：可以指定大小，或直接回车使用默认值，默认值是占用所有剩余空间。</li>
<li>当提示是否移除标识：输入  <code>N</code>。</li>
</ul>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8241057601_576729.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_923/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8241057601_576729.png" alt="image.png"loading="lazy" decoding="async" width="923" height="438" /></picture></figure></div><p>最后，输入 <code>w</code> 确认并执行变更：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8241057561_709726.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_794/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8241057561_709726.png" alt="image.png"loading="lazy" decoding="async" width="794" height="122" /></picture></figure></div></li>
<li><p>再次查询分区情况，可以看到第二个分区现在已经扩大。</p>
<div class="block-code"><pre><code>fdisk -l</code></pre></div>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8241056922_839952.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_899/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8241056922_839952.png" alt="image.png"loading="lazy" decoding="async" width="899" height="279" /></picture></figure></div></li>
<li><p>接下来还需要让系统能够识别这个分区：</p>
<p>先查看当前是否有循环设备：</p>
<div class="block-code"><pre><code>losetup</code></pre></div>
<p>此时，输出可能为空。或者有一些设备。在下个命令中，不要与已有设备冲突，可以用 <code>loop1</code> 或其他未使用的编号。</p>
<p>创建循环设备：</p>
<div class="block-code"><pre><code>losetup /dev/loop0 /dev/mmcblk0p2</code></pre></div>
<p>扩展文件系统到分区全部空间：</p>
<div class="block-code"><pre><code>resize2fs -f /dev/loop0</code></pre></div>
</li>
<li><p>重启系统，网页访问树莓派，可以看到扩容成功，磁盘空间大小已经更新。</p>
<div class="block-code"><pre><code>reboot</code></pre></div>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8241056541_465518.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_765/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8241056541_465518.png" alt="image.png"loading="lazy" decoding="async" width="765" height="307" /></picture></figure></div></li>
</ol>
<h2>4. 参考链接</h2>
<p><a href="https://blog.caliburn.work/archives/1709726837347">https://blog.caliburn.work/archives/1709726837347</a></p>
]]></content:encoded></item><item><title><![CDATA[使用 Docker 在树莓派上安装 Moritx 下载工具]]></title><guid>https://wulu.zone/posts/motrix-arm64-vnc</guid><link>https://wulu.zone/posts/motrix-arm64-vnc</link><description><![CDATA[如何在无头(Headless)树莓派上运行 Motrix ？]]></description><pubDate>Sun, 10 Aug 2025 07:37:37 +0000</pubDate><content:encoded><![CDATA[<p><a href="https://github.com/agalwood/Motrix">Motrix</a> 是一款基于 aria2 的下载工具，支持 HTTP、FTP、BT、磁力链等多种资源下载，界面简洁易用。</p>
<p>Motrix 在 v1.8.19 版本中开始支持 arm64 设备，可以在树莓派等设备上运行。树莓派功耗低、运行安静，很适合 24 小时运行下载服务。由于我的树莓派没有安装桌面系统，所以通过 <a href="https://github.com/jlesage/docker-baseimage-gui">docker-baseimage-gui</a> 项目制作了一个 docker 镜像。<a href="https://github.com/jlesage/docker-baseimage-gui">docker-baseimage-gui</a> 提供了集成轻量级桌面环境、VNC 服务和 Web 访问功能的基础镜像，专门用于在无头服务器上运行 GUI 应用。</p>
<p>项目是开源的，具体实现可以查看：<a href="https://github.com/eMUQI/motrix-arm64-vnc">eMUQI/motrix-arm64-vnc</a></p>
<h2>使用说明</h2>
<p>以下以我的树莓派 5 为例：</p>
<div class="block-code"><pre><code>Raspberry Pi 5 Model B Rev 1.0
OS: Debian GNU/Linux 12 (bookworm) aarch64
Kernel: 6.12.34+rpt-rpi-2712</code></pre></div>
<h3>1. 前置条件</h3>
<p>请确保您的宿主机系统已安装 <a href="https://docs.docker.com/engine/install/debian/">Docker 及 Docker Compose</a>。</p>
<h3>2. 创建并配置 <code>docker-compose.yml</code></h3>
<p>在宿主机上创建项目目录，并在该目录中新建 <code>docker-compose.yml</code> 文件。</p>
<div class="block-code" data-language="bash"><div class="highlight"><pre><span></span><code><div class="line">mkdir motrix-server
</div><div class="line"><span class="nb">cd</span> motrix-server
</div><div class="line">touch docker-compose.yml
</div></code></pre></div>
</div>
<p>将以下内容写入 <code>docker-compose.yml</code> 文件：</p>
<div class="block-code" data-language="yaml"><div class="code-head"><pre class="filename">docker-compose.yml</pre></div>
<div class="highlight"><pre><span></span><code><div class="line"><span class="nt">services</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">  </span><span class="nt">motrix</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">emuqi/motrix-arm64-vnc:latest</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">motrix-vnc</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">ports</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="c1"># 5800: 用于 noVNC (Web 浏览器) 访问的端口</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="s">&quot;5800:5800&quot;</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="c1"># 5900: (可选) 用于标准 VNC 客户端直接访问的端口</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="s">&quot;5900:5900&quot;</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="c1"># 将宿主机的 ./data 目录映射到容器的 /config/Downloads 目录</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="c1"># 用于持久化存储下载的文件</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">./data:/config/Downloads</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="c1"># 关键：设置容器内应用的用户与用户组 ID。</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="c1"># 建议修改为宿主机当前用户的 UID 和 GID，以避免挂载目录的权限冲突。</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="c1"># 可在宿主机终端执行 `id` 命令获取。</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">USER_ID=1000</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">GROUP_ID=1000</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="c1"># 设置 VNC 会话的显示分辨率</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">DISPLAY_WIDTH=1280</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">DISPLAY_HEIGHT=720</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="c1"># (可选) 设置 VNC 访问密码。取消注释并替换为强密码。</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="c1"># - VNC_PASSWORD=your_secret_password</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">unless-stopped</span><span class="w"></span>
</div></code></pre></div>
</div>
<h3>3. 启动容器服务</h3>
<p>在 <code>docker-compose.yml</code> 文件所在的目录下，执行以下命令以启动服务：</p>
<div class="block-code" data-language="bash"><div class="highlight"><pre><span></span><code><div class="line">docker compose up -d
</div></code></pre></div>
</div>
<h4>访问方式</h4>
<ul>
<li><p><strong>Web 浏览器 (noVNC):</strong>
访问 <code>http://&lt;宿主机IP地址&gt;:5800</code></p>
</li>
<li><p><strong>VNC 客户端:</strong>
使用 VNC 客户端 (如 RealVNC Viewer, TigerVNC) 连接至 <code>vnc://&lt;宿主机IP地址&gt;:5900</code></p>
</li>
</ul>
<h4>关键配置：设定下载路径</h4>
<p>为确保下载文件能正确保存至宿主机映射目录，首次启动后必须在 Motrix 应用内完成以下配置：</p>
<ol>
<li><p>在 Motrix 图形界面中，导航至 <strong>偏好设置</strong> -&gt; <strong>基础设置</strong>。</p>
</li>
<li><p>定位到 <strong>下载路径</strong> 选项，点击 <strong>“更改”</strong>。</p>
</li>
<li><p>将路径手动设置为容器内部的绝对路径：<code>/config/Downloads</code>。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8245190019_059318.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1330/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8245190019_059318.png" alt="image.png"loading="lazy" decoding="async" width="1330" height="990" /></picture></figure></div></li>
<li><p>保存并应用设置。</p>
<p>此操作仅需配置一次。完成后，所有下载任务产生的文件，都将被保存在您之前创建的 <code>motrix-server</code> 项目目录内的 <code>data</code> 文件夹中。</p>
</li>
</ol>
<h4>其他提示</h4>
<p>noVNC 不支持传统意义上的直接、无缝剪贴板调用。这主要是由于现代网页浏览器的安全限制。</p>
<p>当你通过浏览器访问此项目时，需要通过以下方式将下载链接复制 Motrix：</p>
<ol>
<li><p>在你的本地电脑上复制文本。</p>
</li>
<li><p>打开 noVNC 界面侧边的控制条，找到剪贴板工具。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8245188836_139815.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1330/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8245188836_139815.png" alt="Motrix-Copy.png"loading="lazy" decoding="async" width="1330" height="990" /></picture></figure></div></li>
<li><p>将文本粘贴到 noVNC 的剪贴板文本框中。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8245188814_970649.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1332/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8245188814_970649.png" alt="Motrix-Copy2.png"loading="lazy" decoding="async" width="1332" height="991" /></picture></figure></div></li>
<li><p>此时，文本被发送到远程服务器的剪贴板。你现在可以在远程桌面环境中使用粘贴命令（如 Ctrl+V）来粘贴内容。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8245188801_332163.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1332/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8245188801_332163.png" alt="Motrix-Copy3.png"loading="lazy" decoding="async" width="1332" height="991" /></picture></figure></div></li>
</ol>
<h3>环境变量参考</h3>
<div class="block-table"><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"><code>USER_ID</code></td>
  <td style="text-align:left">定义容器内运行 Motrix 进程的用户 ID (UID)。</td>
  <td style="text-align:left"><code>1000</code></td>
</tr>
<tr>
  <td style="text-align:left"><code>GROUP_ID</code></td>
  <td style="text-align:left">定义容器内运行 Motrix 进程的用户组 ID (GID)。</td>
  <td style="text-align:left"><code>1000</code></td>
</tr>
<tr>
  <td style="text-align:left"><code>DISPLAY_WIDTH</code></td>
  <td style="text-align:left">VNC 会话的屏幕显示宽度（单位：像素）。</td>
  <td style="text-align:left"><code>1280</code></td>
</tr>
<tr>
  <td style="text-align:left"><code>DISPLAY_HEIGHT</code></td>
  <td style="text-align:left">VNC 会话的屏幕显示高度（单位：像素）。</td>
  <td style="text-align:left"><code>720</code></td>
</tr>
<tr>
  <td style="text-align:left"><code>VNC_PASSWORD</code></td>
  <td style="text-align:left">为 VNC 服务设置连接密码。若留空或注释，则无需密码即可访问。</td>
  <td style="text-align:left">(未设置)</td>
</tr>
</tbody>
</table></div><h2>其他项目</h2>
<p>还有一个 <a href="https://github.com/Jarvay/Motrix-Web">Motrix-Web</a> 项目实现了在网页上运行 Motrix 的功能。该项目的前端用户界面与 aria2 后端是分离的。Motrix-Web 作为前端 UI，直接从浏览器发出请求以控制后端的 aria2。这意味着，当考虑将 Motrix-Web 部署到公网环境时，aria2 也需要相应地部署到公网。</p>
<p>而本项目 <a href="https://github.com/eMUQI/motrix-arm64-vnc">motrix-arm64-vnc</a> 将向 aria2 发送的网络请求封装在容器内部。这种架构的好处是，aria2 无需直接暴露在公网上，从而提供了更为安全的运行环境。</p>
<p>值得注意的是，无论选择哪种部署方案，出于安全考虑，都不建议将上述提及的两个项目直接暴露在公网上。在任何面向公网的部署场景中，都应考虑将其置于某种验证机制之后，例如 Cloudflare Access 或其他反向代理与身份验证解决方案。</p>
]]></content:encoded></item><item><title><![CDATA[使用 Home Assistant 将米家设备接入 HomeKit 教程]]></title><guid>https://wulu.zone/posts/mi-iot-homekit-2025</guid><link>https://wulu.zone/posts/mi-iot-homekit-2025</link><description><![CDATA[Siri，关灯~]]></description><pubDate>Fri, 09 May 2025 15:44:46 +0000</pubDate><content:encoded><![CDATA[<p>本教程帮助你把常用的米家设备都接入 HomeKit，这样就可以通过 Siri 来控制住处中的智能设备。</p>
<p>具体原理是：使用树莓派安装 Home Assistant，通过 Home Assistant 中的<a href="https://github.com/XiaoMi/ha_xiaomi_home">小米官方集成</a>连接米家设备。通过 Home Assistant 中的 HomeKit Bridge 集成，将米家设备桥接到 Apple HomeKit。这样就可以通过 Apple 的“家庭”应用和 Siri 来控制这些设备，即使它们不支持 HomeKit。</p>
<p><strong>目录</strong></p>
<ul>
<li><a href="#install">1. 安装 Home Assistant</a></li>
<li><a href="#install2">2. 安装与配置 Home Assistant  社区商店 (HACS)</a><ul>
<li><a href="#install2.1">2.1 安装 HACS</a></li>
<li><a href="#install2.2">2.2 配置 HACS</a></li>
</ul>
</li>
<li><a href="#install3">3.将米家设备接入 Home Assistant</a><ul>
<li><a href="#install3.1">3.1 安装 Xiaomi Home (米家官方) 集成</a></li>
<li><a href="#install3.2">3.2 配置 Xiaomi Home</a></li>
</ul>
</li>
<li><a href="#install4">4. 桥接米家设备到 HomeKit</a><ul>
<li><a href="#install4.1">4.1 在 Home Assistant 中添加 HomeKit Bridge 集成</a></li>
<li><a href="#install4.2">4.2 在 HomeKit Bridge 中排除不必要的实体</a></li>
<li><a href="#install4.3">4.3 将 HomeKit Bridge 添加到苹果家庭</a></li>
</ul>
</li>
<li><a href="#5">5.常见问题</a></li>
</ul>
<p><strong>我的树莓派配置</strong></p>
<div class="block-code"><pre><code>Raspberry Pi 5 4gb
OS: Raspberry Pi OS Lite
Kernel: Linux 6.12.20+rpt-rpi-2712 #1 SMP PREEMPT Debian 1:6.12.20-1+rpt1~bpo12+1 (2025-03-19) aarch64 GNU/Linux</code></pre></div>
<p><a id="install"></a></p>
<h2>1. 安装 Home Assistant</h2>
<p>Home Assistant <a href="https://www.home-assistant.io/installation/raspberrypi">支持多种安装方式</a>，大致有三种方法：</p>
<ol>
<li>安装 Home Assistant OS 操作系统</li>
<li>通过 Docker 容器安装</li>
<li>直接安装 Home Assistant Core（<a href="https://github.com/home-assistant/architecture/discussions/1197#discussioncomment-13082813">逐步弃用</a>，从 Home Assistant 2025.6 版本开始，此安装方式将进入为期六个月的弃用期。）</li>
</ol>
<p>Home Assistant 官方<a href="https://github.com/home-assistant/architecture/discussions/1197">已提出计划逐步停止对  Home Assistant Core 安装方式的官方支持</a>。建议采用第一种或者第二种方法。</p>
<p>为了便于管理，我选择使用 Docker Compose 来安装 Home Assistant。参考<a href="https://www.home-assistant.io/installation/linux/#docker-compose">官方教程</a>，<code>docker-compose.yml</code> 如下：</p>
<div class="block-code" data-language="yaml"><div class="code-head"><pre class="filename">~/docker/homeassistant/docker-compose.yml</pre></div>
<div class="highlight"><pre><span></span><code><div class="line"><span class="nt">services</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">  </span><span class="nt">homeassistant</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">homeassistant</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ghcr.io/home-assistant/home-assistant:stable</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">./config:/config</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/etc/localtime:/etc/localtime:ro</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/run/dbus:/run/dbus:ro</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">unless-stopped</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">privileged</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">host</span><span class="w"></span>
</div></code></pre></div>
</div>
<p>安装完成后，通过浏览器访问树莓派的 IP 地址加 8123 端口 (例如 <a href="http://%E6%A0%91%E8%8E%93%E6%B4%BEIP:8123)%E3%80%82%E9%A6%96%E6%AC%A1%E8%AE%BF%E9%97%AE%E4%BC%9A%E8%BF%9B%E5%85%A5">http://树莓派IP:8123)。首次访问会进入</a> Home Assistant 初始化向导，按照提示设置管理员账户和密码。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253237388_479254.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1280/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253237388_479254.png" alt="image.png"loading="lazy" decoding="async" width="1280" height="916" /></picture></figure></div><p><a id="install2"></a></p>
<h2>2. 安装与配置 Home Assistant  社区商店</h2>
<p><a id="install2.1"></a></p>
<h3>2.1 安装 HACS</h3>
<p>配置完 Home Assistant 后，我们需要安装 <a href="https://hacs.xyz/">HACS（Home Assistant Community Store）</a>。你可以将其理解为 Home Assistant 的应用商店，通过 HACS 我们能够安装第三方集成来增强 Home Assistant 的功能。后续我们需要通过 HACS 来安装小米官方的 Home Assistant 集成。</p>
<p>参考 <a href="https://hacs.xyz/docs/use/download/download/#to-download-hacs">HACS安装指南</a>，我们需要进入容器内部执行安装脚本。</p>
<div class="block-code" data-language="bash"><div class="highlight"><pre><span></span><code><div class="line">docker <span class="nb">exec</span> -it homeassistant bash
</div><div class="line">wget -O - https://get.hacs.xyz <span class="p">|</span> bash -
</div></code></pre></div>
</div>
<p>安装成功后，退出容器，然后重启容器。<strong>这一步骤很重要，配置HACS前必须重启Home Assistant。</strong></p>
<div class="block-code" data-language="bash"><div class="code-head"><pre class="filename">~/docker/homeassistant/</pre></div>
<div class="highlight"><pre><span></span><code><div class="line"><span class="nb">exit</span>
</div><div class="line">docker compose restart
</div></code></pre></div>
</div>
<p><a id="install2.2"></a></p>
<h3>2.2 配置 HACS</h3>
<p>接下来我们需要初始化 HACS，你可以参考<a href="https://hacs.xyz/docs/use/configuration/basic/#to-set-up-the-hacs-integration">此教程</a>或按照下图步骤配置。注意，你需要提前注册一个 <a href="https://github.com/">Github</a> 账号。</p>
<p>在“设置”中打开“设备与服务”</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253224197_27173.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1265/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253224197_27173.png" alt="image.png"loading="lazy" decoding="async" width="1265" height="964" /></picture></figure></div><p>点击“添加集成”，搜索并选择“HACS”</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253224116_729585.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1275/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253224116_729585.png" alt="image.png"loading="lazy" decoding="async" width="1275" height="964" /></picture></figure></div><p>根据指引逐步操作，打开提示中的网址，登录 GitHub，输入授权码。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253224058_003357.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1273/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253224058_003357.png" alt="image.png"loading="lazy" decoding="async" width="1273" height="964" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253223944_892547.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_895/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253223944_892547.png" alt="image.png"loading="lazy" decoding="async" width="895" height="667" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253223995_529623.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1263/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253223995_529623.png" alt="image.png"loading="lazy" decoding="async" width="1263" height="964" /></picture></figure></div><p>看到下图界面，就说明 HACS 已经安装成功了。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253223957_807803.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1274/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253223957_807803.png" alt="image.png"loading="lazy" decoding="async" width="1274" height="964" /></picture></figure></div><p>指派设备可以先选“跳过并完成”。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253223858_817774.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1273/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253223858_817774.png" alt="image.png"loading="lazy" decoding="async" width="1273" height="964" /></picture></figure></div><p><a id="install3"></a></p>
<h2>3. 将米家设备接入 HomeAssistant</h2>
<p><a id="install3.1"></a></p>
<h3>3.1 安装 Home Assistant 米家官方集成</h3>
<div class="blockquote"><blockquote><p>小米在2024年年底推出了官方的 Home Assistant 集成 (Xiaomi Home)。经过多个版本迭代，目前已趋于稳定可用。这意味着我们多了一个官方选择，而不必像以往主要依赖社区维护的 <a href="https://github.com/al-one/hass-xiaomi-miot">“Xiaomi Miot Auto” 集成</a> 。当然，你依然可以选择使用“Xiaomi Miot Auto”集成，对于某些特定设备或追求稳定性的场景，它可能仍有优势。你可以参考我写的另一篇教程：<a href="https://wulu.zone/posts/mi-iot-homekit">https://wulu.zone/posts/mi-iot-homekit</a></p>
</blockquote></div>
<p>接下来，我们安装米家官方集成以将米家设备接入HomeAssistant。</p>
<p>进入 HACS 页面，找到“Xiaomi Home”。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253222668_642963.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253222668_642963.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><p>点“下载”，然后确认下载。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253222518_959653.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253222518_959653.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><p>同样地，安装完集成之后需要重启 HomeAssistant。</p>
<div class="block-code" data-language="bash"><div class="code-head"><pre class="filename">~/docker/homeassistant/</pre></div>
<div class="highlight"><pre><span></span><code><div class="line">docker compose restart
</div></code></pre></div>
</div>
<p><a id="install3.2"></a></p>
<h3>3.2 配置 Xiaomi Home</h3>
<p>接下来，我们配置 Xiaomi Home 将米家设备接入 Home Assistant。<strong>注意，配置 Xiaomi Home 前需要重启 HomeAssistant。</strong></p>
<p>点击“设置”，选择“设备与服务”</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253219841_93018.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253219841_93018.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><p>点击“添加集成”，搜索并选择“Xiaomi Home”</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253219796_795862.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253219796_795862.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253216199_317771.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253216199_317771.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><p>登录小米账号以获取设备信息。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253216009_295126.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253216009_295126.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253215985_141642.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253215985_141642.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="929" /></picture></figure></div><p>在登录认证过程中，如果遇到类似下图的错误提示，通常是因为集成默认使用 <code>homeassistant.local:8123</code>作为OAuth2 认证跳转地址。你可以通过修改路由器或者本地 host，将 <code>homeassistant.local</code> 指向你安装了 Home Assistant 的设备。也可以直接在地址栏修改地址，将<code>homeassistant.local</code>改为对应设备的 IP, 然后刷新网页完成认证。</p>
<p>认证成功后，该页面会自动关闭跳转回 Home Assistant，之后按照指引完成剩余的设备添加步骤即可。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253215911_444016.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_818/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253215911_444016.png" alt="image.png"loading="lazy" decoding="async" width="818" height="653" /></picture></figure></div><p><a id="install4"></a></p>
<h2>4. 桥接米家设备到 HomeKit</h2>
<p>接下来，我们通过 HomeKit Bridge 将 Home Assistant 中设备桥接到 HomeKit。</p>
<p><a id="install4.1"></a></p>
<h3>4.1 在 Home Assistant 中添加 HomeKit Bridge 集成</h3>
<p>首先，我们要添加 HomeKit Bridge 集成。点击“设置”，进入“设备与服务”页面。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253201251_099466.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253201251_099466.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><p>搜索“homekit”，点击“Apple”</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253200041_948236.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253200041_948236.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><p>点击添加“HomeKit Bridge” 集成，按照指引完成添加。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253199993_81586.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253199993_81586.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><p>需要注意的是，如果你希望桥接传感器类型的设备（如温湿度传感器），确保在“要包含的域”中勾选“Sensor”选项，这个选项默认是未勾选的。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253199827_582739.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253199827_582739.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><p><a id="install4.2"></a></p>
<h3>4.2 在 HomeKit Bridge 中排除不必要的实体</h3>
<p>HomeKit Bridge 会自动识别 Home Assistant 中的设备。在将其同步到 Apple 家庭 App 之前，建议先检查并禁用一些不需要桥接的实体。</p>
<p>否则可能会出现以下情况：例如，当将小米智能插座添加到 HomeKit 时，插座会被识别为三个设备，除了开关之外，其中插座的指示灯被识别为灯具，插座温度也被误认为环境温度传感器。这可能不是我们期望看到的结果。</p>
<p>在 HomeKit Bridge 的详情页面，点击“配置”</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253198782_852893.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253198782_852893.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253198591_9722805.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253198591_9722805.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><p>在“排除的实体”列表中，依次添加要排除的实体</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253198550_458938.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253198550_458938.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><p><a id="install4.3"></a></p>
<h3>4.3 将 HomeKit Bridge 添加到苹果家庭</h3>
<p>最后，将配置好的 HomeKit Bridge 添加到你的 Apple 家庭 App 中。点击界面左下角的通知按钮，查看 homekit 的配对二维码。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253199739_201489.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253199739_201489.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8253199613_877979.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1289/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8253199613_877979.png" alt="image.png"loading="lazy" decoding="async" width="1289" height="964" /></picture></figure></div><p>打开“家庭”应用，点击左上角的“+”号，选择“添加配件”。扫描上个步骤的得到的二维码，点击“添加到家庭”。在加入过程中，可能会提示“未认证设备”，点击“仍要添加”。然后完成剩余步骤，逐个添加设备。完成后，你就能用 Siri 控制你的智能设备了。</p>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8302785845_413984.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1290/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302785845_413984.png" alt="桥接homekit6.png"loading="lazy" decoding="async" width="1290" height="2796" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8302785845_405751.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1290/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302785845_405751.png" alt="桥接homekit7.png"loading="lazy" decoding="async" width="1290" height="2796" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8302785845_417304.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1290/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302785845_417304.png" alt="桥接homekit8.png"loading="lazy" decoding="async" width="1290" height="2796" /></picture></figure></div></div>
<p><a id="5"></a></p>
<h2>5. 常见问题</h2>
<p><strong>Siri 回复设备没有回应？</strong></p>
<p>通过上述方法添加设备后，只能在同一局域网内控制该设备。如果出现这种情况，请检查手机是否连接到家庭网络，并进一步确认 Home Assistant 服务状态是否正常。</p>
<p><strong>如何通过 Siri 在局域网外控制家里的设备？</strong></p>
<p><a href="https://support.apple.com/zh-cn/102557">你需要有一个家庭中枢</a>，比如 HomePod 或者 Apple TV。</p>
<p><strong>更新小米集成相关问题</strong></p>
<p>小米官方的 Home Assistant 集成现在还处于早期开发阶段，版本更新时可能会存在破坏性更新。更新前要注意查看更新说明。</p>
<p><strong>其他问题</strong></p>
<p>其他问题？欢迎在评论区留言讨论！</p>
<h2>参考链接</h2>
<p><a href="https://www.home-assistant.io/installation/linux/#install-home-assistant-container">https://www.home-assistant.io/installation/linux/#install-home-assistant-container</a></p>
<p><a href="https://hacs.xyz/">https://hacs.xyz/</a></p>
<p><a href="https://hacs.xyz/docs/use/download/download/#to-download-hacs">https://hacs.xyz/docs/use/download/download/#to-download-hacs</a></p>
<p><a href="https://github.com/XiaoMi/ha_xiaomi_home">https://github.com/XiaoMi/ha_xiaomi_home</a></p>
]]></content:encoded></item><item><title><![CDATA[Docker容器中的定时任务：使用Supercronic运行Python脚本]]></title><guid>https://wulu.zone/posts/docker-cron-python</guid><link>https://wulu.zone/posts/docker-cron-python</link><description><![CDATA[告别Docker内Cron的环境变量烦恼，Supercronic成为更优选择]]></description><pubDate>Wed, 23 Apr 2025 12:06:09 +0000</pubDate><content:encoded><![CDATA[<p>在<a href="https://wulu.zone/posts/eudic-maimemo-sync">上一篇文章</a>中，我介绍了 <a href="https://github.com/eMUQI/eudic-maimemo-sync">eudic-maimemo-sync</a> 项目——利用 Python 脚本调用<a href="https://www.eudic.net/v4/en/app/eudic">欧路词典</a>和<a href="https://www.maimemo.com/">墨墨背单词</a>的开放API将生词本自动同步到墨墨背单词，并演示了如何用 Docker 将其部署到树莓派上，每天自动执行同步。</p>
<p>这篇文章，我想分享我在配置 Docker 容器实现定时任务时遇到的一个问题，以及我是如何解决它的：我最初在容器内使用标准的 Cron 服务来调度 Python 脚本。但我发现，<strong>即使把环境变量传入了容器，Cron 触发脚本时依然读不到这部分配置，导致 Python 读取不到 API 密钥。原因是 Cron 不会继承容器的环境变量，它运行在相对隔离的环境中。</strong></p>
<p>为了解决这个问题，我开始在网上搜索并向大语言模型求助，最后得到几个可能的方案：</p>
<ul>
<li>将 <code>.env</code> 文件直接挂载进容器，让脚本从指定路径读取</li>
<li>在 <code>entrypoint.sh</code> 文件中，读取环境变量，然后显式地将它们写入 crontab 文件或注入到 Cron 进程环境中</li>
<li>使用 <a href="https://github.com/aptible/supercronic">Supercronic</a> 或其他替代 Cron 方案</li>
</ul>
<p>虽然前两种方法可行，但需要额外的配置和脚本处理。经过测试，我最终选择了 <a href="https://github.com/aptible/supercronic">Supercronic</a>。它是一个与 Cron 语法兼容、专为容器设计的任务调度工具，用法和原生 Cron 几乎一致，且能够直接继承容器内的环境变量，大大简化了配置过程。将 Cron 替换为 Supercronic 后，问题就迎刃而解了。</p>
<p>如果你有同样的需求，想要通过容器定时运行 Python 脚本或其他程序，我推荐试试 Supercronic。我精简了<a href="https://github.com/eMUQI/eudic-maimemo-sync">eudic-maimemo-sync</a> 项目，编写一个基础示例 <a href="https://github.com/eMUQI/docker-python-supercronic-example">docker-python-supercronic-example</a>。示例中展示了如何在 Docker 容器里配置 Supercronic，并定时执行 Python 脚本，供大家参考。</p>
<hr />
<p>接下来我讲讲如何使用这个示例：</p>
<div class="block-code"><pre><code>.
├── Dockerfile          # 用于构建包含 Supercronic 的 Python 镜像
├── docker-compose.yml  # 容器部署的配置
├── entrypoint.sh       # 生成 crontab 并启动 Supercronic 的脚本
├── test.py             # 按计划运行的示例 Python 脚本
└── requirements.txt    # Python 依赖项</code></pre></div>
<h2>开始使用</h2>
<ol>
<li><p>克隆此仓库</p>
<div class="block-code" data-language="bash"><div class="highlight"><pre><span></span><code><div class="line">git clone https://github.com/emuqi/docker-python-supercronic-example.git
</div><div class="line"><span class="nb">cd</span> docker-python-supercronic-example
</div></code></pre></div>
</div>
</li>
<li><p><strong>为你的架构选择 Supercronic</strong></p>
<p>Dockerfile 默认配置为 ARM64 架构。对于其他架构（例如 x86_64），需要修改 <code>Dockerfile</code>：</p>
<p>访问 <a href="https://github.com/aptible/supercronic/releases">Supercronic Releases</a>，找到适合你的 CPU 架构的 <strong>安装说明</strong>。安装说明内一般会包含要添加到 Dockerfile 的代码。</p>
<p>替换以下部分：</p>
<div class="block-code" data-language="Dockerfile"><div class="highlight"><pre><span></span><code><div class="line"><span class="c"># 最新版本请访问 https://github.com/aptible/supercronic/releases</span>
</div><div class="line"><span class="c"># 根据你的CPU架构选择合适的 Supercronic 版本</span>
</div><div class="line"><span class="k">ENV</span><span class="w"> </span><span class="nv">SUPERCRONIC_URL</span><span class="o">=</span>https://github.com/aptible/supercronic/releases/download/v0.2.33/supercronic-linux-arm64 <span class="se">\</span>
</div><div class="line">    <span class="nv">SUPERCRONIC_SHA1SUM</span><span class="o">=</span>e0f0c06ebc5627e43b25475711e694450489ab00 <span class="se">\</span>
</div><div class="line">    <span class="nv">SUPERCRONIC</span><span class="o">=</span>supercronic-linux-arm64
</div><div class="line">
</div><div class="line"><span class="k">RUN</span><span class="w"> </span>curl -fsSLO <span class="s2">&quot;</span><span class="nv">$SUPERCRONIC_URL</span><span class="s2">&quot;</span> <span class="se">\</span>
</div><div class="line"> <span class="o">&amp;&amp;</span> <span class="nb">echo</span> <span class="s2">&quot;</span><span class="si">${</span><span class="nv">SUPERCRONIC_SHA1SUM</span><span class="si">}</span><span class="s2">  </span><span class="si">${</span><span class="nv">SUPERCRONIC</span><span class="si">}</span><span class="s2">&quot;</span> <span class="p">|</span> sha1sum -c - <span class="se">\</span>
</div><div class="line"> <span class="o">&amp;&amp;</span> chmod +x <span class="s2">&quot;</span><span class="nv">$SUPERCRONIC</span><span class="s2">&quot;</span> <span class="se">\</span>
</div><div class="line"> <span class="o">&amp;&amp;</span> mv <span class="s2">&quot;</span><span class="nv">$SUPERCRONIC</span><span class="s2">&quot;</span> <span class="s2">&quot;/usr/local/bin/</span><span class="si">${</span><span class="nv">SUPERCRONIC</span><span class="si">}</span><span class="s2">&quot;</span> <span class="se">\</span>
</div><div class="line"> <span class="o">&amp;&amp;</span> ln -s <span class="s2">&quot;/usr/local/bin/</span><span class="si">${</span><span class="nv">SUPERCRONIC</span><span class="si">}</span><span class="s2">&quot;</span> /usr/local/bin/supercronic
</div></code></pre></div>
</div>
</li>
<li><p>创建 <code>.env</code> 文件用于设置环境变量</p>
<div class="block-code"><pre><code>CUSTOM_MESSAGE=来自计划任务的问候！
CRON_SCHEDULE=*/5 * * * *  # 每 5 分钟运行一次</code></pre></div>
</li>
<li><p>构建并启动容器</p>
<div class="block-code" data-language="bash"><div class="highlight"><pre><span></span><code><div class="line">docker compose up -d --build
</div></code></pre></div>
</div>
</li>
<li><p>检查日志以验证程序是否按预期运行</p>
<div class="block-code" data-language="bash"><div class="highlight"><pre><span></span><code><div class="line">docker logs my_python_cron_job
</div></code></pre></div>
</div>
<p>你应该能看到类似下面的日志输出:</p>
<div class="block-code"><pre><code>my_python_cron_job  | time=&quot;2025-04-23T18:53:00+08:00&quot; level=info msg=&quot;Python script start&quot; channel=stdout iteration=0 job.command=&quot;/usr/local/bin/python /app/test.py&quot; job.position=0 job.schedule=&quot;* * * * *&quot;
my_python_cron_job  | time=&quot;2025-04-23T18:53:00+08:00&quot; level=info msg=&quot;Message: Hello World!&quot; channel=stdout iteration=0 job.command=&quot;/usr/local/bin/python /app/test.py&quot; job.position=0 job.schedule=&quot;* * * * *&quot;
my_python_cron_job  | time=&quot;2025-04-23T18:53:00+08:00&quot; level=info msg=&quot;job succeeded&quot; iteration=0 job.command=&quot;/usr/local/bin/python /app/test.py&quot; job.position=0 job.schedule=&quot;* * * * *&quot;</code></pre></div>
</li>
</ol>
<h2>配置</h2>
<h3>环境变量</h3>
<div class="block-table"><table><thead>
<tr>
  <th>变量</th>
  <th>描述</th>
</tr>
</thead>
<tbody>
<tr>
  <td><code>TZ</code></td>
  <td>容器时区</td>
</tr>
<tr>
  <td><code>CRON_SCHEDULE</code></td>
  <td>用于调度的 Cron 表达式</td>
</tr>
<tr>
  <td><code>CUSTOM_MESSAGE</code></td>
  <td>传递给 Python 脚本的示例变量</td>
</tr>
</tbody>
</table></div><h3>Cron 计划表达式示例</h3>
<ul>
<li><code>* * * * *</code> - 每分钟</li>
<li><code>*/5 * * * *</code> - 每 5 分钟</li>
<li><code>0 * * * *</code> - 每小时（0分时）</li>
<li><code>0 0 * * *</code> - 每天午夜</li>
<li><code>0 18 * * *</code> - 每天下午 6:00</li>
</ul>
<h2>自定义</h2>
<ol>
<li>用你自己的 Python 脚本替换或修改 <code>test.py</code></li>
<li>通过编辑 <code>.env</code> 文件或 <code>docker-compose.yml</code> 中的 <code>environment:</code> 部分来扩展或覆盖变量。添加的任何新变量（例如 <code>NEW_VAR=value</code>）都将被加载到容器中。</li>
<li>将所需的任何依赖项添加到 <code>requirements.txt</code></li>
<li>重新构建并运行容器：<code>docker-compose up -d --build</code></li>
</ol>
]]></content:encoded></item><item><title><![CDATA[树莓派 | 欧路词典生词本 & 墨墨背单词 云同步教程 (eudic-maimemo-sync)]]></title><guid>https://wulu.zone/posts/eudic-maimemo-sync</guid><link>https://wulu.zone/posts/eudic-maimemo-sync</link><description><![CDATA[一个小工具，解决 欧路词典 & 墨墨背单词 生词同步问题]]></description><pubDate>Wed, 16 Apr 2025 08:32:43 +0000</pubDate><content:encoded><![CDATA[<p>在浏览网页时，我常用欧路词典的“<a href="https://www.eudic.net/v4/en/app/plugins">欧路翻译</a>”浏览器插件进行划词翻译。这个插件会自动记录查阅过的单词，并将其添加到欧路词典的生词本中。 然而，在单词记忆方面，我更习惯使用“<a href="https://www.maimemo.com/">墨墨背单词</a>”。</p>
<p>因此，我在寻找一种方法，将欧路词典的生词本同步到墨墨背单词的词库。这样，我就可以用自己习惯的软件来记忆日常阅读中遇到的生词了。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8254795075_041595.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800/format,webp 1x, https://i.typlog.com/wulu/8254795075_041595.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600/format,webp 2x" media="(min-width: 800px)" type="image/webp"><source srcset="https://i.typlog.com/wulu/8254795075_041595.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800 1x, https://i.typlog.com/wulu/8254795075_041595.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600 2x" media="(min-width: 800px)"><img src="https://i.typlog.com/wulu/8254795075_041595.png" alt="欧陆墨墨.png"loading="lazy" decoding="async" width="2910" height="2754" /></picture></figure></div><p>后来我发现，这两个软件其实都提供开放 API。于是，我开发了 <a href="https://github.com/eMUQI/eudic-maimemo-sync">eudic-maimemo-sync</a> 工具，实现欧路词典生词本到墨墨背单词云词库的自动同步。同时，我还将其部署在树莓派上，让它每天自动运行，实现了生词本的无缝同步。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8254967689_481638.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_815/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8254967689_481638.png" alt="image.png"loading="lazy" decoding="async" width="815" height="215" /></picture></figure></div><p>接下来，我将介绍如何配置和使用这个工具，并分享开发过程中遇到的一些问题和解决方法。也欢迎大家<a href="https://github.com/eMUQI/eudic-maimemo-sync">贡献代码</a>或提出建议。</p>
<p><strong>目录</strong></p>
<ul>
<li><a href="#tutorial">eudic-maimemo-sync 使用教程</a><ul>
<li><a href="#install1">1. 下载代码安装依赖</a></li>
<li><a href="#env">2. 配置环境变量</a><ul>
<li><a href="#env_eudic">2.1 欧路词典相关配置</a></li>
<li><a href="#env_momo">2.2 墨墨背单词相关配置</a></li>
</ul>
</li>
<li><a href="#manual_sync">3. 手动同步</a></li>
<li><a href="#auto_sync">4. 自动同步（部署到树莓派上或者其他 Linux 设备）</a><ul>
<li><a href="#docker">使用 Docker</a></li>
<li><a href="#sync_other">使用其他方式</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#faq">开发中遇到的问题</a></li>
<li><a href="#reference">相关链接</a></li>
</ul>
<p><a id="tutorial"></a></p>
<h2>eudic-maimemo-sync 使用教程</h2>
<p><a id="install1"></a></p>
<h3>1. 下载代码安装依赖</h3>
<p>前置条件：已安装 Python 3 环境</p>
<p>下载代码：</p>
<div class="block-code"><pre><code>git clone https://github.com/eMUQI/eudic-maimemo-sync.git</code></pre></div>
<p>安装依赖：</p>
<div class="block-code"><pre><code>cd eudic-maimemo-sync
pip install -r requirements.txt</code></pre></div>
<p><a id="env"></a></p>
<h3>2. 配置环境变量</h3>
<p>接下来，需要配置环境变量。首先，复制 <code>.env.example</code> 为 <code>.env</code>。</p>
<p><a id="env_eudic"></a></p>
<h4>2.1 欧路词典相关配置</h4>
<ul>
<li><p>获取欧路词典 API 密钥</p>
<p>访问<a href="https://my.eudic.net/OpenAPI/Authorization">此页面</a>，登录后，获取你的API密钥。并将获取到的 API 密钥填入<code>.env</code>文件中的<code>EUDIC_API_KEY</code>字段。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8257278409_029172.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1273/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8257278409_029172.png" alt="image.png"loading="lazy" decoding="async" width="1273" height="839" /></picture></figure></div></li>
<li><p>获取生词本 ID</p>
<p>运行 <code>get_wordbook_id.py</code>，查看生词本信息，记下你需要同步的生词本 ID。</p>
<div class="block-code"><pre><code>python get_wordbook_id.py</code></pre></div>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8257177422_501559.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_473/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8257177422_501559.png" alt="image.png"loading="lazy" decoding="async" width="473" height="105" /></picture></figure></div><p>将需要同步的生词本 ID 填入 <code>.env</code> 中的 <code>EUDIC_CATEGORY_ID</code>。</p>
</li>
</ul>
<p><a id="env_momo"></a></p>
<h4>2.2 墨墨背单词相关配置</h4>
<ul>
<li><p>获取墨墨背单词 API 密钥</p>
<p>打开墨墨背单词手机 App，进入「我的」-「更多设置」-「实验功能」-「开放 API」，生成并复制 API 密钥，然后将其填入 <code>.env</code> 文件中的 <code>MOMO_API_KEY</code> 字段。</p>
</li>
<li><p>获取云词库 ID</p>
<p>运行 <code>get_notepad_id.py</code>，查看云词库信息，记住你需要同步的云词库 ID。</p>
<div class="block-code"><pre><code>python get_notepad_id.py</code></pre></div>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8257177462_9182415.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_601/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8257177462_9182415.png" alt="image.png"loading="lazy" decoding="async" width="601" height="207" /></picture></figure></div><p>将需要同步的词库 ID 填入 <code>.env</code> 文件中的 <code>MOMO_NOTEPAD_ID</code> 字段。</p>
</li>
</ul>
<p><a id="manual_sync"></a></p>
<h3>3. 手动同步</h3>
<p>运行 <code>sync.py</code>，即可手动触发一次同步。</p>
<div class="block-code"><pre><code>python sync.py</code></pre></div>
<p><a id="auto_sync"></a></p>
<h3>4. 自动同步（部署到树莓派上或者其他 Linux 设备）</h3>
<p>确保部署前已经成功手动运行过 <code>python sync.py</code>，验证配置无误。</p>
<p><a id="docker"></a></p>
<h4>使用Docker</h4>
<p>我个人比较喜欢用 Docker， 隔离性好，依赖管理简单，不会弄乱系统的环境。在我的树莓派 5 上运行良好，额外的性能开销在可接受范围内。</p>
<p>创建一个 <code>docker-compose.yml</code> 配置文件:</p>
<div class="block-code"><pre><code>services:
  eudic-maimemo-sync:
    image: ghcr.io/emuqi/eudic-maimemo-sync:latest
    container_name: eudic-maimemo-sync
    restart: unless-stopped
    env_file:
      - .env
    # volumes:
    #   - ./words_data.txt:/app/words_data.txt # 如果想查看单词记录，取消此行和上一行的注释
    environment:
      - TZ=Asia/Shanghai
      - RUN_ON_STARTUP=true # 设置为 true 时，容器每次启动时会执行一次同步任务
      # CRON 定时任务表达式配置:
      # 示例：每小时的第 0 分钟执行（即整点执行）
      # - CRON_SCHEDULE=0 * * * *
      # 示例：每天凌晨 3:15 执行
      - CRON_SCHEDULE=15 3 * * *
      # 请确保所有必需的环境变量（如 EUDIC_API_KEY 等）已在 .env 文件中定义或在此处直接指定。
    healthcheck:
      # Test if the supercronic process is running
      test: [&quot;CMD-SHELL&quot;, &quot;pgrep supercronic || exit 1&quot;]
      interval: 2m
      timeout: 5s
      retries: 3
      start_period: 10s</code></pre></div>
<p>你可以通过 <code>CRON_SCHEDULE</code> 来设置任务的运行周期：</p>
<ul>
<li><code>CRON_SCHEDULE=0 * * * *</code>:  每小时的第 0 分钟执行（即整点执行）</li>
<li><code>CRON_SCHEDULE=15 3 * * *</code>: 每天凌晨 3:15 执行</li>
</ul>
<p>在相同目录下创建一个 <code>words_data.txt</code> 文件，用于记录同步的单词列表，方便调试或查看。如果不需要，可以跳过此步。</p>
<div class="block-code"><pre><code>touch words_data.txt</code></pre></div>
<p>启动容器</p>
<div class="block-code"><pre><code>docker compose up -d</code></pre></div>
<p><a id="sync_other"></a></p>
<h4>其他方式</h4>
<p>你还可以使用 <code>cron</code> 或者 <code>systemctl</code> 的方式来定时运行这个同步脚本。如果你熟悉这些工具的配置，欢迎分享你的方法或提交 Pull Request。</p>
<hr />
<p><a id="faq"></a></p>
<h2>开发中遇到的问题</h2>
<ol>
<li><p><strong>欧路词典 API 的 <code>User-Agent</code> 要求：</strong> 欧路词典 API 对请求的 <code>User-Agent</code> 有特定要求，不接受 Python HTTP 库（如 <code>requests</code>）的默认 <code>User-Agent</code>。因此，在与该 API 交互时，必须显式设置一个浏览器类型的 <code>User-Agent</code>，以确保请求被正确处理。本项目中，我采用了 <code>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36</code>。</p>
</li>
<li><p><strong>墨墨背单词 API 云词库格式：</strong> 墨墨背单词 API 文档中关于添加单词到云词库所需的数据格式说明不够清晰。文档中只说明数据类型是 <code>string</code>，但未明确其具体结构。经过试验，结构为以井号 <code>#</code> 开头的行作为分类标记（例如日期），换行后紧跟该分类下的单词，每个单词独占一行。下一个分类同样以 <code>#</code> 开头的标记开始。如 <code>#20250415\napple\nboy#20250416\ncat</code>。</p>
<div class="block-code"><pre><code>#20250415
apple
boy
#20250416
cat</code></pre></div>
</li>
<li><p><strong>Docker 中定时任务：从 Cron 到 Supercronic 的迁移：</strong> 一开始，我尝试在 Docker 容器内部署 Cron 来定时执行 Python 任务。但是，Cron 任务默认在隔离的、极简的环境中执行，无法直接继承 Docker 容器启动时定义的环境变量（例如 API 密钥等配置）。虽然有方法可以间接加载，但配置比较繁琐。于是我迁移到了 <a href="https://github.com/aptible/supercronic">Supercronic</a>。<a href="https://github.com/aptible/supercronic">Supercronic</a> 是一款专为容器环境设计的 Cron 实现，它兼容标准的 Crontab 语法，还能继承容器的环境变量。如果你有类似的项目，推荐你使用 Supercronic 作为替代方案。</p>
</li>
</ol>
<p>最后，欢迎提交 Pull Requests 或 Issues 到 <a href="https://github.com/eMUQI/eudic-maimemo-sync">eudic-maimemo-sync</a>。有任何想法，也欢迎在下方留言。</p>
<p><a id="reference"></a></p>
<h2>相关链接</h2>
<ul>
<li><a href="https://my.eudic.net/OpenAPI/doc_api_study">欧路词典生词本API</a></li>
<li><a href="https://open.maimemo.com/#/">墨墨背单词开放API</a></li>
<li><a href="https://github.com/eMUQI/eudic-maimemo-sync">eudic-maimemo-sync</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[在 AI 时代，我为什么写博客？]]></title><guid>https://wulu.zone/posts/why-i-write</guid><link>https://wulu.zone/posts/why-i-write</link><pubDate>Tue, 04 Mar 2025 13:07:40 +0000</pubDate><content:encoded><![CDATA[<p>这两天，在 Hacker News 上看到 <a href="https://www.gilesthomas.com/">Giles Thomas</a> 的两篇文章，深有感触。</p>
<p>第一篇是 <a href="https://www.gilesthomas.com/2025/02/20250223-til-deep-dive-posts">《On the benefits of learning in public》</a>，讲述了 &quot;learn in public&quot; 的好处，比如能够巩固和深化知识。我写的大多数文章其实都是教程，也算是 &quot;learn in public&quot; 的一种实践，但我有时会怀疑这些教程是否真的有意义，因为它们看起来很简单、基础，似乎谁都能写，不够深刻。我会质疑那些记录基础操作步骤的文章是否值得发布——毕竟它们有时看起来只是对官方文档的简单复述，或是任何开发者通过Google都能找到的常见解决方案。如果说只是为了记录下来，方便以后自己查询，也许它们呆在个人知识库就足够了。</p>
<p>这篇文章给了我启发：他把自己写的教程描述为“我希望在刚开始学习时就能找到的文章”（&quot;tutorials that I wished someone else had written for me before I started trying to learn this stuff&quot;）。这句话让我豁然开朗：即使是简单的教程，只要它能够帮助初学者少走弯路，就有其独特价值。这在很大程度上消除了我的疑虑，给了我很大的鼓舞，因为这也正是一直以来我希望自己的文章能够达到的标准。</p>
<p>比如我的这两篇文章，或许就是某个人摸索时的及时雨：</p>
<p><a href="https://wulu.zone/posts/whisper-cn">https://wulu.zone/posts/whisper-cn</a></p>
<p><a href="https://wulu.zone/posts/mi-iot-homekit">https://wulu.zone/posts/mi-iot-homekit</a></p>
<p>另一篇是 <a href="https://www.gilesthomas.com/2025/02/blogging-in-the-age-of-ai">《It's still worth blogging in the age of AI》</a>，这篇文章探讨了在人工智能普及的时代，博客写作的意义。在他的上一篇文章登上 Hacker News 热门后，一个常见的问题浮现：如果人们都在使用 ChatGPT、Claude 和 DeepSeek 获取信息，谁还会阅读博客内容？除了 AI，还有谁会阅读你写的内容？Giles 认为是值得的，并且给出了他的思考。我觉得如果你是博客作者，你能在其中找到共鸣，推荐大家去看。</p>
<h2>我为什么写博客？</h2>
<p>读完这两篇文章，我再次思考：我为什么写博客？这个问题其实早已存在。从为了满足自己拥有网站的虚荣心而搭建博客的最初时期，到随性有灵感时更新，再到中途停笔的时期，到最后现在有意识地重新开始写作。这种问题总会反复出现。</p>
<p>尽管与作者笔耕不辍不同，我的博客更新并不频繁，不太算是一个经常写博客的人。但文章中提到的几点博客写作的价值依然让我共鸣：</p>
<ol>
<li>知识结构化：将知识记录下来帮助自己更好地掌握，而且也方便后续查询</li>
<li>成就感：当别人阅读并从我的文章中获益时带来的那种多巴胺刺激</li>
<li>个人品牌：通过博客创建一个能展示自己思想观点的作品集</li>
</ol>
<hr />
<p>我认可费曼学习法和 &quot;learn in public&quot; 等观念，就像文章提到的“如果你不能向一个聪明且感兴趣的听众解释清楚某件事，那么你就没有真正理解它。”。写作是思考的升华过程。当我们将想法用自己的语言阐述时，思维才得以精细的加工。而且为了准确表达，我常常会查阅额外资料，这本身是一个深度学习的过程。</p>
<p>记录下这些教程还有一个好处：文字是对抗遗忘的工具。记忆并不那么可靠，记录下来后，回头再看当时写下的文章，能够帮助自己回溯。文字能够复现消逝的自我。</p>
<hr />
<p>另一方面，写作对我而言除了是一种思想训练和学习方式，更是一种存在的证明。在《直视骄阳》这本书中了解到波动影响理论后（在我的<a href="https://wulu.zone/posts/2024-books">《2024 读书总结》</a>中有提到，如果你感兴趣的话），我发现写作能有效缓解我的存在焦虑。</p>
<p>刚接触互联网时，我就读到了《欺骗的艺术》这本书，了解了社会工程学，对在互联网上分享信息产生了警惕。这种警惕加上我的性格特点，导致我一直以来很少在互联网上透露个人信息，甚至很少写一些感想类的文章。我的博客大多数聚焦于技术分享，个人观点则被谨慎地隔离在外。</p>
<p>直到经历了一场深刻的心理危机，接受心理咨询并广泛阅读心理学和哲学书籍后，我的世界观发生了微妙的转变。我开始渴望与人连接，期待真诚的交流。这种认识让我开始思考在博客上分享更多个人感想的可能。虽然仍有矛盾和犹豫，但我开始相信，适度的自我揭示和真诚分享不仅是自我成长的一部分，也可能为他人提供某种共鸣或安慰。我期待我的文字能够帮助人，与更多人产生联系，传播那或许是非常微小但真实的影响。</p>
<p>写作帮助我整理思绪，获得分享的快感，同时也是应对生活空虚感的方式。即便有时感觉像 Giles 文章中提到的 &quot;feel like you're shouting into the void&quot; （就像对着虚空喊叫），但偶尔从“虚空”传来的一条留言、一个点赞，都将成为继续前行的动力。</p>
<h2>AI 时代的写作价值</h2>
<p>在AI盛行的时代，我认为坚持写作变得更加重要。从我的理解来看，现阶段的大语言模型本质上还是基于概率的文本生成，而每个人独特的思考和写作方式是无法被完全替代的。当越来越少的人选择写作，那些仍然坚持的声音反而变得更加珍贵，更加真实，充满温度和灵魂。写作不仅是信息的传递，更是人类思想和情感的独特表达。</p>
<p>这就是为什么，尽管面对AI的崛起，我依然相信博客写作的价值——它帮助我思考，连接他人，留下我存在的印记，同时也为这个世界贡献一份真实的人类声音。</p>
<h2>题外话：一个邀请</h2>
<p>在浏览 <a href="https://news.ycombinator.com/item?id=43154666">Hacker News 的关于上面文章的评论区</a>时，我被 Aditya Athalye 的做法所吸引——他学习Derek Sivers和patio11的做法，在他的网站放了一份“<a href="https://www.evalapply.org/index.html#standing-invitation">长期邀约</a>”。</p>
<p>我觉得这种方式很吸引我，我也想学习这种方式，以下是我的对所有人发起的邀请：</p>
<p>如果你对我的文章，或者我所讨论的任何主题感兴趣，欢迎你给我发送邮件。我的邮箱地址是：<strong>wulu@wulu.zone</strong></p>
<p>我会不定期查看邮件，可能我无法及时回复，但我承诺只要你是以友善和尊重的态度联系我，我一定会回应。每一次真诚的交流都可能成为意外的收获和启发，或许这也是在AI时代写博客和保持人际连接的另一种价值所在。</p>
<p>谢谢你的阅读！期待收到你的来信。</p>
]]></content:encoded></item><item><title><![CDATA[记录 DIY 更换 CASIO G-SHOCK GBA-800 电池过程]]></title><guid>https://wulu.zone/posts/casio-gba800-battery-replacement</guid><link>https://wulu.zone/posts/casio-gba800-battery-replacement</link><pubDate>Wed, 26 Feb 2025 16:04:29 +0000</pubDate><content:encoded><![CDATA[<p>最近动手给我的 CASIO G-SHOCK GBA-800 更换了电池，记录一下过程。参考教程在<a href="#reference">文末</a>，建议先看完两个视频再动手。</p>
<p><strong>注意：自行更换电池可能会影响手表防水性能，并存在进灰等风险。</strong></p>
<h2>需要准备的工具</h2>
<ul>
<li>镊子</li>
<li>螺丝刀</li>
<li>CR2016电池（建议选松下，和出厂时一致）</li>
<li>防静电手套以避免指纹和灰尘（如果有的话）</li>
</ul>
<h2>操作步骤</h2>
<h3>1. 拆出后盖</h3>
<p>用螺丝拧开后盖。然后取下这个膜，记住这个膜的方向。</p>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8259416112_397042.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_768/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8259416112_397042.jpg" alt="IMG_8678 (中).jpg"loading="lazy" decoding="async" width="768" height="768" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8259416112_396936.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_768/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8259416112_396936.jpg" alt="IMG_8683 (中).jpg"loading="lazy" decoding="async" width="768" height="768" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8259415896_699132.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_768/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8259415896_699132.jpg" alt="IMG_8686 (中).jpg"loading="lazy" decoding="async" width="768" height="768" /></picture></figure></div></div>
<h3>2. 打开电池扣取出电池</h3>
<p>打开后盖，取下中间的厚后，可以看到机芯模块。用镊子插入左图箭头所示缝隙，向右撬开电池盖。</p>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8259415732_247625.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_768/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8259415732_247625.png" alt="Snipaste_2025-02-26_23-37-58.png"loading="lazy" decoding="async" width="768" height="768" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8259415641_931132.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_768/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8259415641_931132.jpg" alt="IMG_8690 (中).jpg"loading="lazy" decoding="async" width="768" height="768" /></picture></figure></div></div>
<p>缓慢地取出电池，需要注意，电池和电池盖之间有胶，所以要慢慢撕下来。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8259415497_541493.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_768/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8259415497_541493.jpg" alt="IMG_8691 (中).jpg"loading="lazy" decoding="async" width="768" height="768" /></picture></figure></div><h3>3. 更换电池</h3>
<p>然后，换入新电池。这款手表的电池型号是 CR2016。放入电池后将电池盖向下按，扣回去。</p>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8259415408_016867.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_768/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8259415408_016867.jpg" alt="IMG_8692 (中).jpg"loading="lazy" decoding="async" width="768" height="768" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8259415408_016775.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_768/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8259415408_016775.jpg" alt="IMG_8693 (中).jpg"loading="lazy" decoding="async" width="768" height="768" /></picture></figure></div></div>
<h3>4. 短接AC和地</h3>
<p>按照电池盖上的说明，用镊子短接AC和地。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8259415721_887537.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_768/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8259415721_887537.jpg" alt="IMG_8694 (中).jpg"loading="lazy" decoding="async" width="768" height="768" /></picture></figure></div><h3>5. 盖上覆膜和安装好密封圈</h3>
<p>将覆膜按初始状态放回，注意区分正反面。然后安装密封圈（黑色橡胶环），请参考右图箭头所示位置，确保密封圈正确放入对应槽内。</p>
<p>随后，可以利用这个机会用酒精棉片轻轻清洁表壳内部边缘和外壳，去除积累的汗渍和污垢。注意不要让酒精接触到电子元件，并确保完全干燥后再继续下一步。</p>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8259415142_974779.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_768/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8259415142_974779.jpg" alt="IMG_8695 (中).jpg"loading="lazy" decoding="async" width="768" height="768" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8259414936_119505.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_768/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8259414936_119505.png" alt="image.png"loading="lazy" decoding="async" width="768" height="768" /></picture></figure></div></div>
<h3>6. 装回后盖，大功告成</h3>
<p>拧螺丝时要注意，不要直接拧紧。先将四个螺丝全部拧入，再依次拧紧。</p>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8259414869_4313545.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1500/format,webp 1x, https://i.typlog.com/wulu/8259414869_4313545.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_3000/format,webp 2x" media="(min-width: 1500px)" type="image/webp"><source srcset="https://i.typlog.com/wulu/8259414869_4313545.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1500 1x, https://i.typlog.com/wulu/8259414869_4313545.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_3000 2x" media="(min-width: 1500px)"><source srcset="https://i.typlog.com/wulu/8259414869_4313545.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800/format,webp 1x, https://i.typlog.com/wulu/8259414869_4313545.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600/format,webp 2x" media="(min-width: 800px)" type="image/webp"><source srcset="https://i.typlog.com/wulu/8259414869_4313545.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800 1x, https://i.typlog.com/wulu/8259414869_4313545.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600 2x" media="(min-width: 800px)"><img src="https://i.typlog.com/wulu/8259414869_4313545.jpg" alt="IMG_8699.jpg"loading="lazy" decoding="async" width="3024" height="3024" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8259414869_428832.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1500/format,webp 1x, https://i.typlog.com/wulu/8259414869_428832.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_3000/format,webp 2x" media="(min-width: 1500px)" type="image/webp"><source srcset="https://i.typlog.com/wulu/8259414869_428832.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1500 1x, https://i.typlog.com/wulu/8259414869_428832.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_3000 2x" media="(min-width: 1500px)"><source srcset="https://i.typlog.com/wulu/8259414869_428832.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800/format,webp 1x, https://i.typlog.com/wulu/8259414869_428832.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600/format,webp 2x" media="(min-width: 800px)" type="image/webp"><source srcset="https://i.typlog.com/wulu/8259414869_428832.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800 1x, https://i.typlog.com/wulu/8259414869_428832.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600 2x" media="(min-width: 800px)"><img src="https://i.typlog.com/wulu/8259414869_428832.jpg" alt="IMG_8700.jpg"loading="lazy" decoding="async" width="3024" height="3024" /></picture></figure></div></div>
<h2>注意事项</h2>
<ul>
<li>强烈建议看完两个参考视频后再动手</li>
<li>整个过程大约需要15-20分钟，建议在光线充足、干净的桌面上操作</li>
<li>更换电池后，手表需要重新设置时间和日期</li>
<li>如果操作后发现手表功能异常，建议尽快送专业维修点检查</li>
</ul>
<p>如果你决定自行更换电池，那么祝你好运！</p>
<p><a id="reference"></a></p>
<h2>参考</h2>
<p><a href="https://www.casio.com/content/dam/casio/global/support/manuals/watches/pdf/55/5554/qw5554_CN.pdf">卡西欧 G-SHOCK GBA-800 使用手册</a></p>
<p><a href="https://www.youtube.com/watch?v=8MBkgxxEeI8">https://www.youtube.com/watch?v=8MBkgxxEeI8</a></p>
<p><a href="https://www.bilibili.com/video/BV1PA411P7UB">https://www.bilibili.com/video/BV1PA411P7UB</a></p>
]]></content:encoded></item><item><title><![CDATA[2024 读书总结]]></title><guid>https://wulu.zone/posts/2024-books</guid><link>https://wulu.zone/posts/2024-books</link><description><![CDATA[Wulu的2024读书总结]]></description><pubDate>Mon, 17 Feb 2025 13:35:47 +0000</pubDate><content:encoded><![CDATA[<p>过去这一年，我的阅读主要围绕心理健康、自我认知和个人成长展开。这些书籍帮助我更深入地理解了自我和他人，也为日常生活提供了实用的工具和方法。虽然遗憾没能在读完时及时记录感受，但重温这些书籍时，仍能感受到它们带给我的启发和改变。以下是我对这些书籍的简要回顾与思考。</p>
<h2>《蛤蟆先生去看心理医生》</h2>
<div class="block-code"><pre><code>作者：罗伯特·戴博德
译者：陈赢
出版社：天津人民出版社</code></pre></div>
<p>一本很薄的故事书，有点像童话或者寓言故事，如书名，讲述了蛤蟆先生去看心理医生的故事。
读起来很轻松，流畅，一下就可以读完。这本书提供了一个了解心理咨询的视角，是一本不错的心理学读物。
书中还科普了交互分析理论（Transactional Analysis，TA）中的儿童自我状态，父母自我状态，成人自我状态。这个理论认为我们会在这三种状态不停地切换，非常有趣的理论，有助于帮助了解自我。</p>
<h2>《直视骄阳》</h2>
<div class="block-code"><pre><code>作者：Irvin D. Yalom
译者：张亚
出版社：中国轻工业出版社</code></pre></div>
<p>这是一部关于如何面对死亡的深刻著作。</p>
<p>这本书讲了死亡焦虑的普遍性，如何识别死亡焦虑，它能够带来什么，以及我们可以如何去面对它。</p>
<p>对我而言，这本书帮助最大的就是带我了解了伊比鸠鲁的观念：</p>
<ul>
<li>死亡本身不可怕，因为我们无法感受死亡，死后“我”就消失了，即“完全虚无的死亡”。</li>
<li>生前和死后，是对称的两极。死后其实和生前并无差别。</li>
<li>波动影响。指人有意无意会对周围的任何事物产生影响，就像池塘中的涟漪，即使细微但是很长远。</li>
</ul>
<p>这本书给了我一些方法去处理我的死亡焦虑，也给我带来了一些新的思考去看待自己的死亡和他人的死亡。书中还讨论了死亡意识如何反过来影响我们的生活态度,以及如何将对死亡的思考转化为珍惜当下的动力。如果你有存在焦虑或者死亡焦虑，我非常推荐这本书。</p>
<h2>《非暴力沟通》</h2>
<div class="block-code"><pre><code>作者：马歇尔·卢森堡
译者：刘轶
出版社：华夏出版社</code></pre></div>
<p>这本书介绍了非暴力沟通。也是一种生活理念。它提示我要关注自己内心的感受和需求，真诚地与人沟通。</p>
<p>通过把注意力放到观察、感受、需求和请求这四个要素来改善沟通，同时非暴力沟通还强调自主的重要性，强调个人责任。我觉得这一点和存在主义的观念是很吻合。</p>
<p>书中还提到了很多非常有意思的讨论：比如观察和评论的区别，请求和要求的区别。这些讨论不仅帮助我反思与人的沟通，也帮助我反思人际关系。</p>
<p>非暴力沟通方法在亲密关系中尤其有效,能帮助伴侣之间建立更深入的理解和连接。</p>
<p>书中还有很多内容，需要真正去读并且实践才有用，非常有帮助，非常推荐这本书。</p>
<h2>《Headspace 冥想正念手册》</h2>
<div class="block-code"><pre><code>作者：安迪·帕帝康
译者：李芳龄
出版社：星出版</code></pre></div>
<p>这本书科普了冥想和正念，有很多帮助理解冥想的故事，还提供一些方法帮助入门冥想。</p>
<p>之前一直听说过冥想，听过很多关于冥想的传闻，却也没有真正了解过。今年特别想尝试一下冥想，买了这本书来了解一下，让我对冥想有了不同的认识。书中还提供了很多隐喻帮助理解冥想。我也尝试了冥想，对我而言确实有帮助的。</p>
<p>如果你也对冥想感兴趣，或者正在尝试但觉得摸不着头绪，很推荐这本书。我看的这个版本是繁体中文，还有一个简体中文的版本，名字是《十分钟冥想》。</p>
<h2>《天生敏感》</h2>
<div class="block-code"><pre><code>作者：伊莱恩·阿伦
译者：于娟娟
出版社：华夏出版社</code></pre></div>
<p>这是一本讲述所谓高敏感人群的特质的书。</p>
<p>听了<a href="https://justinyan.me/post/5945?ref=wulu.zone">枫言枫语</a>的节目，专门看了这本书。我大致也属于比较敏感的人群，这本书帮助高敏感人群了解自我，理解自我，并且提供了一些方法更好的与外部世界相处。还有很重要的是，能够带来很大的认同感。</p>
<h2>《素食者》</h2>
<div class="block-code"><pre><code>作者：韩江
译者：胡椒筒
出版社：四川文艺出版社</code></pre></div>
<p>这是一本小说，由2024年诺贝文学奖作者韩江写的。书中通过三个视角来叙述同一个故事，这点比较有趣。我是慕名去看，没有我想象中的好看，整本书像是讲述几个精神病的故事，很压抑。</p>
<h2>《也许你该找个人聊聊》</h2>
<div class="block-code"><pre><code>作者：洛丽·戈特利布
译者：张含笑
出版社：上海文化出版社</code></pre></div>
<p>这是一本讲述心理咨询的书。这本书很厚，由一个心理咨询师的视角写作，书中以一个个故事组成，每一个章节是一个故事，有作者本人的故事，也有作者作为心理咨询师在咨询室里遇到的故事。虽然很厚但是读起来没有压力，可以慢慢看看，每天看几个故事。我喜欢这本书不是一本说教的书，平易近人，没有让人感觉是在尝试告诉你什么道理，而是通过一个个故事，让你自己去感受，找到自己的理解。</p>
<h2>结语</h2>
<p>希望今年能保持阅读的习惯，也期待遇见更多好书。</p>
]]></content:encoded></item><item><title><![CDATA[使用 Audacity 制作立体音效果]]></title><guid>https://wulu.zone/posts/audacity-surround-sound-guide</guid><link>https://wulu.zone/posts/audacity-surround-sound-guide</link><description><![CDATA[轻松实现左右环绕的BGM]]></description><pubDate>Mon, 09 Dec 2024 14:13:53 +0000</pubDate><content:encoded><![CDATA[<p>制作短视频时，巧妙的音效能提升表现力、吸引观众兴趣并提高完播率。比如，下面这个视频，视频和声音有着一致体验。声音跟随着画面的焦点移动，在左右耳朵穿梭。</p>
<iframe width="315" height="560"
src="https://youtube.com/embed/ouxaitWOXx8?si=68iZIwokhhzwII5N"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen></iframe>

<p>这种声音的立体移动效果，实际上是通过精妙的声道控制实现的。</p>
<p>具体而言，声音的左右穿梭可以通过调整左右声道的音量来完成。比如，我们可以逐步减弱左声道的音量，同时逐渐增强右声道的音量。这种渐进式的音量变化，会给观众造成声音从左向右流动的听觉错觉，仿佛声音正在穿越立体空间。通过细腻地控制声音的转换，我们可以为视频增添一层令人着迷的听觉维度，提升视听体验。</p>
<p>接下来，我将分享如何使用 Audacity 制作这种立体音。</p>
<h2>安装 Audacity</h2>
<p>你可以前往 <a href="https://www.audacityteam.org/">Audacity</a> 或者是它的 <a href="https://github.com/audacity/audacity/releases">Github 页面</a>下载。但需要是要注意的是，在官网下载时，如果你没有选择 “Download without Muse Hub” 选项，那么它可能会捆绑安装 Muse Hub。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8268411135_965846.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1309/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8268411135_965846.png" alt="image.png"loading="lazy" decoding="async" width="1309" height="545" /></picture></figure></div><p>你还可以安装可选的 <a href="https://support.audacityteam.org/basics/installing-ffmpeg">FFmpeg 库</a>。如果你要使用 Audacity 编辑  AC3, M4A, MP4 或 WMA 格式的音频，则是必须的。</p>
<p><a href="https://support.audacityteam.org/basics/installing-ffmpeg">https://support.audacityteam.org/basics/installing-ffmpeg</a></p>
<h2>1. 使用包络工具标记左右声道切换的位置</h2>
<p>将音频导入 Audacity，你可以直接将音频拖入 Audacity 或者选择“<strong>文件 &gt; 导入 &gt; 音频</strong>”。</p>
<p>然后你可以看到音频的波形图：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8266252215_190252.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1357/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8266252215_190252.png" alt="image.png"loading="lazy" decoding="async" width="1357" height="548" /></picture></figure></div><p>首先我们使用“包络”工具标记声道切换的位置。</p>
<p>找到“包络”工具，</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8266251863_194357.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_271/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8266251863_194357.png" alt="image.png"loading="lazy" decoding="async" width="271" height="78" /></picture></figure></div><p>在期望声音左右切换的位置点一下，标记声音切换的位置，方便后面我们调整各声轨的音量变换。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8266247210_990223.gif" type="image/webp"><img src="https://i.typlog.com/wulu/8266247210_990223.gif" alt="标记声轨.gif"loading="lazy" decoding="async" width="776" height="410" /></picture></figure></div><p>比如，我想要每一秒声音切换（声音从左到右或者从右到左）一次，我就每隔一秒标记一下：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8266251725_77121.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800/format,webp 1x, https://i.typlog.com/wulu/8266251725_77121.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600/format,webp 2x" media="(min-width: 800px)" type="image/webp"><source srcset="https://i.typlog.com/wulu/8266251725_77121.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800 1x, https://i.typlog.com/wulu/8266251725_77121.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600 2x" media="(min-width: 800px)"><img src="https://i.typlog.com/wulu/8266251725_77121.png" alt="image.png"loading="lazy" decoding="async" width="1884" height="422" /></picture></figure></div><h2>2. 分离音轨左右声轨</h2>
<p>点击“分离立体声轨”，将左右声道分开成两个声轨，方便编辑。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8266250811_587118.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_502/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8266250811_587118.png" alt="image.png"loading="lazy" decoding="async" width="502" height="527" /></picture></figure></div><h2>3. 分别调整左右声轨</h2>
<p>分离声轨后，上面的声轨代表左声道，下面的声轨的右声道。这样就能分别控制左耳和右耳听到的声音。按照下图的方式调整声轨。</p>
<p>逐渐减弱左耳听到的声音，同时逐渐增强右耳的声音，就能制造声音从左到右的效果。</p>
<p>同理，逐渐减弱右耳听到的声音，同时逐渐增强左耳的声音，就能制造声音从右到左的效果。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8266250110_540847.gif" type="image/webp"><img src="https://i.typlog.com/wulu/8266250110_540847.gif" alt="调整声轨音量.gif"loading="lazy" decoding="async" width="776" height="410" /></picture></figure></div><p>反复调节，调整到你期望的效果：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8266249055_735675.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800/format,webp 1x, https://i.typlog.com/wulu/8266249055_735675.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600/format,webp 2x" media="(min-width: 800px)" type="image/webp"><source srcset="https://i.typlog.com/wulu/8266249055_735675.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800 1x, https://i.typlog.com/wulu/8266249055_735675.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600 2x" media="(min-width: 800px)"><img src="https://i.typlog.com/wulu/8266249055_735675.png" alt="image.png"loading="lazy" decoding="async" width="1887" height="412" /></picture></figure></div><p>最后，通过“文件 &gt; 导出音频”，导出降噪后的音频。</p>
<h2>参考链接</h2>
<p><a href="https://manual.audacityteam.org/man/envelope_tool.html">https://manual.audacityteam.org/man/envelope_tool.html</a></p>
<h2>更多</h2>
<p><a href="https://wulu.zone/posts/audacity-noise-reduction-guide">https://wulu.zone/posts/audacity-noise-reduction-guide</a></p>
]]></content:encoded></item><item><title><![CDATA[使用 Audacity 进行音频降噪教程]]></title><guid>https://wulu.zone/posts/audacity-noise-reduction-guide</guid><link>https://wulu.zone/posts/audacity-noise-reduction-guide</link><description><![CDATA[轻量级音频处理的简单方案]]></description><pubDate>Thu, 14 Nov 2024 14:20:20 +0000</pubDate><content:encoded><![CDATA[<p>我一直使用 <a href="https://www.capcut.com/">CapCut</a> 来剪辑视频。有时想做一些安静或突出音效的视频，但当放大声音总会听到底噪（环境音）。可能是空调，也可能是风扇的声音。这种持续噪音基本无法通过静音部分内容去除，所以需要使用音频降噪功能。CapCut 原本提供免费音频降噪的功能，但后面变成了收费功能。于是，开始在网上找能够实现这一功能的软件。我的需求很简单，只要能够实现音频降噪这个功能就行，所以我没有选择使用功能强大的音频剪辑软件，我在寻找一个轻量化的软件。</p>
<p>我找到了 <a href="https://github.com/audacity/audacity">Audacity</a>，它轻量化（不到100MB）且是开源的，功能强大易于使用。它的降噪功能，总体感觉比 CapCut 好。在 Audacity 中，可以选择噪音样本，再设定降噪范围，并且可以调整降噪的参数，最后的效果也比 CapCut 更佳。</p>
<p>接下来，我分享如何使用 Audacity 降噪音频。</p>
<h2>安装 Audacity</h2>
<p>你可以前往 <a href="https://www.audacityteam.org/">Audacity</a> 或者是它的 <a href="https://github.com/audacity/audacity/releases">Github 页面</a>下载。但需要是要注意的是，在官网下载时，如果你没有选择 “Download without Muse Hub” 选项，那么它可能会捆绑安装 Muse Hub。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8268411135_965846.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1309/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8268411135_965846.png" alt="image.png"loading="lazy" decoding="async" width="1309" height="545" /></picture></figure></div><p>你还可以安装可选的 <a href="https://support.audacityteam.org/basics/installing-ffmpeg">FFmpeg 库</a>。如果你要使用 Audacity 编辑  AC3, M4A, MP4 或 WMA 格式的音频，则是必须的。</p>
<p><a href="https://support.audacityteam.org/basics/installing-ffmpeg">https://support.audacityteam.org/basics/installing-ffmpeg</a></p>
<h2>1. 取得噪音特征</h2>
<p>将音频导入 Audacity，你可以直接将音频拖入 Audacity 或者选择“<strong>文件 &gt; 导入 &gt; 音频</strong>”。</p>
<p>然后你可以看到音频的波形图：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8268408982_081041.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800/format,webp 1x, https://i.typlog.com/wulu/8268408982_081041.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600/format,webp 2x" media="(min-width: 800px)" type="image/webp"><source srcset="https://i.typlog.com/wulu/8268408982_081041.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800 1x, https://i.typlog.com/wulu/8268408982_081041.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600 2x" media="(min-width: 800px)"><img src="https://i.typlog.com/wulu/8268408982_081041.png" alt="image.png"loading="lazy" decoding="async" width="1920" height="559" /></picture></figure></div><p>用鼠标左键选取噪音样本（仅包含你想要减少的噪音的区域），然后点击“<strong>效果器 &gt; 噪音移除与修复 &gt; 降噪</strong>”：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8268408884_629431.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800/format,webp 1x, https://i.typlog.com/wulu/8268408884_629431.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600/format,webp 2x" media="(min-width: 800px)" type="image/webp"><source srcset="https://i.typlog.com/wulu/8268408884_629431.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800 1x, https://i.typlog.com/wulu/8268408884_629431.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600 2x" media="(min-width: 800px)"><img src="https://i.typlog.com/wulu/8268408884_629431.png" alt="image.png"loading="lazy" decoding="async" width="1895" height="385" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8268408831_008438.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_964/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8268408831_008438.png" alt="image.png"loading="lazy" decoding="async" width="964" height="617" /></picture></figure></div><p>然后 ，点击“取得噪音特征”。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8268408672_371123.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_543/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8268408672_371123.png" alt="image.png"loading="lazy" decoding="async" width="543" height="524" /></picture></figure></div><h2>2. 调整参数降噪音频</h2>
<p>接下来，选择你要降噪的范围：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8268408510_334326.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800/format,webp 1x, https://i.typlog.com/wulu/8268408510_334326.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600/format,webp 2x" media="(min-width: 800px)" type="image/webp"><source srcset="https://i.typlog.com/wulu/8268408510_334326.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800 1x, https://i.typlog.com/wulu/8268408510_334326.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600 2x" media="(min-width: 800px)"><img src="https://i.typlog.com/wulu/8268408510_334326.png" alt="image.png"loading="lazy" decoding="async" width="1883" height="379" /></picture></figure></div><p>然后再次点击“<strong>效果器 &gt; 噪音移除与修复 &gt; 降噪</strong>”：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8268408451_895218.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_972/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8268408451_895218.png" alt="image.png"loading="lazy" decoding="async" width="972" height="515" /></picture></figure></div><p>点击“预览”可以听降噪后的效果，调整降噪的参数，直到预期的效果。这通常最好通过反复试验来完成，调整滑块并使用预览按钮聆听降噪后的音频。最后，点击“确定”。</p>
<ul>
<li><strong>降噪强度(dB)</strong>: 控制对识别噪声所应用的音量减少量。<em>使用能将噪声减至可接受水平的最低值</em>。高于必要的值可能使噪声更安静，但会导致剩余音频受损。</li>
<li><strong>灵敏度</strong>：控制音频中有多少被视为噪声，范围是 0（关闭）到 24（最大）。灵敏度越高，意味着去除的噪声越多，但也可能会去除一些所需的信号。较低的灵敏度可能会在降噪后的音频中留下伪影（不自然的声音失真）。<em>建议将灵敏度设置为能有效去除噪声且不出现失真的最低值</em>。</li>
<li><strong>频率平滑（频带）</strong>：当值为 1 或更高时，此控制将噪声降低扩展到指定数量的相邻频段中。这会修改您打算保留的信号，但是如果在降噪音频中残留伪影，平滑可以使这些伪影听起来更可接受。平滑可能会使所需的音频不太清晰，因此当<em>噪声较轻时，请尝试将此控件保持在 0（关闭）</em>。</li>
</ul>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8268408393_634952.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_543/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8268408393_634952.png" alt="image.png"loading="lazy" decoding="async" width="543" height="524" /></picture></figure></div><p>最后，通过“文件 &gt; 导出音频”，导出降噪后的音频。</p>
<h2>参考链接和拓展链接</h2>
<p>除了上面的方法，你还可以通过 Audacity 使用频谱编辑（Spectral Editing）、噪音门（Noise Gate）和陷波滤波器（Notch Filter）等方式来降噪音频，如果你感兴趣，下面是参考链接：</p>
<p><a href="https://support.audacityteam.org/repairing-audio/noise-reduction-removal">https://support.audacityteam.org/repairing-audio/noise-reduction-removal</a></p>
<p><a href="https://manual.audacityteam.org/man/noise_reduction.html">https://manual.audacityteam.org/man/noise_reduction.html</a></p>
<p><a href="https://manual.audacityteam.org/man/alternative_noise_reduction_techniques.html">https://manual.audacityteam.org/man/alternative_noise_reduction_techniques.html</a></p>
]]></content:encoded></item><item><title><![CDATA[Moonhack 2024: 缓解气候变化]]></title><guid>https://wulu.zone/posts/moonhack2024</guid><link>https://wulu.zone/posts/moonhack2024</link><description><![CDATA[“今年Moonhack提出的问题是：‘我们能否通过编程创造出行动呼吁，影响他人做出更好的选择，甚至告知他们一些他们之前不知道的事情，以便他们可以与他人分享？’” – Kaye North，Code Club Australia]]></description><pubDate>Sun, 20 Oct 2024 08:06:43 +0000</pubDate><content:encoded><![CDATA[<p>今年八月，树莓派基金会的本地化协调人员联系了我，向我介绍了 <a href="https://moonhack.com">Moonhack</a>，并询问我是否有兴趣翻译该项目。起初，我并不了解这个活动，但在网上搜索后，我发现它是一个有教育意义的活动，旨在通过编程教育，帮助全球各地的孩子提升科技(STEM)素养。同时，我也注意到在中文世界中，这个编程活动并不知名。</p>
<p>我觉得这个项目很有意义，它为儿童编程学习提供了优质资源。我希望能够通过将其翻译成中文，让中文世界的孩子们更方便地获取这些教育资源。因此，我参与了翻译活动，翻译了其中的两个 Scratch 项目。</p>
<p>现在，Moonhack 2024 已经正式启动，我希望通过这篇文章，向更多人推广这个活动，提供多一种学习编程的方式。即使不参加活动，活动中提供的项目教程也是个不错学习资源。</p>
<h2>Moonhack 是什么？</h2>
<p><a href="https://moonhack.com">Moonhack</a> 是一项面向青少年的免费国际编程挑战赛，由 <a href="https://www.codeclubau.org/">Code Club Australia</a> 每年举办。在过去的 8 年里，超过 190,000 名儿童一直在编写 Moonhack 项目。</p>
<p>你可以在这里查看往年的项目：<a href="https://moonhack.com/previous-projects/">https://moonhack.com/previous-projects/</a></p>
<h2>Moonhack 2024</h2>
<p>Moonhack2024 于 10 月 14 日至 31 日举行。今年的主题为：气候变化。这些项目将帮助参与者了解从农业工作者如何利用气候数据提高农作物产量和实践可持续农业，到全球气温上升对海洋生物种群的影响等话题。</p>
<p>参与者可以使用 Scratch、micro：bit 或 Python 进行编程。</p>
<p>今年有六个项目，感兴趣的可以前往 <a href="https://moonhack.com/projects-new/">Moonhack 官网</a>了解：</p>
<ul>
<li><p>Great Pacific Garbage Patch 大太平洋垃圾带（不限制编程平台）</p>
<p>在任何编码平台中使用您的编码技能，创建一个可以清理太平洋大垃圾带的解决方案。</p>
<p><a href="https://www.codeclubau.org/projects/gpgp/">项目主页</a> | <a href="https://assets.codeclubau.org/assets/Chinese-Simplified_GPGP_2024-09-10-025122_avrl.pdf">中文教程PDF</a></p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8270589862_491404.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8270589862_491404.png" alt="image.png"loading="lazy" decoding="async" width="300" height="225" /></picture></figure></div></li>
<li><p>In Deep Water 深陷水中（Scratch项目）</p>
<p>创建一个迷宫游戏，帮助减缓上升的水位。帮助乌龟在水位上升之前回到地球。</p>
<p><a href="https://www.codeclubau.org/projects/in-deep-water/">项目主页</a> | <a href="https://assets.codeclubau.org/assets/ChineseSimplified_InDeepWater.pdf">中文教程PDF</a></p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8270589692_8731165.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8270589692_8731165.png" alt="image.png"loading="lazy" decoding="async" width="300" height="227" /></picture></figure></div></li>
<li><p>Sweeten the Crop 让作物更甜美 （Scratch项目）</p>
<p>你能种出完美的甘蔗作物吗？创建一个点击游戏，尽力尝试一下吧。</p>
<p><a href="https://www.codeclubau.org/projects/sweeten-the-crop/">项目主页</a> | <a href="https://assets.codeclubau.org/assets/Chinesesimplified_SweetentheCrop.pdf">中文教程PDF</a></p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8270589641_425972.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8270589641_425972.png" alt="image.png"loading="lazy" decoding="async" width="300" height="224" /></picture></figure></div></li>
<li><p>Water Adventure 水之旅（Scratch项目）</p>
<p>创建一个展示水循环的动画。然后进一步开发，反映人类的影响。</p>
<p><a href="https://www.codeclubau.org/projects/water-adventure/">项目主页</a> | <a href="https://assets.codeclubau.org/assets/Chinese_Simplified_WaterAdventure_2024-09-10-051720_sdht.pdf">中文教程PDF</a></p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8270589441_773853.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8270589441_773853.png" alt="image.png"loading="lazy" decoding="async" width="300" height="222" /></picture></figure></div></li>
<li><p>Talking Rubbish 垃圾会说话（micro：bit项目）</p>
<p>创建一个设备，用于跟踪放入垃圾桶中的垃圾类型，并利用数据制定行动计划。</p>
<p><a href="https://www.codeclubau.org/projects/talking-rubbish/">项目主页</a> | <a href="https://assets.codeclubau.org/assets/Chinese-Simplified_TalkingRubbish.pdf">中文教程PDF</a></p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8270589455_638693.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8270589455_638693.png" alt="image.png"loading="lazy" decoding="async" width="300" height="241" /></picture></figure></div></li>
<li><p>Turtles and Temperature 海龟与温度（Python项目）</p>
<p>编写一个程序，利用温度数据来观察这对海龟幼崽性别的影响。</p>
<p><a href="https://www.codeclubau.org/projects/turtles-and-temp/">项目主页</a> | <a href="https://assets.codeclubau.org/assets/ChineseSimplified_TurtlesandTemperature_2024-09-10-043519_kshr.pdf">中文教程PDF</a></p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8270589290_538235.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8270589290_538235.png" alt="image.png"loading="lazy" decoding="async" width="300" height="255" /></picture></figure></div></li>
</ul>
<p>相关链接：</p>
<p><a href="https://www.raspberrypi.org/blog/moonhack-2024/">https://www.raspberrypi.org/blog/moonhack-2024/</a></p>
<p><a href="https://moonhack.com/">https://moonhack.com/</a></p>
<p><a href="https://www.codeclubau.org/moonhack-2023/">https://www.codeclubau.org/moonhack-2023/</a></p>
]]></content:encoded></item><item><title><![CDATA[谈谈 Follow 这款 RSS 阅读器]]></title><guid>https://wulu.zone/posts/follow</guid><link>https://wulu.zone/posts/follow</link><pubDate>Thu, 10 Oct 2024 14:39:34 +0000</pubDate><content:encoded><![CDATA[<h2>简介</h2>
<p><a href="https://github.com/RSSNext/Follow">Follow</a> 是一个最近新出的 RSS阅读器，由 <a href="https://github.com/DIYgod/RSSHub">RSSHub</a> 的作者 <a href="https://diygod.cc/">DIYgod</a> 的新团队 <a href="https://github.com/RSSNext">RSSNext</a> 开发。</p>
<p>我喜欢 RSS 这个概念，尤其是 RSSHub 使得许多原生不支持 RSS 的网站和平台都能够通过 RSS 来订阅，让 RSS 有更多可能。我喜欢互联网开放的理念，更倾向不受特定平台限制地获取信息，并希望避免推荐算法的影响。长期以来，我使用 <a href="https://github.com/FreshRSS/FreshRSS">FreshRSS</a> 来管理的 RSS 订阅。看到 Follow 这个新兴的 RSS 阅读器项目出现，我感到非常兴奋，期待它为 RSS 生态注入新的活力。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8271434101_462002.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_925/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8271434101_462002.png" alt="image.png"loading="lazy" decoding="async" width="925" height="238" /></picture></figure></div><p>Follow 目前处于内测阶段，需要邀请码才能体验。当我在社交媒体看到 Follow 的宣传时，我向 <a href="https://diygod.cc/">DIYgod</a> 私信，并且幸运地获得了一个邀请码以参加早期测试。现在我使用 Follow 已经差不多一个月，接下来谈谈我的体会。如果你也对Follow 感兴趣，<strong>文末我提供了两个邀请码</strong>。</p>
<h2>Follow 吸引我的地方</h2>
<ul>
<li><p><strong>出色的UI设计和动效</strong></p>
<p>具体可以查看 Follow 的核心开发者 <a href="https://innei.in/">Innei</a> 写的文章<a href="https://innei.in/posts/design/design-concepts-in-follow-app">《浅谈 Follow 中的设计理念》</a>，这里就不再赘述。</p>
</li>
<li><p><strong>与 RSSHub 深度结合</strong></p>
<p>通过与 RSSHub 深度结合，Follow 提供了非常便捷的订阅体验，你可以直接在 Follow 里面搜索订阅 X、bilibili、youtube 等热门的社交平台以及各种 RSSHub支持的网站。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8271433924_321492.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1412/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8271433924_321492.png" alt="image.png"loading="lazy" decoding="async" width="1412" height="900" /></picture></figure></div></li>
<li><p><strong>对媒体提供不同的视图</strong></p>
<p>在不同的视图下，Follow 将 RSS 订阅以不同的形式呈现。大多数的 RSS 阅读器，只提供了一个统一的视图，也就是文章视图。而 Follow 团队别出心裁的为各个视图设计不同的信息处理方式。</p>
<p>比如在“播客视图”，你会感觉 Follow 变成了一个优秀的播客播放器。有一个精致的播放器，展示 shownote，甚至支持点击 shownote 中时间轴节点跳转播放进度。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8271433574_105192.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1412/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8271433574_105192.png" alt="image.png"loading="lazy" decoding="async" width="1412" height="900" /></picture></figure></div><p>在“视频视图”，信息以视频封面呈现。点击视频，能够直接在 Follow 播放视频。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8271433189_096323.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1423/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8271433189_096323.png" alt="image.png"loading="lazy" decoding="async" width="1423" height="913" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8271433096_710176.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1423/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8271433096_710176.png" alt="image.png"loading="lazy" decoding="async" width="1423" height="913" /></picture></figure></div></li>
<li><p><strong>自动化</strong>
提供了丰富的自动化能力，比如AI摘要、翻译、重写和 Webhooks 等。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8271432811_207182.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_955/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8271432811_207182.png" alt="image.png"loading="lazy" decoding="async" width="955" height="783" /></picture></figure></div></li>
<li><p><strong>处于活跃开发阶段，反馈问题能够快速的处理</strong></p>
<p>Follow的开发者非常活跃，也有全职开发人员，问题处理的速度很快。有功能请求开发者也会积极考虑和开发。我反馈了一些问题都得到了回复和处理。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8271432652_514868.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1138/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8271432652_514868.png" alt="image.png"loading="lazy" decoding="async" width="1138" height="458" /></picture></figure></div></li>
</ul>
<h2>缺点？</h2>
<p>谈完了又优点，再来谈谈我认为的一些缺点。其实也不至于说是这款软件的缺点，只能说是我个人不是那么喜欢的地方。</p>
<ul>
<li><p><strong>默认索引用户订阅的站点，可能暴露付费RSS订阅或者私人订阅</strong>。目前，Follow 自动将用户的 RSS 订阅整合到其数据库中，并在其他用户搜索时显示。虽然这提高了用户体验，但也带来了隐私和安全风险。特别是对于私人RSS源（如Wallabag）或付费内容，即使选择了&quot;私人关注&quot;，它们仍可能被包含并被公开搜索。我向 Follow 反应了这个<a href="https://github.com/RSSNext/Follow/issues/283">问题</a>，但是遗憾的是开发团队认为这不是目前开发的重点。</p>
</li>
<li><p><strong>后端不是开源的，无法自部署</strong>。这一点就见仁见智，习惯了使用 FreshRSS，我确实有点贪心希望 Follow 能够自部署。我看到 Follow 团队正在<a href="https://x.com/follow_app_/status/1841328503863849172">招聘</a>全职开发、产品经理和市场营销专家。我猜测 Follow会发展成为一个付费服务，如果定价合理的话，我会愿意支持。希望Follow 团队能够越走越远。</p>
</li>
</ul>
<h2>展望</h2>
<ul>
<li>修正隐私问题，在维护互联网开放的精神同时，保护用户的隐私。克制合理地分享。</li>
<li>发布移动版本。</li>
</ul>
<h2>Follow内测邀请码</h2>
<p>如果你曾在 RSSHub 项目贡献过代码，你可以直接私信 DIYgod 或者 Follow 的X账号获取邀请码。</p>
<p>你也可以向内测用户获取邀请码，这里提供两个邀请码，先到先得，使用后请在评论区反馈。如果你很想参加内测，也可以直接评论，并且谈谈你对Follow 的看法，我会直接在评论回复邀请码。但是我的邀请码也十分有限（10天一个），只能尽量邀请。</p>
<ul>
<li><del>8i19XX0IQa</del> （已使用）</li>
<li><del>4d8Xv451u8</del>（已使用）</li>
</ul>
<hr />
<p>241024更新：现在 Follow 已经开始 Beta 测试，不用邀请码也能体验一些功能，但是会有一些限制。</p>
<ul>
<li><del>soGuIpSY1Q</del>（已使用）</li>
</ul>
<hr />
<p>241125更新：现在 Follow 网页终于支持移动端访问了，还支持PWA! 在墨水平板上也能使用，效果也很不错。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8267451348_119061.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1080/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8267451348_119061.jpg" alt="IMG_5900 (大).jpg"loading="lazy" decoding="async" width="1080" height="1440" /></picture></figure></div><ul>
<li><del>cMGg7BIhgy</del>（已使用）</li>
<li><del>Wa65ezWJTP</del>（已使用）</li>
</ul>
<hr />
<p>2025.02.14 更新的新邀请码：</p>
<ul>
<li><del>nkTrKI8ZPA</del>（已使用）</li>
<li><del>05C71sAN4L</del>（已使用）</li>
<li><del>QQUyUYGOJY</del>（已使用）</li>
</ul>
<hr />
<p>2025.03.01 更新</p>
<p>Follow 开始了 ios 内测，原生支持移动端了🎉</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8259207078_812886.jpg?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1290/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8259207078_812886.jpg" alt="IMG_8748.jpeg"loading="lazy" decoding="async" width="1290" height="2658" /></picture></figure></div><p>分享几个新的邀请码：</p>
<ul>
<li><del>8uEXAEpB6K</del>（已使用）</li>
<li><del>3xXiqHMCEj</del>（已使用）</li>
<li><del>BTmconUxsQ</del>（已使用）</li>
</ul>
<hr />
<p>2025.03.23 更新：Follow 正式发布 iOS 版本 Folo</p>
<p><a href="https://apps.apple.com/us/app/folo-follow-everything/id6739802604">https://apps.apple.com/us/app/folo-follow-everything/id6739802604</a></p>
<p>分享几个新的邀请码：</p>
<ul>
<li><del>fbsYJICV12</del>（已使用）</li>
<li><del>GgdjYNUTMz</del>（已使用）</li>
<li><del>K5GQEjXUHe</del>（已使用）</li>
<li><del>wxIoi5HpFE</del>（已使用）</li>
<li><del>sq_cuxWahO</del>（已使用）</li>
</ul>
<hr />
<p>欢迎在 Follow 上订阅本博客：<a href="https://app.follow.is/feed/53322153570297857">https://app.follow.is/feed/53322153570297857</a></p>
<p>我整理的 STEAM 教育硬件资讯列表：<a href="https://app.follow.is/share/lists/72173389013837824">https://app.follow.is/share/lists/72173389013837824</a></p>
<p>学习英语的播客列表：<a href="https://app.follow.is/share/lists/92088247676273664">https://app.follow.is/share/lists/92088247676273664</a></p>
]]></content:encoded></item><item><title><![CDATA[OpenAI Python API 新版本示例]]></title><guid>https://wulu.zone/posts/openai-api-py</guid><link>https://wulu.zone/posts/openai-api-py</link><description><![CDATA[迁移至 openai>=1.0.0]]></description><pubDate>Sun, 12 Nov 2023 08:20:10 +0000</pubDate><content:encoded><![CDATA[<p>最近升级了 OpenAI Python 包的最新版本。运行旧代码时出现编译错误：</p>
<div class="block-code"><pre><code>You tried to access openai.ChatCompletion, but this is no longer supported in openai&gt;=1.0.0 - see the README at https://github.com/openai/openai-python for the API.

You can run `openai migrate` to automatically upgrade your codebase to use the 1.0.0 interface.

Alternatively, you can pin your installation to the old version, e.g. `pip install openai==0.28`

A detailed migration guide is available here: https://github.com/openai/openai-python/discussions/742</code></pre></div>
<h2>openai&gt;=1.0.0 示例</h2>
<p>在查看了提示中<a href="https://github.com/openai/openai-python/discussions/742">迁移说明</a>的后，写一个基本示例来调用openai&gt;=1.0.0版本，供大家参考：</p>
<p>说明：代码中设置 <code>base_url</code> 以自定义主机，从而能够使用第三方 OpenAI 代理，这个选项的可选的，如果你使直接访问openai的服务，可以删除这一个配置。</p>
<div class="block-code" data-language="python"><div class="highlight"><pre><span></span><code><div class="line"><span class="kn">from</span> <span class="nn">openai</span> <span class="kn">import</span> <span class="n">OpenAI</span>
</div><div class="line">
</div><div class="line"><span class="n">client</span> <span class="o">=</span> <span class="n">OpenAI</span><span class="p">(</span>
</div><div class="line">  <span class="n">api_key</span><span class="o">=</span><span class="s2">&quot;xxx&quot;</span><span class="p">,</span>
</div><div class="line">  <span class="n">base_url</span> <span class="o">=</span> <span class="s1">&#39;xxx&#39;</span>
</div><div class="line"><span class="p">)</span>
</div><div class="line">
</div><div class="line"><span class="k">def</span> <span class="nf">get_completion</span><span class="p">(</span><span class="n">prompt</span><span class="p">,</span> <span class="n">model</span><span class="o">=</span><span class="s2">&quot;gpt-3.5-turbo-1106&quot;</span><span class="p">):</span>
</div><div class="line">    <span class="n">messages</span> <span class="o">=</span> <span class="p">[{</span><span class="s2">&quot;role&quot;</span><span class="p">:</span> <span class="s2">&quot;user&quot;</span><span class="p">,</span> <span class="s2">&quot;content&quot;</span><span class="p">:</span> <span class="n">prompt</span><span class="p">}]</span>
</div><div class="line">    <span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">completions</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</div><div class="line">        <span class="n">model</span><span class="o">=</span><span class="n">model</span><span class="p">,</span>
</div><div class="line">        <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</div><div class="line">        <span class="n">temperature</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span>
</div><div class="line">    <span class="p">)</span>
</div><div class="line">    <span class="k">return</span> <span class="n">response</span><span class="o">.</span><span class="n">choices</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">content</span>
</div><div class="line">
</div><div class="line"><span class="n">prompt</span> <span class="o">=</span> <span class="s2">&quot;你好，ChatGPT！&quot;</span>
</div><div class="line">
</div><div class="line"><span class="nb">print</span><span class="p">(</span><span class="n">get_completion</span><span class="p">(</span><span class="n">prompt</span><span class="p">))</span>
</div></code></pre></div>
</div>
<p>如果要启用 OpenAI 新推出的 <a href="https://platform.openai.com/docs/guides/text-generation/json-mode">JSON mode</a>：</p>
<div class="block-code" data-language="python"><div class="highlight"><pre><span></span><code><div class="line"><span class="k">def</span> <span class="nf">get_completion</span><span class="p">(</span><span class="n">prompt</span><span class="p">,</span> <span class="n">model</span><span class="o">=</span><span class="s2">&quot;gpt-3.5-turbo-1106&quot;</span><span class="p">):</span>
</div><div class="line">    <span class="n">messages</span> <span class="o">=</span> <span class="p">[{</span><span class="s2">&quot;role&quot;</span><span class="p">:</span> <span class="s2">&quot;user&quot;</span><span class="p">,</span> <span class="s2">&quot;content&quot;</span><span class="p">:</span> <span class="n">prompt</span><span class="p">}]</span>
</div><div class="line">    <span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">completions</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</div><div class="line">        <span class="n">model</span><span class="o">=</span><span class="n">model</span><span class="p">,</span>
</div><div class="line">        <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</div><div class="line hll">        <span class="n">response_format</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;type&quot;</span><span class="p">:</span> <span class="s2">&quot;json_object&quot;</span><span class="p">},</span>
</div><div class="line">        <span class="n">temperature</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span>
</div><div class="line">    <span class="p">)</span>
</div><div class="line">    <span class="k">return</span> <span class="n">response</span><span class="o">.</span><span class="n">choices</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">content</span>
</div></code></pre></div>
</div>
<h2>openai==0.28 示例</h2>
<div class="block-code" data-language="python"><div class="highlight"><pre><span></span><code><div class="line"><span class="kn">import</span> <span class="nn">openai</span>
</div><div class="line">
</div><div class="line"><span class="n">openai</span><span class="o">.</span><span class="n">api_key</span>  <span class="o">=</span> <span class="s1">&#39;&#39;</span>
</div><div class="line"><span class="n">openai</span><span class="o">.</span><span class="n">api_base</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span>
</div><div class="line">
</div><div class="line"><span class="k">def</span> <span class="nf">get_completion</span><span class="p">(</span><span class="n">prompt</span><span class="p">,</span> <span class="n">model</span><span class="o">=</span><span class="s2">&quot;gpt-3.5-turbo-1106&quot;</span><span class="p">):</span>
</div><div class="line">    <span class="n">messages</span> <span class="o">=</span> <span class="p">[{</span><span class="s2">&quot;role&quot;</span><span class="p">:</span> <span class="s2">&quot;user&quot;</span><span class="p">,</span> <span class="s2">&quot;content&quot;</span><span class="p">:</span> <span class="n">prompt</span><span class="p">}]</span>
</div><div class="line">    <span class="n">response</span> <span class="o">=</span> <span class="n">openai</span><span class="o">.</span><span class="n">ChatCompletion</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
</div><div class="line">        <span class="n">model</span><span class="o">=</span><span class="n">model</span><span class="p">,</span>
</div><div class="line">        <span class="n">messages</span><span class="o">=</span><span class="n">messages</span><span class="p">,</span>
</div><div class="line">        <span class="n">temperature</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span>  
</div><div class="line">    <span class="p">)</span>
</div><div class="line">    <span class="k">return</span> <span class="n">response</span><span class="o">.</span><span class="n">choices</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">message</span><span class="p">[</span><span class="s2">&quot;content&quot;</span><span class="p">]</span>
</div><div class="line">
</div><div class="line"><span class="n">prompt</span> <span class="o">=</span> <span class="s2">&quot;你好，ChatGPT！&quot;</span>
</div><div class="line">
</div><div class="line"><span class="nb">print</span><span class="p">(</span><span class="n">get_completion</span><span class="p">(</span><span class="n">prompt</span><span class="p">))</span>
</div></code></pre></div>
</div>
]]></content:encoded></item><item><title><![CDATA[使用HomeAssistant将米家设备接入到HomeKit]]></title><guid>https://wulu.zone/posts/mi-iot-homekit</guid><link>https://wulu.zone/posts/mi-iot-homekit</link><description><![CDATA[嘿Siri，开空调~]]></description><pubDate>Fri, 13 Oct 2023 17:34:30 +0000</pubDate><content:encoded><![CDATA[<div class="blockquote"><blockquote><p>【2024.12.17更新】：下文方法仍然可用，基于 Xiaomi Miot Atuo 集成。但近日小米发布了官方的<a href="https://github.com/XiaoMi/ha_xiaomi_home">Home Assistant 集成</a>，目前处于初期阶段，尚有一些问题。等版本稳定后，我会将下面的方法切换到米家官方集成。如果你感兴趣，可以在文末输入邮箱订阅本博客以获取更新。</p>
<p>【2025.05.10更新】：使用小米官方集成的教程已经写好了，请查看<a href="https://wulu.zone/posts/mi-iot-homekit-2025">《使用 Home Assistant 将米家设备接入 HomeKit 教程》</a></p>
</blockquote></div>
<p>最近把常用的米家设备都接入到了HomeKit，这样就可以通过Siri来控制住处中的智能设备了。</p>
<p>具体原理是：使用树莓派安装HomeAssistant，连接米家设备。通过 HomeAssistant 中的 HomeKit Bridge 集成，将米家设备桥接到 Apple HomeKit。这样就可以通过Apple的家庭应用和Siri来控制这些设备，即使它们不支持HomeKit。</p>
<p><strong>目录</strong></p>
<ul>
<li><a href="#install">1.安装HomeAssistant</a></li>
<li><a href="#install2">2.安装与配置 Home Assistant  社区商店</a><ul>
<li><a href="#install2.1">2.1安装 HACS</a></li>
<li><a href="#install2.2">2.2配置 HACS</a></li>
</ul>
</li>
<li><a href="#install3">3.将米家设备接入HomeAssistant</a><ul>
<li><a href="#install3.1">3.1安装 Xiaomi Miot Atuo</a></li>
<li><a href="#install3.2">3.2配置 Xiaomi Miot Atuo</a></li>
<li><a href="#install3.3">3.3删除不必要的实体（非必要，但强烈推荐）</a></li>
</ul>
</li>
<li><a href="#install4">4.桥接米家设备到HomeKit</a></li>
<li><a href="#5">5.常见问题</a></li>
</ul>
<p><strong>我的树莓派配置</strong></p>
<div class="block-code"><pre><code>Raspberry Pi 4b 4gb
OS: OpenWrt
Kernel: aarch64 Linux 5.4.203</code></pre></div>
<p><a id="install"></a></p>
<h2>1. 安装HomeAssistant</h2>
<p>HomeAssistant <a href="https://www.home-assistant.io/installation/raspberrypi">支持多种安装方式</a>，对于树莓派来说，大致有三种方法：</p>
<ol>
<li>安装 Assistant 操作系统</li>
<li>使用容器安装（比如Docker）</li>
<li>直接安装Home Assistant Core</li>
</ol>
<p>为了便于管理，我选择使用Docker-compose来安装HomeAssistant。</p>
<p>如果你和我一样使用的是<code>openwrt</code>系统，参考<a href="https://www.home-assistant.io/installation/raspberrypi#docker-compose">官方教程</a>，你可能会遇到以下错误：</p>
<div class="block-code"><pre><code>[+] Running 0/1
 ⠿ Container homeassistant  Starting                                                                             0.3s
Error response from daemon: error while creating mount source path '/etc/localtime': mkdir /etc/localtime: file exists</code></pre></div>
<p>错误的原因在 <a href="https://community.home-assistant.io/t/solved-ha-installation-in-openwrt-using-dockers/262262">HomeAssistant论坛</a> 可以找到。这里是我解决问题的方法：删除原<code>.yml</code>文件中<code>- /etc/localtime:/etc/localtime:ro</code>，将时区作为环境变量传递。</p>
<p>修改后的<code>docker-compose.yml</code>：</p>
<div class="block-code" data-language="yaml"><div class="code-head"><pre class="filename">~/homeas/docker-compose.yml</pre></div>
<div class="highlight"><pre><span></span><code><div class="line"><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="s">&#39;3&#39;</span><span class="w"></span>
</div><div class="line"><span class="nt">services</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">  </span><span class="nt">homeassistant</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">homeassistant</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;ghcr.io/home-assistant/home-assistant:stable&quot;</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TZ=Asia/Shanghai</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">      </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">~/homeas/config:/config</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">unless-stopped</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">privileged</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span><span class="w"></span>
</div><div class="line"><span class="w">    </span><span class="nt">network_mode</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">host</span><span class="w"></span>
</div></code></pre></div>
</div>
<p>安装完HomeAssistant后，访问树莓派的 <strong>8123</strong> 端口。初始化HomeAssistant，设置管理员账号密码。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302796087_438843.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_895/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302796087_438843.png" alt="初始化HA.png"loading="lazy" decoding="async" width="895" height="644" /></picture></figure></div><p><a id="install2"></a></p>
<h2>2. 安装与配置 Home Assistant  社区商店</h2>
<p><a id="install2.1"></a></p>
<h3>2.1 安装 HACS</h3>
<p>配置完 HomeAssistant 后，我们需要安装 <a href="https://hacs.xyz/">HACS（Home Assistant Community Store）</a>。你可以将其理解为 HomeAssistant 的应用商店，通过 HACS 我们能够安装第三方集成来增强 HomeAssistant 的功能。</p>
<p>参考 <a href="https://hacs.xyz/docs/setup/download/">HACS安装指南</a>，我们需要进入容器内部执行安装脚本。</p>
<div class="block-code" data-language="bash"><div class="code-head"><pre class="filename">~/homeas/</pre></div>
<div class="highlight"><pre><span></span><code><div class="line">docker <span class="nb">exec</span> -it homeassistant bash
</div><div class="line">wget -O - https://get.hacs.xyz <span class="p">|</span> bash -
</div></code></pre></div>
</div>
<p>安装成功后，退出容器，然后重启容器。<strong>这一步骤很重要，配置HACS前必须重启Home Assistant。</strong></p>
<div class="block-code" data-language="bash"><div class="code-head"><pre class="filename">~/homeas/</pre></div>
<div class="highlight"><pre><span></span><code><div class="line"><span class="nb">exit</span>
</div><div class="line">docker-compose restart
</div></code></pre></div>
</div>
<p><a id="install2.2"></a></p>
<h3>2.2 配置 HACS</h3>
<p>接下来我们需要初始HACS，你可以参考<a href="https://hacs.xyz/docs/configuration/basic">此教程</a>或按照下图步骤配置。注意，你需要提前注册一个 <a href="https://github.com/">Github</a> 账号。</p>
<p>在“设置”中打开“设备与服务”</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302793775_068366.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_876/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302793775_068366.png" alt="安装HACS1.png"loading="lazy" decoding="async" width="876" height="664" /></picture></figure></div><p>点击“添加集成”，搜索并选择“HACS”</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302793774_901773.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_895/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302793774_901773.png" alt="安装HACS3.png"loading="lazy" decoding="async" width="895" height="666" /></picture></figure></div><p>跟据指引一步一步操作，打开提示中的网址，登录GitHub，输入授权码。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302793380_755269.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_639/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302793380_755269.png" alt="image.png"loading="lazy" decoding="async" width="639" height="300" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302793775_071568.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_895/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302793775_071568.png" alt="安装HACS4.png"loading="lazy" decoding="async" width="895" height="667" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302793775_060922.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_895/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302793775_060922.png" alt="安装HACS5.png"loading="lazy" decoding="async" width="895" height="666" /></picture></figure></div><p>看到下图界面，就说明HACS以及安装成功了。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302793775_066552.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_895/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302793775_066552.png" alt="安装HACS6.png"loading="lazy" decoding="async" width="895" height="663" /></picture></figure></div><p><a id="install3"></a></p>
<h2>3. 将米家设备接入HomeAssistant</h2>
<p><a id="install3.1"></a></p>
<h3>3.1 安装 Xiaomi Miot Atuo</h3>
<p>接下来，我们需要安装 “Xiaomi Miot Atuo” 集成以将米家设备接入HomeAssistant。</p>
<p>进入 HACS 页面，点击 “集成”。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302791733_035404.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_901/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302791733_035404.png" alt="安装MIIOT.png"loading="lazy" decoding="async" width="901" height="683" /></picture></figure></div><p>点击右下角的“浏览并下载储存库”，然后搜索并安装“Xiaomi Miot Atuo”。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302791733_034981.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_901/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302791733_034981.png" alt="安装MIIOT2.png"loading="lazy" decoding="async" width="901" height="684" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302791733_03169.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_901/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302791733_03169.png" alt="安装MIIOT3.png"loading="lazy" decoding="async" width="901" height="684" /></picture></figure></div><p>同样地，安装完集成之后需要重启 HomeAssistant。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302791733_031982.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_901/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302791733_031982.png" alt="安装MIIOT4.png"loading="lazy" decoding="async" width="901" height="683" /></picture></figure></div><div class="block-code" data-language="bash"><div class="code-head"><pre class="filename">~/homeas/</pre></div>
<div class="highlight"><pre><span></span><code><div class="line">docker-compose restart
</div></code></pre></div>
</div>
<p><a id="install3.2"></a></p>
<h3>3.2 配置 Xiaomi Miot Atuo</h3>
<p>接下来，我们配置 Xiaomi Miot Atuo 将米家设备接入HomeAssistant。<strong>注意，配置 Xiaomi Miot Atuo 前需要重启 HomeAssistant。</strong></p>
<p>点击“设置”，选择“设备与服务”</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302793775_068366.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_876/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302793775_068366.png" alt="安装HACS1.png"loading="lazy" decoding="async" width="876" height="664" /></picture></figure></div><p>切换到 “设备” ， 然后点击 “添加设备”</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302790493_390191.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_901/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302790493_390191.png" alt="配置MIIOT.png"loading="lazy" decoding="async" width="901" height="682" /></picture></figure></div><p>搜索并选择“Xiaomi Miot Atuo”</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302790493_388063.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_901/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302790493_388063.png" alt="配置MIIOT2.png"loading="lazy" decoding="async" width="901" height="684" /></picture></figure></div><p>选择“账号集成”，登录小米账号获取设备信息。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302790493_39134.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_901/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302790493_39134.png" alt="配置MIIOT3.png"loading="lazy" decoding="async" width="901" height="683" /></picture></figure></div><p>按照配置指引完成剩余步骤，选择你想要接入 HomeAssistant 的设备。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302790493_385441.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_901/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302790493_385441.png" alt="配置MIIOT4.png"loading="lazy" decoding="async" width="901" height="684" /></picture></figure></div><p><a id="install3.3"></a></p>
<h3>3.3 删除不必要的实体（非必要，但强烈推荐）</h3>
<p>在将米家设备桥接到HomeKit之前，建议禁用一些不必要的实体。否则可能会出现以下情况：例如，当将小米智能插座添加到homekit时，插座会被识别为三个设备，除了开关之外，其中插座的指示灯被识别为灯具，插座温度也被误认为环境温度传感器。这可能不是我们期望看到的结果。</p>
<p>以我浴室的智能开关为例，切换到“实体注册表”。找到对应的实体，我的智能开关名为“浴室热水器”，对应指示灯的实体就是“浴室热水器 Indicator Light”，点击这个实体。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302789020_570658.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302789020_570658.png" alt="禁用实体.png"loading="lazy" decoding="async" width="1300" height="758" /></picture></figure></div><p>点击右上角“设置”按钮</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302789020_570467.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302789020_570467.png" alt="禁用实体2.png"loading="lazy" decoding="async" width="1300" height="756" /></picture></figure></div><p>关闭“已启用”，将这个实体禁用。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302786199_064772.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302786199_064772.png" alt="禁用实体3.png"loading="lazy" decoding="async" width="1300" height="756" /></picture></figure></div><p>以此类推，你可禁用掉所有不必要的实体。</p>
<p><a id="install4"></a></p>
<h2>4. 桥接米家设备到HomeKit</h2>
<p>接下来，我们通过 HomeKit Bridge 将 Home Assistant 中设备桥接到 HomeKit。</p>
<p>首先，我们要添加 HomeKit Bridge 集成。点击“设置”，进入“设备与服务”页面。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302793775_068366.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_876/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302793775_068366.png" alt="安装HACS1.png"loading="lazy" decoding="async" width="876" height="664" /></picture></figure></div><p>搜索“homekit”，点击“Apple”</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302785845_410344.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1265/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302785845_410344.png" alt="桥接homekit.png"loading="lazy" decoding="async" width="1265" height="757" /></picture></figure></div><p>点击添加“HomeKit Bridge 集成”，按照指引完成添加。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302785845_420177.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1265/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302785845_420177.png" alt="桥接homekit2.png"loading="lazy" decoding="async" width="1265" height="757" /></picture></figure></div><p>需要注意是的，如果你有温湿度传感器，记得勾选“Sensor”，这个选项默认是不勾选的。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302785845_40595.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1265/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302785845_40595.png" alt="桥接homekit3.png"loading="lazy" decoding="async" width="1265" height="756" /></picture></figure></div><p>添加 HomeKit Bridge 集成成功后，点击界面左下角的通知按钮。查看 homekit 的配对二维码。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302785845_42004.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1265/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302785845_42004.png" alt="桥接homekit4.png"loading="lazy" decoding="async" width="1265" height="757" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8302785845_415117.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1265/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302785845_415117.png" alt="桥接homekit5.png"loading="lazy" decoding="async" width="1265" height="759" /></picture></figure></div><p>打开“家庭”应用，点击左上角的“+”号，选择“添加配件”。扫描上个步骤的得到的二维码，点击“添加到家庭”。在加入过程中，可能会提示“未认证设备”，点击“仍要添加”。然后完成剩余步骤，逐个添加设备。完成后，你就能能用Siri控制你的智能设备了。</p>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8302785845_413984.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1290/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302785845_413984.png" alt="桥接homekit6.png"loading="lazy" decoding="async" width="1290" height="2796" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8302785845_405751.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1290/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302785845_405751.png" alt="桥接homekit7.png"loading="lazy" decoding="async" width="1290" height="2796" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8302785845_417304.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1290/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8302785845_417304.png" alt="桥接homekit8.png"loading="lazy" decoding="async" width="1290" height="2796" /></picture></figure></div></div>
<p>大功告成！🎉</p>
<p><a id="5"></a></p>
<h2>5. 常见问题</h2>
<p><strong>Siri 回复设备没有回应？</strong></p>
<p>通过上述方法添加设备后，只能在同一局域网内控制该设备。如果出现这种情况，请检查手机是否连接到家庭网络，并进一步确认 HomeAssistant 服务状态是否正常。</p>
<p><strong>米家空调伴侣导致环境温度错误？</strong></p>
<p><a href="https://github.com/al-one/hass-xiaomi-miot/issues/800">https://github.com/al-one/hass-xiaomi-miot/issues/800</a></p>
<p>我通过修改配置文件解决这个问题：</p>
<ol>
<li>在<code>config</code>目录下的<code>configuration.yaml</code>添加下面内容：</li>
</ol>
<div class="block-code" data-language="yaml"><div class="code-head"><pre class="filename">~/homeas/config/configuration.yaml</pre></div>
<div class="highlight"><pre><span></span><code><div class="line"><span class="nt">homeassistant</span><span class="p">:</span><span class="w"></span>
</div><div class="line"><span class="w">  </span><span class="nt">customize</span><span class="p">:</span><span class="w"> </span><span class="kt">!include</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">customize.yaml</span><span class="w"></span>
</div></code></pre></div>
</div>
<ol start="2">
<li>在config目录下创建<code>customize.yaml</code>，将温度传感器绑定到空调伴侣实体。对应的设备名称和实体名称需要根据实际情况调整（在“设置-设备与服务-实体注册表”中可以得到）：</li>
</ol>
<div class="block-code" data-language="yaml"><div class="code-head"><pre class="filename">~/homeas/config/customize.yaml</pre></div>
<div class="highlight"><pre><span></span><code><div class="line"><span class="nt">climate.lumi_mcn02_d045_air_conditioner</span><span class="p">:</span><span class="w">    </span><span class="c1"># 空调伴侣实体ID</span><span class="w"></span>
</div><div class="line"><span class="w">  </span><span class="nt">bind_sensor</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">sensor.miaomiaoce_t2_0b9e_temperature_humidity_sensor</span><span class="w">    </span><span class="c1">#温度传感器实体ID</span><span class="w"></span>
</div></code></pre></div>
</div>
<ol start="3">
<li>重启 HomeAssistant</li>
</ol>
<div class="block-code" data-language="bash"><div class="code-head"><pre class="filename">~/homeas/</pre></div>
<div class="highlight"><pre><span></span><code><div class="line">docker-compose restart
</div></code></pre></div>
</div>
<p><strong>其他问题</strong></p>
<p>欢迎在评论区讨论</p>
]]></content:encoded></item><item><title><![CDATA[AutoHotkey 脚本实现一键复制文本到 ChatGPT 提示模板]]></title><guid>https://wulu.zone/posts/chatgpt-ahk</guid><link>https://wulu.zone/posts/chatgpt-ahk</link><description><![CDATA[AutoHotkey 实用技巧：自动复制文本到 ChatGPT 模板]]></description><pubDate>Tue, 12 Sep 2023 15:08:59 +0000</pubDate><content:encoded><![CDATA[<p>在使用ChatGPT时，常常需要借助各种提示（prompt）模板。对于翻译工作，我通常使用以下模板：</p>
<div class="block-code" data-language="text"><div class="highlight"><pre><span></span><code><div class="line">我希望你能担任英语翻译、拼写校对和修辞改进的角色。
</div><div class="line">我会用任何语言和你交流，你会识别语言，将其翻译并用更为优美和精炼的英语回答我。
</div><div class="line">请将我简单的词汇和句子替换成更为优美和高雅的表达方式，确保意思不变，但使其更具文学性。
</div><div class="line">请仅回答更正和改进的部分，不要写解释。
</div><div class="line">我提供的文本遵循Markdown格式，请不要修改我的格式。
</div><div class="line">你的回复应该以```开始```结束。
</div><div class="line">
</div><div class="line">这是我的第一个文本：
</div><div class="line">
</div><div class="line hll">&lt;需要翻译的内容&gt;
</div></code></pre></div>
</div>
<p>尽管ChatGPT的网页版具备持续对话的能力，只需在对话开始时输入上面提示模板，之后就无需再次输入，ChatGPT会理解你后面发给它的内容是需要翻译的。然而，由于对话的上下文长度是有限的，随着对话长了以后，ChatGPT可能会在后续对话中&quot;遗忘&quot;前面的内容，并将需要翻译的内容误认为是与它的对话内容。</p>
<p>因此，我更倾向于将模板放置在文本编辑器中，每次将待翻译的内容替换到提示词模板中，然后将完整的提示词发给ChatGPT。不过，当需要翻译多个文本时，就需要不断复制要翻译的内容、替换模板、然后粘贴，操作很繁琐。</p>
<p>于是，我想到使用AutoHotkey（AHK）来实现：<strong>每当我选中文本并使用Ctrl+C复制后，自动将复制的内容替换到提示模板中，并更新剪贴板。这样，在粘贴时就能直接发送给ChatGPT了。</strong> 通过这种方式省去了手动替换文本到模板步骤，提高效率。</p>
<p>效果如下：</p>
<img src="https://i.typlog.com/wulu/8305473864_453348.gif" alt="使用效果" style="max-width: 70%;">

<h3>什么是AutoHotkey（AHK）？</h3>
<p><a href="https://www.autohotkey.com/">AutoHotkey</a> 是一种免费的开源脚本编程语言和自动化工具，用于创建自定义脚本和宏来自动化计算机任务和增强工作流程。它支持自定义快捷键、鼠标动作、窗口操作等，并可以与其他应用程序交互。它简单易用，适用于Windows系统，可提高效率和简化重复任务。</p>
<h3>编写ank脚本</h3>
<p>下载并安装AutoHotkey（AHK）后，新建一个<code>.ahk</code>文件（例如<code>chatgpt_copy.ahk</code>），并使用你喜欢的文本编辑器进行编辑。Windows自带的记事本也可以，但我推荐使用VScode。将<a href="https://gist.github.com/eMUQI/3d3eaf5241ab6dff32283fecd7eeb899">此gist</a>内容复制到该文件中即可：</p>
<p><a href="https://gist.github.com/eMUQI/3d3eaf5241ab6dff32283fecd7eeb899">https://gist.github.com/eMUQI/3d3eaf5241ab6dff32283fecd7eeb899</a></p>
<p>这个脚本绑定了Ctrl+Shift+C快捷键。当你按下这个快捷键时，它会执行以下操作：</p>
<ol>
<li>复制选中的文本到剪贴板。</li>
<li>将剪贴板的内容插入到模板中的相应位置。</li>
<li>更新剪贴板内容为最终的文本。</li>
</ol>
<p>如果你要修改代码，关于代码的说明：</p>
<ol>
<li>为了避免破坏原来<code>Ctrl + C</code>的体验，我设置激活的按钮为<code>Ctrl + Shift + C</code>。如需修改，参考：<a href="https://www.autohotkey.com/docs/v1/Hotkeys.htm">AHK - How to Write Hotkeys</a></li>
<li>在 AutoHotkey 的脚本中，如果你需要在字符串里表示一个反引号（`），你需要使用两个反引号（``）来转义它。</li>
<li><code>;</code>分号后的内容是注释。</li>
</ol>
<h3>运行ank脚本</h3>
<p>由于文本编码问题，编写完脚本之后记得<strong>打开 AutoHotkey ，进入设置页面，勾选&quot;default to UTF-8 even for v1 scripts&quot;</strong>。否则粘贴出来的文本会变成乱码。</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8305474719_412026.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_791/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8305474719_412026.png" alt="ank-set-1.png"loading="lazy" decoding="async" width="791" height="347" /></picture></figure></div><div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8305474714_119097.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_473/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8305474714_119097.png" alt="ank-set-2.png"loading="lazy" decoding="async" width="473" height="355" /></picture></figure></div><p>完成了以上步骤后，只需<strong>双击<code>.ahk</code>文件</strong>即可运行。程序会在右下角的系统托盘中显示其正在运行。</p>
]]></content:encoded></item><item><title><![CDATA[开放课程推荐 「面向开发者的 ChatGPT 提示词工程」]]></title><guid>https://wulu.zone/posts/ChatGPT-Prompt-Engineering-for-Developers-in-Chinese</guid><link>https://wulu.zone/posts/ChatGPT-Prompt-Engineering-for-Developers-in-Chinese</link><pubDate>Mon, 12 Jun 2023 14:16:45 +0000</pubDate><content:encoded><![CDATA[<div class="blockquote"><blockquote><p>ChatGPT 上线至今已经有一段时间了，但是不少人还没真正掌握它的使用技巧。</p>
<p>其实，ChatGPT 的难点，在于 Prompt（提示词）的编写，OpenAI 创始人在今年 2 月时，在 Twitter 上说：「能够出色编写 Prompt 跟聊天机器人对话，是一项能令人惊艳的高杠杆技能」。</p>
<p>因为从 ChatGPT 发布之后，如何写好 Prompt 已经成为了一个分水岭。熟练掌握 Prompt 编写的人，能够很快让 ChatGPT 理解需求，并很好的执行任务。</p>
<p>目前你在网上看到的所有 AI 助理、智能翻译、角色扮演，本质上还是通过编写 Prompt 来实现。</p>
<p>只要你的 Prompt 写的足够好，ChatGPT 可以帮你快速完成很多工作，包括写爬虫脚本、金融数据分析、文案润色与翻译等等，并且这些工作还做的比一般人出色。</p>
<p>为了帮助大家能更好的掌握 Prompt 工程，DeepLearning.ai 创始人吴恩达与 OpenAI 开发者 Iza Fulford 联手推出了一门面向开发者的技术教程：<a href="https://learn.deeplearning.ai/">《ChatGPT 提示工程》</a>。</p>
<p>--- <a href="https://github.com/GitHubDaily/ChatGPT-Prompt-Engineering-for-Developers-in-Chinese">https://github.com/GitHubDaily/ChatGPT-Prompt-Engineering-for-Developers-in-Chinese</a></p>
</blockquote></div>
<p>ChatGPT的难点在于Prompt（提示词）的编写，熟练掌握Prompt编写的人能够很快让ChatGPT理解需求，并很好地执行任务。为了帮助开发者更好地掌握Prompt工程，吴恩达与OpenAI联手推出了一门面向开发者的技术教程《ChatGPT提示工程》。</p>
<p>虽然这门课程已经推出一段时间了，但我最近才开始学习。学完确实受益匪浅，推荐给大家。<strong>课程介绍了大型语言模型时的提示原则和相关策略，并提供了每个策略的实例。</strong>可在 <a href="deeplearning.ai">deeplearning.ai</a> 平台上学习，<strong>并提供预置OpenAI Key的Jupyter Notebook环境</strong>。可以边观看视频边使用Jupyter Notebook运行课程中的代码实例。</p>
<p>如果你觉得全英文视频有些吃力，也可以查看<a href="https://github.com/GitHubDaily/ChatGPT-Prompt-Engineering-for-Developers-in-Chinese">这个项目</a>，在<a href="https://space.bilibili.com/15467823/channel/collectiondetail?sid=1354861">B站</a>上传了相关视频并提供中英文字幕。即使你是跟着B站的课程学习，<strong>依然强烈建议跟着视频在 <a href="deeplearning.ai">deeplearning.ai</a> 平台上运行课程案例。</strong></p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8313420314_331628.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800/format,webp 1x, https://i.typlog.com/wulu/8313420314_331628.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600/format,webp 2x" media="(min-width: 800px)" type="image/webp"><source srcset="https://i.typlog.com/wulu/8313420314_331628.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_800 1x, https://i.typlog.com/wulu/8313420314_331628.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1600 2x" media="(min-width: 800px)"><img src="https://i.typlog.com/wulu/8313420314_331628.png" alt="image.png"loading="lazy" decoding="async" width="1920" height="932" /></picture></figure></div><ul>
<li><strong>中文视频地址</strong>：<a href="https://www.bilibili.com/video/BV1s24y1F7eq/">面向开发者的 ChatGPT 提示词工程</a></li>
<li><strong>英文原视频地址</strong>：<a href="https://learn.deeplearning.ai/">ChatGPT Prompt Engineering for Developers</a></li>
</ul>
<h2>课程大纲与笔记</h2>
<p><strong>建议至少学习完第一章</strong>，以下是我整理的课程大纲与笔记：</p>
<p>访问链接：<a href="https://www.mubucm.com/doc/4cB6bOjmGP">《ChatGPT Prompt Engineering for Developers-大纲&amp;笔记》</a></p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8313421821_677766.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_975/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8313421821_677766.png" alt="ChatGPT Prompt Engineering for Developers-大纲&amp;amp;笔记.png"loading="lazy" decoding="async" width="975" height="3666" /></picture></figure></div><h2>相关文章</h2>
<p><a href="https://wulu.zone/posts/API2D">https://wulu.zone/posts/API2D</a></p>
]]></content:encoded></item><item><title><![CDATA[指定 Whisper 输出为简体中文]]></title><guid>https://wulu.zone/posts/whisper-cn</guid><link>https://wulu.zone/posts/whisper-cn</link><pubDate>Tue, 16 May 2023 15:29:57 +0000</pubDate><content:encoded><![CDATA[<div class="blockquote"><blockquote><p><a href="https://github.com/openai/whisper">Whisper</a>是OpenAI推出的一种开源语音识别模型，能够自动识别多种语言，将音频转换文字。Whisper由python实现，同时拥有丰富的社区支持。除了原始的Whisper之外，还有一些相关的项目，有移植到 C/C++的<a href="https://github.com/ggerganov/whisper.cpp">whisper.cpp</a>和能使用GPU加速的<a href="https://github.com/guillaumekln/faster-whisper">faster-whisper</a>。如果你不懂编程或者不熟悉命令行，也有也有很多开发者开发了图形界面，比如<a href="https://github.com/chidiwilliams/buzz">buzz</a>和<a href="https://github.com/Const-me/Whisper">Const-me/Whisper</a>等。</p>
</blockquote></div>
<p><a href="https://github.com/openai/whisper">Whisper</a> 支持直接输出srt格式的字幕文件。我最近用 <a href="https://github.com/openai/whisper">Whisper</a> 生成字幕文件，再配合ChatGPT 使用<a href="https://github.com/machinewrapped/gpt-subtrans">GPT-Subtrans</a> 翻译字幕，整体效果很好。不过， <a href="https://github.com/openai/whisper">Whisper</a>有一个问题，就是<a href="https://github.com/openai/whisper">Whisper</a> 使用<code>--language</code>来指定语言，但无论是简体中文还是繁体中文，对应的代码都是<code>zh</code>。很多情况下，使用<a href="https://github.com/openai/whisper">Whisper</a> 生成字幕文件，设置参数<code>--language zh</code>，会生成繁体中文的字幕文件。</p>
<h2>解决方案</h2>
<p>在网上终于查到解决方案，分享给大家。 在 Whisper 的<a href="https://github.com/openai/whisper/discussions/277">讨论区</a>中，<a href="https://github.com/jongwook">@jongwook</a> 提出：</p>
<ol>
<li>使用 <code>--initial_prompt</code> 参数，用简体中文输入 <code>&quot;以下是普通话的句子。&quot;</code> 就能生成简体中文字幕。（补充：whisper.cpp 用户可以尝试使用<code>--prompt</code>参数）</li>
<li>以此类推，用繁体中文输入 <code>&quot;以下是普通話的句子。&quot;</code> 就能得到繁体字幕。</li>
</ol>
<div class="block-code"><pre><code>$ whisper --language Chinese --model large audio.wav
[00:00.000 --&gt; 00:08.000] 如果他们使用航空的方式运输货物在某些航线上可能要花几天的时间才能卸货和通关
$ whisper --language Chinese --model large audio.wav --initial_prompt &quot;以下是普通話的句子。&quot;  # traditional
[00:00.000 --&gt; 00:08.000] 如果他們使用航空的方式運輸貨物,在某些航線上可能要花幾天的時間才能卸貨和通關。
$ whisper --language Chinese --model large audio.wav --initial_prompt &quot;以下是普通话的句子。&quot;  # simplified
[00:00.000 --&gt; 00:08.000] 如果他们使用航空的方式运输货物,在某些航线上可能要花几天的时间才能卸货和通关。</code></pre></div>
<p>另外，有关 <code>--initial_prompt</code> 参数，可在 <a href="https://platform.openai.com/docs/guides/speech-to-text/prompting">openai的文档</a> 查看更多。其中也提到  &quot;有些语言可以用不同的方式书写，比如简体或繁体中文。模型可能默认不会使用你想要的转录写作风格。你可以通过使用你偏好的写作风格的提示来改善这一点。&quot;。</p>
]]></content:encoded></item><item><title><![CDATA[Api2d 国内可用的chatgpt api代理]]></title><guid>https://wulu.zone/posts/API2D</guid><link>https://wulu.zone/posts/API2D</link><description><![CDATA[国内可用chatgpt接口-api2d]]></description><pubDate>Sun, 16 Apr 2023 14:46:45 +0000</pubDate><content:encoded><![CDATA[<div class="blockquote"><blockquote><p>前言：AI技术的普及和应用，让我们的生活更加便捷和愉悦。尤其是近期火热的ChatGPT，在自然语言交互等方面，已经取得了很重要的突破。然而，由于诸多因素的影响，使用ChatGPT在国内变得越来越困难。希望通过这篇博客，让更多的人了解到 <a href="https://api2d.com/r/192523">API2D</a> 这个很好的ChatGPT 访问方案，让大家都能受益于AI技术的进步。</p>
</blockquote></div>
<h2>api2d 是什么？与ChatGPT是什么关系？</h2>
<p>最近openai开始封禁亚洲用户的账号还有部分机房ip，使得在国内使用ChatGPT越来越难。再加上ChatGPT本来注册就有一定门槛，付费也不方便，只能用美国本地的银行卡支付。</p>
<p>找到一个替代方案：<a href="https://api2d.com/r/192523">API2D</a> 。<a href="https://api2d.com/r/192523">API2D</a> 是一个集成OpenAI接口的工具，为用户提供国内可用的API支持，而且还支持微信支付。它实质上为一个国内可用的ChatGPT API代理，会将请求转发到ChatGPT api，再将结果返回给用户。由于api2d的使用方式与chatgpt基本一致，只要应用程序支持设置OpenAI API Host，就可以轻松地使用。</p>
<p>更多详细信息可以查看他们的<a href="https://api2d.com/r/192523">官网</a>。这篇文章主要介绍两个最重要的地方：1. 价格 2. 使用方法。3. 支持ChatGPT 4.0</p>
<ol>
<li><strong>价格</strong>。<a href="https://api2d.com/r/192523">API2D</a>按实际使用的Token数量收费，聊天接口价格大约为OpenAI的1.5倍（考虑到国内可以支付和使用，还可以接受）。<a href="https://api2d.com/r/192523">API2D</a> 使用P作为计费单位，1P=100token，每次调用最低消耗1P。<strong>建议通过Github账号注册，这样能够获得50P的免费点数。</strong>
<img src="https://i.typlog.com/wulu/8318350825_854592.png" alt="image.png" /></li>
</ol>
<p>2.使用方法。对于用户来说，找支持填写第三方OpenAI API Host的应用。填入<code>https://openai.api2d.net/</code>和api2d的<code>forwardkey</code>。对于开发者来说，<a href="https://api2d.com/r/192523">API2D</a> 提供了开发者文档。</p>
<h2>利用api2d快速搭建一个属于自己的ChatGPT网站</h2>
<ol>
<li><strong>注册 <a href="https://api2d.com/r/192523">api2d</a></strong>。
注册没什么特别的。有一点需要注意：<strong>注册的时候建议使用github账户注册，可以获得50P（相当5000token）的额度。</strong></li>
<li><strong>搭建 <a href="https://github.com/Yidadaa/ChatGPT-Next-Web">ChatGPT-Next-Web</a></strong>。毕竟api是无法直接使用的，所以需要搭建一个网页应用来使用ChatGPT。ChatGPT-Next-Web 是一个支持 chatgpt api 私人 ChatGPT 网页应用。具体可以查看他的<a href="https://github.com/Yidadaa/ChatGPT-Next-Web">中文文档</a>。使用 Vercel 可以免费部署。参考链接：<a href="https://github.com/Yidadaa/ChatGPT-Next-Web/blob/main/docs/vercel-cn.md#%E5%A6%82%E4%BD%95%E6%96%B0%E5%BB%BA%E9%A1%B9%E7%9B%AE">如何在Vercel搭建ChatGPT-Next-Web/</a>。需要注意的是，设置环境变量步骤时，需要额外添加环境变量<code>BASE_URL</code>，值设为<code>stream.api2d.net</code>。设置<code>OPENAI_API_KEY</code>的值为api2d的<code>forwardkey</code>。最后，一定要设置<code>CODE</code>变量，不然别人就能用你的api访问chatgpt，<code>CODE</code>是 ChatGPT-Next-Web 的访问密码，设置了访问密码后，在设置页面填入密码就能使用。
<img src="https://i.typlog.com/wulu/8318349660_383815.png" alt="image.png" /></li>
<li><strong>绑定域名</strong>。如果你有域名，强烈<strong>建议绑定自己的域名</strong>，然后删掉Vercel分配给你的域名访问。Vercel 分配的域名 DNS 在某些区域被污染了，绑定自定义域名即可直连，而且有些人会根据 Vercel 提供域名的规律找到你的域名然后爆破。绑定域名也很简单。在 Vercel 项目设置添加域名，按照指引添加一条CNAME记录即可。</li>
</ol>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8318344407_21591.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_1319/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8318344407_21591.png" alt="image.png"loading="lazy" decoding="async" width="1319" height="347" /></picture></figure></div><h2>api2d还能做什么？</h2>
<p>只要应用程序支持设置OpenAI API Host，就可以轻松地使用。如下图的开源项目 <a href="https://github.com/usememos/memos">memos</a>。
<img src="https://i.typlog.com/wulu/8318344257_045887.png" alt="image.png" /></p>
<p>更多项目在<a href="https://api2d.com/r/192523">api2d</a>的官网找到：</p>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8318344115_87062.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_900/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8318344115_87062.png" alt="image.png"loading="lazy" decoding="async" width="900" height="686" /></picture></figure></div>]]></content:encoded></item><item><title><![CDATA[利用chatgpt实现编程想法的实践-PyPower]]></title><guid>https://wulu.zone/posts/pypower-chagpt</guid><link>https://wulu.zone/posts/pypower-chagpt</link><pubDate>Wed, 22 Mar 2023 14:25:41 +0000</pubDate><content:encoded><![CDATA[<p><a href="https://github.com/eMUQI/PyPower">https://github.com/eMUQI/PyPower</a></p>
<div class="photo"><figure><picture><source srcset="https://raw.githubusercontent.com/eMUQI/PyPower/main/demo.png" type="image/webp"><img src="https://raw.githubusercontent.com/eMUQI/PyPower/main/demo.png" alt="PyPower"loading="lazy" decoding="async" width="846" height="453" /></picture></figure></div><p>使用chatgpt一段时间后，萌生了一个想法：利用chatgpt辅助我编程。</p>
<p>大致需求是通过运行在树莓派上的网页服务来控制Windows主机关机，同时还可让树莓派发送<code>wakeonlan</code>数据包唤醒Windows电脑。最终实现的效果见上方链接。</p>
<h2>代码编写过程</h2>
<p>通过了好几天，数十次对话，终于把程序写出了。由于没有经验，这样一个简单的功能花了好几天的空闲时间才完成，中间数次向chatgpt请教网页知识。而且还不断调整需求。</p>
<p>下面是几个主要的提问：</p>
<ol>
<li>“如何实现利用python远程控制Windows电脑开机和关机。通过网络（局域网内）来控制，需要服务端是Windows，客户端是任何支持网络的设备。”</li>
<li>“能否在Windows开启一个web服务，通过在局域网内网页来控制电脑关机呢”</li>
<li>“如何添加身份验证呢？能否添加一个确认关机功能，直接访问网页就执行光机操作很容易误操作”</li>
<li>“程序的架构是：Windows端作为服务器，只提供接口不需要渲染网页。树莓派运行网页服务，通过访问树莓派的上运行的网页来控制Windows关机。通过python来实现。”</li>
<li>“修改树莓派的代码，用变量来设置 服务器的端口和ip”</li>
<li>“不要修改代码原有的功能，在代码的基础上，添加一个检测电脑端服务是否开启的功能，并显示到网页上”</li>
<li>“现在根据我刚刚给你的两个代码文件，判断项目内容。为这个项目写一个README”</li>
</ol>
<h2>经验&amp;技巧</h2>
<ol>
<li><strong>选择你擅长或者至少熟悉基础语法的语言。</strong>chatgpt生成的代码如果你不能大致看懂，那么让他写复杂一点的代码给你就很难了，chatgpt生成的代码可能有错误。比如说在这个项目的例子中，我只懂python的基础语法，对于用到<code>flask</code>框架，<code>request </code>和<code>wakeonlan</code>库我都不了解。但是通过让chatgpt写上注释，我能做到简单的debug。</li>
<li>每次和chatgpt对话，当你向他要代码时，可以在最后加上“请加上合理的注释”。或者在对话最开始和chatgpt约定，只要发送代码都加上易读的指数。</li>
<li>由于chatgpt的会话限制，有可能chatgpt无法一次将完整内容发给你，内容会戛然而止。可以试着和chatgpt说“继续”，但是也有可能会出现chatgpt前言不搭后语。或者不同部分的功能分别询问，有意地控制chatgpt的内容不要超过限制。</li>
<li>当项目逐渐成型，代码变得很长，可以试着和chatgpt说：“请只给我修改或者新增的部分”。</li>
<li>如果让chagpt设计css，可以尝试让他使用bootstrap，效果还可以。</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[树莓派安装docker版百度网盘]]></title><guid>https://wulu.zone/posts/baidunetdeck-arm-docker</guid><link>https://wulu.zone/posts/baidunetdeck-arm-docker</link><description><![CDATA[docker部署，可以通过浏览器和VNC访问]]></description><pubDate>Sat, 25 Feb 2023 11:45:12 +0000</pubDate><content:encoded><![CDATA[<h2>前言</h2>
<p>有时候需要下载百度网盘上的资料，但是百度网盘下载速度非常慢，又不想一直开着电脑挂着百度云盘费电。可以试着将百度网盘客户端下载到树莓派上。目前百度网盘的官网下载页面虽然有提供Linux版的安装包，但是没有提供arm架构的安装包。</p>
<p>不过，通过搜索发现百度其实有提供arm的安装包，通过链接 <strong><a href="https://issuepcdn.baidupcs.com/issue/netdisk/LinuxGuanjia/$%7B%E7%89%88%E6%9C%AC%E5%8F%B7%7D/baidunetdisk_$%7B%E7%89%88%E6%9C%AC%E5%8F%B7%7D_arm64.deb">https://issuepcdn.baidupcs.com/issue/netdisk/LinuxGuanjia/${版本号}/baidunetdisk_${版本号}_arm64.deb</a></strong> 就能得到，但是有时候amd64的版本arm64不一定有。目前我测试到最新的arm版本号是4.14.6。</p>
<p>总结起来，现在有下面这几个问题：</p>
<ol>
<li>只有rpm和deb包，其他linux系统比如archlinux和openwrt安装就无从下手。</li>
<li>需要有桌面环境，没有桌面环境就无法使用。</li>
<li>版本维护麻烦。</li>
</ol>
<p>怎么样才能够在各种Linux发行版上运行，不依赖桌面环境。那就是使用docker，将百度网盘安装docker容器里。再借助<a href="https://github.com/jlesage/docker-baseimage-gui">docker-baseimage-gui</a> 项目，这样就可以通过浏览器或任何VNC客户端访问百度网盘的GUI。</p>
<p>总之，最后我整理了一下把项目放到github了，项目地址：</p>
<p><a href="https://github.com/eMUQI/baidunetdisk-arm64-vnc">https://github.com/eMUQI/baidunetdisk-arm64-vnc</a></p>
<h2>用法</h2>
<p>可以通过docker或者docker-compose来部署，使用前确保你安装了docker或者docker-compose。</p>
<h3>docker 部署</h3>
<div class="block-code" data-language="bash"><div class="highlight"><pre><span></span><code><div class="line">docker run -d <span class="se">\</span>
</div><div class="line">       --name baidunetdisk-vnc <span class="se">\</span>
</div><div class="line">       -p <span class="m">5800</span>:5800 <span class="se">\</span>
</div><div class="line">       -p <span class="m">5900</span>:5900 <span class="se">\</span>
</div><div class="line">       -v /配置文件位置:/config <span class="se">\</span>
</div><div class="line">       -v /下载位置:/config/baidunetdiskdownload <span class="se">\</span>
</div><div class="line">       --restart unless-stopped <span class="se">\</span>
</div><div class="line">       emuqi/baidunetdisk-arm64-vnc:latest
</div></code></pre></div>
</div>
<p>其中需要修改的是<code>/配置文件位置:/config</code>和<code>/下载位置:/config/baidunetdiskdownload</code>，冒号前的路径修改为你希望储存位置（比如将下载文件存放到你树莓派上挂载的硬盘上）。</p>
<p>修改<code>5800:5800</code>冒号前的数字可以修改通过浏览器访问的端口号，修改<code>5900:5900</code>冒号前的数字可以修改VNC的端口号。</p>
<p>如果希望用密码限制访问，在<code>-p 5900:5900 \</code>后加上<code>-e VNC_PASSWORD=password \</code>，等号后面写你要设置的密码。<strong>如果你只在你的家的内部网络环境使用，可以不设置密码，但是如果你将端口暴露到外网，那么强烈建议你设置密码以防止隐私泄露。</strong></p>
<p>执行完成后，可以在浏览器中访问noVNC端口，例如<code>http://localhost:5800</code>，网页打开后等待加载就行，使用方法和正常客户端一致，确保下载位置为<code>baidunetdiskdownload</code>。也通过VNC客户端来访问<code>vnc://localhost:5900</code>。</p>
<p><strong>注意</strong>：如果百度网盘弹出升级提示，请忽略，点击升级按钮并不会执行程序升级而且新版本不一定有适配arm。可以将截图版本号提交到<a href="https://github.com/eMUQI/baidunetdisk-arm64-vnc/issues">issue</a>，我会根据适配情况维护升级。</p>
<p>常用docker命令：</p>
<div class="block-code"><pre><code>docker stop baidunetdisk-vnc # 启动容器
docker stop baidunetdisk-vnc # 停止容器
docker rm baidunetdisk-vnc # 删除容器
docker image rm johngong/baidunetdisk:latest #删除镜像</code></pre></div>
<h3>docker-compose 部署</h3>
<div class="block-code" data-language="bash"><div class="highlight"><pre><span></span><code><div class="line"><span class="c1"># 创建文件夹用于存放docker-compose配置文件</span>
</div><div class="line">mkdir baidunetdisk-vnc
</div><div class="line"><span class="c1"># 进入 baidunetdisk-vnc 文件夹</span>
</div><div class="line"><span class="nb">cd</span> baidunetdisk-vnc
</div><div class="line"><span class="c1"># 下载docker-compose配置文件</span>
</div><div class="line">wget https://raw.githubusercontent.com/eMUQI/baidunetdisk-arm64-vnc/main/docker-compose.yml
</div><div class="line"><span class="c1"># 根据需要修改docker-compose配置文件</span>
</div><div class="line">nano docker-compose.yml
</div><div class="line"><span class="c1"># 以后台形式运行</span>
</div><div class="line">docker-compose up -d
</div></code></pre></div>
</div>
<p>你可能希望修改<code>docker-compose.yml</code>里配置存放的位置<code>${PWD}/bdnetdisk-config:/config</code>和下载文件的位置<code>${PWD}/downloads:/config/baidunetdiskdownload</code>。修改冒号前的部分。</p>
<p>修改<code>5800:5800</code>冒号前的数字可以修改通过浏览器访问的端口号，修改<code>5900:5900</code>冒号前的数字可以修改VNC的端口号。</p>
<p>如果希望用密码限制访问，在<code>- GROUP_ID=1000 </code>后加上<code>- VNC_PASSWORD=password</code>，等号后面写你要设置的密码。<strong>如果你只在你的家的内部网络环境使用，可以不设置密码，但是如果你将端口暴露到外网，那么强烈建议你设置密码以防止隐私泄露。</strong></p>
<p>执行完成后，可以在浏览器中访问noVNC端口，例如<code>http://localhost:5800</code>，网页打开后等待加载就行，使用方法和正常客户端一致，确保下载位置为<code>baidunetdiskdownload</code>。也通过VNC客户端来访问<code>vnc://localhost:5900</code>。</p>
<p><strong>注意</strong>：如果百度网盘弹出升级提示，请忽略，点击升级按钮并不会执行程序升级而且新版本不一定有适配arm。可以将截图版本号提交到<a href="https://github.com/eMUQI/baidunetdisk-arm64-vnc/issues">issue</a>，我会根据适配情况维护升级。</p>
<p>常用docker-compose命令：</p>
<div class="block-code"><pre><code>docker-compose up -d # 以后台形式运行
docker-compose stop # 停止
docker-compose down # 停止并删除</code></pre></div>
<h2>配置</h2>
<div class="block-table"><table><thead>
<tr>
  <th style="text-align:left">参数</th>
  <th style="text-align:left">说明</th>
</tr>
</thead>
<tbody>
<tr>
  <td style="text-align:left"><code>--name=baidunetdisk</code></td>
  <td style="text-align:left">容器名</td>
</tr>
<tr>
  <td style="text-align:left"><code>-p 5800:5800</code></td>
  <td style="text-align:left">Web界面访问端口</td>
</tr>
<tr>
  <td style="text-align:left"><code>-p 5900:5900</code></td>
  <td style="text-align:left">VNC协议访问端口。如果未使用VNC客户端，则为可选</td>
</tr>
<tr>
  <td style="text-align:left"><code>-v /配置文件位置:/config</code></td>
  <td style="text-align:left">baidunetdisk配置文件位置</td>
</tr>
<tr>
  <td style="text-align:left"><code>-v /下载位置:/config/baidunetdiskdownload</code></td>
  <td style="text-align:left">baidunetdisk下载路径</td>
</tr>
<tr>
  <td style="text-align:left"><code>-e VNC_PASSWORD=VNC密码</code></td>
  <td style="text-align:left">VNC密码，默认为无</td>
</tr>
<tr>
  <td style="text-align:left"><code>-e USER_ID=1000</code></td>
  <td style="text-align:left">uid设置，默认为1000</td>
</tr>
<tr>
  <td style="text-align:left"><code>-e GROUP_ID=1000</code></td>
  <td style="text-align:left">gid设置，默认为1000</td>
</tr>
<tr>
  <td style="text-align:left"><code>-e NOVNC_LANGUAGE=&quot;zh_Hans&quot;</code></td>
  <td style="text-align:left">(zh_Hans|en)设定novnc语言，默认为中文</td>
</tr>
</tbody>
</table></div><h2>感谢以下项目:</h2>
<p><a href="https://github.com/jlesage/docker-baseimage-gui" title="https://github.com/jlesage/docker-baseimage-gui">https://github.com/jlesage/docker-baseimage-gui</a></p>
<p><a href="https://github.com/gshang2017/docker" title="https://github.com/gshang2017/docker">https://github.com/gshang2017/docker</a></p>
]]></content:encoded></item><item><title><![CDATA[近期音乐分享]]></title><guid>https://wulu.zone/posts/202211music</guid><link>https://wulu.zone/posts/202211music</link><description><![CDATA[2022.11]]></description><pubDate>Sun, 04 Dec 2022 08:33:40 +0000</pubDate><content:encoded><![CDATA[<p><a href="https://open.spotify.com/track/7pKfPomDEeI4TPT6EOYjn9?si=f7e8554ac8ec4f43">https://open.spotify.com/track/7pKfPomDEeI4TPT6EOYjn9?si=f7e8554ac8ec4f43</a></p>
<p><a href="https://open.spotify.com/track/49qhKNDnvA792NHeFwTKvk?si=e29e4337c9394c3b">https://open.spotify.com/track/49qhKNDnvA792NHeFwTKvk?si=e29e4337c9394c3b</a></p>
<p><a href="https://open.spotify.com/track/0g8H61FNXHHhMVHB0jwdzH?si=992ef4c4e0e64ead">https://open.spotify.com/track/0g8H61FNXHHhMVHB0jwdzH?si=992ef4c4e0e64ead</a></p>
<p><a href="https://open.spotify.com/track/7FeF8ywQi6Auovb94rEjOG?si=9ff72885e4f045a7">https://open.spotify.com/track/7FeF8ywQi6Auovb94rEjOG?si=9ff72885e4f045a7</a></p>
]]></content:encoded></item><item><title><![CDATA[AI绘画 6PEN 人工智能艺术？]]></title><guid>https://wulu.zone/posts/6penai</guid><link>https://wulu.zone/posts/6penai</link><pubDate>Sat, 03 Dec 2022 08:29:31 +0000</pubDate><content:encoded><![CDATA[<p>最近人工智能绘画的越来越火，很多人讨论，逐渐地也有更多人开始使用AI来绘画。我最早接触到AI绘画是在今年的七月份，那时候AI绘画已经慢慢开始在各个社交媒体平台可以看到了。</p>
<h3>6PEN.ART</h3>
<p>初次使用的AI绘画平台，以及我使用最多的是 <a href="https://6pen.art/?invite=2273545#no_universal_links">6pen.art</a> 。AI绘画其实是有一定门槛的：如果使用开源的模型，那么你需要有一定的编程基础（你需要知道怎么能让模型跑起来，还有大量的参数需要调整，除此，你还需要有一张不错的显卡）。如果使用商用的模型，那么就需要花钱，而且并不便宜。 <a href="https://6pen.art/?invite=2273545#no_universal_links">6pen.art</a> 不需要拥有编程知识，直接就能使用，甚至支持中文关键词。而且，<a href="https://6pen.art/?invite=2273545#no_universal_links">6pen</a>还把生成的图片版权归属于用户，每天都提供免费的生成次数。这些特点都非常吸引我。</p>
<p>具体是通过什么渠道知道这个平台的已经忘了。但是我仍然清晰地记得，在我刚开始接触人工智能绘画的时候，我很高兴，因为我对人工智能的绘画很感兴趣。作为一个在艺术上没有什么天赋的人，我也许也能够通过另一种方式表达自己脑中想象的画面，去捕获脑海中偶尔会出现的灵光一闪。我注册了 6pen 并开始AI绘画，我加入了 6pen 的用户群，看到群友生成的许多精妙的作品，我也跃跃欲试。</p>
<p>生成图片方式比较简单。有这些地方可以调整：<strong>画面描述</strong>、<strong>画面类型</strong>、<strong>风格修饰</strong>、<strong>艺术家</strong>、<strong>模型</strong>、<strong>参考图</strong>、<strong>尺寸</strong>和<strong>随机种子</strong>。如果你只需要你是新手，可以考虑使用禅思模式，这样只需要输入<strong>画面描述</strong>即可。</p>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8329958883_350382.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_390/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8329958883_350382.png" alt="image.png"loading="lazy" decoding="async" width="390" height="844" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8329958853_64318.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_390/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8329958853_64318.png" alt="image.png"loading="lazy" decoding="async" width="390" height="844" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8329958841_587859.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_390/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8329958841_587859.png" alt="image.png"loading="lazy" decoding="async" width="390" height="844" /></picture></figure></div></div>
<p>另外，可以使用我的 <a href="https://6pen.art/?invite=2273545#no_universal_links">分享链接</a> 注册，这样我们都能获得用于生成图片的点数，点数可以缩短图片生成的排队时间。</p>
<h3>效果图</h3>
<p>下面是我用AI生成的一些图片：如果对图片感兴趣，想知道关键词和风格，直接留言提问即可。</p>
<p>版权提示：下面部分图片由 stable diffusion 生成，版权属于公共领域。其余图片与本文保持同样的协议。</p>
<h4>蓝色群山星空夜晚</h4>
<div class="photo"><figure><picture><source srcset="https://i.typlog.com/wulu/8330879721_285832.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330879721_285832.png" alt="蓝色群山星空夜晚.png"loading="lazy" decoding="async" width="300" height="465" /></picture></figure></div><h4>一只慵懒的猫拿着花自画像</h4>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8330879419_463877.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330879419_463877.png" alt="一只慵懒的猫拿着一朵花 自画像.png"loading="lazy" decoding="async" width="300" height="465" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8330879419_465429.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330879419_465429.png" alt="一一只慵懒的猫拿着花自画像.png"loading="lazy" decoding="async" width="300" height="465" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8330879419_462446.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330879419_462446.png" alt="一只慵懒的猫抱着一朵花，自画像.png"loading="lazy" decoding="async" width="300" height="465" /></picture></figure></div></div>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8330878137_786694.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330878137_786694.png" alt="一只慵懒的猫拿着一朵花 自画像 (1).png"loading="lazy" decoding="async" width="300" height="465" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8330878137_784684.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330878137_784684.png" alt="一只慵懒的猫拿着一朵花 自画像 (4).png"loading="lazy" decoding="async" width="300" height="430" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8330878137_786976.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_300/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330878137_786976.png" alt="一只慵懒的猫拿着一朵花 自画像 (3).png"loading="lazy" decoding="async" width="300" height="430" /></picture></figure></div><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8330879419_4617.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_374/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330879419_4617.png" alt="一只慵懒的猫手上拿着一朵花 自画像.png"loading="lazy" decoding="async" width="374" height="465" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8330877944_83234.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_240/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330877944_83234.png" alt="一只慵懒的猫拿着一朵花 自画像 (5).png"loading="lazy" decoding="async" width="240" height="430" /></picture></figure></div></div>
<h4>一只狐狸在层层叠叠的玫瑰花开在山坡上</h4>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8330877502_411009.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330877502_411009.png" alt="一只狐狸在层层叠叠的玫瑰花开在山坡上 (3).png"loading="lazy" decoding="async" width="500" height="491" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8330877502_414551.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330877502_414551.png" alt="一只狐狸在层层叠叠的玫瑰花开在山坡上 (2).png"loading="lazy" decoding="async" width="500" height="491" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8330877502_419464.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330877502_419464.png" alt="一只狐狸在层层叠叠的玫瑰花开在山坡上 (1).png"loading="lazy" decoding="async" width="500" height="491" /></picture></figure></div><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8330877502_415201.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330877502_415201.png" alt="一直狐狸在层层叠叠的玫瑰花开在山坡上.png"loading="lazy" decoding="async" width="500" height="491" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8330877502_41924.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330877502_41924.png" alt="一只狐狸在层层叠叠的玫瑰花开在山坡上.png"loading="lazy" decoding="async" width="500" height="491" /></picture></figure></div></div>
<h4>玫瑰花山坡上新人类的核避难所</h4>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8330877447_639845.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330877447_639845.png" alt="灾难过后，玫瑰花开在山坡上，山坡上是新人类的核避难所.png"loading="lazy" decoding="async" width="500" height="555" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8330877447_631232.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330877447_631232.png" alt="无题.png"loading="lazy" decoding="async" width="500" height="523" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8330877447_638721.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330877447_638721.png" alt="灾难过后，层层叠叠的玫瑰花开在山坡上，山坡上是新人类的核避难所 (2).png"loading="lazy" decoding="async" width="500" height="555" /></picture></figure></div><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8330877447_616153.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330877447_616153.png" alt="灾难过后，层层叠叠的玫瑰花开在山坡上，山坡上是新人类的核避难所 (1).png"loading="lazy" decoding="async" width="500" height="491" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8330877447_612549.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330877447_612549.png" alt="灾难过后，层层叠叠的玫瑰花开在山坡上，山坡上是新人类的核避难所.png"loading="lazy" decoding="async" width="500" height="491" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8330877447_615648.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8330877447_615648.png" alt="玫瑰坡避难所.png"loading="lazy" decoding="async" width="500" height="525" /></picture></figure></div></div>
<h4>其他</h4>
<div class="gallery"><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8329944433_902563.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8329944433_902563.png" alt="夜，微风在树梢摇摆，流星对雪山表白.png"loading="lazy" decoding="async" width="500" height="451" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8329944433_818378.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8329944433_818378.png" alt="夜，微风，树梢摇摆，雪山，流星.png"loading="lazy" decoding="async" width="500" height="451" /></picture></figure></div><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8329944433_8036995.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8329944433_8036995.png" alt="流萤雪山.png"loading="lazy" decoding="async" width="500" height="486" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8329944433_809171.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_500/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8329944433_809171.png" alt="神的预言.png"loading="lazy" decoding="async" width="500" height="477" /></picture></figure></div><div class="gallery_column"><figure><picture><source srcset="https://i.typlog.com/wulu/8329944433_817063.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_450/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8329944433_817063.png" alt="桥 微光与黑暗分界.png"loading="lazy" decoding="async" width="450" height="430" /></picture></figure><figure><picture><source srcset="https://i.typlog.com/wulu/8329944433_813087.png?x-oss-process=image/auto-orient,1/interlace,1/quality,q_90/resize,m_lfit,w_459/format,webp" type="image/webp"><img src="https://i.typlog.com/wulu/8329944433_813087.png" alt="桥 微光与黑暗.png"loading="lazy" decoding="async" width="459" height="430" /></picture></figure></div></div>
]]></content:encoded></item></channel></rss>