<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Eson Wong&#39;s Blog</title>
  
  <subtitle>生活随想、学习笔记、读书总结、创作记录</subtitle>
  <link href="https://blog.esonwong.com/atom.xml" rel="self"/>
  
  <link href="https://blog.esonwong.com/"/>
  <updated>2026-02-27T10:20:27.251Z</updated>
  <id>https://blog.esonwong.com/</id>
  
  <author>
    <name>Eson Wong</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>我为什么开发 AI 英语听力生成器：Im-Listening</title>
    <link href="https://blog.esonwong.com/why-i-developed-listening-esonwong-com/"/>
    <id>https://blog.esonwong.com/why-i-developed-listening-esonwong-com/</id>
    <published>2026-02-26T14:00:00.000Z</published>
    <updated>2026-02-27T10:20:27.251Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/./why-i-developed-listening-esonwong-com/cover.webp" alt="我为什么开发 AI 英语听力生成器：Im-Listening"></p><p>我一直在保持自学英语。在听力方面，我经常面临一个艰难的挑战：市面上的听力材料要么太简单（比如慢速英语），没有挑战就无法学到新的知识；要么太难（比如 CNN&#x2F;BBC 原声），语速过快，生词太多，挫败感极强。</p><p>我尝试过市面上的各种听力 App 和网络上推荐的资源，但始终找不到<strong>既符合我兴趣又适合我当前水平</strong>的听力材料。</p><p>既然找不到合适自己的工具，那就自己写一个。于是，我决定自己动手，开发一个工具，利用生成式 AI，根据我的兴趣和水平，<strong>即时生成个性化的英语听力材料</strong>：**<a href="https://listening.esonwong.com/">listening.esonwong.com</a>**</p><span id="more"></span><h2 id="为什么要开发-listening-esonwong-com"><a href="#为什么要开发-listening-esonwong-com" class="headerlink" title="为什么要开发 listening.esonwong.com"></a>为什么要开发 <a href="https://listening.esonwong.com/">listening.esonwong.com</a></h2><h3 id="1-i-1-学习体验"><a href="#1-i-1-学习体验" class="headerlink" title="1. i + 1 学习体验"></a>1. i + 1 学习体验</h3><p>语言习得大师 Stephen Krashen 提出的 “输入假说” 认为，只有当输入材料的难度稍微高于学习者当前水平（即 i+1）时，习得才会发生。如果材料太难（i+10），就是无效噪音；如果太简单（i+0），则学不到新东西。</p><p>想找到适合自己的材料是个大难题。市面上的听力材料往往是往往难以满足个性化需求。而通过 AI 生成听力材料，可以根据我的水平和兴趣，动态调整难度，实现真正的 i+1 学习体验。</p><h3 id="2-即时学习"><a href="#2-即时学习" class="headerlink" title="2. 即时学习"></a>2. 即时学习</h3><p>听力练习需要大量的输入材料。传统的听力资源往往是预先录制好的，无法满足即时需求。而通过 AI 生成听力材料，可以根据将要面对的场景和兴趣，<strong>即时生成</strong>相关的听力内容，大大提高学习欲望。</p><p>比如，奖近年关，我就用 <a href="https://listening.esonwong.com/">listening.esonwong.com</a> 生成了和同事讨论 Spring Festival 的听力材料，帮助熟悉对这个话题听力能力：<a href="https://listening.esonwong.com/play/39">Chinese New Year Plans - ImListening</a></p><h3 id="3-Cost-Efficiency-成本效益"><a href="#3-Cost-Efficiency-成本效益" class="headerlink" title="3. Cost Efficiency (成本效益)"></a>3. Cost Efficiency (成本效益)</h3><p>市面上的听力材料和订阅听力 App 往往需要持续的费用。<a href="https://listening.esonwong.com/">listening.esonwong.com</a> 可以 0 成本生成听力材料，极大的提高了我练听力的动力。</p><h2 id="核心功能与体验"><a href="#核心功能与体验" class="headerlink" title="核心功能与体验"></a>核心功能与体验</h2><h3 id="难度控制"><a href="#难度控制" class="headerlink" title="难度控制"></a>难度控制</h3><p><a href="https://listening.esonwong.com/">listening.esonwong.com</a> 允许你根据 Difficulty Level（难度等级）和 Length（长度）来控制生成的听力材料整体难度。</p><p><img src="/./why-i-developed-listening-esonwong-com/create-free-material.webp" alt="难度控制"></p><h3 id="自定义话题"><a href="#自定义话题" class="headerlink" title="自定义话题"></a>自定义话题</h3><p>你可以自由的让 AI 生成你感兴趣的话题。例如输入主题让 AI 根据该主题生成听力材料。</p><p>或者输入单词列表让 AI 生成包含这些单词的听力材料。</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">生成一段包含以下单词的对话：economy, inflation, investment, market, growth</span><br></pre></td></tr></table></figure><p>或者直接输入对话来生成音频听力材料：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Li: Hi, how are you doing today?</span><br><span class="line">Wang: I&#x27;m doing well, thanks! How about you?</span><br><span class="line">Li: I&#x27;m great, thanks for asking. Have you heard about the new project at work?</span><br><span class="line">Wang: Yes, I have. It sounds really exciting!</span><br><span class="line">Li: Definitely! I think it&#x27;s going to be a great opportunity for all of us.</span><br><span class="line">Wang: I agree. I&#x27;m looking forward to getting started on it.</span><br></pre></td></tr></table></figure><p>又或者把一篇新闻文章输入进去，让 AI 帮你生成听力材料：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">播报下面的新闻：</span><br><span class="line"></span><br><span class="line">......</span><br></pre></td></tr></table></figure><h3 id="播放交互"><a href="#播放交互" class="headerlink" title="播放交互"></a>播放交互</h3><p>了提供便捷的听力练习体验，支持多种设备和控制方式， <a href="https://listening.esonwong.com/">listening.esonwong.com</a> 的播放界面设计简洁，支持多种平台的媒体控制按键。可以指定重复模式为单句重复、段落重复或者整篇重复，满足不同的练习需求。也可以指定媒体的上&#x2F;下一首按键的行为，比如切换到下一句或者下一段，方便在练习过程中快速切换听力内容。</p><p><img src="/./why-i-developed-listening-esonwong-com/play-interface.webp" alt="播放界面"></p><p>并且支持在锁屏显示听力材料的字幕，方便在各种场景下练习听力。</p><p>有了上述功能，让我在开车时练习听力成为了可能：</p><p><img src="/./why-i-developed-listening-esonwong-com/driving-listening.webp" alt="开车听听力"></p><h2 id="未来展望"><a href="#未来展望" class="headerlink" title="未来展望"></a>未来展望</h2><p>目前的 <a href="https://listening.esonwong.com/">listening.esonwong.com</a> 已经实现了核心的听力生成和播放功能，但仍然有很多可以改进和扩展的空间。</p><p>未来我可能会添加以下功能：</p><ul><li>听写模式</li><li>回顾提醒</li><li>播放列表</li><li>自定义语音 API</li></ul><p>如果你也是英语学习者，欢迎体验 <a href="https://listening.esonwong.com/">Listening.esonwong.com</a> 并给我反馈！</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;/./why-i-developed-listening-esonwong-com/cover.webp&quot; alt=&quot;我为什么开发 AI 英语听力生成器：Im-Listening&quot;&gt;&lt;/p&gt;
&lt;p&gt;我一直在保持自学英语。在听力方面，我经常面临一个艰难的挑战：市面上的听力材料要么太简单（比如慢速英语），没有挑战就无法学到新的知识；要么太难（比如 CNN&amp;#x2F;BBC 原声），语速过快，生词太多，挫败感极强。&lt;/p&gt;
&lt;p&gt;我尝试过市面上的各种听力 App 和网络上推荐的资源，但始终找不到&lt;strong&gt;既符合我兴趣又适合我当前水平&lt;/strong&gt;的听力材料。&lt;/p&gt;
&lt;p&gt;既然找不到合适自己的工具，那就自己写一个。于是，我决定自己动手，开发一个工具，利用生成式 AI，根据我的兴趣和水平，&lt;strong&gt;即时生成个性化的英语听力材料&lt;/strong&gt;：**&lt;a href=&quot;https://listening.esonwong.com/&quot;&gt;listening.esonwong.com&lt;/a&gt;**&lt;/p&gt;</summary>
    
    
    
    <category term="Project" scheme="https://blog.esonwong.com/categories/Project/"/>
    
    
    <category term="Web 开发" scheme="https://blog.esonwong.com/tags/Web-%E5%BC%80%E5%8F%91/"/>
    
    <category term="AI" scheme="https://blog.esonwong.com/tags/AI/"/>
    
    <category term="业余项目" scheme="https://blog.esonwong.com/tags/%E4%B8%9A%E4%BD%99%E9%A1%B9%E7%9B%AE/"/>
    
    <category term="Nuxt3" scheme="https://blog.esonwong.com/tags/Nuxt3/"/>
    
    <category term="English Learning" scheme="https://blog.esonwong.com/tags/English-Learning/"/>
    
  </entry>
  
  <entry>
    <title>Playwright E2E 测试框架入门教程</title>
    <link href="https://blog.esonwong.com/playwright/"/>
    <id>https://blog.esonwong.com/playwright/</id>
    <published>2025-10-26T07:14:49.000Z</published>
    <updated>2026-02-27T10:20:27.208Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://api-next.esonwong.com/blog-banner?title=Playwright%20E2E%20%E6%B5%8B%E8%AF%95%E6%A1%86%E6%9E%B6%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B" alt="Playwright"></p><p><a href="https://www.einktodo.com/">www.einktodo.com</a> 是我为 E-ink Todo List 设备开发的网站，为了减少在它上面的测试工作的时间，我使用了 <a href="https://playwright.dev/">Playwright</a> 来进行 E2E 测试。</p><p><a href="https://playwright.dev/">Playwright</a> 是一个由微软开发的 E2E 测试框架，它可以模拟用户在浏览器中的操作，比如点击、输入、滚动等等。Playwright 支持多种浏览器，包括 Chrome、Firefox、Safari 等等，而且它还支持多种编程语言，比如 Javascript、Python、C# 等等。</p><p>在这篇文章中，我将向你展示如何使用 Playwright 来进行 E2E 测试。我们将会使用 Typescript 来编写测试代码。</p><span id="more"></span><h2 id="安装-Playwright"><a href="#安装-Playwright" class="headerlink" title="安装 Playwright"></a>安装 Playwright</h2><p>在项目根目录下，运行以下命令来在项目中初始化 Playwright：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># npm</span></span><br><span class="line">npm init playwright@latest</span><br><span class="line"></span><br><span class="line"><span class="comment"># yarn</span></span><br><span class="line">yarn create playwright</span><br></pre></td></tr></table></figure><p>初始化完成后，Playwright 会在项目中生成一个 <code>playwright.config.ts</code> 文件，和一个测试示例文件 <code>example.spec.ts</code>。</p><h2 id="Playwright-配置"><a href="#Playwright-配置" class="headerlink" title="Playwright 配置"></a>Playwright 配置</h2><p>生成的 <code>playwright.config.ts</code> 文件用 <code>testDir</code> 字段来指定测试文件的目录，<code>projects</code> 字段来指定义 Playwright 中的 Project 概念。</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">PlaywrightTestConfig</span> &#125; <span class="keyword">from</span> <span class="string">&quot;@playwright/test&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title function_">defineConfig</span>(&#123;</span><br><span class="line">  <span class="comment">// 测试文件目录</span></span><br><span class="line">  <span class="attr">testDir</span>: <span class="string">&quot;tests&quot;</span>,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// 项目配置</span></span><br><span class="line">  <span class="attr">projects</span>: [</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h2 id="第一个测试"><a href="#第一个测试" class="headerlink" title="第一个测试"></a>第一个测试</h2><p>初始化完成后，Playwright 会在测试文件目录中生成一个测试示例的测试文件 <code>example.spec.ts</code>，我们可以在这个文件中编写我们的第一个测试。</p><p>下面以 <a href="https://www.einktodo.com/">www.einktodo.com</a> 的首页标题为例，来编写一个测试。</p><ol><li>从<code>@playwright/test</code>中导入<code>test</code>和<code>expect</code>函数</li><li>使用<code>test</code>函数来定义一个测试</li><li>使用<code>page.goto</code>方法来打开网站</li><li>使用<code>expect</code>和<code>toHaveTitle</code>方法来判断页面的标题是否为<code>E-ink Todo List</code></li></ol><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; test, expect &#125; <span class="keyword">from</span> <span class="string">&quot;@playwright/test&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="title function_">test</span>(<span class="string">&quot;E-ink Todo List 首页标题&quot;</span>, <span class="title function_">async</span> (&#123; page &#125;) =&gt; &#123;</span><br><span class="line">  <span class="keyword">await</span> page.<span class="title function_">goto</span>(<span class="string">&quot;https://www.einktodo.com&quot;</span>);</span><br><span class="line">  <span class="keyword">await</span> <span class="title function_">expect</span>(page).<span class="title function_">toHaveTitle</span>(<span class="string">&quot;E-ink Todo List&quot;</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h3 id="运行测试"><a href="#运行测试" class="headerlink" title="运行测试"></a>运行测试</h3><h4 id="默认模式"><a href="#默认模式" class="headerlink" title="默认模式"></a>默认模式</h4><p>运行所有的 Projects</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># npm</span></span><br><span class="line">npx playwright <span class="built_in">test</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># yarn</span></span><br><span class="line">yarn playwright <span class="built_in">test</span></span><br></pre></td></tr></table></figure><p>运行一个 Project</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># npm</span></span><br><span class="line">npx playwright <span class="built_in">test</span> --project=projectName</span><br><span class="line"></span><br><span class="line"><span class="comment"># yarn</span></span><br><span class="line">yarn playwright <span class="built_in">test</span> --project=projectName</span><br></pre></td></tr></table></figure><h4 id="UI-模式"><a href="#UI-模式" class="headerlink" title="UI 模式"></a>UI 模式</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># npm</span></span><br><span class="line">npx playwright <span class="built_in">test</span> --ui</span><br><span class="line"></span><br><span class="line"><span class="comment"># yarn</span></span><br><span class="line">yarn playwright <span class="built_in">test</span> --ui</span><br></pre></td></tr></table></figure><h2 id="Playwright-中的-Project"><a href="#Playwright-中的-Project" class="headerlink" title="Playwright 中的 Project"></a>Playwright 中的 Project</h2><p>Playwright 中的 Project 概念用于组织多个可以并行运行的测试文件、Project 运行的依赖和运行结束的后置任务，以及 Project 的环境配置。</p><pre><code class="highlight mermaid">mindmap  root((Project))</code></pre><h3 id="Projects-们的依赖关系"><a href="#Projects-们的依赖关系" class="headerlink" title="Projects 们的依赖关系"></a>Projects 们的依赖关系</h3><h3 id="保存和使用登陆状态"><a href="#保存和使用登陆状态" class="headerlink" title="保存和使用登陆状态"></a>保存和使用登陆状态</h3><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><a href="https://playwright.dev/">Playwright 官方文档</a></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://api-next.esonwong.com/blog-banner?title=Playwright%20E2E%20%E6%B5%8B%E8%AF%95%E6%A1%86%E6%9E%B6%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B&quot; alt=&quot;Playwright&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.einktodo.com/&quot;&gt;www.einktodo.com&lt;/a&gt; 是我为 E-ink Todo List 设备开发的网站，为了减少在它上面的测试工作的时间，我使用了 &lt;a href=&quot;https://playwright.dev/&quot;&gt;Playwright&lt;/a&gt; 来进行 E2E 测试。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://playwright.dev/&quot;&gt;Playwright&lt;/a&gt; 是一个由微软开发的 E2E 测试框架，它可以模拟用户在浏览器中的操作，比如点击、输入、滚动等等。Playwright 支持多种浏览器，包括 Chrome、Firefox、Safari 等等，而且它还支持多种编程语言，比如 Javascript、Python、C# 等等。&lt;/p&gt;
&lt;p&gt;在这篇文章中，我将向你展示如何使用 Playwright 来进行 E2E 测试。我们将会使用 Typescript 来编写测试代码。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Web 开发" scheme="https://blog.esonwong.com/tags/Web-%E5%BC%80%E5%8F%91/"/>
    
    <category term="技术" scheme="https://blog.esonwong.com/tags/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="Javascript" scheme="https://blog.esonwong.com/tags/Javascript/"/>
    
  </entry>
  
  <entry>
    <title>如何使用 LlamaIndex 构建一个 RAG 检索系统</title>
    <link href="https://blog.esonwong.com/llamaindex/"/>
    <id>https://blog.esonwong.com/llamaindex/</id>
    <published>2025-10-12T11:37:41.000Z</published>
    <updated>2026-02-27T10:20:27.163Z</updated>
    
    <content type="html"><![CDATA[<pre><code class="highlight mermaid">mindmap  ((LLamaIndex))    ((知识库))    ((搜索引擎))    ((Agent))    ((Workflow))    ((大语言模型))</code></pre><p>LLamaIndex 是一个基于大语言模型的应用的开源框架，可以用于构建 RAG 检索系统和其他基于大语言模型的应用。</p><p>本文将从浅及深地介绍如何使用 LlamaIndex 实现一个简单的以向量检索和搜索引擎检索作为基础的 RAG 检索系统。</p><span id="more"></span><h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><h3 id="安装-VSCode，准备-Python-环境"><a href="#安装-VSCode，准备-Python-环境" class="headerlink" title="安装 VSCode，准备 Python 环境"></a>安装 VSCode，准备 Python 环境</h3><p>我们从 <a href="https://code.visualstudio.com/">VSCode 官网</a>下载并安装 VSCode。</p><p>在电脑上新建一个 <code>llamaindex-rag</code> 的文件夹，然后在 VSCode 中打开这个文件夹。</p><p><img src="/llamaindex/open-folder.png" alt="打开目录"></p><p>接下来我们安装 VSCode 的 Python 官方插件。</p><p><img src="/llamaindex/install-python-extension.png" alt="安装 VSCode 的 Python 官方插件"></p><p>然后我们在 VSCode 使用下面的按键组合打开 VSCode 命令面板：</p><ul><li>Windows&#x2F;Linux: <code>Ctrl + Shift + P</code></li><li>Mac: <code>Cmd + Shift + P</code></li></ul><p><img src="/llamaindex/open-command-palette.png" alt="打开命令面板"></p><p>在命令面板中输入 <code>&gt; Python: Create Environment</code>， 回车后选择 <code>Venv</code> 创建一个 Python 虚拟环境。</p><p><img src="/llamaindex/create-python-venv.png" alt="创建 Python 虚拟环境"></p><p>创建虚拟环境之后，我们可以在打开的目录下看到一个 <code>venv</code> 的文件夹，这个文件夹内包含了 Python 的虚拟环境。同时 VSCode 也会自动激活这个虚拟环境。</p><h2 id="接入大语言模型"><a href="#接入大语言模型" class="headerlink" title="接入大语言模型"></a>接入大语言模型</h2><h3 id="Ollama-本地运行-llama-3-1-模型"><a href="#Ollama-本地运行-llama-3-1-模型" class="headerlink" title="Ollama 本地运行 llama 3.1 模型"></a>Ollama 本地运行 llama 3.1 模型</h3><p>从 <a href="https://ollama.com/download">Ollama</a> 下载并安装 Ollama。</p><p><img src="/llamaindex/download-ollama.png" alt="下载 Ollama"></p><p>用组合键：</p><ul><li>Windows&#x2F;Linux: <code>Ctrl + ` </code></li><li>Mac: <code>Cmd + ` </code></li></ul><p>在 VSCode 中打开终端，输入下面的命令在 Ollama 中安装 <code>llama 3.1</code> 模型:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ollama run llama3.1</span><br></pre></td></tr></table></figure><h3 id="使用-LlamaIndex-接入-Ollama"><a href="#使用-LlamaIndex-接入-Ollama" class="headerlink" title="使用 LlamaIndex 接入 Ollama"></a>使用 LlamaIndex 接入 Ollama</h3><p><img src="/llamaindex/install-llamaindex.png" alt="安装 LlamaIndex"></p><p>在 VSCode 中打开终端，输入下面的命令安装 <code>llama_index.llms.ollama</code> LLamaIndex 的 Ollama 模块：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install llama_index.llms.ollama</span><br></pre></td></tr></table></figure><p>在 VSCode 中新建 <code>rag.py</code> 文件：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> llama_index.llms.ollama <span class="keyword">import</span> Ollama</span><br><span class="line"></span><br><span class="line">llm = Ollama(model=<span class="string">&quot;llama3.1:latest&quot;</span>, request_timeout=<span class="number">120.0</span>)</span><br><span class="line">resp = llm.complete(<span class="string">&quot;Who are you?&quot;</span>);</span><br><span class="line"><span class="built_in">print</span>(resp)</span><br></pre></td></tr></table></figure><p>点击 VSCode 左上角的三角形的运行按钮，我们可以看到在终端中看到打印出来的模型的输出。</p><p><img src="/llamaindex/run-rag-py.png" alt="运行 rag.py"></p><h2 id="构建和接入知识库"><a href="#构建和接入知识库" class="headerlink" title="构建和接入知识库"></a>构建和接入知识库</h2><h3 id="准备知识库示例文件"><a href="#准备知识库示例文件" class="headerlink" title="准备知识库示例文件"></a>准备知识库示例文件</h3><p><img src="/llamaindex/create-sources-directory.png" alt="创建知识库目录"></p><p>在<code>llamaindex-rag</code>目录下新建一个 <code>knowledge</code> 目录，然后在 <code>knowledge</code> 目录，用于存放我们要检索的原始知识库的文件。</p><p>然后在 <code>knowledge</code> 目录下新建一个 <code>example.txt</code> 文件，用于存放我们的知识库示例。</p><p>用下面的内容填充 <code>example.txt</code> 文件：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Eson 是一个博客作者. 他的博客链接是 https://blog.eonwong.com.</span><br></pre></td></tr></table></figure><p>你也可以在 <code>knowledge</code> 目录下面放置其它<code>.txt</code>、<code>.docx</code>、<code>.pdf</code>等格式的文件。</p><h3 id="使用-LlamaIndex-构建知识库"><a href="#使用-LlamaIndex-构建知识库" class="headerlink" title="使用 LlamaIndex 构建知识库"></a>使用 LlamaIndex 构建知识库</h3><p>安装 <code>llama_index.core</code> 和 <code>llama_index.embeddings.huggingface</code> 模块。</p><p>在命令面板中执行下面的命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install llama-index llama_index.core llama_index.embeddings.huggingface</span><br></pre></td></tr></table></figure><ul><li><code>llama_index.core</code> 模块提供了 LLamaIndex 的核心功能</li><li><code>llama_index.embeddings.huggingface</code> 模块提供了 HuggingFace 的 embeddings 模型的接入功能。</li></ul><p>在 VSCode 中新建 <code>knowledge.py</code> 文件，首先导入 <code>llama_index.core</code> 和 <code>llama_index.embeddings.huggingface</code> 模块：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> llama_index.core <span class="keyword">import</span> ( SimpleDirectoryReader, Settings, VectorStoreIndex)</span><br><span class="line"><span class="keyword">from</span> llama_index.embeddings.huggingface <span class="keyword">import</span> HuggingFaceEmbedding</span><br></pre></td></tr></table></figure><p>设置 HuggingFace 的 embeddings 模型，我们选择在 HuggingFace 网站上热门的 <code>baai/bge-m3</code> 作为 LLamaIndex 向量化数据的 embedding 模型，在 <code>knowledge.py</code> 文件中添加下面的代码：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 配置嵌入模型</span></span><br><span class="line">Settings.embed_model = HuggingFaceEmbedding(model_name=<span class="string">&quot;baai/bge-m3&quot;</span>)</span><br></pre></td></tr></table></figure><p>接下来我们使用 <code>SimpleDirectoryReader</code> 读取 <code>knowledge</code> 目录下的文件：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 读取文件</span></span><br><span class="line">reader = SimpleDirectoryReader(input_dir=<span class="string">&quot;./knowledge&quot;</span>)</span><br><span class="line">documents = reader.load_data()</span><br></pre></td></tr></table></figure><p>然后我们使用 <code>VectorStoreIndex</code> 向量化我们的知识库：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># embedding 向量化</span></span><br><span class="line">index = VectorStoreIndex.from_documents(documents)</span><br></pre></td></tr></table></figure><p>向量化之后我们要把向量化的知识库保存到磁盘上，以便后续的检索：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 保存向量化的知识库</span></span><br><span class="line">index.storage_context.persist(persist_dir=<span class="string">&quot;./storage&quot;</span>)</span><br></pre></td></tr></table></figure><p>运行 <code>knowledge.py</code> 文件，我们可以看到在终端中看，该脚本会先下载 <code>baai/bge-m3</code> 模型。</p><p><img src="/llamaindex/run-knowledge-py.png" alt="运行 knowledge.py"></p><p>下载完成之后就会开始向量化知识库，然后保存向量化的数据保存到 <code>storage</code> 目录。</p><p><img src="/llamaindex/vectorize-knowledge.png" alt="向量化知识库"></p><h3 id="检索知识库"><a href="#检索知识库" class="headerlink" title="检索知识库"></a>检索知识库</h3><p>在 <code>rag.py</code> 文件顶部导入 <code>StorageContext</code> 和 <code>load_index_from_storage</code> 模块：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> llama_index.core <span class="keyword">import</span> (StorageContext, load_index_from_storage)</span><br></pre></td></tr></table></figure><p>在 <code>rag.py</code> 文件内容替换为下面的代码：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 导入模块</span></span><br><span class="line"><span class="keyword">from</span> llama_index.llms.ollama <span class="keyword">import</span> Ollama</span><br><span class="line"><span class="keyword">from</span> llama_index.core <span class="keyword">import</span> (StorageContext, load_index_from_storage, Settings)</span><br><span class="line"><span class="keyword">from</span> llama_index.embeddings.huggingface <span class="keyword">import</span> HuggingFaceEmbedding</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置 LLM 和 Embedding 模型</span></span><br><span class="line">llm = Ollama(model=<span class="string">&quot;llama3.1:latest&quot;</span>, request_timeout=<span class="number">120.0</span>)</span><br><span class="line">Settings.llm = Ollama(model=<span class="string">&quot;llama3.1&quot;</span>, request_timeout=<span class="number">360.0</span>)</span><br><span class="line">Settings.embed_model = HuggingFaceEmbedding(model_name=<span class="string">&quot;baai/bge-m3&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 读取知识库</span></span><br><span class="line">storage_context = StorageContext.from_defaults(persist_dir=<span class="string">&quot;./storage&quot;</span>)</span><br><span class="line">index = load_index_from_storage(storage_context)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配制查询引擎</span></span><br><span class="line">query_engine = index.as_query_engine(streaming=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查询</span></span><br><span class="line">response = query_engine.query(<span class="string">&quot;Eson 的博客地址是什么？&quot;</span>)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;输出结果：&quot;</span>)</span><br><span class="line"><span class="built_in">print</span>(response)</span><br></pre></td></tr></table></figure><h2 id="接入搜索引擎"><a href="#接入搜索引擎" class="headerlink" title="接入搜索引擎"></a>接入搜索引擎</h2><h2 id="为大语言模型输入提供检索结果"><a href="#为大语言模型输入提供检索结果" class="headerlink" title="为大语言模型输入提供检索结果"></a>为大语言模型输入提供检索结果</h2>]]></content>
    
    
    <summary type="html">&lt;pre&gt;&lt;code class=&quot;highlight mermaid&quot;&gt;mindmap
  ((LLamaIndex))
    ((知识库))
    ((搜索引擎))
    ((Agent))
    ((Workflow))
    ((大语言模型))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;LLamaIndex 是一个基于大语言模型的应用的开源框架，可以用于构建 RAG 检索系统和其他基于大语言模型的应用。&lt;/p&gt;
&lt;p&gt;本文将从浅及深地介绍如何使用 LlamaIndex 实现一个简单的以向量检索和搜索引擎检索作为基础的 RAG 检索系统。&lt;/p&gt;</summary>
    
    
    
    
    <category term="AI" scheme="https://blog.esonwong.com/tags/AI/"/>
    
    <category term="Large Language Models" scheme="https://blog.esonwong.com/tags/Large-Language-Models/"/>
    
  </entry>
  
  <entry>
    <title>批评</title>
    <link href="https://blog.esonwong.com/criticism/"/>
    <id>https://blog.esonwong.com/criticism/</id>
    <published>2025-08-20T00:00:00.000Z</published>
    <updated>2026-02-27T10:20:27.140Z</updated>
    
    <content type="html"><![CDATA[<p>真正能接受批评的人，能把“批评的事件”和“自我身份的认同”进行课题分离。</p><p>通常这样的人，也能从负面信息里提炼出值得改进的行为。（包括是否应该远离发出不当批评的人）</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;真正能接受批评的人，能把“批评的事件”和“自我身份的认同”进行课题分离。&lt;/p&gt;
&lt;p&gt;通常这样的人，也能从负面信息里提炼出值得改进的行为。（包括是否应该远离发出不当批评的人）&lt;/p&gt;
</summary>
      
    
    
    
    <category term="随笔" scheme="https://blog.esonwong.com/categories/%E9%9A%8F%E7%AC%94/"/>
    
    
    <category term="随笔" scheme="https://blog.esonwong.com/tags/%E9%9A%8F%E7%AC%94/"/>
    
  </entry>
  
  <entry>
    <title>Milvus 入门教程</title>
    <link href="https://blog.esonwong.com/milvus/"/>
    <id>https://blog.esonwong.com/milvus/</id>
    <published>2024-10-10T15:47:55.000Z</published>
    <updated>2026-02-27T10:20:27.195Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://api-next.esonwong.com/blog-banner?title=Milvus%20%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B" alt="Milvus"></p><p>Milvus 是一个开源的向量数据库，它是为了生成式 AI 的应用设计的。它支持大规模的向量检索。</p><p>Milvus 的发音是 &#x2F;ˈmil vəs&#x2F;。</p><p>本文将是 Milvus 的使用入门。</p><span id="more"></span><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374200691037971"     crossorigin="anonymous"></script><!-- Horizontal ad 1 --><p><ins class="adsbygoogle"     style="display:block"     data-ad-client="ca-pub-4374200691037971"     data-ad-slot="6994298150"     data-ad-format="auto"     data-full-width-responsive="true"></ins></p><script>     (adsbygoogle = window.adsbygoogle || []).push({});</script><h2 id="安装-Milvus"><a href="#安装-Milvus" class="headerlink" title="安装 Milvus"></a>安装 Milvus</h2><p>先准备好 Python 环境，然后使用 pip 安装 Milvus：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install -U pymilvus</span><br></pre></td></tr></table></figure><h2 id="使用-Milvus"><a href="#使用-Milvus" class="headerlink" title="使用 Milvus"></a>使用 Milvus</h2><h3 id="创建一个本地的-Milvus-文件"><a href="#创建一个本地的-Milvus-文件" class="headerlink" title="创建一个本地的 Milvus 文件"></a>创建一个本地的 Milvus 文件</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pymilvus <span class="keyword">import</span> MilvusClient</span><br><span class="line"></span><br><span class="line">client = MilvusClient(<span class="string">&quot;milvus_demo.db&quot;</span>)</span><br></pre></td></tr></table></figure><p>运行上面的代码，在当前目录下会生成一个名为 <code>milvus_demo.db</code> 的文件。</p><h3 id="创建一个集合-Collection"><a href="#创建一个集合-Collection" class="headerlink" title="创建一个集合 Collection"></a>创建一个集合 Collection</h3><p>我们通常把相关联的数据放在 Milvus 中的一个集合(Collection)中，我们可以把集合想象成一个传统数据库中的表。</p><p>下面的代码会创建一个集合，它存储的向量数据的的维度数是 768，这个维度数是接下来准备的向量数据的维度。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">collection_name = <span class="string">&quot;milvus_demo&quot;</span></span><br><span class="line">client.create_collection(collection_name, dimension=<span class="number">768</span>)</span><br></pre></td></tr></table></figure><p>为了避免重复创建 Collection，我们可以先检查 Collection 是否存在：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">collection_name = <span class="string">&quot;milvus_demo&quot;</span></span><br><span class="line"><span class="keyword">if</span> <span class="keyword">not</span> client.has_collection(collection_name):</span><br><span class="line">    client.create_collection(collection_name, dimension=<span class="number">768</span>)</span><br></pre></td></tr></table></figure><h3 id="准备数据"><a href="#准备数据" class="headerlink" title="准备数据"></a>准备数据</h3><p><code>pymilvus[model]</code> python 库中提供了一些工具函数，可以帮助我们把文本数据转换成向量，来进行 Milvus 的学习。</p><p>下面会把<code>hello world</code>、<code>你好世界</code>、<code>milvus is great</code>这三个文本数据转换成向量数据：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pymilvus <span class="keyword">import</span> model</span><br><span class="line"></span><br><span class="line">embedding_fn = model.DefaultEmbeddingFunction()</span><br><span class="line">docs = [<span class="string">&quot;hello world&quot;</span>, <span class="string">&quot;hi&quot;</span>, <span class="string">&quot;你好世界&quot;</span>, <span class="string">&quot;milvus is great&quot;</span>]</span><br><span class="line"></span><br><span class="line">vectors = embedding_fn.encode_documents(docs)</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span> (<span class="string">&quot;向量数据的维度:&quot;</span>, <span class="built_in">len</span>(vectors[<span class="number">0</span>]))</span><br></pre></td></tr></table></figure><p>我们会得到一个向量数据的列表，每个向量数据的维度是 768。</p><p>然后我们可以把向量数据和文本数据组合成由<code>id</code>、<code>vector</code>、<code>text</code>组成的数据列表：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">data = [</span><br><span class="line">    &#123;<span class="string">&quot;id&quot;</span>: i, <span class="string">&quot;vector&quot;</span>: vectors[i], <span class="string">&quot;text&quot;</span>: docs[i]&#125;</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(vectors))</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;数据包含&quot;</span>, <span class="built_in">len</span>(data), <span class="string">&quot;个条目，每个条目包含字段: &quot;</span>, data[<span class="number">0</span>].keys())</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;vector 维度:&quot;</span>, <span class="built_in">len</span>(data[<span class="number">0</span>][<span class="string">&quot;vector&quot;</span>]))</span><br></pre></td></tr></table></figure><h3 id="插入数据"><a href="#插入数据" class="headerlink" title="插入数据"></a>插入数据</h3><p>使用 <code>insert(collection_name, data)</code> 方法把列数据插入到 Milvus 的 <code>milvus_demo</code> 集合中：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">response = client.insert(collection_name, data)</span><br><span class="line"><span class="built_in">print</span>(response)</span><br></pre></td></tr></table></figure><p>此时我们插入了三条数据，每条数据包含了向量和原始文本。</p><h3 id="检索数据"><a href="#检索数据" class="headerlink" title="检索数据"></a>检索数据</h3><p>在 <a href="/retrieval-augmented-generation">Retrieval Augmented Generation(RAG)</a> 的应用场景中，通常要检索与输入文本最关度最高的文本数据。向量数据之间的关度可以通过计算向量之间的距离来衡量。</p><p>首先我们要把输入的数据转换成向量：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1.将要查询的数据转换为向量</span></span><br><span class="line">query = <span class="string">&quot;hi&quot;</span></span><br><span class="line">query_vectors = embedding_fn.encode_queries([query])</span><br></pre></td></tr></table></figure><p>然后我们可以使用 <code>search(collection_name, data)</code> 方法来检索与输入文本在向量空间中最相近的数据：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 2.向量查询</span></span><br><span class="line">query_response = client.search(</span><br><span class="line">    collection_name,</span><br><span class="line">    data=query_vectors,  <span class="comment"># 查询向量</span></span><br><span class="line">    limit=<span class="number">2</span>,  <span class="comment"># 返回的最大结果数</span></span><br><span class="line">    output_fields=[<span class="string">&quot;id&quot;</span>, <span class="string">&quot;text&quot;</span>],  <span class="comment"># 返回的字段</span></span><br><span class="line">)</span><br><span class="line"><span class="built_in">print</span>(query_response)</span><br></pre></td></tr></table></figure><p>我们会得到一个列表，列表中的每个元素包含了检索到的数据的<code>id</code>、<code>distance</code>、<code>entity</code>字段，其中<code>distance</code>字段表示检索到的数据与输入数据的距离。</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">data: [&quot;[</span><br><span class="line">          &#123;&#x27;id&#x27;: 1, &#x27;distance&#x27;: 1.0, &#x27;entity&#x27;: &#123;&#x27;text&#x27;: &#x27;hi&#x27;, &#x27;id&#x27;: 1&#125;&#125;,</span><br><span class="line">          &#123;&#x27;id&#x27;: 0, &#x27;distance&#x27;: 0.5280660390853882, &#x27;entity&#x27;: &#123;&#x27;text&#x27;: &#x27;hello world&#x27;, &#x27;id&#x27;: 0&#125;&#125;,</span><br><span class="line">          &#123;&#x27;id&#x27;: 2, &#x27;distance&#x27;: 0.44701865315437317, &#x27;entity&#x27;: &#123;&#x27;text&#x27;: &#x27;你好世界&#x27;, &#x27;id&#x27;: 2&#125;&#125;</span><br><span class="line">      ]&quot;]</span><br></pre></td></tr></table></figure><p><code>distance</code> 越接近 1，表示两个向量距离越近。从上面的结果中，我们可以看到，查询结果中的 <code>hi</code> 的与查询的文本相同，所以 <code>distance</code> 值为 <code>1</code> 。与查询文本<code>hi</code>距离最近的文本依次是<code>hi</code>、<code>hello world</code>、<code>你好世界</code>。这意味着它们之间的相关度排序也是这样的。</p><h3 id="删除数据"><a href="#删除数据" class="headerlink" title="删除数据"></a>删除数据</h3><p><code>delete()</code> 方法可以删除集合中的数据：</p><p>通过 id 删除数据：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">client.delete(collection_name, ids=[<span class="number">1</span>])</span><br></pre></td></tr></table></figure><p>通过条件删除数据：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">client.delete(collection_name, <span class="built_in">filter</span>=<span class="string">&quot;id == 1&quot;</span>)</span><br></pre></td></tr></table></figure><h3 id="删除集合"><a href="#删除集合" class="headerlink" title="删除集合"></a>删除集合</h3><p><code>drop_collection()</code> 方法可以删除集合：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">client.drop_collection(collection_name)</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://api-next.esonwong.com/blog-banner?title=Milvus%20%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B&quot; alt=&quot;Milvus&quot;&gt;&lt;/p&gt;
&lt;p&gt;Milvus 是一个开源的向量数据库，它是为了生成式 AI 的应用设计的。它支持大规模的向量检索。&lt;/p&gt;
&lt;p&gt;Milvus 的发音是 &amp;#x2F;ˈmil vəs&amp;#x2F;。&lt;/p&gt;
&lt;p&gt;本文将是 Milvus 的使用入门。&lt;/p&gt;</summary>
    
    
    
    
    <category term="AI" scheme="https://blog.esonwong.com/tags/AI/"/>
    
    <category term="Large Language Models" scheme="https://blog.esonwong.com/tags/Large-Language-Models/"/>
    
  </entry>
  
  <entry>
    <title>怎么在网页中实现自动调整视频的清晰度</title>
    <link href="https://blog.esonwong.com/use-hls-to-automatically-switch-the-split-rate-of-video/"/>
    <id>https://blog.esonwong.com/use-hls-to-automatically-switch-the-split-rate-of-video/</id>
    <published>2024-09-11T03:49:08.000Z</published>
    <updated>2026-02-27T10:20:27.250Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://api-next.esonwong.com/blog-banner?title=HTTP%20Live%20Streaming%20(HLS)" alt="HTTP Live Streaming (HLS)"></p><p>HTTP Live Streaming (HLS) 是 Apple 开发的一种流媒体协议。能够根据用户的网络状况自动调整视频的清晰度。它将整个视频分成一系列小的 HTTP 文件，每个文件包含一小段视频内容。这种方式可以让视频在不同的网络环境下更加流畅地播放。</p><p>本文们将介绍如何在网页中使用实现基于 HLS 视频播放，并显示当前播放的分辨率。</p><span id="more"></span><h2 id="使用-FFmpeg-生成-HLS-视频流"><a href="#使用-FFmpeg-生成-HLS-视频流" class="headerlink" title="使用 FFmpeg 生成 HLS 视频流"></a>使用 FFmpeg 生成 HLS 视频流</h2><h3 id="转码视频为多码率版本"><a href="#转码视频为多码率版本" class="headerlink" title="转码视频为多码率版本"></a>转码视频为多码率版本</h3><p>使用 FFmpeg 命令行工具将原始视 <code>input.mp4</code> 频转码为多个分辨率（1080p、720p、480p）的 HLS 视频：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">ffmpeg -i input.mp4 \</span><br><span class="line">    -filter_complex \</span><br><span class="line">    <span class="string">&quot;[0:v]split=3[v1][v2][v3]; \</span></span><br><span class="line"><span class="string">     [v1]scale=1920:1080[v1out]; \</span></span><br><span class="line"><span class="string">     [v2]scale=1280:720[v2out]; \</span></span><br><span class="line"><span class="string">     [v3]scale=854:480[v3out]&quot;</span> \</span><br><span class="line">    -map <span class="string">&quot;[v1out]&quot;</span> -map 0:a -c:v:0 libx264 -b:v:0 5000k -maxrate:v:0 5350k -bufsize:v:0 7500k \</span><br><span class="line">    -map <span class="string">&quot;[v2out]&quot;</span> -map 0:a -c:v:1 libx264 -b:v:1 3000k -maxrate:v:1 3210k -bufsize:v:1 4500k \</span><br><span class="line">    -map <span class="string">&quot;[v3out]&quot;</span> -map 0:a -c:v:2 libx264 -b:v:2 1500k -maxrate:v:2 1605k -bufsize:v:2 2250k \</span><br><span class="line">    -c:a aac -b:a 128k -ac 2 \</span><br><span class="line">    -f hls -hls_time 6 -hls_list_size 0 \</span><br><span class="line">    -hls_segment_filename <span class="string">&#x27;stream_%v/segment_%03d.ts&#x27;</span> \</span><br><span class="line">    -master_pl_name master.m3u8 \</span><br><span class="line">    -var_stream_map <span class="string">&quot;v:0,a:0 v:1,a:1 v:2,a:2&quot;</span> \</span><br><span class="line">    <span class="string">&#x27;stream_%v/index.m3u8&#x27;</span></span><br></pre></td></tr></table></figure><p>生成的文件包括：</p><ul><li><code>master.m3u8</code>: 主播放列表。</li><li><code>stream_0/</code>: 1080p 版本的切片。</li><li><code>stream_1/</code>: 720p 版本。</li><li><code>stream_2/</code>: 480p 版本。</li></ul><h2 id="在网页中实现-HLS-视频的播放"><a href="#在网页中实现-HLS-视频的播放" class="headerlink" title="在网页中实现 HLS 视频的播放"></a>在网页中实现 HLS 视频的播放</h2><p>使用以下 HTML 和 JavaScript 代码来播放 HLS 视频并显示当前分辨率</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>自动切换清晰度的视频示例<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="comment">/* 定义显示分辨率的样式 */</span></span></span><br><span class="line"><span class="language-css">      <span class="selector-id">#resolution-display</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">position</span>: absolute;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">top</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">left</span>: <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">5px</span> <span class="number">10px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.7</span>);</span></span><br><span class="line"><span class="language-css">        <span class="attribute">color</span>: <span class="number">#fff</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">font-size</span>: <span class="number">14px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border-radius</span>: <span class="number">5px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="comment">/* 确保视频容器是相对定位 */</span></span></span><br><span class="line"><span class="language-css">      <span class="selector-id">#video-container</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">position</span>: relative;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">display</span>: inline-block;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-tag">video</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">height</span>: auto;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 视频播放器 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">video</span> <span class="attr">id</span>=<span class="string">&quot;video&quot;</span> <span class="attr">controls</span>&gt;</span><span class="tag">&lt;/<span class="name">video</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 分辨率显示 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;resolution-display&quot;</span>&gt;</span>分辨率：未知<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 引入 hls.js 库 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/hls.js@latest&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 获取视频元素</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">var</span> video = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;video&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 获取分辨率显示元素</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">var</span> resolutionDisplay = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;resolution-display&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// HLS 视频源地址（.m3u8 文件）</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">var</span> videoSrc = <span class="string">&quot;./video/video2/master.m3u8&quot;</span>;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 检查浏览器是否支持 hls.js</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">if</span> (<span class="title class_">Hls</span>.<span class="title function_">isSupported</span>()) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">var</span> hls = <span class="keyword">new</span> <span class="title class_">Hls</span>();</span></span><br><span class="line"><span class="language-javascript">        hls.<span class="title function_">loadSource</span>(videoSrc);</span></span><br><span class="line"><span class="language-javascript">        hls.<span class="title function_">attachMedia</span>(video);</span></span><br><span class="line"><span class="language-javascript">        hls.<span class="title function_">on</span>(<span class="title class_">Hls</span>.<span class="property">Events</span>.<span class="property">MANIFEST_PARSED</span>, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          video.<span class="title function_">play</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 监听 LEVEL_SWITCHED 事件，当播放级别切换时触发</span></span></span><br><span class="line"><span class="language-javascript">        hls.<span class="title function_">on</span>(<span class="title class_">Hls</span>.<span class="property">Events</span>.<span class="property">LEVEL_SWITCHED</span>, <span class="keyword">function</span> (<span class="params">event, data</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">updateResolution</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 初始获取当前分辨率</span></span></span><br><span class="line"><span class="language-javascript">        hls.<span class="title function_">on</span>(<span class="title class_">Hls</span>.<span class="property">Events</span>.<span class="property">LEVEL_LOADED</span>, <span class="keyword">function</span> (<span class="params">event, data</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">updateResolution</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 定义更新分辨率的函数</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">function</span> <span class="title function_">updateResolution</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">var</span> level = hls.<span class="property">levels</span>[hls.<span class="property">currentLevel</span>];</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">if</span> (level) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">var</span> width = level.<span class="property">width</span>;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">var</span> height = level.<span class="property">height</span>;</span></span><br><span class="line"><span class="language-javascript">            resolutionDisplay.<span class="property">textContent</span> = <span class="string">&quot;分辨率：&quot;</span> + width + <span class="string">&quot;x&quot;</span> + height;</span></span><br><span class="line"><span class="language-javascript">          &#125;</span></span><br><span class="line"><span class="language-javascript">        &#125;</span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 对于支持原生 HLS 的浏览器（如 Safari）</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">else</span> <span class="keyword">if</span> (video.<span class="title function_">canPlayType</span>(<span class="string">&quot;application/vnd.apple.mpegurl&quot;</span>)) &#123;</span></span><br><span class="line"><span class="language-javascript">        video.<span class="property">src</span> = videoSrc;</span></span><br><span class="line"><span class="language-javascript">        video.<span class="title function_">addEventListener</span>(<span class="string">&quot;loadedmetadata&quot;</span>, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          video.<span class="title function_">play</span>();</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">// 获取视频的实际分辨率</span></span></span><br><span class="line"><span class="language-javascript">          resolutionDisplay.<span class="property">textContent</span> =</span></span><br><span class="line"><span class="language-javascript">            <span class="string">&quot;分辨率：&quot;</span> + video.<span class="property">videoWidth</span> + <span class="string">&quot;x&quot;</span> + video.<span class="property">videoHeight</span>;</span></span><br><span class="line"><span class="language-javascript">        &#125;);</span></span><br><span class="line"><span class="language-javascript">      &#125; <span class="keyword">else</span> &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&quot;该浏览器不支持 HLS 播放。&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://api-next.esonwong.com/blog-banner?title=HTTP%20Live%20Streaming%20(HLS)&quot; alt=&quot;HTTP Live Streaming (HLS)&quot;&gt;&lt;/p&gt;
&lt;p&gt;HTTP Live Streaming (HLS) 是 Apple 开发的一种流媒体协议。能够根据用户的网络状况自动调整视频的清晰度。它将整个视频分成一系列小的 HTTP 文件，每个文件包含一小段视频内容。这种方式可以让视频在不同的网络环境下更加流畅地播放。&lt;/p&gt;
&lt;p&gt;本文们将介绍如何在网页中使用实现基于 HLS 视频播放，并显示当前播放的分辨率。&lt;/p&gt;</summary>
    
    
    
    
    <category term="前端" scheme="https://blog.esonwong.com/tags/%E5%89%8D%E7%AB%AF/"/>
    
    <category term="FFmpeg" scheme="https://blog.esonwong.com/tags/FFmpeg/"/>
    
  </entry>
  
  <entry>
    <title>什么是检索增强生成（Retrieval-Augmented Generation）？</title>
    <link href="https://blog.esonwong.com/retrieval-augmented-generation/"/>
    <id>https://blog.esonwong.com/retrieval-augmented-generation/</id>
    <published>2024-09-10T01:50:51.000Z</published>
    <updated>2026-02-27T10:20:27.219Z</updated>
    
    <content type="html"><![CDATA[<p>最近在主导一个 AI 检索的项目，需要对检索增强生成（RAG）有所了解，下面是我对检索增强生成（RAG）的一个初浅的了解。</p><p>索增强生成（RAG）是指对大型语言模型输出进行优化，使其能够在生成响应之前引用训练数据来源之外的权威知识库。</p><p>检索增强生成（RAG）的原理图如下：</p><pre><code class="highlight mermaid">graph TB  subgraph 用户交互    Start([用户查询]):::user    End([交互响应]):::user  end  subgraph 大语言模型  end  subgraph 知识库构建    SD[(结构化知识库)] --&gt; 向量化知识库 --&gt; VD[(向量知识库)]  end  Start ==&gt; 向量化用户查询 ==&gt; 向量检索 ==&gt; 相关知识  Start ==&gt; 提示词模版  相关知识 ==&gt; 提示词模版  提示词模版 == 组合 ==&gt; 模型输入  模型输入 ==&gt; 大语言模型 ==&gt; 模型输出 ==&gt; End  相关知识 ==&gt; End  向量化知识库 o-.-o 大语言模型  向量化用户查询 o-.-o 大语言模型  向量检索 o-.-o VD  相关知识 o-.匹配.-o SD  classDef user fill:green,color:white</code></pre>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;最近在主导一个 AI 检索的项目，需要对检索增强生成（RAG）有所了解，下面是我对检索增强生成（RAG）的一个初浅的了解。&lt;/p&gt;
&lt;p&gt;索增强生成（RAG）是指对大型语言模型输出进行优化，使其能够在生成响应之前引用训练数据来源之外的权威知识库。&lt;/p&gt;
&lt;p&gt;检索增强生成</summary>
      
    
    
    
    
    <category term="AI" scheme="https://blog.esonwong.com/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>Phonics 自然拼读常见规则 - 辅音字母的发音规律</title>
    <link href="https://blog.esonwong.com/phonics-of-consonants/"/>
    <id>https://blog.esonwong.com/phonics-of-consonants/</id>
    <published>2024-09-09T14:53:47.000Z</published>
    <updated>2026-02-27T10:20:27.207Z</updated>
    
    <content type="html"><![CDATA[<p>辅音字母的读音通常是辅音字母发音的辅音部份。但是存在非常多的例外情况。</p><table><thead><tr><th>字母</th><th>常见</th><th></th><th>组合发音</th></tr></thead><tbody><tr><td>B</td><td>&#x2F;b&#x2F;</td><td>不发音</td><td></td></tr><tr><td>C</td><td>&#x2F;k&#x2F; 和 &#x2F;s&#x2F;</td><td></td><td>&#x2F;tʃ&#x2F;</td></tr><tr><td>D</td><td>&#x2F;d&#x2F;</td><td></td><td>&#x2F;dʒ&#x2F;</td></tr><tr><td>F</td><td>&#x2F;f&#x2F;</td><td>&#x2F;v&#x2F;</td><td></td></tr><tr><td>G</td><td>&#x2F;g&#x2F; 和 &#x2F;dʒ&#x2F;</td><td></td><td>&#x2F;ŋ&#x2F;</td></tr><tr><td>H</td><td>&#x2F;h&#x2F;</td><td></td><td>&#x2F;θ&#x2F; &#x2F;ð&#x2F; &#x2F;tʃ&#x2F; &#x2F;ʃ&#x2F; &#x2F;w&#x2F; &#x2F;f&#x2F; 不发音</td></tr><tr><td>J</td><td>&#x2F;dʒ&#x2F;</td><td></td><td></td></tr><tr><td>K</td><td>&#x2F;k&#x2F;</td><td></td><td></td></tr><tr><td>L</td><td>&#x2F;l&#x2F;</td><td>元音化</td><td></td></tr><tr><td>M</td><td>&#x2F;m&#x2F;</td><td></td><td></td></tr><tr><td>N</td><td>&#x2F;n&#x2F;</td><td></td><td>&#x2F;ŋ&#x2F;</td></tr><tr><td>P</td><td>&#x2F;p&#x2F;</td><td></td><td>&#x2F;f&#x2F;</td></tr><tr><td>Q</td><td>&#x2F;k&#x2F;</td><td></td><td>&#x2F;kw&#x2F;</td></tr><tr><td>R</td><td>&#x2F;r&#x2F;</td><td></td><td>&#x2F;r&#x2F;</td></tr><tr><td>S</td><td>&#x2F;s&#x2F;</td><td>&#x2F;z&#x2F;</td><td>&#x2F;ʃ&#x2F; &#x2F;ʒer&#x2F; &#x2F;ʃ(ə)n&#x2F; &#x2F;ʒən&#x2F;</td></tr><tr><td>T</td><td>&#x2F;t&#x2F;</td><td></td><td>&#x2F;ʃ&#x2F; &#x2F;tʃ&#x2F; &#x2F;tr&#x2F;</td></tr><tr><td>V</td><td>&#x2F;v&#x2F;</td><td></td><td></td></tr><tr><td>W</td><td>&#x2F;w&#x2F;</td><td>元音化</td><td>不发音</td></tr><tr><td>X</td><td>&#x2F;ks&#x2F;</td><td>&#x2F;gz&#x2F;</td><td>&#x2F;z&#x2F;</td></tr><tr><td>Y</td><td>&#x2F;j&#x2F; &#x2F;aɪ&#x2F; &#x2F;ɪ&#x2F;</td><td></td><td></td></tr><tr><td>Z</td><td>&#x2F;z&#x2F;</td><td></td><td></td></tr></tbody></table><span id="more"></span><p>本文持续更新中…</p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374200691037971"     crossorigin="anonymous"></script><p><ins class="adsbygoogle"     style="display:block; text-align:center;"     data-ad-layout="in-article"     data-ad-format="fluid"     data-ad-client="ca-pub-4374200691037971"     data-ad-slot="5501484908"></ins></p><script>     (adsbygoogle = window.adsbygoogle || []).push({});</script><p>音节的划分对于一个单词的读音至关重要，自然拼读的规律基本上是针对单个音节的。如果你不了解什么是音节请阅读我的另一篇博客：<a href="/phonics">Phonics 自然拼读常见规则 - 音节和元音字母的发音规律</a></p><h2 id="什么是辅音"><a href="#什么是辅音" class="headerlink" title="什么是辅音"></a>什么是辅音</h2><p>辅音是什么见 <a href="/phonics#%E8%BE%85%E9%9F%B3">辅音</a></p><h2 id="辅音字母的常见发音规律"><a href="#辅音字母的常见发音规律" class="headerlink" title="辅音字母的常见发音规律"></a>辅音字母的常见发音规律</h2><h3 id="B-的发音规律"><a href="#B-的发音规律" class="headerlink" title="B 的发音规律"></a>B 的发音规律</h3><p>B 通常读作 &#x2F;b&#x2F;。</p><ol><li>B 在音结尾部的 mb 和 bt 组合中，B 通常不发音。</li></ol><ul><li>comb &#x2F;kəʊm&#x2F;</li><li>bomb &#x2F;bɒm&#x2F;</li><li>climb &#x2F;klaɪm&#x2F;</li><li>lamb &#x2F;læm&#x2F;</li><li>thumb &#x2F;θʌm&#x2F;</li><li>debt &#x2F;det&#x2F;</li><li>doubt &#x2F;daʊt&#x2F;</li><li>subtle &#x2F;ˈsʌtl&#x2F;</li><li>plumb &#x2F;plʌm&#x2F;</li></ul><h3 id="C-的发音规律"><a href="#C-的发音规律" class="headerlink" title="C 的发音规律"></a>C 的发音规律</h3><pre><code class="highlight mermaid">mindmap((C 的发音规律))  (字母发音)   /k/   /s/   /ʃ/   /tʃ/  (组合发音)    (sc)      /sk/      /s/    (ch)      /tʃ/      /k/    (ck)      /k/</code></pre><ol><li><p>C 通常读作 &#x2F;k&#x2F;</p></li><li><p>C 在音节中后面跟 E, I, Y 时，通常读作 &#x2F;s&#x2F;</p><p>在英语中它被称为 Soft C</p><ul><li>cent &#x2F;sent&#x2F;</li><li>city &#x2F;ˈsɪti&#x2F;</li><li>cycle &#x2F;ˈsaɪkl&#x2F;</li><li>cell &#x2F;sel&#x2F;</li><li>ice &#x2F;aɪs&#x2F;</li><li>city &#x2F;ˈsɪti&#x2F;</li></ul><p>有时候也会读作 &#x2F;ʃ&#x2F;，如</p><ul><li>ocean &#x2F;ˈəʊʃən&#x2F;</li><li>social &#x2F;ˈsəʊʃəl&#x2F;</li><li>special &#x2F;ˈspeʃəl&#x2F;</li></ul></li><li><p>C 在音节中后面跟 A, O, U 时，通常读作 &#x2F;k&#x2F;</p><p>在英语中它被称为 Hard C</p><ul><li>cat &#x2F;kæt&#x2F;</li><li>car &#x2F;kɑːr&#x2F;</li><li>cot &#x2F;kɒt&#x2F;</li><li>corn &#x2F;kɔːn&#x2F;</li><li>cut &#x2F;kʌt&#x2F;</li><li>cup &#x2F;kʌp&#x2F;</li></ul></li><li><p>C 与 S 组合成 sc 时，与上面类似。sc 后面跟 A, O, U 时，通常读作 &#x2F;sk&#x2F;，在 sc 后面跟 E, I, Y 时，读作 &#x2F;s&#x2F;</p><ul><li>scan &#x2F;skæn&#x2F;</li><li>scent &#x2F;sent&#x2F;</li><li>science &#x2F;ˈsaɪəns&#x2F;</li><li>scythe &#x2F;saɪð&#x2F;</li><li>scope &#x2F;skəʊp&#x2F;</li><li>sculpture &#x2F;ˈskʌlptʃər&#x2F;</li></ul></li><li><p>C 在音节中与 H 组合成 ch 时，通常读作 &#x2F;tʃ&#x2F;</p><ul><li>chat &#x2F;tʃæt&#x2F;</li><li>check &#x2F;tʃek&#x2F;</li><li>achieve &#x2F;əˈtʃiːv&#x2F;</li><li>chocolate &#x2F;ˈtʃɒklət&#x2F;</li><li>chunk &#x2F;tʃʌŋ&#x2F;</li></ul></li><li><p>C 在音节中与 H 组合成的 ch 有时读作 &#x2F;k&#x2F;</p><ul><li>character &#x2F;ˈkærəktər&#x2F;</li><li>chemistry &#x2F;ˈkemɪstri&#x2F;</li><li>anchor &#x2F;ˈæŋkər&#x2F;</li><li>ache &#x2F;eɪk&#x2F;</li></ul></li><li><p>C 在音节中与 K 组合成 ck 时，通常读作 &#x2F;k&#x2F;</p><ul><li>back &#x2F;bæk&#x2F;</li><li>black &#x2F;blæk&#x2F;</li><li>clock &#x2F;klɒk&#x2F;</li><li>duck &#x2F;dʌk&#x2F;</li><li>luck &#x2F;lʌk&#x2F;</li><li>sock &#x2F;sɒk&#x2F;</li></ul></li></ol><h3 id="D-的发音规律"><a href="#D-的发音规律" class="headerlink" title="D 的发音规律"></a>D 的发音规律</h3><ol><li><p>D 通常读作 &#x2F;d&#x2F;</p></li><li><p>D 有时候会读作 &#x2F;t&#x2F;</p><ul><li>advanced &#x2F;ədˈvɑːnst&#x2F;</li></ul></li><li><p>但在音节中的 dg 组合常读作 &#x2F;dʒ&#x2F;</p><ul><li>edge &#x2F;edʒ&#x2F;</li><li>judge &#x2F;dʒʌdʒ&#x2F;</li><li>bridge &#x2F;brɪdʒ&#x2F;</li><li>badge &#x2F;bædʒ&#x2F;</li><li>knowledge &#x2F;ˈnɒlɪdʒ&#x2F;</li></ul></li></ol><h3 id="F-的发音规律"><a href="#F-的发音规律" class="headerlink" title="F 的发音规律"></a>F 的发音规律</h3><ol><li><p>F 通常读作 &#x2F;f&#x2F;。</p><ul><li>fan &#x2F;fæn&#x2F;</li><li>feel &#x2F;fiːl&#x2F;</li><li>fish &#x2F;fɪʃ&#x2F;</li><li>food &#x2F;fuːd&#x2F;</li><li>fun &#x2F;fʌn&#x2F;</li></ul></li><li><p>极少数情况下会读作 &#x2F;v&#x2F;</p></li></ol><ul><li>of &#x2F;ɒv&#x2F;</li></ul><h3 id="G-的发音规律"><a href="#G-的发音规律" class="headerlink" title="G 的发音规律"></a>G 的发音规律</h3><pre><code class="highlight mermaid">mindmap((G 的发音规律))  (字母发音)   /g/   /dʒ/  (组合发音)    (dg)      /dʒ/    (gn)      /n/    (ng)      /ŋ/    (gh)      /g/</code></pre><ol><li><p>G 通常读作 &#x2F;g&#x2F;</p><ul><li>gap &#x2F;ɡæp&#x2F;</li><li>get &#x2F;ɡet&#x2F;</li><li>gift &#x2F;ɡɪft&#x2F;</li><li>go &#x2F;ɡəʊ&#x2F;</li><li>gun &#x2F;ɡʌn&#x2F;</li></ul></li><li><p>G 在音节中后面跟 E, I, Y 时，有时读作 &#x2F;dʒ&#x2F;，这被称为 Soft G</p><ul><li>age &#x2F;eɪdʒ&#x2F;</li><li>change &#x2F;tʃeɪndʒ&#x2F;</li><li>gym &#x2F;dʒɪm&#x2F;</li><li>giant &#x2F;ˈdʒaɪənt&#x2F;</li><li>imagine &#x2F;ɪˈmædʒɪn&#x2F;</li><li>general &#x2F;ˈdʒenrəl&#x2F;</li><li>gentle &#x2F;ˈdʒentl&#x2F;</li></ul><p>也有一些例外情况，称为 Hard G</p><ul><li>get &#x2F;ɡet&#x2F;</li><li>give &#x2F;ɡɪv&#x2F;</li></ul></li><li><p>音节中的 dg 组合常读作 &#x2F;dʒ&#x2F;</p><ul><li>knowledge &#x2F;ˈnɒlɪdʒ&#x2F;</li><li>edge &#x2F;edʒ&#x2F;</li><li>judge &#x2F;dʒʌdʒ&#x2F;</li><li>bridge &#x2F;brɪdʒ&#x2F;</li></ul></li><li><p>ng 在音节中的组合通常读作 &#x2F;ŋ&#x2F;</p><ul><li>bang &#x2F;bæŋ&#x2F;</li><li>length &#x2F;leŋθ&#x2F;</li><li>sing &#x2F;sɪŋ&#x2F;</li><li>song &#x2F;sɒŋ&#x2F;</li><li>hungry &#x2F;ˈhʌŋɡri&#x2F;</li></ul></li><li><p>G 在音节中与 N 组合成 gn 时，G 通常不发音</p><p>这被称为 Silent G，字母 K 也有类似的情况。</p><ul><li>gnaw &#x2F;nɔː&#x2F;</li><li>gnome &#x2F;nəʊm&#x2F;</li><li>gnat &#x2F;næt&#x2F;</li><li>gnu &#x2F;nuː&#x2F;</li><li>sign &#x2F;saɪn&#x2F;</li></ul></li><li><p>G 在音节中与 H 组合成的 gh 通常读作 &#x2F;g&#x2F;</p><ul><li>ghost &#x2F;ɡəʊst&#x2F;</li><li>ghastly &#x2F;ˈɡæstli&#x2F;</li><li>ghetto &#x2F;ˈɡetəʊ&#x2F;</li></ul></li></ol><h3 id="H-的发音规律"><a href="#H-的发音规律" class="headerlink" title="H 的发音规律"></a>H 的发音规律</h3><pre><code class="highlight mermaid">mindmap((H 的发音规律))  (字母发音)   /h/  (组合发音)    (th)      /θ/      /ð/    (ch)      /tʃ/      /k/    (gh)      /f/      不发音    (wh)      /w/      /h/    (ph)      /f/    (sh)      /ʃ/</code></pre><ol><li><p>H 通常读作 &#x2F;h&#x2F;</p><ul><li>hat &#x2F;hæt&#x2F;</li><li>help &#x2F;help&#x2F;</li><li>hit &#x2F;hɪt&#x2F;</li><li>hot &#x2F;hɒt&#x2F;</li><li>hut &#x2F;hʌt&#x2F;</li></ul></li><li><p>H 在音节中的与 T 组合成 th 通常读作 &#x2F;θ&#x2F;</p><ul><li>thank &#x2F;θæŋk&#x2F;</li><li>theory &#x2F;ˈθɪəri&#x2F;</li><li>think &#x2F;θɪŋk&#x2F;</li><li>thought &#x2F;θɔːt&#x2F;</li><li>thumb &#x2F;θʌm&#x2F;</li></ul></li><li><p>但上面的组合在定词、冠词、介词、连词或副词以及后面跟着 er 时，通常读作 &#x2F;ð&#x2F;</p><ul><li>that &#x2F;ðæt&#x2F;</li><li>the &#x2F;ðə&#x2F;</li><li>this &#x2F;ðɪs&#x2F;</li><li>those &#x2F;ðəʊz&#x2F;</li><li>father &#x2F;ˈfɑːðər&#x2F;</li></ul></li><li><p>H 在音节中与 C 组合成 ch 通常读作 &#x2F;tʃ&#x2F;</p><ul><li>chat &#x2F;tʃæt&#x2F;</li><li>check &#x2F;tʃek&#x2F;</li><li>achieve &#x2F;əˈtʃiːv&#x2F;</li><li>chocolate &#x2F;ˈtʃɒklət&#x2F;</li><li>chunk &#x2F;tʃʌŋ&#x2F;</li></ul></li><li><p>H 在音节中与 C 组合成的 ch 有时读作 &#x2F;k&#x2F;</p><ul><li>character &#x2F;ˈkærəktər&#x2F;</li><li>chemistry &#x2F;ˈkemɪstri&#x2F;</li><li>anchor &#x2F;ˈæŋkər&#x2F;</li><li>ache &#x2F;eɪk&#x2F;</li></ul></li><li><p>H 在音节中与 S 组合成 sh 通常读作 &#x2F;ʃ&#x2F;</p><ul><li>she &#x2F;ʃiː&#x2F;</li><li>ship &#x2F;ʃɪp&#x2F;</li><li>shoe &#x2F;ʃuː&#x2F;</li><li>shop &#x2F;ʃɒp&#x2F;</li><li>shut &#x2F;ʃʌt&#x2F;</li></ul></li><li><p>H 在音节中与 W 组合成 wh 通常读作 &#x2F;w&#x2F;</p><ul><li>what &#x2F;wɒt&#x2F;</li><li>when &#x2F;wen&#x2F;</li><li>which &#x2F;wɪtʃ&#x2F;</li><li>why &#x2F;waɪ&#x2F;</li></ul></li><li><p>在上面的组合中，如果后面跟着元音字母 O，通常读作 &#x2F;h&#x2F;</p><ul><li>who &#x2F;huː&#x2F;</li><li>whole &#x2F;həʊl&#x2F;</li><li>whose &#x2F;huːz&#x2F;</li><li>whom &#x2F;huːm&#x2F;</li></ul></li><li><p>H 在音节中的组合 gh 通常读作 &#x2F;f&#x2F;</p><ul><li>laugh &#x2F;lɑːf&#x2F;</li><li>enough &#x2F;ɪˈnʌf&#x2F;</li><li>rough &#x2F;rʌf&#x2F;</li><li>tough &#x2F;tʌf&#x2F;</li><li>cough &#x2F;kɒf&#x2F;</li></ul></li><li><p>H 在音节中的组合 gh 也可能不发音</p><ul><li>height &#x2F;haɪt&#x2F;</li><li>high &#x2F;haɪ&#x2F;</li><li>though &#x2F;ðəʊ&#x2F;</li></ul></li><li><p>H 在音节中的组合 ph 通常读作 &#x2F;f&#x2F;</p><ul><li>phase &#x2F;feɪz&#x2F;</li><li>phenomenon &#x2F;fɪˈnɒmɪnən&#x2F;</li><li>philosophy &#x2F;fɪˈlɒsəfi&#x2F;</li><li>physical &#x2F;ˈfɪzɪkl&#x2F;</li><li>photo &#x2F;ˈfəʊtəʊ&#x2F;</li></ul></li><li><p>H 在音节中处于 ex 后面组成 exh 时，H 通常不发音</p><ul><li>exhaust &#x2F;ɪɡˈzɔːst&#x2F;</li><li>exhibit &#x2F;ɪɡˈzɪbɪt&#x2F;</li></ul></li></ol><h3 id="J-的发音规律"><a href="#J-的发音规律" class="headerlink" title="J 的发音规律"></a>J 的发音规律</h3><ol><li><p>J 通常读作 &#x2F;dʒ&#x2F;</p><ul><li>jam &#x2F;dʒæm&#x2F;</li><li>jet &#x2F;dʒet&#x2F;</li><li>jingle &#x2F;ˈdʒɪŋɡl&#x2F;</li><li>job &#x2F;dʒɒb&#x2F;</li><li>jump &#x2F;dʒʌmp&#x2F;</li></ul></li></ol><h3 id="K-的发音规律"><a href="#K-的发音规律" class="headerlink" title="K 的发音规律"></a>K 的发音规律</h3><p>K 通常读作 &#x2F;k&#x2F;。</p><ol><li><p>K 在音节中与 N 组合成 kn 时，K 通常不发音</p><p>这被称为 Silent K</p><ul><li>knack &#x2F;næk&#x2F;</li><li>knee &#x2F;niː&#x2F;</li><li>knife &#x2F;naɪf&#x2F;</li><li>know &#x2F;nəʊ&#x2F;</li><li>knuckle &#x2F;ˈnʌkl&#x2F;</li></ul></li></ol><h3 id="L-的发音规律"><a href="#L-的发音规律" class="headerlink" title="L 的发音规律"></a>L 的发音规律</h3><p>L 通常读作 &#x2F;l&#x2F;。</p><ol><li><p>在音节中位于元音后面的 l 的发音也用 &#x2F;l&#x2F;表示，但是一种特殊的发音方式，称为模糊 L（Dark L）, 类似于呕的发音。</p><ul><li>all &#x2F;ɔːl&#x2F;</li><li>well &#x2F;wel&#x2F;</li><li>till &#x2F;tɪl&#x2F;</li><li>cold &#x2F;kəʊld&#x2F;</li><li>bull &#x2F;bʊl&#x2F;</li></ul></li><li><p>L 在音节中的处于元音 a、o、ou 和辅音 f、v、k、m 之间会产生元音化现象</p><ul><li>talk &#x2F;tɔːk&#x2F;</li><li>behalf &#x2F;bɪˈhɑːf&#x2F;</li><li>folk &#x2F;fəʊk&#x2F;</li><li>walk &#x2F;wɔːk&#x2F;</li><li>should &#x2F;ʃʊd&#x2F;</li><li>would &#x2F;wʊd&#x2F;</li><li>calm &#x2F;kɑːm&#x2F;</li><li>palm &#x2F;pɑːm&#x2F;</li></ul></li></ol><h3 id="M-的发音规律"><a href="#M-的发音规律" class="headerlink" title="M 的发音规律"></a>M 的发音规律</h3><p>M 通常读作 &#x2F;m&#x2F;。</p><h3 id="N-的发音规律"><a href="#N-的发音规律" class="headerlink" title="N 的发音规律"></a>N 的发音规律</h3><pre><code class="highlight mermaid">mindmap((N 的发音规律))  (字母发音)   /n/  (组合发音)    (mn)      /m/    (ng)      /ŋ/    (nk)      /ŋ/</code></pre><p>N 通常读作 &#x2F;n&#x2F;。</p><ol><li><p>N 在音节中与 M 组合成 mn 时，N 通常不发音</p><ul><li>column &#x2F;ˈkɒləm&#x2F;</li><li>condemn &#x2F;kənˈdem&#x2F;</li><li>autumn &#x2F;ˈɔːtəm&#x2F;</li><li>hymn &#x2F;hɪm&#x2F;</li></ul></li><li><p>N 在音节中与 G 组合成 ng 时，N 通常读作 &#x2F;ŋ&#x2F;</p><ul><li>bang &#x2F;bæŋ&#x2F;</li><li>length &#x2F;leŋθ&#x2F;</li><li>sing &#x2F;sɪŋ&#x2F;</li><li>song &#x2F;sɒŋ&#x2F;</li><li>hungry &#x2F;ˈhʌŋɡri&#x2F;</li></ul></li><li><p>N 在单词中后面跟着 K 时，N 通常发 &#x2F;ŋ&#x2F; 的音</p><ul><li>bank &#x2F;bæŋk&#x2F;</li><li>drink &#x2F;drɪŋk&#x2F;</li><li>donkey &#x2F;ˈdɒŋki&#x2F;</li><li>thunk &#x2F;θʌŋk&#x2F;</li></ul></li></ol><h3 id="P-的发音规律"><a href="#P-的发音规律" class="headerlink" title="P 的发音规律"></a>P 的发音规律</h3><p>P 通常读作 &#x2F;p&#x2F;。</p><ol><li><p>P 在音节中与 H 组合成 ph 时，通常读作 &#x2F;f&#x2F;</p><ul><li>phase &#x2F;feɪz&#x2F;</li><li>phenomenon &#x2F;fɪˈnɒmɪnən&#x2F;</li><li>philosophy &#x2F;fɪˈlɒsəfi&#x2F;</li><li>physical &#x2F;ˈfɪzɪkl&#x2F;</li><li>photo &#x2F;ˈfəʊtəʊ&#x2F;</li></ul></li></ol><h3 id="Q-的发音规律"><a href="#Q-的发音规律" class="headerlink" title="Q 的发音规律"></a>Q 的发音规律</h3><p>Q 通常读作 &#x2F;k&#x2F;。Q 通常与 U 一起使用，读作 &#x2F;kw&#x2F;</p><ul><li>quarter &#x2F;ˈkwɔːtər&#x2F;</li><li>queen &#x2F;kwiːn&#x2F;</li><li>quick &#x2F;kwɪk&#x2F;</li><li>quote &#x2F;kwəʊt&#x2F;</li></ul><h3 id="R-的发音规律"><a href="#R-的发音规律" class="headerlink" title="R 的发音规律"></a>R 的发音规律</h3><p>R 通常读作 &#x2F;r&#x2F;。</p><ol><li><p>R 在音节中的组合 wr 通常读作 &#x2F;r&#x2F;</p><ul><li>wrap &#x2F;ræp&#x2F;</li><li>wreck &#x2F;rek&#x2F;</li><li>wrist &#x2F;rɪst&#x2F;</li><li>wrong &#x2F;rɒŋ&#x2F;</li><li>wrinkle &#x2F;ˈrɪŋkl&#x2F;</li></ul></li><li><p>R 在音节中的组合 rh 通常读作 &#x2F;r&#x2F;</p><ul><li>rhyme &#x2F;raɪm&#x2F;</li><li>rhythm &#x2F;ˈrɪðəm&#x2F;</li></ul></li></ol><h3 id="S-的发音规律"><a href="#S-的发音规律" class="headerlink" title="S 的发音规律"></a>S 的发音规律</h3><p>S 通常读作 &#x2F;s&#x2F;。</p><pre><code class="highlight mermaid">mindmap  ((S 的发音规律))   (字母发音)      /s/      /z/   (组合发音)      (su)        /ʃ/      (sure)        /ʒər/      (sion)        /ʃən/        /ʒən/</code></pre><ol><li><p>有一些情况下，S 会发 &#x2F;z&#x2F; 音</p><ul><li>is &#x2F;ɪz&#x2F;</li><li>was &#x2F;wɒz&#x2F;</li><li>his &#x2F;hɪz&#x2F;</li><li>has &#x2F;hæz&#x2F;</li></ul></li><li><p>S 在音节中与 U 组合成 su 时并且是重读音节时，通常读作 &#x2F;ʃ&#x2F;</p><ul><li>sure &#x2F;ʃʊər&#x2F;</li><li>sugar &#x2F;ˈʃʊɡər&#x2F;</li><li>assure &#x2F;əˈʃʊər&#x2F;</li></ul></li><li><p>sure 的组合通常读作 &#x2F;ʒər&#x2F;</p><ul><li>measure &#x2F;ˈmeʒər&#x2F;</li><li>pleasure &#x2F;ˈpleʒər&#x2F;</li><li>treasure &#x2F;ˈtreʒər&#x2F;</li></ul></li><li><p>S 在音节中与 H 组合成 sh 时，通常读作 &#x2F;ʃ&#x2F;</p><p>见于 <a href="#H-%E7%9A%84%E5%8F%91%E9%9F%B3%E8%A7%84%E5%BE%8B">H 的发音规律</a></p></li><li><p>S 在音节中与 ion 组合成 sion 时，通常读作 &#x2F;ʃ(ə)n&#x2F; 或 &#x2F;ʒən&#x2F;</p><ul><li>vision &#x2F;ˈvɪʒən&#x2F;</li><li>decision &#x2F;dɪˈsɪʒən&#x2F;</li><li>version &#x2F;ˈvɜːrʒən&#x2F;</li><li>explosion &#x2F;ɪkˈspləʊʒən&#x2F;</li><li>confusion &#x2F;kənˈfjuːʒən&#x2F;</li></ul></li></ol><h3 id="T-的发音规律"><a href="#T-的发音规律" class="headerlink" title="T 的发音规律"></a>T 的发音规律</h3><pre><code class="highlight mermaid">mindmap  ((T 的发音规律))   (字母发音)      /t/   (组合发音)      (th)        /θ/        /ð/      (tch)        /tʃ/      (tr)        /tr/      (ture)        /tʃ/      (tu)        /ʃ/</code></pre><ol><li><p>T 通常读作 &#x2F;t&#x2F;。</p></li><li><p>T 在音节中与 H 组合成 th 时，见于 <a href="#H-%E7%9A%84%E5%8F%91%E9%9F%B3%E8%A7%84%E5%BE%8B">H 的发音规律</a></p><ul><li><p>thank &#x2F;θæŋk&#x2F;</p></li><li><p>theory &#x2F;ˈθɪəri&#x2F;</p></li><li><p>think &#x2F;θɪŋk&#x2F;</p></li><li><p>thought &#x2F;θɔːt&#x2F;</p></li><li><p>thumb &#x2F;θʌm&#x2F;</p></li><li><p>that &#x2F;ðæt&#x2F;</p></li><li><p>the &#x2F;ðə&#x2F;</p></li><li><p>this &#x2F;ðɪs&#x2F;</p></li><li><p>those &#x2F;ðəʊz&#x2F;</p></li><li><p>father &#x2F;ˈfɑːðər&#x2F;</p></li></ul></li><li><p>T 在音节中的 ia, io 前面的 t 通常读作 &#x2F;ʃ&#x2F;</p><ul><li>partial &#x2F;ˈpɑːʃəl&#x2F;</li><li>nation &#x2F;ˈneɪʃən&#x2F;</li><li>situation &#x2F;ˌsɪtjʊˈeɪʃən&#x2F;</li><li>action &#x2F;ˈækʃən&#x2F;</li><li>question &#x2F;ˈkwestʃən&#x2F;</li></ul></li><li><p>T 在音节中与 U 组合成 ture 时，T 通常读作 &#x2F;tʃ&#x2F;</p><ul><li>nature &#x2F;ˈneɪtʃər&#x2F;</li><li>picture &#x2F;ˈpɪktʃər&#x2F;</li><li>future &#x2F;ˈfjuːtʃər&#x2F;</li><li>situation &#x2F;ˌsɪtʃuˈeɪʃən&#x2F;</li></ul></li><li><p>T 在音节中与 U 组合成 tu 时，T 有时读作 &#x2F;ʃ&#x2F;</p><ul><li>situation &#x2F;ˌsɪtʃuˈeɪʃən&#x2F;</li></ul></li><li><p>T 在音节中与 CH 组合成 tch 时，通常读作 &#x2F;tʃ&#x2F;</p><ul><li>catch &#x2F;kætʃ&#x2F;</li><li>watch &#x2F;wɒtʃ&#x2F;</li><li>match &#x2F;mætʃ&#x2F;</li><li>stitch &#x2F;stɪtʃ&#x2F;</li><li>witch &#x2F;wɪtʃ&#x2F;</li></ul></li><li><p>T 在音节中与 R 组合成 tr 时，通常读作 &#x2F;tr&#x2F;, &#x2F;t&#x2F; 在这里是清音</p><ul><li>track &#x2F;træk&#x2F;</li><li>train &#x2F;treɪn&#x2F;</li><li>tree &#x2F;triː&#x2F;</li><li>try &#x2F;traɪ&#x2F;</li><li>true &#x2F;truː&#x2F;</li></ul></li></ol><h3 id="V-的发音规律"><a href="#V-的发音规律" class="headerlink" title="V 的发音规律"></a>V 的发音规律</h3><p>V 通常读作 &#x2F;v&#x2F;。</p><h3 id="W-的发音规律"><a href="#W-的发音规律" class="headerlink" title="W 的发音规律"></a>W 的发音规律</h3><p>W 通常读作 &#x2F;w&#x2F;。</p><pre><code class="highlight mermaid">mindmap  ((W 的发音规律))   (字母发音)      /w/   (组合发音)      (wh)        /w/      (wr)        /r/      (who)         W 不发音      (在元音字母后面)        半元音</code></pre><ol><li><p>W 在音节中在元音后面会变成半元音（Semi-vowel）。</p><ul><li>saw &#x2F;sɔː&#x2F;</li><li>nephew &#x2F;ˈnɛfjuː&#x2F;</li><li>cow &#x2F;kaʊ&#x2F;</li><li>now &#x2F;naʊ&#x2F;</li><li>low &#x2F;ləʊ&#x2F;</li><li>how &#x2F;haʊ&#x2F;</li></ul></li><li><p>W 在音节中与 H 组合成 wh 时 通常读作 &#x2F;w&#x2F;</p><ul><li>what &#x2F;wɒt&#x2F;</li><li>when &#x2F;wen&#x2F;</li><li>which &#x2F;wɪtʃ&#x2F;</li><li>why &#x2F;waɪ&#x2F;</li></ul></li><li><p>W 在音节中的组合 who, W 通常不发音</p><ul><li>who &#x2F;huː&#x2F;</li><li>whole &#x2F;həʊl&#x2F;</li><li>whose &#x2F;huːz&#x2F;</li></ul></li><li><p>W 在音节中的组合 wr 时常读作 &#x2F;r&#x2F;，W 不发音</p><ul><li>wrap &#x2F;ræp&#x2F;</li><li>wreck &#x2F;rek&#x2F;</li><li>wrist &#x2F;rɪst&#x2F;</li><li>write &#x2F;raɪt&#x2F;</li><li>wrong &#x2F;rɒŋ&#x2F;</li><li>wrinkle &#x2F;ˈrɪŋkl&#x2F;</li></ul></li></ol><h3 id="X-的发音规律"><a href="#X-的发音规律" class="headerlink" title="X 的发音规律"></a>X 的发音规律</h3><ol><li><p>X 在音节中的中间和结尾通常读作 &#x2F;ks&#x2F;。</p><ul><li>box &#x2F;bɒks&#x2F;</li><li>six &#x2F;sɪks&#x2F;</li><li>mix &#x2F;mɪks&#x2F;</li><li>fox &#x2F;fɒks&#x2F;</li><li>tax &#x2F;tæks&#x2F;</li></ul></li><li><p>X 在单词中与 E 组合成 xe 时，X 通常读作 &#x2F;gz&#x2F;。</p><ul><li>example &#x2F;ɪɡˈzɑːmpl&#x2F;</li><li>exam &#x2F;ɪɡˈzæm&#x2F;</li><li>exact &#x2F;ɪɡˈzækt&#x2F;</li></ul></li><li><p>X 在单词的起始位置通常读作 &#x2F;z&#x2F;。</p><ul><li>xerox &#x2F;ˈzɪərɒks&#x2F;</li><li>xylophone &#x2F;ˈzaɪləfəʊn&#x2F;</li></ul></li></ol><h3 id="Y-的发音规律"><a href="#Y-的发音规律" class="headerlink" title="Y 的发音规律"></a>Y 的发音规律</h3><p>Y 可以作为元音字母，也可以作为辅音字母。作为元音字母时，Y 通常读作 &#x2F;aɪ&#x2F; 或 &#x2F;ɪ&#x2F;，与 I 的发音规律类似。</p><p>作为辅音字母时，Y 通常读作 &#x2F;j&#x2F;。</p><ol><li><p>Y 作为元音字母时并在重音节中发 &#x2F;aɪ&#x2F; 的音</p><ul><li>my &#x2F;maɪ&#x2F;</li><li>by &#x2F;baɪ&#x2F;</li><li>fly &#x2F;flaɪ&#x2F;</li><li>sky &#x2F;skaɪ&#x2F;</li><li>cry &#x2F;kraɪ&#x2F;</li><li>try &#x2F;traɪ&#x2F;</li></ul></li><li><p>Y 作为元音字母时并在非重音节中发 &#x2F;ɪ&#x2F; 的音</p><ul><li>happy &#x2F;ˈhæpi&#x2F;</li><li>baby &#x2F;ˈbeɪbi&#x2F;</li><li>city &#x2F;ˈsɪti&#x2F;</li><li>family &#x2F;ˈfæmɪli&#x2F;</li><li>carry &#x2F;ˈkæri&#x2F;</li></ul></li><li><p>Y 作为辅音字母时的发音规律</p><ul><li>yes &#x2F;jes&#x2F;</li><li>yellow &#x2F;ˈjeləʊ&#x2F;</li><li>young &#x2F;jʌŋ&#x2F;</li><li>year &#x2F;jɪər&#x2F;</li><li>you &#x2F;juː&#x2F;</li></ul></li></ol><h3 id="Z-的发音规律"><a href="#Z-的发音规律" class="headerlink" title="Z 的发音规律"></a>Z 的发音规律</h3><ol><li><p>Z 通常读作 &#x2F;z&#x2F;。</p><ul><li>zoo &#x2F;zuː&#x2F;</li><li>zero &#x2F;ˈzɪərəʊ&#x2F;</li><li>zip &#x2F;zɪp&#x2F;</li><li>zone &#x2F;zəʊn&#x2F;</li><li>buzz &#x2F;bʌz&#x2F;</li></ul></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;辅音字母的读音通常是辅音字母发音的辅音部份。但是存在非常多的例外情况。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;字母&lt;/th&gt;
&lt;th&gt;常见&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;组合发音&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;&amp;#x2F;b&amp;#x2F;&lt;/td&gt;
&lt;td&gt;不发音&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;&amp;#x2F;k&amp;#x2F; 和 &amp;#x2F;s&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;tʃ&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;&amp;#x2F;d&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;dʒ&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;&amp;#x2F;f&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;v&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G&lt;/td&gt;
&lt;td&gt;&amp;#x2F;g&amp;#x2F; 和 &amp;#x2F;dʒ&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ŋ&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H&lt;/td&gt;
&lt;td&gt;&amp;#x2F;h&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;θ&amp;#x2F; &amp;#x2F;ð&amp;#x2F; &amp;#x2F;tʃ&amp;#x2F; &amp;#x2F;ʃ&amp;#x2F; &amp;#x2F;w&amp;#x2F; &amp;#x2F;f&amp;#x2F; 不发音&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;J&lt;/td&gt;
&lt;td&gt;&amp;#x2F;dʒ&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;K&lt;/td&gt;
&lt;td&gt;&amp;#x2F;k&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L&lt;/td&gt;
&lt;td&gt;&amp;#x2F;l&amp;#x2F;&lt;/td&gt;
&lt;td&gt;元音化&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M&lt;/td&gt;
&lt;td&gt;&amp;#x2F;m&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;&amp;#x2F;n&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ŋ&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P&lt;/td&gt;
&lt;td&gt;&amp;#x2F;p&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;f&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Q&lt;/td&gt;
&lt;td&gt;&amp;#x2F;k&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;kw&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;R&lt;/td&gt;
&lt;td&gt;&amp;#x2F;r&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;r&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S&lt;/td&gt;
&lt;td&gt;&amp;#x2F;s&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;z&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ʃ&amp;#x2F; &amp;#x2F;ʒer&amp;#x2F; &amp;#x2F;ʃ(ə)n&amp;#x2F; &amp;#x2F;ʒən&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;&amp;#x2F;t&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ʃ&amp;#x2F; &amp;#x2F;tʃ&amp;#x2F; &amp;#x2F;tr&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;V&lt;/td&gt;
&lt;td&gt;&amp;#x2F;v&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;W&lt;/td&gt;
&lt;td&gt;&amp;#x2F;w&amp;#x2F;&lt;/td&gt;
&lt;td&gt;元音化&lt;/td&gt;
&lt;td&gt;不发音&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ks&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;gz&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;z&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td&gt;&amp;#x2F;j&amp;#x2F; &amp;#x2F;aɪ&amp;#x2F; &amp;#x2F;ɪ&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Z&lt;/td&gt;
&lt;td&gt;&amp;#x2F;z&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;</summary>
    
    
    
    <category term="English" scheme="https://blog.esonwong.com/categories/English/"/>
    
    
    <category term="English" scheme="https://blog.esonwong.com/tags/English/"/>
    
  </entry>
  
  <entry>
    <title>ESP8266EX 自动下载电路</title>
    <link href="https://blog.esonwong.com/esp8266-auto-flashing/"/>
    <id>https://blog.esonwong.com/esp8266-auto-flashing/</id>
    <published>2024-07-07T06:15:53.000Z</published>
    <updated>2026-02-27T10:20:27.158Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://api-next.esonwong.com/blog-banner?title=ESP-12F%20%E8%87%AA%E5%8A%A8%E4%B8%8B%E8%BD%BD%E7%94%B5%E8%B7%AF" alt="ESP-12F 自动下载电路"></p><p>ESP-12F 是一款集成了 ESP8266EX 芯片的模块，在 ESP-12F 上 GPIO0 引脚 在 EN 引脚上升沿（从低电平到高电平）时，如果 GPIO0 引脚为低电平，ESP-12F 将进入下载模式。</p><span id="more"></span><p><em>在电子设备中，EN 引脚（Enable Pin），也称为使能引脚，是一个控制信号引脚，用于控制芯片或模块的使能状态。当 EN 引脚为高电平时，芯片或模块处于工作状态；当 EN 引脚为低电平时，芯片或模块处于待机或关断状态。</em></p><p>所以可以用 USB 转 TTL 串口芯片通过控制 GPIO0 和 EN 引脚的电平，来实现自动下载固件和进入运行模式，而不需要增加一个下载按键。</p><h2 id="USB-转-TTL-串口芯片"><a href="#USB-转-TTL-串口芯片" class="headerlink" title="USB 转 TTL 串口芯片"></a>USB 转 TTL 串口芯片</h2><p>USB 转 TTL 串口芯片通常有 DTR, RTS, TXD, RXD 等引脚，其中 DTR 和 RTS 引脚则可以用来控制 ESP12F 的 GPIO0 和 EN 引脚。TXD 和 RXD 用于串口通信，下载固件时传输固件数据。</p><p><strong>DTR：</strong> Data Terminal Ready，数据终端就绪，用于控制数据终端设备是否准备好接收数据，当 DTR 为高电平时，表示数据终端设备准备好接收数据。</p><p><strong>RTS：</strong> Request To Send，请求发送，用于控制数据终端设备发送数据的请求，当 RTS 为高电平时，表示数据终端设备请求发送数据。</p><p><strong>TXD：</strong> Transmit Data，发送数据，用于发送数据。</p><p><strong>RXD：</strong> Receive Data，接收数据，用于接收数据。</p><h2 id="自动下载电路"><a href="#自动下载电路" class="headerlink" title="自动下载电路"></a>自动下载电路</h2><p>以 USB 转 TTL 串口芯片 CH340C 为例 GPIO0 和 EN 与 DTR 和 RTS 的连接方式如下：</p><p><img src="/./esp8266-auto-flashing/auto-download.webp" alt="自动下载电路"></p><ul><li>EN 和 GPIO0 通过两个上拉电阻连接到 VCC，默认为高电平</li><li>EN 连接一个电容，让 EN 引脚在电平变化时有一个延时</li><li>EN 连接到 NPN 三极管 Q1 的发射极</li><li>DTR 连接到 Q1 的基极</li><li>RTS 连接到 Q1 的发射极，和 DTR 共同控制 EN 的电平</li><li>GPIO0 连接到 NPN 三极管 Q2 的发射极</li><li>RTS 连接到 Q2 的基极</li><li>DTR 连接到 Q2 的发射极，和 RTS 共同控制 GPIO0 的电平</li></ul><h3 id="自动下载过程中电路的状态变化"><a href="#自动下载过程中电路的状态变化" class="headerlink" title="自动下载过程中电路的状态变化"></a>自动下载过程中电路的状态变化</h3><ol><li><p>初始状态 DTR 和 RTS、EN 和 GPIO0 均为高电平</p><ul><li>Q1 和 Q2 导通</li><li>ESP-12F 处于运行模式</li></ul><p><img src="/./esp8266-auto-flashing/running-mode.webp" alt="运行模式"></p></li><li><p>当我们用 esptool 开时下载固件时，esptool 会先拉低串口芯片的 RTS</p><ul><li>Q1: 维持导通</li><li>EN: 通过 Q1 连接到低电平的 RTS，被拉为低电平</li><li>Q2: 因为连接到 Q2 的基极的 RTS 为低电平，不导通</li><li>GPIO0: 维持高电平</li></ul><p><img src="/./esp8266-auto-flashing/reset-pulled-down.webp" alt="ESP-12F 停止工作"></p><p>EN 会在电容放完电之后被拉低，ESP-12F 停止工作。</p></li><li><p>然后 esptool 会拉低 DTR, 拉高 RTS</p><ul><li>Q1: 不导通</li><li>Q2: 导通</li><li>GPIO0: 通过 Q2 连接到低电平的 DTR，被拉为低电平</li><li>EN: 通过 Q1 连接到高电平的 RTS，给电容充电的同时，逐渐拉为高电平</li></ul><p><img src="/./esp8266-auto-flashing/enter-download-mode.webp" alt="ESP-12F 进入下载模式"></p><p>此时 ESP-12F 进入下载模式</p></li><li><p>esptool 会让串口芯片发送固件</p></li></ol><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><a href="https://docs.ai-thinker.com/_media/esp8266/docs/esp-12f_product_specification_en.pdf">ESP8266EX 技术规格书</a></li><li><a href="https://wmsc.lcsc.com/wmsc/upload/file/pdf/v2/lcsc/2403131141_WCH-Jiangsu-Qin-Heng-CH340C_C7464026.pdf">CH340C 说明书</a></li></ul><h2 id="广告"><a href="#广告" class="headerlink" title="广告"></a>广告</h2><p>本文由我在制作 E-ink Todo List 墨水屏待办 DIY 的 PCB 板时总结的，我还写了一篇<a href="/e-ink-screen-todo-list-creation-turial">《墨水屏 Todo List 制作教程》</a>。</p><p>👋 E-ink Todo List 墨水屏待办 DIY 的 PCB 现已上架售卖 😇，此 PCB 板可代替教程中的开发板和屏幕转接板。爱好 DIY 的朋友们可以下单购买制作。</p><p>E-ink Todo List 墨水屏待办的成品正在起来的路上！！！</p><p>下面是 PCB 板的购买途径。</p><div style="display: flex; max-width:100%; flex-wrap: wrap; align-items: stretch; justify-content: space-between;">  <div style="display: flex; justify-content: center; flex-direction: column; align-items: center;">    <h3>EsonWong 的微信小店</h3>    <img style="max-width:360px" src="/asset/e-ink-todo-list-pcb.jpeg" alt="E-ink Todo List PCB" />   </div></div>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://api-next.esonwong.com/blog-banner?title=ESP-12F%20%E8%87%AA%E5%8A%A8%E4%B8%8B%E8%BD%BD%E7%94%B5%E8%B7%AF&quot; alt=&quot;ESP-12F 自动下载电路&quot;&gt;&lt;/p&gt;
&lt;p&gt;ESP-12F 是一款集成了 ESP8266EX 芯片的模块，在 ESP-12F 上 GPIO0 引脚 在 EN 引脚上升沿（从低电平到高电平）时，如果 GPIO0 引脚为低电平，ESP-12F 将进入下载模式。&lt;/p&gt;</summary>
    
    
    
    
    <category term="esp8266" scheme="https://blog.esonwong.com/tags/esp8266/"/>
    
    <category term="PCB" scheme="https://blog.esonwong.com/tags/PCB/"/>
    
    <category term="嵌入式" scheme="https://blog.esonwong.com/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    
  </entry>
  
  <entry>
    <title>浅聊 esp8266</title>
    <link href="https://blog.esonwong.com/esp8266/"/>
    <id>https://blog.esonwong.com/esp8266/</id>
    <published>2024-06-02T08:25:27.000Z</published>
    <updated>2026-02-27T10:20:27.159Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/./esp8266/cover.webp" alt="PCB"></p><p>最近在做 <a href="https://www.einktodo.com/">E-ink Todo List</a> 项目，用到了 ESP8266，所以就简单的聊一下 ESP8266。</p><span id="more"></span><p><img src="/./esp8266/e-ink-todo-list.webp" alt="E-ink Todo List 网站"></p><h2 id="ESP8266EX"><a href="#ESP8266EX" class="headerlink" title="ESP8266EX"></a>ESP8266EX</h2><p>ESP8266 是由乐鑫科技推出的一个芯片系列，ESP8266EX 是其中的一款。</p><p><img src="/./esp8266/esp8266-pin-payout.webp" alt="ESP8266EX Pin Layout"></p><p>ESP8266EX 提供了完整 TCP&#x2F;IP 协议栈和 WiFi 功能，一个 10 位 ADC，支持 SPI、I2C、UART、PWM 等接口。是一个非常适合用于做一些需要无线联网且由电池供电的项目的芯片。</p><h2 id="ESP-12F-模组"><a href="#ESP-12F-模组" class="headerlink" title="ESP-12F 模组"></a>ESP-12F 模组</h2><p><img src="https://aithinker-static.oss-cn-shenzhen.aliyuncs.com/officialwebsite/bgpic/module_1.png" alt="ESP-12F 模组"></p><p>为了快速创造我想要的东西，我使用了安可信的 <a href="https://docs.ai-thinker.com/_media/esp8266/docs/esp-12f_product_specification_en.pdf">ESP-12F</a> 模组。使用 SMD 封装方式。它集成了 ESP8266EX 芯片，WiFi 天线和外部闪存的模组。</p><p>SMD 是 Surface-Mounted Device（表面贴装设备）的缩写。起源于 1960 年代，最初由美国 IBM 公司进行技术研发，之后于 1980 年代后期渐趋成熟。它的特点是元件直接贴装在电路板的表面，而不需要通过电路板的孔进行焊接。这种封装方式使得元件可以更小，更轻，而且可以在电路板的两面进行贴装。SMD0805 和 SMD0603 是常见的 SMD 封装规格，0805 封装的尺寸是 0.08 英寸 x 0.05 英寸（ 2.0mm x 1.25mm），0603 封装的尺寸是 0.06 英寸 x 0.03 英寸（1.6mm x 0.8mm）。</p><p>ESP-12F 是特殊尺寸的 SMD 封装。</p><p><img src="/./esp8266/esp12.png" alt="ESP-12F Pin Layout"></p><h3 id="固件下载"><a href="#固件下载" class="headerlink" title="固件下载"></a>固件下载</h3><p>项目中用了 USB 转 TTL 串口芯片 CH340C 通过下面的引脚来实现自动下载固件和进入运行模式。</p><ul><li><p>ENABLE</p><p>使能引脚，当使能引脚为高电平时，芯片或模块处于工作状态；当使能引脚为低电平时，芯片或模块处于待机或关断状态。</p></li><li><p>GPIO0(FLASH)</p><p>用于控制 ESP8266EX 进入下载模式。当 GPIO0 为低电平时, 让 ENABLE 引脚上升沿（从低电平到高电平）时，ESP8266EX 将进入下载模式。当 ESP8266EX 处于运行模式时，GPIO0 引脚可作为普通的输入输出引脚使用。</p></li><li><p>GPIO1(TX)</p><p>UART 通用串口通讯的接收引脚</p></li><li><p>GPIO3(RX)</p><p>UART 通用串口通讯的接收引脚</p></li></ul><p>我会单独写一篇文章详细介绍自动下载电路的原理。</p><h3 id="SPI-电路"><a href="#SPI-电路" class="headerlink" title="SPI 电路"></a>SPI 电路</h3><p>SPI(Serial Peripheral Interface) 是一种芯片与芯片的外围设备通信协议。需要用到 4 条线路，分别是：</p><ul><li><p>SCK(Serial Clock)</p><p>串行时钟信号，由主设备产生，用于对齐数据传输的间隔。</p></li><li><p>MOSI(Master Out Slave In)</p><p>主设备输出，从设备输入，主设备发送数据到从设备。</p></li><li><p>MISO(Master In Slave Out)</p><p>主设备输入，从设备输出，从设备发送数据到主设备。</p></li><li><p>SS(Slave Select) 或 CS(Chip Select)</p><p>从设备选择信号，由主设备产生，用于选择从设备。</p></li></ul><p>我在项目中使用 SPI 通信方式与 E-ink 屏幕通信。除了上面的 4 条线路外，还用要控制 E-ink 屏幕的复位，以及读取 E-ink 屏幕是否忙碌的状态。</p><p>我在 ESP-12F 上使用了下面的引脚：</p><table><thead><tr><th>ESP-12F</th><th>E-ink 驱动电路</th><th>功能</th></tr></thead><tbody><tr><td>GPIO2</td><td>RST</td><td>控制屏幕复位的引脚，低电平复位屏幕</td></tr><tr><td>GPIO4</td><td>DC</td><td>控制引脚屏幕的数据和命令模式，高电平表示数据，低电平表示命令</td></tr><tr><td>GPIO5</td><td>BUSY</td><td>屏幕忙碌状态输出引脚，高电平表示屏幕忙碌，低电平表示屏幕空闲</td></tr><tr><td>GPIO13(MOSI)</td><td>DIN</td><td>SPI 通信 MOSI 引脚</td></tr><tr><td>GPIO14(SCK)</td><td>CLK</td><td>SPI 通信 SCK 引脚</td></tr><tr><td>GPIO15(CS)</td><td>CS</td><td>SPI 片选引脚</td></tr></tbody></table><h3 id="ADC-引脚"><a href="#ADC-引脚" class="headerlink" title="ADC 引脚"></a>ADC 引脚</h3><p>ESP-12F 有一个 10 位 ADC，可以用来读取模拟量信号。我将会用这个引脚来读取电池电压。ADC0 引脚可读取 0-1V 的电压。需要使用一个电阻分压电路将电池电压分压到 0-1V 范围内再通过 ADC0 引脚读取。</p><h2 id="编程平台"><a href="#编程平台" class="headerlink" title="编程平台"></a>编程平台</h2><p>ESP8266EX 的开发环境有很多，我选择了 PlatformIO。一开始我是使用 Arduino IDE 来开发的，但是 Arduino IDE 的功能太过简单，不适合太复杂的项目。</p><p>我使用 VSCode 安装了 PlatformIO 插件，通过 PlatformIO 的 CLI 工具来编译和下载固件。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><a href="https://www.espressif.com/en/products/socs/esp8266">ESP8266EX</a></li><li><a href="https://docs.ai-thinker.com/_media/esp8266/docs/esp-12f_product_specification_en.pdf">ESP-12F</a></li></ul><h2 id="广告"><a href="#广告" class="headerlink" title="广告"></a>广告</h2><p>本文由我在制作 E-ink Todo List 墨水屏待办 DIY 的 PCB 板时总结的，我还写了一篇<a href="/e-ink-screen-todo-list-creation-turial">《墨水屏 Todo List 制作教程》</a>。</p><p>👋 E-ink Todo List 墨水屏待办 DIY 的 PCB 现已上架售卖 😇，此 PCB 板可代替教程中的开发板和屏幕转接板。爱好 DIY 的朋友们可以下单购买制作。</p><p>E-ink Todo List 墨水屏待办的成品正在起来的路上！！！</p><p>下面是 PCB 板的购买途径。</p><div style="display: flex; max-width:100%; flex-wrap: wrap; align-items: stretch; justify-content: space-between;">  <div style="display: flex; justify-content: center; flex-direction: column; align-items: center;">    <h3>EsonWong 的微信小店</h3>    <img style="max-width:360px" src="/asset/e-ink-todo-list-pcb.jpeg" alt="E-ink Todo List PCB" />   </div></div>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;/./esp8266/cover.webp&quot; alt=&quot;PCB&quot;&gt;&lt;/p&gt;
&lt;p&gt;最近在做 &lt;a href=&quot;https://www.einktodo.com/&quot;&gt;E-ink Todo List&lt;/a&gt; 项目，用到了 ESP8266，所以就简单的聊一下 ESP8266。&lt;/p&gt;</summary>
    
    
    
    
    <category term="esp8266" scheme="https://blog.esonwong.com/tags/esp8266/"/>
    
    <category term="PCB" scheme="https://blog.esonwong.com/tags/PCB/"/>
    
    <category term="嵌入式" scheme="https://blog.esonwong.com/tags/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    
  </entry>
  
  <entry>
    <title>墨水屏 Todo List 制作教程</title>
    <link href="https://blog.esonwong.com/e-ink-screen-todo-list-creation-turial/"/>
    <id>https://blog.esonwong.com/e-ink-screen-todo-list-creation-turial/</id>
    <published>2024-03-08T16:00:00.000Z</published>
    <updated>2026-02-27T10:20:27.140Z</updated>
    
    <content type="html"><![CDATA[<style>.post-body img {   max-height: 800px;}</style><script> window.difyChatbotConfig = {  token: 'gc7zMgtbwd6BAygx',  baseUrl: 'https://dify.esonwong.com' }</script><script src="https://dify.esonwong.com/embed.min.js" id="gc7zMgtbwd6BAygx" defer></script><style>  #dify-chatbot-bubble-button {    background-color: #1C64F2 !important;  }  #dify-chatbot-bubble-window {    width: 24rem !important;    height: 40rem !important;  }</style><p><img src="/./e-ink-screen-todo-list-creation-turial/cover.webp" alt="墨水屏 Todo List 制作教程"></p><p>我在 Twitter 发布的一条 tweet，写了我使用了墨水屏制作了一个 Todo List，可以同步苹果提醒的全家待办列表。收到了很多推友的关注，所以我决定写一个教程，帮助大家制作一个墨水屏 Todo List。</p><p>同步服务由我开发的 <a href="https://einktodo.com/">einktodo.com</a> 提供。</p><span id="more"></span><blockquote class="twitter-tweet"><p lang="zh" dir="ltr">同步苹果提醒的全家待办列表<br><br>创造真的令人感到愉快 <a href="https://t.co/guVXon73n5">https://t.co/guVXon73n5</a> <a href="https://t.co/Rb9Fg3fUP7">pic.twitter.com/Rb9Fg3fUP7</a></p>&mdash; Eson Wong (@eson000) <a href="https://twitter.com/eson000/status/1746692171141398841?ref_src=twsrc%5Etfw">January 15, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script><h2 id="更新记录"><a href="#更新记录" class="headerlink" title="更新记录"></a>更新记录</h2><ol><li>2024-04 支持了滴答清单的同步</li></ol><h2 id="对成品感兴趣吗？"><a href="#对成品感兴趣吗？" class="headerlink" title="对成品感兴趣吗？"></a>对成品感兴趣吗？</h2><p>我正在尝试将墨水屏 Todo List 制作成产品，如果你对这个产品感兴趣，可以在前往 <a href="https://einktodo.com/">einktodo.com</a> 加入行等待邮件列表，你将会收到产品制作的最新进度信息。</p><p>如果你对 E-ink Todo List DIY 也有兴趣和有意购买 DIY 电路板、DIY 套件、3D 打印版原型机，欢迎加入交流微信群。添加 <code>EsonWong_</code> 微信号，备注<code>E-ink Todo List</code> 加入。也可以关注我的 X(Twitter) <a href="https://twitter.com/eson000">@eson000</a> 。</p><h3 id="广告"><a href="#广告" class="headerlink" title="广告"></a>广告</h3><ul><li><p><a href="https://esonwong.taobao.com/">Eson 的淘宝小店</a></p><ul><li>E-ink Todo List 3D 打印版已经上架 售卖 😇</li><li>E-ink Todo List 墨水屏待办 DIY 的 PCB 现已在 <a href="https://esonwong.taobao.com/">Eson 的淘宝小店</a> 上架售卖 😇</li><li>E-ink Todo List 墨水屏待办 DIY 的外壳也已经在 <a href="https://esonwong.taobao.com/">Eson 的淘宝小店</a> 开始售卖</li></ul></li><li><p><a href="https://www.goofish.com/personal?spm=a21ybx.item.itemHeader.1.227e3da6VQXD0M&userId=1697947792">Eson 的闲鱼小店</a></p><ul><li>👋 E-ink Todo List 墨水屏待办 DIY 的 PCB 现已在 <a href="https://www.goofish.com/personal?spm=a21ybx.item.itemHeader.1.227e3da6VQXD0M&userId=1697947792">Eson 的闲鱼小店</a> 上架售卖 😇，此 PCB 板可代替教程中的开发板和屏幕转接板。爱好 DIY 的朋友们可以下单购买制作。</li><li>👋 E-ink Todo List 墨水屏待办 DIY 的外壳也已经在 <a href="https://www.goofish.com/personal?spm=a21ybx.item.itemHeader.1.227e3da6VQXD0M&userId=1697947792">Eson 的闲鱼小店</a> 开始售卖</li><li>👋 E-ink Todo List 墨水屏待办的成品 3D 打印版也已经在 <a href="https://www.goofish.com/personal?spm=a21ybx.item.itemHeader.1.227e3da6VQXD0M&userId=1697947792">Eson 的闲鱼小店</a> 开始售卖</li></ul></li></ul><p>下面开始制作墨水屏 Todo List 的教程。</p><h2 id="必要材料和工具"><a href="#必要材料和工具" class="headerlink" title="必要材料和工具"></a>必要材料和工具</h2><h3 id="材料"><a href="#材料" class="headerlink" title="材料"></a>材料</h3><p><img src="/./e-ink-screen-todo-list-creation-turial/materials.webp" alt="ESP32 开发板、墨水屏驱动板和微雪 7.5 寸墨水屏"></p><ul><li>ESP8266&#x2F;ESP32 开发板</li><li>24 pin 墨水屏驱动板</li><li>微雪 7.5 寸 800*480 分辨率墨水屏</li></ul><p><strong>注意</strong>: 开源固件已经放弃对 ESP32 的支持。</p><p>微雪 7.5 寸墨水屏可以在网上找到拆机屏，也可以买新的。注意要买 800x480 分辨率的。</p><p>墨水屏驱动板在闲鱼搜索<code>墨水屏驱动板</code>，买 24 pin 的通用驱动板。</p><p>或者</p><ul><li>上文中售卖的 E-ink Todo List 墨水屏待办 DIY PCB</li><li>微雪 7.5 寸 800*480 分辨率墨水屏</li></ul><p>E-ink Todo List 墨水屏待办 DIY PCB 可以代替开发板和墨水屏驱动板。</p><h3 id="工具"><a href="#工具" class="headerlink" title="工具"></a>工具</h3><ul><li>电烙铁</li><li>电脑</li></ul><p>注：如果你购买了 E-ink Todo List 墨水屏待办 DIY 的 PCB，则不需要电烙铁来焊接。</p><h2 id="制作步骤"><a href="#制作步骤" class="headerlink" title="制作步骤"></a>制作步骤</h2><h3 id="1-焊接转接板和-ESP8266-开发板"><a href="#1-焊接转接板和-ESP8266-开发板" class="headerlink" title="1. 焊接转接板和 ESP8266 开发板"></a>1. 焊接转接板和 ESP8266 开发板</h3><ul><li><p>将墨水屏驱动板按下面的表格对应的脚位连接到 ESP8266 开发板上。</p><table><thead><tr><th>墨水屏驱动板</th><th>ESP8266 开发板</th></tr></thead><tbody><tr><td>VCC</td><td>3.3V</td></tr><tr><td>GND</td><td>GND</td></tr><tr><td>SDA</td><td>Pin 14</td></tr><tr><td>SCK</td><td>Pin 13</td></tr><tr><td>CS</td><td>Pin 15</td></tr><tr><td>DC</td><td>Pin 4</td></tr><tr><td>RST</td><td>Pin 2</td></tr><tr><td>BUSY</td><td>Pin 5</td></tr></tbody></table></li><li><p>将墨水屏的 FPC 排线连接到墨水屏驱动板。</p><p><strong>注意</strong>:排线的正反面。这个 FPC 排线端子的触点是在上面的，所以排线的触点朝上。我在第一次尝试点亮墨水屏的时候，就因为排线插反了，当时信心受到了极大的打击。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/eink-connect-to-driver-board.webp" alt="墨水屏连接到墨水屏驱动板"></p></li></ul><h3 id="2-安装固件编译和刷写环境"><a href="#2-安装固件编译和刷写环境" class="headerlink" title="2. 安装固件编译和刷写环境"></a>2. 安装固件编译和刷写环境</h3><p><a href="https://code.visualstudio.com/">下载 VSCode</a>，并安装。</p><p>安装好 VSCode 后，打开 VSCode，点击左侧的扩展按钮，搜索 PlatformIO，点击安装。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/install-platformio.webp" alt="安装 PlatformIO"></p><h3 id="3-下载代码"><a href="#3-下载代码" class="headerlink" title="3. 下载代码"></a>3. 下载代码</h3><p>然后从 <a href="https://github.com/esonwong/e-ink-todo-list">E-ink Todo List 固件代码开源仓库</a> 下载固件代码。</p><p>点击右上角的绿色按钮，选择<code>Download ZIP</code>。下载完成后解压得到固件代码文件夹。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/download-firmware-code.webp" alt="下载固件代码"></p><h3 id="4-编译和烧录固件"><a href="#4-编译和烧录固件" class="headerlink" title="4. 编译和烧录固件"></a>4. 编译和烧录固件</h3><ol><li><p>用 VSCode 打开固件代码文件夹。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/open-folder.webp" alt="打开文件夹"></p></li><li><p>选择固件代码文件夹, PlatformIO 插件会自动安装编译固件所需依赖。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/opened-folder.webp" alt="打开的代码"></p></li><li><p>将开发板用 USB 线连接到电脑。</p></li><li><p>编译和烧录固件到开发板。</p><p>在 VSCode 上点击蚂蚁头形状的<code>PlatformIO</code>菜单来打开 PlatformIO 的面板。</p><ul><li>如果你用的是 E-ink Todo List 墨水屏待办 DIY 的 PCB，选择 <code>Einktodo-</code>开头的环境下的 <code>General</code> -&gt; <code>Upload and Monitor</code><br>具体选哪个根据你的屏幕的型号来选择。比如是微雪 7.5 寸 800x480 分辨率的屏幕，选择 <code>E-inktodo-Waveshare-750-W800</code> -&gt; <code>General</code> -&gt; <code>Upload and Monitor</code></li><li>如果你使用的是 ESP8266 开发板，选择 <code>esp8266</code> -&gt; <code>General</code> -&gt; <code>Upload and Monitor</code></li></ul><p><img src="/./e-ink-screen-todo-list-creation-turial/compile-and-burn-firmware.webp" alt="编译和烧录固件"></p><p>等待烧录完成。</p></li></ol><h2 id="墨水屏-Todo-List-设置"><a href="#墨水屏-Todo-List-设置" class="headerlink" title="墨水屏 Todo List 设置"></a>墨水屏 Todo List 设置</h2><h3 id="在-einktodo-com-获取-API-Token"><a href="#在-einktodo-com-获取-API-Token" class="headerlink" title="在 einktodo.com 获取 API Token"></a>在 einktodo.com 获取 API Token</h3><ol><li><p><a href="https://einktodo.com/signin">登录 einktodo.com</a>。</p></li><li><p>在 <a href="https://einktodo.com/setting/api-key">API Key 页面</a> 创建 API Key。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/create-api-key.webp" alt="创建 API Key"></p></li></ol><h3 id="设置墨水屏-Todo-List"><a href="#设置墨水屏-Todo-List" class="headerlink" title="设置墨水屏 Todo List"></a>设置墨水屏 Todo List</h3><p>固件编译和烧录完成，墨水屏上会提示你连接墨水屏的热点和热点密码，接下来要连接热点进行设置。</p><ol><li><p>连接墨水屏 Todo List 的 Wi-Fi: <code>E-ink Todo List AP</code>，密码: <code>einktodo.com</code>。</p></li><li><p>打开浏览器，进入墨水屏上显示的设置页面。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/eink-todo-list-init-screen.webp" alt="墨水屏 Todo List 初始化屏幕"></p><p><img src="/./e-ink-screen-todo-list-creation-turial/settings-page.webp" alt="设置页面"></p></li><li><p>设置墨水屏要连接的 Wi-Fi 网络和要使用的 API Token。</p><p>点击<code>Configure WiFi</code>按钮进入设置页面。然后选择你想要让默水屏连接的 Wi-Fi 或在 SSID 输入框里输入 Wi-Fi 名。在 Password 输入框里输入这个 Wi-Fi 的密码。在 API Key 输入框里输入刚刚在 <a href="https://einktodo.com/">einktodo.com</a> 获取的 API Key。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/eink-todo-list-settings.webp" alt="墨水屏 Todo List 设置页面"></p></li><li><p>点击<code>Save</code>按钮。</p><p>墨水屏 Todo List 会自动重启并尝试连接 Wi-Fi。如果没有开始连接，你可以按 Reset 按钮重启 ESP32 开发板来触发连接。注意保持 Wi-Fi 信号良好。</p></li></ol><p>如果尝试连接 3 次没有成功，墨水屏将会重新打开 Wi-Fi 热点，你可以重新连接 Wi-Fi 进行设置。</p><p><em>如果你使用 E-ink Todo List 墨水屏待办 DIY 的 PCB，长按靠近 USB 接口的按键也可以重新进入设置页面。</em></p><h2 id="使用-E-ink-Todo-同步助手同步苹果提醒"><a href="#使用-E-ink-Todo-同步助手同步苹果提醒" class="headerlink" title="使用 E-ink Todo 同步助手同步苹果提醒"></a>使用 E-ink Todo 同步助手同步苹果提醒</h2><p>E-ink Todo 同步助手 beta 版已经发布，可以在 <a href="https://testflight.apple.com/join/ndYGQcyR">TestFlight 下载 E-ink Todo 同步助手</a> 下载。</p><h2 id="使用快捷指令同步苹果提醒"><a href="#使用快捷指令同步苹果提醒" class="headerlink" title="使用快捷指令同步苹果提醒"></a>使用快捷指令同步苹果提醒</h2><blockquote><p>推荐使用 E-ink Todo 同步助手替代快捷指令来同步苹果提醒。</p></blockquote><p>同步的 Todo List 目前支持苹果的提醒事项应用。其它常用的待办应用将来会逐步集成到 <a href="https://einktodo.com/">einktodo.com</a>。</p><h3 id="安装和配制快捷指令"><a href="#安装和配制快捷指令" class="headerlink" title="安装和配制快捷指令"></a>安装和配制快捷指令</h3><ol><li><p>点击下面的链接在 iPhone 上安装<code>Sync Einktodo.com</code>快捷指令。</p><p><a href="https://www.icloud.com/shortcuts/2977e378ce0644739e2a3192f750f93a">Sync Einktodo.com 快捷指令</a></p><p><img src="/./e-ink-screen-todo-list-creation-turial/einktodo-sync-shortcut-install.webp" alt="安装 Sync Einktodo.com 快捷指令"></p><p>在 Safari 中打开上面的链接，点击<code>获取捷径</code>。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/einktodo-sync-shortcut-install-2.webp" alt="安装 Sync Einktodo.com 快捷指令"></p><p>点击<code>添加快捷指令</code>。</p></li><li><p>添加完之后，找到 <code>Sync Einktodo.com</code> 快捷指令，点击它上面的<code>...</code>按钮，进入编辑界面。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/einktodo-sync-shortcut-edit.webp" alt="Sync Einktodo.com 快捷指令编辑页面"></p></li><li><p>在<code>Sync Einktodo.com</code>快捷指令中的文本块中输入刚刚在 <a href="https://einktodo.com/">einktodo.com</a> 获取的 API Key。</p></li><li><p>按<code>完成</code>保存快捷指令。</p></li></ol><h3 id="设置快捷指令自动化"><a href="#设置快捷指令自动化" class="headerlink" title="设置快捷指令自动化"></a>设置快捷指令自动化</h3><p>在快捷指令自动化中，设置打开或关闭“提醒事项”应用时运行此快捷指令来同步待办。</p><ol><li><p>打开快捷指令应用，点击<code>自动化</code> Tab</p><p><img src="/./e-ink-screen-todo-list-creation-turial/shortcut-automation.webp" alt="设置快捷指令自动化"></p></li><li><p>点击<code>+</code>按钮创建自动化, 选择<code>App</code>，点击<code>下一步</code>。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/create-automation.webp" alt="创建自动化"></p></li><li><p>设置为<code>打开</code>或<code>关闭</code> <code>提醒事项</code>应用时运行快捷指令</p><p>App 那一项选择<code>提醒事项</code>,勾选<code>打开</code>或<code>关闭</code>，并选择<code>立即执行</code>，然后点击<code>下一步</code>。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/setting-automation.webp" alt="设置同步触发条件"></p></li><li><p>选择<code>Sync Einktodo.com</code>快捷指令。</p><p><img src="/./e-ink-screen-todo-list-creation-turial/select-sync-einktodo-shortcut.webp" alt="选择 Sync Einktodo.com 快捷指令"></p><p>这样设置后，当你打开或关闭提醒事项应用时，快捷指令会自动同步待办到墨水屏 Todo List。</p></li><li><p>允许快捷指令访问提醒事项</p><p>当你第一次触发这个自动化时，系统会提示你允许快捷指令将提醒事项应用的数据发送到 <a href="https://einktodo.com/">einktodo.com</a>，点击<code>始终允许</code></p><p><img src="/./e-ink-screen-todo-list-creation-turial/allow-shortcut-access-reminder.webp" alt="允许快捷指令访问提醒事项"></p></li></ol>]]></content>
    
    
    <summary type="html">&lt;style&gt;
.post-body img {
   max-height: 800px;
}
&lt;/style&gt;

&lt;script&gt;
 window.difyChatbotConfig = {
  token: &#39;gc7zMgtbwd6BAygx&#39;,
  baseUrl: &#39;https://dify.esonwong.com&#39;
 }
&lt;/script&gt;
&lt;script
 src=&quot;https://dify.esonwong.com/embed.min.js&quot;
 id=&quot;gc7zMgtbwd6BAygx&quot;
 defer&gt;
&lt;/script&gt;
&lt;style&gt;
  #dify-chatbot-bubble-button {
    background-color: #1C64F2 !important;
  }
  #dify-chatbot-bubble-window {
    width: 24rem !important;
    height: 40rem !important;
  }
&lt;/style&gt;

&lt;p&gt;&lt;img src=&quot;/./e-ink-screen-todo-list-creation-turial/cover.webp&quot; alt=&quot;墨水屏 Todo List 制作教程&quot;&gt;&lt;/p&gt;
&lt;p&gt;我在 Twitter 发布的一条 tweet，写了我使用了墨水屏制作了一个 Todo List，可以同步苹果提醒的全家待办列表。收到了很多推友的关注，所以我决定写一个教程，帮助大家制作一个墨水屏 Todo List。&lt;/p&gt;
&lt;p&gt;同步服务由我开发的 &lt;a href=&quot;https://einktodo.com/&quot;&gt;einktodo.com&lt;/a&gt; 提供。&lt;/p&gt;</summary>
    
    
    
    
    <category term="教程" scheme="https://blog.esonwong.com/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="业余项目" scheme="https://blog.esonwong.com/tags/%E4%B8%9A%E4%BD%99%E9%A1%B9%E7%9B%AE/"/>
    
  </entry>
  
  <entry>
    <title>2023 年我买过的最好用的商品</title>
    <link href="https://blog.esonwong.com/the-best-product-i-bought-in-2023/"/>
    <id>https://blog.esonwong.com/the-best-product-i-bought-in-2023/</id>
    <published>2024-01-29T15:11:39.000Z</published>
    <updated>2026-02-27T10:20:27.234Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://api-next.esonwong.com/blog-banner?title=2023%20%E5%B9%B4%E6%88%91%E4%B9%B0%E8%BF%87%E7%9A%84%E6%9C%80%E5%A5%BD%E7%94%A8%E7%9A%84%E5%95%86%E5%93%81" alt="2023 年我买过的最好用的商品"></p><p>我在 2022 的年末写了一篇文章 <a href="/the-best-product-i-bought-in-2022">2022 年我买过的最好用的商品</a>，介绍了我 2022 年购入的我觉得最好用的商品。</p><p>在这个中文互联网自媒体觉大多数都依赖厂家推广费存活的时代，看到真实的商品评价越来越难。所以我打算每年年末都写一篇这样的文章，介绍我买过的那些我觉得好用或者每天者在使用的商品。让中文互联网上多一丝丝真实消费者的声音。</p><span id="more"></span><p>这是我 2023 年购入的值得推荐的产品：</p><ol><li>Aqara 人体存在传感器 FP2</li><li>淘宝的 Apple Watch 高山回环 表带</li><li>iPad 通勤包</li><li>田宫 1 比 10 比例的电动越野车 BBX</li></ol><h2 id="Aqara-人体存在传感器-FP2"><a href="#Aqara-人体存在传感器-FP2" class="headerlink" title="Aqara 人体存在传感器 FP2"></a>Aqara 人体存在传感器 FP2</h2><p>买了房子之后我就加大了智能家居的折腾力度。在 <a href="/the-best-product-i-bought-in-2022">2022 年我买过的最好用的商品</a> 中我推荐了 Aqara 的窗帘伴侣。今年他们家的毫米波人体传感器发布了第二代，我买了一个试了水。</p><p>在使用它之前我用了 4 个红外人体传动作传感器。红外动作人体传感器的缺点是，如果你在房间里不动它就会认为房间里没人。我以前用它们用它们控制灯的开关，在上厕所和其它动作幅度不大的场景下会关灯，导致我常被我家人吐槽。红外人体传感器不适合在家居场景下使用。</p><p>购入 Aqara 人体存在传感器 FP2 是我认为毫米波人体传感器经过了几年的发展也差不多成熟了。体验下来它有超出我预期的地方，也有让我对 Aqara 的做法及其失望的地方。</p><p><img src="/the-best-product-i-bought-in-2023/aqara-fp2.jpeg" alt="Aqara FP2"></p><p>超出预期的地方有：</p><ol><li>它可以在 Aqara App 里去给监测空间划分区域并同步到 HomeKit 里。</li><li>可以多长时间某个区域有人或无人时触发 Aqara App 内的自动化。</li></ol><p><img src="/the-best-product-i-bought-in-2023/aqara-app-fp2.jpeg" alt="Aqara App FP2"></p><p><img src="/the-best-product-i-bought-in-2023/homekit-fp2.jpeg" alt="HomeKit FP2"></p><p>缺点：</p><ol><li><p>Aqara 有意的让他们家的设备无法在其它智能家居平台上触发自动化。</p><p>表面上看 Aqara 表现的很开放，几乎所有的设备都支持 HomeKit。但实际上 FP2 上的包含时间限制的触发自动化功能只能在 Aqara App 里使用。Aqara 既不开放 API（无法通过 HomeBridge 接入 HomeKit），也不能通过什么场景控制等其它方式绕过限制。</p></li><li><p>安装问题</p><p>毫米波人体传感器设备不是低功耗设备，所以它需要接入电源。所以只能选择安装在有电源的地方或者为它拉电源线。而且安装的高度也有要求，不能太高也不能太低。安放它有些麻烦。</p></li><li><p>识别准确度</p><p>识别不能达到 100% 的准确度，有时候会有误判。之前我把它安装在电风扇附近，电风扇的转动会让它误判有人在房间里，我不得不把它移到其它地方。更新的 AI 预测干扰在一定程度上优化了这个问题。但是最近我并没有使用风扇，灯到天所热一些之后才能再次验证这个问题是否解决。</p></li></ol><p>综合考虑对智能家居的自动化提升程度和可接受的准确度，我又买了 3 个 FP2，分别安装在两个卧室和洗手间。目前家中大多数的灯都可以在合适的时候自动打开和关闭了。</p><p>我的购买渠道是咸鱼，因为 Aqara 对线上渠道的价格有保护，所以在咸鱼上才能以正常价格买到。</p><h2 id="淘宝的-Apple-Watch-高山回环-表带"><a href="#淘宝的-Apple-Watch-高山回环-表带" class="headerlink" title="淘宝的 Apple Watch 高山回环 表带"></a>淘宝的 Apple Watch 高山回环 表带</h2><p><img src="/./the-best-product-i-bought-in-2023/the-watch-strap.jpeg" alt="淘宝的 Apple Watch 高山回环 表带"></p><p>去年买了 Apple Watch Series 7，到现在使用了原装运动表带，淘宝上买的海洋回环、高山回环、和野径回环表带。最后高山回环表带是我最常用的表带。</p><p><img src="/./the-best-product-i-bought-in-2023/the-watch-strap-2.jpeg" alt="淘宝的 Apple Watch 高山回环 表带"></p><p>它的优点是：弹性效适中，带着不晃动。透气，不会让手腕潮湿。比较薄，让我可以在晚上睡觉的时候戴着 Apple Watch，在穿长袖厚衣服的时候也最小限度的影响到了 Apple Watch 的佩戴。</p><p>这个表带不耐脏，最好买深色的。</p><h2 id="iPad-通勤包"><a href="#iPad-通勤包" class="headerlink" title="iPad 通勤包"></a>iPad 通勤包</h2><p><img src="/./the-best-product-i-bought-in-2023/ipad-bag-2.jpeg" alt="iPad 背包"></p><p>我使用的是 11 寸的 iPad，日常通勤的时候我会带着它在地铁上看书学习英语。为了方便拿取，以及在过地铁安检的时候不用过安检，我找了很久才找到这个包。它刚好能装下我的 iPad，不会感到太累赘。带有磁吸扣的设计，让我在进地铁的可以方便的打开给安检人员看，避免过安检机。使用 iPad 的时候也也以快速的拿出来。</p><p><img src="/./the-best-product-i-bought-in-2023/ipad-bag-1.jpeg" alt="iPad 背包"></p><p>但是价格在我看来略贵。</p><p><img src="/./the-best-product-i-bought-in-2023/ipad-bag-3.jpeg" alt="iPad 背包掉漆"></p><p>还有一个非常让人不爽的问题是挂带子的金属件容易掉漆，我要想办法把它们换掉。</p><h2 id="田宫-1-比-10-比例的电动越野车-BBX"><a href="#田宫-1-比-10-比例的电动越野车-BBX" class="headerlink" title="田宫 1 比 10 比例的电动越野车 BBX"></a>田宫 1 比 10 比例的电动越野车 BBX</h2><p><img src="/./the-best-product-i-bought-in-2023/bbx-packaging.jpeg" alt="田宫 1 比 10 比例的电动越野车 BBX 包装"></p><p>今年入手的玩具车，和我以前喜欢玩的游戏 PUBG《绝地求生》中的越野车“蹦蹦”同款。它的对地形的要求很低，哪里都可以玩。</p><p><img src="/./the-best-product-i-bought-in-2023/bbx.jpeg" alt="田宫 1 比 10 比例的电动越野车 BBX"></p><p>不过价格有点贵，组装也有点麻烦。如果手残的话建议闲鱼上买成品车。</p><p><img src="/./the-best-product-i-bought-in-2023/bbx-parts.jpeg" alt="田宫 1 比 10 比例的电动越野车 BBX 零件"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://api-next.esonwong.com/blog-banner?title=2023%20%E5%B9%B4%E6%88%91%E4%B9%B0%E8%BF%87%E7%9A%84%E6%9C%80%E5%A5%BD%E7%94%A8%E7%9A%84%E5%95%86%E5%93%81&quot; alt=&quot;2023 年我买过的最好用的商品&quot;&gt;&lt;/p&gt;
&lt;p&gt;我在 2022 的年末写了一篇文章 &lt;a href=&quot;/the-best-product-i-bought-in-2022&quot;&gt;2022 年我买过的最好用的商品&lt;/a&gt;，介绍了我 2022 年购入的我觉得最好用的商品。&lt;/p&gt;
&lt;p&gt;在这个中文互联网自媒体觉大多数都依赖厂家推广费存活的时代，看到真实的商品评价越来越难。所以我打算每年年末都写一篇这样的文章，介绍我买过的那些我觉得好用或者每天者在使用的商品。让中文互联网上多一丝丝真实消费者的声音。&lt;/p&gt;</summary>
    
    
    
    <category term="硬件产品" scheme="https://blog.esonwong.com/categories/%E7%A1%AC%E4%BB%B6%E4%BA%A7%E5%93%81/"/>
    
    
    <category term="数码产品" scheme="https://blog.esonwong.com/tags/%E6%95%B0%E7%A0%81%E4%BA%A7%E5%93%81/"/>
    
    <category term="智能家居" scheme="https://blog.esonwong.com/tags/%E6%99%BA%E8%83%BD%E5%AE%B6%E5%B1%85/"/>
    
  </entry>
  
  <entry>
    <title>转变自我的密码：《Atomic Habits》读后感</title>
    <link href="https://blog.esonwong.com/atomic-habits/"/>
    <id>https://blog.esonwong.com/atomic-habits/</id>
    <published>2023-11-30T10:24:43.000Z</published>
    <updated>2026-02-27T10:20:27.136Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/./atomic-habits/cover.webp" alt="掌控习惯"></p><p>在我们的生活里，习惯就像是无声的指挥官，默默地引导着我们的行动和选择。在《Atomic Habits》这本书中，詹姆斯·克利尔（James Clear）用他洞见卓识的笔触，展现了如何通过习惯的力量来雕塑更好的自我。这本书不仅是养成好习惯的指南，更是一部自我改革的宝典，它教会我们将小变化累加成巨大的成果。</p><span id="more"></span><h2 id="作者简介"><a href="#作者简介" class="headerlink" title="作者简介"></a>作者简介</h2><p>作者詹姆斯·克利尔，一个以自己的转变故事激励人们追求强大个人习惯的灵魂导师。通过在个人发展领域中的不懈努力和深刻的思考，他不仅在书籍的篇章中分享了他的智慧，也在他的网站和各类讲座中，持续地影响着那些渴望改变的灵魂。</p><h2 id="习惯为什么如此重要"><a href="#习惯为什么如此重要" class="headerlink" title="习惯为什么如此重要"></a>习惯为什么如此重要</h2><p>书中明示，习惯是我们日常决策的结果，它们定义了我们的效能和最终能达到的高度。我们之所以被困在不满的迷宫，很大程度源于那些未经意识审视的自动行为。因为习惯一旦养成，在无意识的驱动下，就会反复执行而不易察觉。</p><h2 id="培养习惯的三层追求"><a href="#培养习惯的三层追求" class="headerlink" title="培养习惯的三层追求"></a>培养习惯的三层追求</h2><p>克利尔在书中提出，培养习惯不仅是为了达成目标，更是为了雕塑身份。那种“我是谁”的信念，影响着我们的选择和行为。比如我自身的经历，将发布 iOS 应用视为过程而非一次性目标，还有每天阅读 15 分钟的习惯，正是这种理念的反映。</p><h2 id="习惯的四大定律"><a href="#习惯的四大定律" class="headerlink" title="习惯的四大定律"></a>习惯的四大定律</h2><p>书里提到的四大定律，为我们提供了改变习惯的明确路径。</p><h3 id="让期望的习惯变得更加看得见、难以忽视"><a href="#让期望的习惯变得更加看得见、难以忽视" class="headerlink" title="让期望的习惯变得更加看得见、难以忽视"></a>让期望的习惯变得更加看得见、难以忽视</h3><p>我们的大脑趋向于自动反应日常环境中的线索。通过创建显眼的触发器，如备好健身包放在门口，我们就构筑了迈向健身房的第一步。类似方法可以用于任何我们想要建立的习惯。</p><h3 id="让习惯变得更有吸引力"><a href="#让习惯变得更有吸引力" class="headerlink" title="让习惯变得更有吸引力"></a>让习惯变得更有吸引力</h3><p>积极的感觉是维持习惯的关键因素。我们可以把习惯与自己喜爱的活动关联起来，比如在跑步机上听喜爱的播客，以此增强坚持的动力。</p><h3 id="让习惯变得更简单"><a href="#让习惯变得更简单" class="headerlink" title="让习惯变得更简单"></a>让习惯变得更简单</h3><p>降低好习惯的入门门槛至关重要。比如要养成早起的习惯，可以先从调早闹钟五分钟做起。而同时，增加不良习惯的难度，就像删除手机上的社交媒体应用，以避免不必要的干扰。</p><h3 id="让习惯变得更有满足感"><a href="#让习惯变得更有满足感" class="headerlink" title="让习惯变得更有满足感"></a>让习惯变得更有满足感</h3><p>适当的即时奖励可以巩固好习惯。每当完成一项任务后给予自己奖励，无论是一杯咖啡还是一个小时的电视时间，都能够加强我们的积极反馈回路。</p><h2 id="行动指南"><a href="#行动指南" class="headerlink" title="行动指南"></a>行动指南</h2><p>书籍最终落脚在如何实践。制定一个鲜明的计划，如何每天写博客、读书、运动，然后根据习惯的四大定律将计划付诸行动。重要的是，要让这些活动符合你的身份认同，让自己真正相信“我是一个写作者”，“我是一个爱读书的人”，“我是一个健身者”。</p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>《Atomic Habits》不仅是一本关于习惯的书，它是一张改变生活的地图。詹姆斯·克利尔回答了我们在寻求进步路上的那些困惑，他用科学的方法和真实的故事，指引我们向着更好的自己前进。现在，是时候把这些理念应用于实践，开始自我改革的旅程了！</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;/./atomic-habits/cover.webp&quot; alt=&quot;掌控习惯&quot;&gt;&lt;/p&gt;
&lt;p&gt;在我们的生活里，习惯就像是无声的指挥官，默默地引导着我们的行动和选择。在《Atomic Habits》这本书中，詹姆斯·克利尔（James Clear）用他洞见卓识的笔触，展现了如何通过习惯的力量来雕塑更好的自我。这本书不仅是养成好习惯的指南，更是一部自我改革的宝典，它教会我们将小变化累加成巨大的成果。&lt;/p&gt;</summary>
    
    
    
    <category term="读书笔记" scheme="https://blog.esonwong.com/categories/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="笔记" scheme="https://blog.esonwong.com/tags/%E7%AC%94%E8%AE%B0/"/>
    
    <category term="读书" scheme="https://blog.esonwong.com/tags/%E8%AF%BB%E4%B9%A6/"/>
    
    <category term="摘录" scheme="https://blog.esonwong.com/tags/%E6%91%98%E5%BD%95/"/>
    
  </entry>
  
  <entry>
    <title>Phonics 自然拼读常见规则 - 音节和元音字母的发音规律</title>
    <link href="https://blog.esonwong.com/phonics/"/>
    <id>https://blog.esonwong.com/phonics/</id>
    <published>2023-10-28T07:13:53.000Z</published>
    <updated>2026-02-27T10:20:27.207Z</updated>
    
    <content type="html"><![CDATA[<p>自然拼读法是通过英语中的音节和音素之间的关系，根据这些规则正确地发音和拼写单词的方法。通过自然拼读法，学习者可以更轻松地理解和记忆英语单词的发音，提高阅读流畅性和拼写准确性。</p><table><thead><tr><th></th><th>重读开音节</th><th>重读闭音节</th><th>非重读音节</th></tr></thead><tbody><tr><td>A</td><td>&#x2F;eɪ&#x2F;</td><td>&#x2F;æ&#x2F;</td><td>&#x2F;ə&#x2F;</td></tr><tr><td>E</td><td>&#x2F;iː&#x2F;</td><td>&#x2F;e&#x2F;</td><td>&#x2F;ə&#x2F; or &#x2F;ɪ&#x2F;</td></tr><tr><td>I</td><td>&#x2F;aɪ&#x2F;</td><td>&#x2F;ɪ&#x2F;</td><td>&#x2F;ə&#x2F; or &#x2F;ɪ&#x2F;</td></tr><tr><td>O</td><td>&#x2F;əʊ&#x2F;</td><td>&#x2F;ɒ&#x2F;</td><td>&#x2F;ə&#x2F;</td></tr><tr><td>U</td><td>&#x2F;juː&#x2F;</td><td>&#x2F;ʌ&#x2F;</td><td>&#x2F;ə&#x2F;</td></tr></tbody></table><p>辅音字母的拼读规则见我的另一篇博客 <a href="/phonics-of-consonants">Phonics 自然拼读常见规则 - 辅音字母的发音规律</a>。</p><h2 id="音节"><a href="#音节" class="headerlink" title="音节"></a>音节</h2><h3 id="什么是音节"><a href="#什么是音节" class="headerlink" title="什么是音节"></a>什么是音节</h3><p>音节是发音的基本单位，是一个发音的完整单位。音节的划分对于一个单词的读音至关重要，自然拼读的规律基本上是针对单个音节的。</p><p>一个音节，只会包含一次出气，出气时的声带的振动被称为元音；牙齿、舌头、嘴唇等部位的阻碍气流发出的声音被称为辅音。</p><p>音节由一个元音或一个元音加一个或几个辅音组成。中文里每个字都是一个音节。英文里每个单词会有一个或多个音节。</p><span id="more"></span><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374200691037971"     crossorigin="anonymous"></script><p><ins class="adsbygoogle"     style="display:block; text-align:center;"     data-ad-layout="in-article"     data-ad-format="fluid"     data-ad-client="ca-pub-4374200691037971"     data-ad-slot="5501484908"></ins></p><script>     (adsbygoogle = window.adsbygoogle || []).push({});</script><h4 id="元音"><a href="#元音" class="headerlink" title="元音"></a>元音</h4><p>元音是发音时，舌头不接触上下牙齿，不接触嘴唇的音。通常元音发音时，气流从喉咙出来，通过口腔或鼻腔，不受阻碍，形成的音。</p><p>比如：cat &#x2F;kæt&#x2F; 中的 &#x2F;æ&#x2F; 是一个元音。</p><blockquote><p>短元音：&#x2F;æ&#x2F;、&#x2F;e&#x2F;、&#x2F;ɪ&#x2F;、&#x2F;ɒ&#x2F;、&#x2F;ʌ&#x2F;、&#x2F;ʊ&#x2F;、&#x2F;ə&#x2F;<br>长元音：&#x2F;iː&#x2F;、&#x2F;ɑː&#x2F;、&#x2F;ɔː&#x2F;、&#x2F;ɜː&#x2F;、&#x2F;uː&#x2F;、&#x2F;ɔɪ&#x2F;、&#x2F;aɪ&#x2F;、&#x2F;eɪ&#x2F;、&#x2F;aʊ&#x2F;、&#x2F;əʊ&#x2F;、&#x2F;ɪə&#x2F;、&#x2F;eə&#x2F;、&#x2F;ʊə&#x2F;</p></blockquote><h4 id="辅音"><a href="#辅音" class="headerlink" title="辅音"></a>辅音</h4><p>辅音是发音时，舌头接触上下牙齿，接触嘴唇的音。通常辅音发音时，气流在口腔、鼻腔或咽头受阻碍而形成的音。</p><p>比如：cat &#x2F;kæt&#x2F; 中的 &#x2F;k&#x2F; 和 &#x2F;t&#x2F; 是辅音。</p><blockquote><p>辅音：&#x2F;b&#x2F;、&#x2F;d&#x2F;、&#x2F;f&#x2F;、&#x2F;g&#x2F;、&#x2F;h&#x2F;、&#x2F;j&#x2F;、&#x2F;k&#x2F;、&#x2F;l&#x2F;、&#x2F;m&#x2F;、&#x2F;n&#x2F;、&#x2F;ŋ&#x2F;、&#x2F;p&#x2F;、&#x2F;r&#x2F;、&#x2F;s&#x2F;、&#x2F;ʃ&#x2F;、&#x2F;t&#x2F;、&#x2F;tʃ&#x2F;、&#x2F;θ&#x2F;、&#x2F;ð&#x2F;、&#x2F;v&#x2F;、&#x2F;w&#x2F;、&#x2F;z&#x2F;、&#x2F;ʒ&#x2F;</p></blockquote><p>一个音节中，必须有一个元音，可以有一个辅音或几个辅音，但是不能有一个以上的元音。</p><h3 id="音节类型"><a href="#音节类型" class="headerlink" title="音节类型"></a>音节类型</h3><h4 id="开音节"><a href="#开音节" class="headerlink" title="开音节"></a>开音节</h4><p>开音节（open syllable）是一种音节类型。在开音节中，音节的末尾是一个元音字母，即元音字母后面没有紧跟的辅音字母。<br>开音节的特征：</p><ul><li>音节末尾是元音字母。</li><li>元音字母后面没有紧跟的辅音字母。</li><li>元音字母通常发字母本身的发音。</li></ul><p>开音节单词的例子：</p><ul><li>go &#x2F;goʊ&#x2F;</li><li>me &#x2F;mi:&#x2F;</li><li>hi &#x2F;haɪ&#x2F;</li><li>so &#x2F;soʊ&#x2F;</li><li>flu &#x2F;flu:&#x2F;</li></ul><p>词内开音节的例子：</p><ul><li>table &#x2F;ˈteɪ.bəl&#x2F; 中的 ta &#x2F;teɪ&#x2F;</li><li>open &#x2F;ˈoʊ.pən&#x2F; 中的 o &#x2F;oʊ&#x2F;</li><li>remote &#x2F;rɪˈmoʊt&#x2F; 中的 re &#x2F;rɪ&#x2F;</li><li>tiger &#x2F;ˈtaɪ.ɡɚ&#x2F; 中的 ti &#x2F;taɪ&#x2F;</li><li>baby &#x2F;ˈbeɪbi&#x2F; 中的 ba &#x2F;beɪ&#x2F; 和 bi &#x2F;biː&#x2F;</li><li>computer &#x2F;kəmˈpjuːtər&#x2F; 中的 pu &#x2F;pjuː&#x2F;</li></ul><h4 id="相对开音节"><a href="#相对开音节" class="headerlink" title="相对开音节"></a>相对开音节</h4><p>音节后面是一个辅音字母加上不发音的 e，前面这个音节叫做相对开音节。<br>如：</p><ul><li>bite &#x2F;baɪt&#x2F; 中的 bi &#x2F;baɪ&#x2F;</li><li>cake &#x2F;keɪk&#x2F; 中的 ca &#x2F;keɪ&#x2F;</li><li>cute &#x2F;kjuːt&#x2F; 中的 cu &#x2F;kjuː&#x2F;</li><li>fine &#x2F;faɪn&#x2F; 中的 fi &#x2F;faɪ&#x2F;</li><li>remote &#x2F;rɪˈmoʊt&#x2F; 中的 mo &#x2F;moʊ&#x2F;</li></ul><h4 id="闭音节"><a href="#闭音节" class="headerlink" title="闭音节"></a>闭音节</h4><p>闭音节（closed syllable）是由辅音结尾的音节。</p><p>如：</p><ul><li>cat &#x2F;kæt&#x2F;</li><li>bed &#x2F;bed&#x2F;</li><li>big &#x2F;bɪɡ&#x2F;</li><li>fish &#x2F;fɪʃ&#x2F;</li><li>seven &#x2F;ˈsevən&#x2F; 中的 ven &#x2F;vən&#x2F;</li></ul><h4 id="重读音节"><a href="#重读音节" class="headerlink" title="重读音节"></a>重读音节</h4><p>一个单词中重读的音节，音标中用<code>&#39;</code>表示</p><p>比如：</p><ul><li>about &#x2F;əˈbaʊt&#x2F; 中的 bout &#x2F;‘baʊt&#x2F;</li><li>again &#x2F;əˈɡen&#x2F; 中的 gain &#x2F;‘ɡen&#x2F;</li><li>banana &#x2F;bəˈnɑːnə&#x2F; 中的 na &#x2F;‘nɑː&#x2F;</li></ul><h4 id="次重读音节"><a href="#次重读音节" class="headerlink" title="次重读音节"></a>次重读音节</h4><p>一个单词中次重读的音节，音标中用<code>ˌ</code>表示</p><p>比如：</p><ul><li>chinese &#x2F;ˌtʃaɪˈniːz&#x2F; 中的 chi &#x2F;ˌtʃaɪ&#x2F;</li><li>information &#x2F;ˌɪnfərˈmeɪʃn&#x2F; 中的 in &#x2F;ˌɪn&#x2F;</li><li>understand &#x2F;ˌʌndərˈstænd&#x2F; 中的 un &#x2F;ˌʌn&#x2F;</li></ul><h2 id="字母的发音常见规则"><a href="#字母的发音常见规则" class="headerlink" title="字母的发音常见规则"></a>字母的发音常见规则</h2><p>下面是自然拼读的常见规则，并不是所有的单词都符合这些规律，仅列出常见的规律。</p><h3 id="元音字母的发音"><a href="#元音字母的发音" class="headerlink" title="元音字母的发音"></a>元音字母的发音</h3><table><thead><tr><th></th><th>重读</th><th>重读</th><th>重读</th><th>重读</th><th>重读</th><th>非重读</th></tr></thead><tbody><tr><td></td><td>单个元音</td><td>单个元音</td><td>单个元音</td><td>与 re 组合</td><td>与 er 组合</td><td>单个元音</td></tr><tr><td></td><td>开音节</td><td>相对开音节</td><td>闭音节</td><td></td><td></td><td></td></tr><tr><td>A</td><td>&#x2F;eɪ&#x2F; baby</td><td>&#x2F;eɪ&#x2F; make</td><td>&#x2F;æ&#x2F; cat</td><td>&#x2F;ɑː&#x2F; arm</td><td>&#x2F;eə&#x2F; care</td><td>&#x2F;ə&#x2F; about</td></tr><tr><td>E</td><td>&#x2F;iː&#x2F; be</td><td>&#x2F;iː&#x2F; theme</td><td>&#x2F;e&#x2F; bed</td><td>&#x2F;ɜː&#x2F; her</td><td>&#x2F;ɪə&#x2F; here</td><td>&#x2F;ə&#x2F; the <br> &#x2F;ɪ&#x2F; basket</td></tr><tr><td>I</td><td>&#x2F;aɪ&#x2F; hi</td><td>&#x2F;aɪ&#x2F; bite</td><td>&#x2F;ɪ&#x2F; sit</td><td>&#x2F;ɜː&#x2F; bird</td><td>&#x2F;aɪə&#x2F; fire</td><td>&#x2F;ə&#x2F; pencil <br> &#x2F;ɪ&#x2F; rabbit</td></tr><tr><td>O</td><td>&#x2F;əʊ&#x2F; go</td><td>&#x2F;əʊ&#x2F; home</td><td>&#x2F;ɒ&#x2F; hot</td><td>&#x2F;ɔː&#x2F; born</td><td>&#x2F;ɔː&#x2F; bore</td><td>&#x2F;ə&#x2F; today&#x2F;</td></tr><tr><td>U</td><td>&#x2F;juː&#x2F; july</td><td>&#x2F;juː&#x2F; cube</td><td>&#x2F;ʌ&#x2F; cup</td><td>&#x2F;ɜː&#x2F; burn</td><td>&#x2F;jʊə&#x2F; cure</td><td>&#x2F;ə&#x2F; until</td></tr></tbody></table><blockquote><p>字母 Y 有时候等同于元音字母 I。</p></blockquote><h4 id="单个元音字母在重读开音节中的发音"><a href="#单个元音字母在重读开音节中的发音" class="headerlink" title="单个元音字母在重读开音节中的发音"></a>单个元音字母在重读开音节中的发音</h4><p>单个元音字母在重读音节里读字母本身的发音。</p><table><thead><tr><th>A</th><th>E</th><th>I</th><th>O</th><th>U</th></tr></thead><tbody><tr><td>&#x2F;eɪ&#x2F;</td><td>&#x2F;iː&#x2F;</td><td>&#x2F;aɪ&#x2F;</td><td>&#x2F;əʊ&#x2F;</td><td>&#x2F;juː&#x2F;</td></tr></tbody></table><p>如：</p><ul><li>baby &#x2F;ˈbeɪbi&#x2F;</li><li>be &#x2F;biː&#x2F;</li><li>hi &#x2F;haɪ&#x2F;</li><li>my &#x2F;maɪ&#x2F;</li><li>go &#x2F;gəʊ&#x2F;</li><li>july &#x2F;dʒuːlaɪ&#x2F;</li></ul><h4 id="单个元音字母在重读相对开音节中的发音"><a href="#单个元音字母在重读相对开音节中的发音" class="headerlink" title="单个元音字母在重读相对开音节中的发音"></a>单个元音字母在重读相对开音节中的发音</h4><p>相对开音节中的元音字母也是字母本身的发音。</p><p>比如：</p><ul><li>A<ul><li>bate &#x2F;beɪt&#x2F;</li><li>cake &#x2F;keɪk&#x2F;</li><li>date &#x2F;deɪt&#x2F;</li><li>face &#x2F;feɪs&#x2F;</li><li>gate &#x2F;geɪt&#x2F;</li><li>hate &#x2F;heɪt&#x2F;</li><li>lake &#x2F;leɪk&#x2F;</li><li>make &#x2F;meɪk&#x2F;</li><li>name &#x2F;neɪm&#x2F;</li></ul></li><li>E<ul><li>these &#x2F;ðiːz&#x2F;</li><li>theme &#x2F;θiːm&#x2F;</li><li>scene &#x2F;siːn&#x2F;</li><li>gene &#x2F;dʒiːn&#x2F;</li></ul></li><li>I<ul><li>bike &#x2F;baɪk&#x2F;</li><li>bite &#x2F;baɪt&#x2F;</li><li>file &#x2F;faɪl&#x2F;</li><li>fine &#x2F;faɪn&#x2F;</li><li>hide &#x2F;haɪd&#x2F;</li><li>like &#x2F;laɪk&#x2F;</li><li>mile &#x2F;maɪl&#x2F;</li><li>mine &#x2F;maɪn&#x2F;</li><li>nine &#x2F;naɪn&#x2F;</li><li>pipe &#x2F;paɪp&#x2F;</li><li>ride &#x2F;raɪd&#x2F;</li><li>rice &#x2F;raɪs&#x2F;</li><li>side &#x2F;saɪd&#x2F;</li><li>site &#x2F;saɪt&#x2F;</li><li>time &#x2F;taɪm&#x2F;</li><li>wide &#x2F;waɪd&#x2F;</li><li>wife &#x2F;waɪf&#x2F;</li><li>wine &#x2F;waɪn&#x2F;</li></ul></li><li>Y<ul><li>byte &#x2F;baɪt&#x2F;</li><li>type &#x2F;taɪp&#x2F;</li><li>style &#x2F;staɪl&#x2F;</li><li>rhyme &#x2F;raɪm&#x2F;</li></ul></li><li>O<ul><li>bone &#x2F;bəʊn&#x2F;</li><li>code &#x2F;kəʊd&#x2F;</li><li>hole &#x2F;həʊl&#x2F;</li><li>home &#x2F;həʊm&#x2F;</li><li>hope &#x2F;həʊp&#x2F;</li><li>joke &#x2F;dʒəʊk&#x2F;</li><li>note &#x2F;nəʊt&#x2F;</li><li>pole &#x2F;pəʊl&#x2F;</li><li>role &#x2F;rəʊl&#x2F;</li><li>rose &#x2F;rəʊz&#x2F;</li><li>rope &#x2F;rəʊp&#x2F;</li><li>vote &#x2F;vəʊt&#x2F;</li></ul></li><li>U<ul><li>cute &#x2F;kjuːt&#x2F;</li><li>cube &#x2F;kjuːb&#x2F;</li><li>huge &#x2F;hjuːdʒ&#x2F;</li><li>June &#x2F;dʒuːn&#x2F;</li><li>mute &#x2F;mjuːt&#x2F;</li><li>tube &#x2F;tjuːb&#x2F;</li></ul></li></ul><h4 id="单个元音字母在重读闭音节中的常见发音"><a href="#单个元音字母在重读闭音节中的常见发音" class="headerlink" title="单个元音字母在重读闭音节中的常见发音"></a>单个元音字母在重读闭音节中的常见发音</h4><table><thead><tr><th>A</th><th>E</th><th>I</th><th>O</th><th>U</th></tr></thead><tbody><tr><td>&#x2F;æ&#x2F;</td><td>&#x2F;e&#x2F;</td><td>&#x2F;ɪ&#x2F;</td><td>&#x2F;ɒ&#x2F;</td><td>&#x2F;ʌ&#x2F;</td></tr></tbody></table><ul><li>A &#x2F;æ&#x2F;<ul><li>bad &#x2F;bæd&#x2F;</li><li>bag &#x2F;bæg&#x2F;</li><li>bat &#x2F;bæt&#x2F;</li><li>black &#x2F;blæk&#x2F;</li><li>back &#x2F;bæk&#x2F;</li><li>cap &#x2F;kæp&#x2F;</li><li>cat &#x2F;kæt&#x2F;</li><li>dad &#x2F;dæd&#x2F;</li><li>fat &#x2F;fæt&#x2F;</li><li>flag &#x2F;flæg&#x2F;</li><li>glad &#x2F;glæd&#x2F;</li><li>hat &#x2F;hæt&#x2F;</li><li>jam &#x2F;dʒæm&#x2F;</li><li>lap &#x2F;læp&#x2F;</li><li>mad &#x2F;mæd&#x2F;</li><li>map &#x2F;mæp&#x2F;</li><li>pack &#x2F;pæk&#x2F;</li><li>pan &#x2F;pæn&#x2F;</li><li>pat &#x2F;pæt&#x2F;</li><li>plan &#x2F;plæn&#x2F;</li><li>sad &#x2F;sæd&#x2F;</li><li>sack &#x2F;sæk&#x2F;</li><li>tag &#x2F;tæg&#x2F;</li><li>tan &#x2F;tæn&#x2F;</li><li>tap &#x2F;tæp&#x2F;</li></ul></li><li>E &#x2F;e&#x2F;<ul><li>bed &#x2F;bed&#x2F;</li><li>bell &#x2F;bel&#x2F;</li><li>check &#x2F;tʃek&#x2F;</li><li>deck &#x2F;dek&#x2F;</li><li>egg &#x2F;eg&#x2F;</li><li>end &#x2F;end&#x2F;</li><li>fell &#x2F;fel&#x2F;</li><li>fed &#x2F;fed&#x2F;</li><li>get &#x2F;get&#x2F;</li><li>help &#x2F;help&#x2F;</li><li>jet &#x2F;dʒet&#x2F;</li><li>kept &#x2F;kept&#x2F;</li></ul></li><li>I &#x2F;ɪ&#x2F;<ul><li>big &#x2F;bɪg&#x2F;</li><li>bin &#x2F;bɪn&#x2F;</li><li>bit &#x2F;bɪt&#x2F;</li><li>bill &#x2F;bɪl&#x2F;</li><li>chip &#x2F;tʃɪp&#x2F;</li><li>dig &#x2F;dɪg&#x2F;</li><li>fill &#x2F;fɪl&#x2F;</li><li>fit &#x2F;fɪt&#x2F;</li><li>hill &#x2F;hɪl&#x2F;</li><li>hit &#x2F;hɪt&#x2F;</li><li>ill &#x2F;ɪl&#x2F;</li><li>kid &#x2F;kɪd&#x2F;</li><li>kit &#x2F;kɪt&#x2F;</li><li>lip &#x2F;lɪp&#x2F;</li><li>list &#x2F;lɪst&#x2F;</li><li>mill &#x2F;mɪl&#x2F;</li><li>mix &#x2F;mɪks&#x2F;</li><li>pick &#x2F;pɪk&#x2F;</li><li>pig &#x2F;pɪg&#x2F;</li><li>pill &#x2F;pɪl&#x2F;</li><li>pin &#x2F;pɪn&#x2F;</li><li>pit &#x2F;pɪt&#x2F;</li><li>ship &#x2F;ʃɪp&#x2F;</li><li>sick &#x2F;sɪk&#x2F;</li><li>sit &#x2F;sɪt&#x2F;</li><li>skill &#x2F;skɪl&#x2F;</li><li>skin &#x2F;skɪn&#x2F;</li><li>slip &#x2F;slɪp&#x2F;</li><li>spin &#x2F;spɪn&#x2F;</li><li>stick &#x2F;stɪk&#x2F;</li><li>still &#x2F;stɪl&#x2F;</li><li>swim &#x2F;swɪm&#x2F;</li><li>thin &#x2F;θɪn&#x2F;</li><li>tick &#x2F;tɪk&#x2F;</li><li>tip &#x2F;tɪp&#x2F;</li><li>trip &#x2F;trɪp&#x2F;</li><li>twin &#x2F;twɪn&#x2F;</li><li>win &#x2F;wɪn&#x2F;</li><li>will &#x2F;wɪl&#x2F;</li></ul></li><li>O &#x2F;ɒ&#x2F;<ul><li>box &#x2F;bɒks&#x2F;</li><li>clock &#x2F;klɒk&#x2F;</li><li>dog &#x2F;dɒg&#x2F;</li><li>doll &#x2F;dɒl&#x2F;</li><li>dot &#x2F;dɒt&#x2F;</li><li>fog &#x2F;fɒg&#x2F;</li><li>fox &#x2F;fɒks&#x2F;</li><li>got &#x2F;gɒt&#x2F;</li><li>hot &#x2F;hɒt&#x2F;</li><li>job &#x2F;dʒɒb&#x2F;</li><li>lock &#x2F;lɒk&#x2F;</li><li>lot &#x2F;lɒt&#x2F;</li><li>mom &#x2F;mɒm&#x2F;</li><li>mop &#x2F;mɒp&#x2F;</li><li>not &#x2F;nɒt&#x2F;</li><li>odd &#x2F;ɒd&#x2F;</li><li>off &#x2F;ɒf&#x2F;</li><li>on &#x2F;ɒn&#x2F;</li><li>ox &#x2F;ɒks&#x2F;</li><li>pot &#x2F;pɒt&#x2F;</li><li>rock &#x2F;rɒk&#x2F;</li><li>rod &#x2F;rɒd&#x2F;</li><li>sock &#x2F;sɒk&#x2F;</li><li>stop &#x2F;stɒp&#x2F;</li><li>top &#x2F;tɒp&#x2F;</li></ul></li><li>U &#x2F;ʌ&#x2F;<ul><li>bush &#x2F;bʊʃ&#x2F;</li><li>bug &#x2F;bʌg&#x2F;</li><li>bun &#x2F;bʌn&#x2F;</li><li>bus &#x2F;bʌs&#x2F;</li><li>but &#x2F;bʌt&#x2F;</li><li>cup &#x2F;kʌp&#x2F;</li><li>cut &#x2F;kʌt&#x2F;</li><li>duck &#x2F;dʌk&#x2F;</li><li>dull &#x2F;dʌl&#x2F;</li><li>fun &#x2F;fʌn&#x2F;</li></ul></li></ul><h4 id="元音字母与-r-组合在重读音节中的常见发音"><a href="#元音字母与-r-组合在重读音节中的常见发音" class="headerlink" title="元音字母与 r 组合在重读音节中的常见发音"></a>元音字母与 r 组合在重读音节中的常见发音</h4><table><thead><tr><th>ar</th><th>er</th><th>ir</th><th>or</th><th>ur</th></tr></thead><tbody><tr><td>&#x2F;ɑː&#x2F;</td><td>&#x2F;ɜː&#x2F;</td><td>&#x2F;ɜː&#x2F;</td><td>&#x2F;ɔː&#x2F;</td><td>&#x2F;ɜː&#x2F;</td></tr></tbody></table><ul><li>ar &#x2F;ɑː&#x2F;<ul><li>arm &#x2F;ɑːm&#x2F;</li><li>art &#x2F;ɑːt&#x2F;</li><li>car &#x2F;kɑː&#x2F;</li></ul></li><li>er &#x2F;ɜː&#x2F;<ul><li>her &#x2F;hɜː&#x2F;</li><li>term &#x2F;tɜːm&#x2F;</li><li>verb &#x2F;vɜːb&#x2F;</li></ul></li><li>ir &#x2F;ɜː&#x2F;<ul><li>bird &#x2F;bɜːd&#x2F;</li><li>dirt &#x2F;dɜːt&#x2F;</li><li>shirt &#x2F;ʃɜːt&#x2F;</li></ul></li><li>or &#x2F;ɔː&#x2F;<ul><li>born &#x2F;bɔːn&#x2F;</li><li>corn &#x2F;kɔːn&#x2F;</li><li>fork &#x2F;fɔːk&#x2F;</li><li>form &#x2F;fɔːm&#x2F;</li><li>horn &#x2F;hɔːn&#x2F;</li><li>north &#x2F;nɔːθ&#x2F;</li><li>pork &#x2F;pɔːk&#x2F;</li><li>short &#x2F;ʃɔːt&#x2F;</li><li>sort &#x2F;sɔːt&#x2F;</li><li>storm &#x2F;stɔːm&#x2F;</li><li>torn &#x2F;tɔːn&#x2F;</li><li>worn &#x2F;wɔːn&#x2F;</li></ul></li><li>ur &#x2F;ɜː&#x2F;<ul><li>burn &#x2F;bɜːn&#x2F;</li><li>burst &#x2F;bɜːst&#x2F;</li><li>church &#x2F;tʃɜːtʃ&#x2F;</li><li>fur &#x2F;fɜː&#x2F;</li><li>hurt &#x2F;hɜːt&#x2F;</li><li>nurse &#x2F;nɜːs&#x2F;</li><li>purse &#x2F;pɜːs&#x2F;</li><li>turn &#x2F;tɜːn&#x2F;</li><li>turtle &#x2F;tɜːtl&#x2F;</li><li>urge &#x2F;ɜːdʒ&#x2F;</li></ul></li></ul><h4 id="元音字母与-re-组合在重读音节中的常见发音"><a href="#元音字母与-re-组合在重读音节中的常见发音" class="headerlink" title="元音字母与 re 组合在重读音节中的常见发音"></a>元音字母与 re 组合在重读音节中的常见发音</h4><table><thead><tr><th>are</th><th>ere</th><th>ire</th><th>ore</th><th>ure</th></tr></thead><tbody><tr><td>&#x2F;eə&#x2F;</td><td>&#x2F;ɪə&#x2F;</td><td>&#x2F;aɪə&#x2F;</td><td>&#x2F;ɔː&#x2F;</td><td>&#x2F;jʊə&#x2F;</td></tr></tbody></table><ul><li>are &#x2F;eə&#x2F;<ul><li>care &#x2F;keə&#x2F;</li><li>share &#x2F;ʃeə&#x2F;</li></ul></li><li>ere &#x2F;ɪə&#x2F;<ul><li>here &#x2F;hɪə&#x2F;</li><li>mere &#x2F;mɪə&#x2F;</li><li>sphere &#x2F;sfɪə&#x2F;</li></ul></li><li>ire &#x2F;aɪə&#x2F;<ul><li>fire &#x2F;faɪə&#x2F;</li><li>hire &#x2F;haɪə&#x2F;</li><li>wire &#x2F;waɪə&#x2F;</li></ul></li><li>ore &#x2F;ɔː&#x2F;<ul><li>core &#x2F;kɔː&#x2F;</li><li>more &#x2F;mɔː&#x2F;</li><li>store &#x2F;stɔː&#x2F;</li></ul></li><li>ure &#x2F;jʊə&#x2F;<ul><li>cure &#x2F;kjʊə&#x2F;</li><li>pure &#x2F;pjʊə</li></ul></li></ul><h4 id="单个元音字母在非重读音节中的发音"><a href="#单个元音字母在非重读音节中的发音" class="headerlink" title="单个元音字母在非重读音节中的发音"></a>单个元音字母在非重读音节中的发音</h4><table><thead><tr><th>A</th><th>E</th><th>I</th><th>O</th><th>U</th></tr></thead><tbody><tr><td>&#x2F;ə&#x2F;</td><td>&#x2F;ə&#x2F; or &#x2F;ɪ&#x2F;</td><td>&#x2F;ə&#x2F; or &#x2F;ɪ&#x2F;</td><td>&#x2F;ə&#x2F;</td><td>&#x2F;ə&#x2F;</td></tr></tbody></table><ul><li>A &#x2F;ə&#x2F;<ul><li>about &#x2F;əˈbaʊt&#x2F;</li><li>again &#x2F;əˈɡen&#x2F;</li><li>ago &#x2F;əˈɡəʊ&#x2F;</li><li>alone &#x2F;əˈləʊn&#x2F;</li><li>along &#x2F;əˈlɒŋ&#x2F;</li><li>among &#x2F;əˈmʌŋ&#x2F;</li><li>around &#x2F;əˈraʊnd&#x2F;</li><li>away &#x2F;əˈweɪ&#x2F;</li><li>banana &#x2F;bəˈnɑːnə&#x2F;</li></ul></li><li>E &#x2F;ə&#x2F; or &#x2F;ɪ&#x2F;<ul><li>the &#x2F;ðə&#x2F;</li><li>basket &#x2F;ˈbɑːskɪt&#x2F;</li><li>blanket &#x2F;ˈblæŋkɪt&#x2F;</li></ul></li><li>I &#x2F;ə&#x2F; or &#x2F;ɪ&#x2F;<ul><li>animal &#x2F;ˈænɪməl&#x2F;</li><li>pencil &#x2F;ˈpensəl&#x2F;</li><li>possible &#x2F;ˈpɒsəbl&#x2F;</li><li>rabbit &#x2F;ˈræbɪt&#x2F;</li><li>ticket &#x2F;ˈtɪkɪt&#x2F;</li><li>visit &#x2F;ˈvɪzɪt&#x2F;</li></ul></li><li>O &#x2F;ə&#x2F;<ul><li>bottom &#x2F;ˈbɒtəm&#x2F;</li><li>today &#x2F;təˈdeɪ&#x2F;</li><li>tomorrow &#x2F;təˈmɒrəʊ&#x2F;</li></ul></li><li>U &#x2F;ə&#x2F;<ul><li>until &#x2F;ənˈtɪl&#x2F;</li><li>upon &#x2F;əˈpɒn&#x2F;</li><li>suppose &#x2F;səˈpəʊz&#x2F;</li><li>support &#x2F;səˈpɔːt&#x2F;</li><li>supply &#x2F;səˈplaɪ&#x2F;</li></ul></li></ul><h4 id="常见元音字母组合的发音"><a href="#常见元音字母组合的发音" class="headerlink" title="常见元音字母组合的发音"></a>常见元音字母组合的发音</h4><h5 id="字母-A-的元音组合"><a href="#字母-A-的元音组合" class="headerlink" title="字母 A 的元音组合"></a>字母 A 的元音组合</h5><table><thead><tr><th>ai ay</th></tr></thead><tbody><tr><td>&#x2F;eɪ&#x2F;</td></tr></tbody></table><ul><li>ai ay &#x2F;eɪ&#x2F;<ul><li>aim &#x2F;eɪm&#x2F;</li><li>aid &#x2F;eɪd&#x2F;</li><li>daily &#x2F;ˈdeɪli&#x2F;</li><li>day &#x2F;deɪ&#x2F;</li><li>fail &#x2F;feɪl&#x2F;</li><li>gain &#x2F;ɡeɪn&#x2F;</li><li>mail &#x2F;meɪl&#x2F;</li><li>pain &#x2F;peɪn&#x2F;</li><li>rain &#x2F;reɪn&#x2F;</li><li>sail &#x2F;seɪl&#x2F;</li><li>tail &#x2F;teɪl&#x2F;</li><li>wait &#x2F;weɪt&#x2F;</li><li>way &#x2F;weɪ&#x2F;</li></ul></li></ul><h5 id="字母-E-的元音组合"><a href="#字母-E-的元音组合" class="headerlink" title="字母 E 的元音组合"></a>字母 E 的元音组合</h5><table><thead><tr><th>ea</th><th>ee</th><th>ey ei</th><th>er</th><th>eir</th></tr></thead><tbody><tr><td>&#x2F;iː&#x2F; \ &#x2F;e&#x2F;</td><td>&#x2F;iː&#x2F;</td><td>&#x2F;eɪ&#x2F;</td><td>&#x2F;ɜː&#x2F;</td><td>&#x2F;eə&#x2F;</td></tr></tbody></table><ul><li>ea &#x2F;iː&#x2F;<ul><li>beach &#x2F;biːtʃ&#x2F;</li><li>bean &#x2F;biːn&#x2F;</li><li>beat &#x2F;biːt&#x2F;</li><li>cheap &#x2F;tʃiːp&#x2F;</li><li>clean &#x2F;kliːn&#x2F;</li><li>cream &#x2F;kriːm&#x2F;</li><li>dream &#x2F;driːm&#x2F;</li></ul></li><li>ea &#x2F;e&#x2F; （在重读闭音节中）<ul><li>bread &#x2F;bred&#x2F;</li><li>dead &#x2F;ded&#x2F;</li><li>head &#x2F;hed&#x2F;</li><li>lead &#x2F;led&#x2F;</li><li>read &#x2F;red&#x2F;</li><li>spread &#x2F;spred&#x2F;</li></ul></li><li>ee &#x2F;iː&#x2F;<ul><li>bee &#x2F;biː&#x2F;</li><li>beef &#x2F;biːf&#x2F;</li><li>deep &#x2F;diːp&#x2F;</li><li>feel &#x2F;fiːl&#x2F;</li><li>feet &#x2F;fiːt&#x2F;</li><li>free &#x2F;friː&#x2F;</li><li>green &#x2F;ɡriːn&#x2F;</li><li>keep &#x2F;kiːp&#x2F;</li><li>meet &#x2F;miːt&#x2F;</li><li>need &#x2F;niːd&#x2F;</li><li>queen &#x2F;kwiːn&#x2F;</li><li>see &#x2F;siː&#x2F;</li><li>seed &#x2F;siːd&#x2F;</li><li>sleep &#x2F;sliːp&#x2F;</li><li>speed &#x2F;spiːd&#x2F;</li><li>street &#x2F;striːt&#x2F;</li><li>sweet &#x2F;swiːt&#x2F;</li><li>tree &#x2F;triː&#x2F;</li><li>week &#x2F;wiːk&#x2F;</li><li>wheel &#x2F;wiːl&#x2F;</li></ul></li><li>ei ey &#x2F;eɪ&#x2F;<ul><li>beige &#x2F;beɪʒ&#x2F;</li><li>eight &#x2F;eɪt&#x2F;</li><li>they &#x2F;ðeɪ&#x2F;</li><li>grey &#x2F;ɡreɪ&#x2F;</li><li>hey &#x2F;heɪ&#x2F;</li><li>obey &#x2F;əˈbeɪ&#x2F;</li></ul></li><li>er &#x2F;ɜː&#x2F;<ul><li>her &#x2F;hɜː&#x2F;</li><li>verb &#x2F;vɜːb&#x2F;</li></ul></li><li>eir &#x2F;eə&#x2F; or &#x2F;ɪə&#x2F;<ul><li>heir &#x2F;eə&#x2F;</li><li>their &#x2F;ðeə&#x2F;</li><li>there &#x2F;ðeə&#x2F;</li><li>weird &#x2F;wɪəd&#x2F;</li></ul></li></ul><h5 id="字母-I-的元音组合"><a href="#字母-I-的元音组合" class="headerlink" title="字母 I 的元音组合"></a>字母 I 的元音组合</h5><table><thead><tr><th>ie</th></tr></thead><tbody><tr><td>&#x2F;iː&#x2F;</td></tr></tbody></table><ul><li>ie &#x2F;iː&#x2F;<ul><li>chief &#x2F;tʃiːf&#x2F;</li><li>field &#x2F;fiːld&#x2F;</li><li>piece &#x2F;piːs&#x2F;</li><li>thief &#x2F;θiːf&#x2F;</li><li>yield &#x2F;jiːld&#x2F;</li></ul></li></ul><h5 id="字母-O-的元音组合"><a href="#字母-O-的元音组合" class="headerlink" title="字母 O 的元音组合"></a>字母 O 的元音组合</h5><table><thead><tr><th>oa</th><th>oe</th><th>oi oy</th><th>oo</th><th>ou</th></tr></thead><tbody><tr><td>&#x2F;əʊ&#x2F;</td><td>&#x2F;əʊ&#x2F;</td><td>&#x2F;ɔɪ&#x2F;</td><td>&#x2F;uː&#x2F;</td><td>&#x2F;aʊ&#x2F;</td></tr></tbody></table><ul><li><p>oa &#x2F;əʊ&#x2F;</p><ul><li>boat &#x2F;bəʊt&#x2F;</li><li>coat &#x2F;kəʊt&#x2F;</li><li>goat &#x2F;ɡəʊt&#x2F;</li><li>load &#x2F;ləʊd&#x2F;</li><li>road &#x2F;rəʊd&#x2F;</li><li>soap &#x2F;səʊp&#x2F;</li><li>toad &#x2F;təʊd&#x2F;</li><li>toast &#x2F;təʊst&#x2F;</li><li>throat &#x2F;θrəʊt&#x2F;</li></ul></li><li><p>oe &#x2F;əʊ&#x2F;</p><ul><li>doe &#x2F;dəʊ&#x2F;</li><li>foe &#x2F;fəʊ&#x2F;</li><li>hoe &#x2F;həʊ&#x2F;</li><li>toe &#x2F;təʊ&#x2F;</li><li>woe &#x2F;wəʊ&#x2F;</li></ul></li><li><p>oi oy &#x2F;ɔɪ&#x2F;</p><ul><li>boy &#x2F;bɔɪ&#x2F;</li><li>boil &#x2F;bɔɪl&#x2F;</li><li>coin &#x2F;kɔɪn&#x2F;</li><li>join &#x2F;dʒɔɪn&#x2F;</li><li>noise &#x2F;nɔɪz&#x2F;</li><li>point &#x2F;pɔɪnt&#x2F;</li><li>soil &#x2F;sɔɪl&#x2F;</li><li>toy &#x2F;tɔɪ&#x2F;</li><li>voice &#x2F;vɔɪs&#x2F;</li></ul></li><li><p>oo &#x2F;uː&#x2F; or &#x2F;ʊ&#x2F;</p><ul><li>boot &#x2F;buːt&#x2F;</li><li>cool &#x2F;kuːl&#x2F;</li><li>food &#x2F;fuːd&#x2F;</li><li>fool &#x2F;fuːl&#x2F;</li><li>good &#x2F;ɡʊd&#x2F;</li><li>hood &#x2F;hʊd&#x2F;</li><li>hook &#x2F;hʊk&#x2F;</li><li>look &#x2F;lʊk&#x2F;</li><li>moon &#x2F;muːn&#x2F;</li><li>noon &#x2F;nuːn&#x2F;</li><li>pool &#x2F;puːl&#x2F;</li><li>root &#x2F;ruːt&#x2F;</li><li>soon &#x2F;suːn&#x2F;</li><li>stood &#x2F;stʊd&#x2F;</li><li>took &#x2F;tʊk&#x2F;</li><li>tool &#x2F;tuːl&#x2F;</li><li>wood &#x2F;wʊd&#x2F;</li><li>wool &#x2F;wʊl&#x2F;</li></ul></li><li><p>ou &#x2F;aʊ&#x2F;</p><ul><li>about &#x2F;əˈbaʊt&#x2F;</li><li>cloud &#x2F;klaʊd&#x2F;</li><li>count &#x2F;kaʊnt&#x2F;</li><li>doubt &#x2F;daʊt&#x2F;</li><li>found &#x2F;faʊnd&#x2F;</li><li>ground &#x2F;ɡraʊnd&#x2F;</li><li>house &#x2F;haʊs&#x2F;</li><li>loud &#x2F;laʊd&#x2F;</li><li>mouth &#x2F;maʊθ&#x2F;</li><li>mouse &#x2F;maʊs&#x2F;</li><li>out &#x2F;aʊt&#x2F;</li><li>pound &#x2F;paʊnd&#x2F;</li><li>round &#x2F;raʊnd&#x2F;</li><li>shout &#x2F;ʃaʊt&#x2F;</li><li>south &#x2F;saʊθ&#x2F;</li><li>sound &#x2F;saʊnd&#x2F;</li><li>town &#x2F;taʊn&#x2F;</li><li>trout &#x2F;traʊt&#x2F;</li><li>vowel &#x2F;ˈvaʊəl&#x2F;</li><li>wound &#x2F;wuːnd&#x2F;</li></ul></li></ul><h5 id="字母-U-的元音组合"><a href="#字母-U-的元音组合" class="headerlink" title="字母 U 的元音组合"></a>字母 U 的元音组合</h5><table><thead><tr><th>ue</th><th>ui</th></tr></thead><tbody><tr><td>&#x2F;uː&#x2F;</td><td>&#x2F;uː&#x2F;</td></tr></tbody></table><ul><li>ue &#x2F;uː&#x2F;<ul><li>blue &#x2F;bluː&#x2F;</li><li>clue &#x2F;kluː&#x2F;</li><li>due &#x2F;duː&#x2F;</li><li>glue &#x2F;ɡluː&#x2F;</li><li>true &#x2F;truː&#x2F;</li></ul></li><li>ui &#x2F;u:&#x2F;<ul><li>fruit &#x2F;fruːt&#x2F;</li><li>juice &#x2F;dʒuːs&#x2F;</li><li>suit &#x2F;suːt&#x2F;</li></ul></li></ul><h3 id="辅音字母的常见发音"><a href="#辅音字母的常见发音" class="headerlink" title="辅音字母的常见发音"></a>辅音字母的常见发音</h3><p>见 <a href="/phonics-of-consonants">Phonics 自然拼读常见规则 - 辅音字母的发音规律</a>。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;自然拼读法是通过英语中的音节和音素之间的关系，根据这些规则正确地发音和拼写单词的方法。通过自然拼读法，学习者可以更轻松地理解和记忆英语单词的发音，提高阅读流畅性和拼写准确性。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;重读开音节&lt;/th&gt;
&lt;th&gt;重读闭音节&lt;/th&gt;
&lt;th&gt;非重读音节&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;&amp;#x2F;eɪ&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;æ&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ə&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;&amp;#x2F;iː&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;e&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ə&amp;#x2F; or &amp;#x2F;ɪ&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I&lt;/td&gt;
&lt;td&gt;&amp;#x2F;aɪ&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ɪ&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ə&amp;#x2F; or &amp;#x2F;ɪ&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;&amp;#x2F;əʊ&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ɒ&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ə&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;U&lt;/td&gt;
&lt;td&gt;&amp;#x2F;juː&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ʌ&amp;#x2F;&lt;/td&gt;
&lt;td&gt;&amp;#x2F;ə&amp;#x2F;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;辅音字母的拼读规则见我的另一篇博客 &lt;a href=&quot;/phonics-of-consonants&quot;&gt;Phonics 自然拼读常见规则 - 辅音字母的发音规律&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id=&quot;音节&quot;&gt;&lt;a href=&quot;#音节&quot; class=&quot;headerlink&quot; title=&quot;音节&quot;&gt;&lt;/a&gt;音节&lt;/h2&gt;&lt;h3 id=&quot;什么是音节&quot;&gt;&lt;a href=&quot;#什么是音节&quot; class=&quot;headerlink&quot; title=&quot;什么是音节&quot;&gt;&lt;/a&gt;什么是音节&lt;/h3&gt;&lt;p&gt;音节是发音的基本单位，是一个发音的完整单位。音节的划分对于一个单词的读音至关重要，自然拼读的规律基本上是针对单个音节的。&lt;/p&gt;
&lt;p&gt;一个音节，只会包含一次出气，出气时的声带的振动被称为元音；牙齿、舌头、嘴唇等部位的阻碍气流发出的声音被称为辅音。&lt;/p&gt;
&lt;p&gt;音节由一个元音或一个元音加一个或几个辅音组成。中文里每个字都是一个音节。英文里每个单词会有一个或多个音节。&lt;/p&gt;</summary>
    
    
    
    <category term="English" scheme="https://blog.esonwong.com/categories/English/"/>
    
    
    <category term="English" scheme="https://blog.esonwong.com/tags/English/"/>
    
  </entry>
  
  <entry>
    <title>怎么用 Github Actions 部署 Next.js 项目到服务器</title>
    <link href="https://blog.esonwong.com/how-to-deploy-next-js-project-to-the-server-using-github-actions/"/>
    <id>https://blog.esonwong.com/how-to-deploy-next-js-project-to-the-server-using-github-actions/</id>
    <published>2023-10-09T14:42:14.000Z</published>
    <updated>2026-02-27T10:20:27.160Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/./how-to-deploy-next-js-project-to-the-server-using-github-actions/cover.webp" alt="怎么用 Github Actions 部署 Next.js 项目到服务器？"></p><p>最近开发一个项目 Next.js，部署到 Vercel 上在国内访问速度和稳定性都不太好，所以想部署到自己的服务器上。经过实践后，分享一下怎么用 Github Actions 部署 Next.js 项目到 Linux 服务器上。</p><span id="more"></span><h2 id="服务器环境配置"><a href="#服务器环境配置" class="headerlink" title="服务器环境配置"></a>服务器环境配置</h2><p>在服务器要安装 Node.js 和 PM2，然后配置 Nginx。</p><h3 id="安装-Node-js"><a href="#安装-Node-js" class="headerlink" title="安装 Node.js"></a>安装 Node.js</h3><p>推荐使用 <a href="https://fnm.vercel.app/">fnm</a> 来安装 Node.js，以后可以方便的使用不同版本的 Node.js。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -fsSL https://fnm.vercel.app/install | bash</span><br></pre></td></tr></table></figure><p>安装好后重新 SSH 连接到服务器终端，用 fnm 安装 Node.js。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fnm install 18</span><br></pre></td></tr></table></figure><h3 id="安装-PM2"><a href="#安装-PM2" class="headerlink" title="安装 PM2"></a>安装 PM2</h3><p>我们使用 <a href="https://pm2.keymetrics.io/">PM2</a> 来管理 Node.js 进程。以便在服务器重启后自动启动项目。</p><p>用 npm 安装 PM2：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install pm2 -g</span><br></pre></td></tr></table></figure><h3 id="Nginx-配置"><a href="#Nginx-配置" class="headerlink" title="Nginx 配置"></a>Nginx 配置</h3><p>Node.js 项目默认运行在 3000 端口，我们使用 Nginx 来反向代理到 3000 端口。这样就可以使用 80 或 443 端口来访问项目。</p><p>在 nginx 配置文件夹 <code>/etc/nginx/sites-available</code> 中创建一个配置文件 <code>example.com</code>：</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">  <span class="attribute">listen</span> <span class="number">80</span>;</span><br><span class="line">  <span class="attribute">server_name</span> example.com;</span><br><span class="line"></span><br><span class="line">  <span class="section">location</span> / &#123;</span><br><span class="line">    <span class="attribute">proxy_pass</span> http://localhost:3000;</span><br><span class="line">    <span class="attribute">proxy_http_version</span> <span class="number">1</span>.<span class="number">1</span>;</span><br><span class="line">    <span class="attribute">proxy_set_header</span> Upgrade <span class="variable">$http_upgrade</span>;</span><br><span class="line">    <span class="attribute">proxy_set_header</span> Connection <span class="string">&quot;upgrade&quot;</span>;</span><br><span class="line">    <span class="attribute">proxy_set_header</span> Host <span class="variable">$host</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后在 <code>sites-enabled</code> 文件夹中创建一个软链接。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> <span class="built_in">ln</span> -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com</span><br></pre></td></tr></table></figure><p>然后重新加载 Nginx 配置文件:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> nginx -s reload</span><br></pre></td></tr></table></figure><h3 id="生成-SSL-证书"><a href="#生成-SSL-证书" class="headerlink" title="生成 SSL 证书"></a>生成 SSL 证书</h3><p><a href="https://certbot.eff.org/instructions">安装 certbot</a> 来生成证书并修改 Nginx 配置文件以使用证书。</p><p>生成证书：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> certbot  --nginx</span><br></pre></td></tr></table></figure><p>命令执行后会提示输入邮箱，然后选择同意条款，最后选择要生成证书的域名，然后就会自动的生成证书并修改 Nginx 配置文件和重新加载。</p><h3 id="代码拉取-SSH-密钥配置"><a href="#代码拉取-SSH-密钥配置" class="headerlink" title="代码拉取 SSH 密钥配置"></a>代码拉取 SSH 密钥配置</h3><ol><li><p><a href="https://docs.github.com/zh/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent">生成 SSH 密钥</a></p></li><li><p>把公钥添加到 Github 仓库的 Deploy keys 中</p><p><img src="/./how-to-deploy-next-js-project-to-the-server-using-github-actions/add-deploy-public-key.webp" alt="添加公钥"></p></li><li><p>把私钥到放到服务器的用于发布项目的用户的 <code>~/.ssh/id_rsa</code> 路径，以便 Github Actions 用 SSH 连接服务器拉取 Github 上的代码。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;private-key&quot;</span> &gt;&gt; ~/.ssh/id_rsa</span><br></pre></td></tr></table></figure></li></ol><h2 id="Github-Actions-配置"><a href="#Github-Actions-配置" class="headerlink" title="Github Actions 配置"></a>Github Actions 配置</h2><p>我们使用 <a href="https://github.com/appleboy/ssh-action">appleboy&#x2F;ssh-action@master</a> 这个 Github Action 用 ssh 来连接服务器，然后执行命令来部署项目。为了安全起见，我们把服务器 host 和端口，还有 ssh 密钥都配置到 Github 仓库的 Secrets 中，这样就不会把服务器的信息暴露到配置文件中。</p><h3 id="准备部署-SSH-密钥"><a href="#准备部署-SSH-密钥" class="headerlink" title="准备部署 SSH 密钥"></a>准备部署 SSH 密钥</h3><ol><li><p>再<a href="https://docs.github.com/zh/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent">生成 SSH 密钥</a>对用于发布项目</p></li><li><p>把公钥添加到服务器的 <code>~/.ssh/authorized_keys</code> 文件中</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;public-key&quot;</span> &gt;&gt; ~/.ssh/authorized_keys</span><br></pre></td></tr></table></figure></li><li><p>在 Github 仓库的 Settings -&gt; Secrets -&gt; Actions 中添加名为 <code>key</code> 的 secret，值为私钥。</p><p><img src="/./how-to-deploy-next-js-project-to-the-server-using-github-actions/add-ssh-key.webp" alt="添加私钥"></p></li></ol><h3 id="设置-host-和端口"><a href="#设置-host-和端口" class="headerlink" title="设置 host 和端口"></a>设置 host 和端口</h3><p>同样在 Github 仓库的 Settings -&gt; Secrets -&gt; Actions 中添加 <code>host</code> 和 <code>port</code>。</p><h3 id="创建-Github-Actions-配置文件"><a href="#创建-Github-Actions-配置文件" class="headerlink" title="创建 Github Actions 配置文件"></a>创建 Github Actions 配置文件</h3><p>在仓库的根目录中创建文件夹 <code>.github/workflows</code>。在此文件夹中创建一个 <code>.yml</code> 后缀的文件。</p><p>在配置文件中指定<code>main</code>分支在 push 时触发 Github Actions，然后指定一个 job 名为 <code>deploy</code>，在这个 job 中使用 <code>appleboy/ssh-action@master</code> 这个 Github Action 来连接服务器，然后执行部署脚本。在 Github Actions 中可以使用 Secrets 中的变量，这样就不会把服务器的信息暴露到配制文件中。</p><p>部署脚本首先用 <code>git clone</code> 拉取代码, 然后安装依赖，最后使用 PM2 启动项目。最后用 <code>pm2 save</code> 保存项目配置，以便在服务器重启后自动启动项目。</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">on:</span></span><br><span class="line">  <span class="attr">push:</span></span><br><span class="line">    <span class="attr">branches:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">main</span></span><br><span class="line"><span class="attr">jobs:</span></span><br><span class="line">  <span class="attr">deploy:</span></span><br><span class="line">    <span class="attr">runs-on:</span> <span class="string">ubuntu-latest</span></span><br><span class="line">    <span class="attr">steps:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Deploy</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">appleboy/ssh-action@master</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">host:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.host</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">username:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.username</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">key:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.key</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">port:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.port</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">script:</span> <span class="string">|</span></span><br><span class="line"><span class="string">            git clone $&#123;&#123; github.repository &#125;&#125; /home/username/project</span></span><br><span class="line"><span class="string">            cd /home/username/project</span></span><br><span class="line"><span class="string">            npm install</span></span><br><span class="line"><span class="string">            pm2 start npm --name &quot;project&quot; -- start</span></span><br><span class="line"><span class="string">            pm2 save</span></span><br></pre></td></tr></table></figure><p>此后每次 push 到 main 分支时，Github Actions 就会自动部署项目到服务器上。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><a href="https://help.github.com/cn/actions/automating-your-workflow-with-github-actions">GitHub Actions Documentation</a></li><li><a href="https://github.com/marketplace?type=actions">actions 市场</a></li><li><a href="https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions">Workflow syntax for GitHub Actions</a></li><li><a href="https://docs.github.com/zh/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent">生成 SSH 密钥</a></li><li><a href="https://certbot.eff.org/instructions">安装 certbot</a></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;/./how-to-deploy-next-js-project-to-the-server-using-github-actions/cover.webp&quot; alt=&quot;怎么用 Github Actions 部署 Next.js 项目到服务器？&quot;&gt;&lt;/p&gt;
&lt;p&gt;最近开发一个项目 Next.js，部署到 Vercel 上在国内访问速度和稳定性都不太好，所以想部署到自己的服务器上。经过实践后，分享一下怎么用 Github Actions 部署 Next.js 项目到 Linux 服务器上。&lt;/p&gt;</summary>
    
    
    
    <category term="教程" scheme="https://blog.esonwong.com/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="Web 开发" scheme="https://blog.esonwong.com/tags/Web-%E5%BC%80%E5%8F%91/"/>
    
    <category term="前端" scheme="https://blog.esonwong.com/tags/%E5%89%8D%E7%AB%AF/"/>
    
    <category term="Next.js" scheme="https://blog.esonwong.com/tags/Next-js/"/>
    
    <category term="Github" scheme="https://blog.esonwong.com/tags/Github/"/>
    
    <category term="Github Actions" scheme="https://blog.esonwong.com/tags/Github-Actions/"/>
    
    <category term="Linux" scheme="https://blog.esonwong.com/tags/Linux/"/>
    
    <category term="Nginx" scheme="https://blog.esonwong.com/tags/Nginx/"/>
    
    <category term="PM2" scheme="https://blog.esonwong.com/tags/PM2/"/>
    
    <category term="Node.js" scheme="https://blog.esonwong.com/tags/Node-js/"/>
    
    <category term="前端部署" scheme="https://blog.esonwong.com/tags/%E5%89%8D%E7%AB%AF%E9%83%A8%E7%BD%B2/"/>
    
    <category term="自动化" scheme="https://blog.esonwong.com/tags/%E8%87%AA%E5%8A%A8%E5%8C%96/"/>
    
    <category term="自动部署" scheme="https://blog.esonwong.com/tags/%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2/"/>
    
  </entry>
  
  <entry>
    <title>使用 v4l 采集摄像头</title>
    <link href="https://blog.esonwong.com/how-to-use-ffmpeg-with-camera-on-linux/"/>
    <id>https://blog.esonwong.com/how-to-use-ffmpeg-with-camera-on-linux/</id>
    <published>2023-09-28T13:48:41.000Z</published>
    <updated>2026-02-27T10:20:27.162Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/./how-to-use-ffmpeg-with-camera-on-linux/cover.webp" alt="怎么在 Linux 上使用 FFmpeg 采集摄像头"></p><p>FFmpeg 是一个非常强大的视频处理工具。大多数应用都会使用 FFmpeg 来处理视频。我的 <a href="https://network-rc.esonwong.com/">Network RC</a> 项目也使用了 FFmpeg 来处理视频。</p><span id="more"></span><h2 id="Video4Linux2"><a href="#Video4Linux2" class="headerlink" title="Video4Linux2"></a>Video4Linux2</h2><p>Video4Linux2(v4l2) 是 Linux 上的一个视频采集框架，它提供了一套统一的接口，可以方便的接入视频设备的输入和输出。FFmpeg 也可以通过 Video4Linux2 接口来采集摄像头的视频。</p><h3 id="v4l2-ctl"><a href="#v4l2-ctl" class="headerlink" title="v4l2-ctl"></a>v4l2-ctl</h3><p>v4l2-ctl 是 Video4Linux2 的一个命令行工具，可以用来查看和设置视频设备的参数。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看视频输入设备</span></span><br><span class="line">v4l2-ctl -n</span><br><span class="line"><span class="comment"># or</span></span><br><span class="line">v4l2-ctl --list-inputs</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置视频输入设备</span></span><br><span class="line">v4l2-ctl -i 0 <span class="comment"># 设置 index 为 0 的视频输入设备作为当前视频输入设备</span></span><br><span class="line"><span class="comment"># or</span></span><br><span class="line">v4l2-ctl --set-input 0</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看支持的输出的格式</span></span><br><span class="line">v4l2-ctl --list-formats</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看支持的分辨率</span></span><br><span class="line">v4l2-ctl --list-framesizes=YUYV</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看支持的帧率</span></span><br><span class="line">v4l2-ctl --list-frameintervals width=1920,height=1080,pixelformat=YUYV</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看视频输入设备的控制参数</span></span><br><span class="line">v4l2-ctl --list-ctrls</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看视频输入设备的控制参数的值</span></span><br><span class="line">v4l2-ctl --get-ctrl=iso_sensitivity</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置视频输入设备的控制参数的值</span></span><br><span class="line">v4l2-ctl --set-ctrl=iso_sensitivity=100</span><br></pre></td></tr></table></figure><h2 id="FFmpeg-使用-Video4Linux2-采集摄像头"><a href="#FFmpeg-使用-Video4Linux2-采集摄像头" class="headerlink" title="FFmpeg 使用 Video4Linux2 采集摄像头"></a>FFmpeg 使用 Video4Linux2 采集摄像头</h2><h3 id="输入设备"><a href="#输入设备" class="headerlink" title="输入设备"></a>输入设备</h3><p>在 ffmpeg 命令中，使用 <code>-f v4l2</code> 或 <code>-f video4linux2</code> 指定视频输入接口为 Video4Linux2。<br>使用 <code>-i /dev/video0</code> 指定视频输入设备路径为。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ffmpeg -f v4l2 -i /dev/video0 -c:v libx264 -preset ultrafast -f mp4 camera-test.mp4</span><br></pre></td></tr></table></figure><h3 id="采集格式"><a href="#采集格式" class="headerlink" title="采集格式"></a>采集格式</h3><p>使用 <code>-input_format</code> 指定视频输入格式。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ffmpeg -f v4l2 -i /dev/video0 -input_format yuyv422 -c:v libx264 -preset ultrafast -f mp4 camera-test.mp4</span><br></pre></td></tr></table></figure><h3 id="分辨率"><a href="#分辨率" class="headerlink" title="分辨率"></a>分辨率</h3><p>使用 <code>-video_size</code> 指定视频分辨率。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ffmpeg -f v4l2 -i /dev/video0 -video_size 1920x1080 -c:v libx264 -preset ultrafast -f mp4 camera-test.mp4</span><br><span class="line"><span class="comment"># or</span></span><br><span class="line">ffmpeg -f v4l2 -i /dev/video0 -s 1920x1080 -c:v libx264 -preset ultrafast -f mp4 camera-test.mp4</span><br></pre></td></tr></table></figure><h3 id="帧率"><a href="#帧率" class="headerlink" title="帧率"></a>帧率</h3><p>使用 <code>-framerate</code> 指定视频帧率。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ffmpeg -f v4l2 -i /dev/video0 -framerate 30 -c:v libx264 -preset ultrafast -f mp4 camera-test.mp4</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;/./how-to-use-ffmpeg-with-camera-on-linux/cover.webp&quot; alt=&quot;怎么在 Linux 上使用 FFmpeg 采集摄像头&quot;&gt;&lt;/p&gt;
&lt;p&gt;FFmpeg 是一个非常强大的视频处理工具。大多数应用都会使用 FFmpeg 来处理视频。我的 &lt;a href=&quot;https://network-rc.esonwong.com/&quot;&gt;Network RC&lt;/a&gt; 项目也使用了 FFmpeg 来处理视频。&lt;/p&gt;</summary>
    
    
    
    
    <category term="技术" scheme="https://blog.esonwong.com/tags/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="Linux" scheme="https://blog.esonwong.com/tags/Linux/"/>
    
    <category term="FFmpeg" scheme="https://blog.esonwong.com/tags/FFmpeg/"/>
    
    <category term="v4l" scheme="https://blog.esonwong.com/tags/v4l/"/>
    
  </entry>
  
  <entry>
    <title>怎么解决 Prettier 和 ESLint 在 VSCode 里的冲突?</title>
    <link href="https://blog.esonwong.com/how-to-resolve-prettier-and-eslint-and-vscode-auto-fix-conflict/"/>
    <id>https://blog.esonwong.com/how-to-resolve-prettier-and-eslint-and-vscode-auto-fix-conflict/</id>
    <published>2023-09-18T13:36:29.000Z</published>
    <updated>2026-02-27T10:20:27.162Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/./how-to-resolve-prettier-and-eslint-and-vscode-auto-fix-conflict/cover.webp" alt="怎么解决 Prettier 和 ESLint 在 VSCode 里的冲突?"></p><p>Prettier 是一个代码格式化工具。ESLint 是一个代码检查工具，它可以检查你的代码是否遵循了规范。他们通常会在项目中一起使用。前端开发过程中，我们通常会使用 Prettier 和 ESLint 来保持代码的可读性和统一代码风格和规范。项目脚手架工具和代码编辑器都可以引入 Prettier 和 ESLint 工具。</p><span id="more"></span><p>Prettier 和 ESlint 配置不当，会导致代码格式化和代码检查的冲突。项目脚手架工具和代码编辑器的配置不统一也会导致格式自动修复的冲突。</p><p>下面是配制 Prettier 和 ESLint 的方法：</p><ol><li><p>安装 eslint-config-prettier</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add --dev eslint-config-prettier</span><br></pre></td></tr></table></figure></li><li><p>在 ESLint 配置文件中添加配置</p><p>在 <code>.eslintrc.json</code> 文件中的 <code>extends</code> 的最后中添加 <code>&quot;prettier&quot;</code>;</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;extends&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;eslint:recommended&quot;</span><span class="punctuation">,</span> <span class="string">&quot;prettier&quot;</span><span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure></li></ol><p>这样 VSCode 使用 Prettier 插件来格式化代码就不会冲突了。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;/./how-to-resolve-prettier-and-eslint-and-vscode-auto-fix-conflict/cover.webp&quot; alt=&quot;怎么解决 Prettier 和 ESLint 在 VSCode 里的冲突?&quot;&gt;&lt;/p&gt;
&lt;p&gt;Prettier 是一个代码格式化工具。ESLint 是一个代码检查工具，它可以检查你的代码是否遵循了规范。他们通常会在项目中一起使用。前端开发过程中，我们通常会使用 Prettier 和 ESLint 来保持代码的可读性和统一代码风格和规范。项目脚手架工具和代码编辑器都可以引入 Prettier 和 ESLint 工具。&lt;/p&gt;</summary>
    
    
    
    <category term="技术" scheme="https://blog.esonwong.com/categories/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="Web 开发" scheme="https://blog.esonwong.com/categories/%E6%8A%80%E6%9C%AF/Web-%E5%BC%80%E5%8F%91/"/>
    
    
    <category term="ECMAScript" scheme="https://blog.esonwong.com/tags/ECMAScript/"/>
    
    <category term="Web 开发" scheme="https://blog.esonwong.com/tags/Web-%E5%BC%80%E5%8F%91/"/>
    
    <category term="前端" scheme="https://blog.esonwong.com/tags/%E5%89%8D%E7%AB%AF/"/>
    
    <category term="技术" scheme="https://blog.esonwong.com/tags/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="Javascript" scheme="https://blog.esonwong.com/tags/Javascript/"/>
    
    <category term="开发规范" scheme="https://blog.esonwong.com/tags/%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83/"/>
    
    <category term="ESLint" scheme="https://blog.esonwong.com/tags/ESLint/"/>
    
    <category term="VS Code" scheme="https://blog.esonwong.com/tags/VS-Code/"/>
    
  </entry>
  
  <entry>
    <title>《微习惯》 - 读书笔记</title>
    <link href="https://blog.esonwong.com/mini-habits/"/>
    <id>https://blog.esonwong.com/mini-habits/</id>
    <published>2023-09-15T16:00:00.000Z</published>
    <updated>2026-02-27T10:20:27.195Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/./mini-habits/cover.jpg" alt="微习惯封面"></p><p>这本书我是与《自控力》一起读的。都是基于相同的目的而读：学习和运用其中实际可操作的方法，为我开发的 App 设计功能帮用户能够改变自己。</p><span id="more"></span><h2 id="这本书讲了什么"><a href="#这本书讲了什么" class="headerlink" title="这本书讲了什么"></a>这本书讲了什么</h2><p>前三章探讨习惯建立过程、大脑、意志力、动力以及这些因素之间是如何相互关联的。接下来的两个章节将探讨合理、科学的途径。最后两章是行动指南和原则。</p><h2 id="习惯是什么"><a href="#习惯是什么" class="headerlink" title="习惯是什么"></a>习惯是什么</h2><p>一个微习惯，是坚持做一件感知不到困难、不会消耗意志的事情。它是潜意识行为。</p><blockquote><p>重复就是（潜意识）大脑使用的语言。</p></blockquote><p>大脑的有两种工作模式，通过重复行为识别模式；抑制模式，改进行为。”模式识别”由基底神经节完成。效率高，消耗能量少。它很稳定，不易改变。</p><p>前额皮层可以抑制模式识别，改进已经形成习惯的行为，但能耗较大。</p><blockquote><p>压力会促进习惯性行为，无论这种习惯是好是坏。</p></blockquote><p>因为在压力下，大脑会倾向于使用能耗较少的”模式识别”。</p><h3 id="大脑中习惯的样子"><a href="#大脑中习惯的样子" class="headerlink" title="大脑中习惯的样子"></a>大脑中习惯的样子</h3><p>一个习惯在大脑中，是很多条件触发一系列动作的不断的强化结果。也许是某些条件触发某些动作的神经通路在不断重复的过程当中，神经细胞们自发的生长出信号越来越强烈和畅通的连接。</p><blockquote><p>神经通路是大脑里的沟通渠道，这些通路就是习惯在身体里的“长相”。</p></blockquote><blockquote><p>一旦某个习惯指定的神经通路被一个想法或外部信号触发，脑中就会有一个电荷沿着这条通路放电，然后你就会有一股想进行这项习惯行为的强烈欲望。</p></blockquote><p>在特定条件下总是重复的触发一系列动作，我们要让大脑执行这个过程要消耗的能量越来越少，来获得竞争优势。这就是习惯的生理学和演化学上的意义。</p><blockquote><p>潜意识大脑喜欢效率，这就是我们能养成习惯的原因。当你重复某个行为一段时间后，大脑就能自动完成这个过程了。比起每次都要有意识地进行权衡和选择再决定以同样的方式行动，这种做法更节能。</p></blockquote><h3 id="习惯对人的影响比人们预想的要大得多"><a href="#习惯对人的影响比人们预想的要大得多" class="headerlink" title="习惯对人的影响比人们预想的要大得多"></a>习惯对人的影响比人们预想的要大得多</h3><blockquote><p>相比某一天做很多事，每天做一点儿事的影响力会更大。</p></blockquote><blockquote><p>哪怕是一点点行动，也比毫不作为强无数倍（在数学意义上如此，实际生活中也是如此）</p></blockquote><blockquote><p>杜克大学的一项研究表明：我们的行为中大约有 45% 源于习惯。</p></blockquote><blockquote><p>而且大部分每天都在重复，长远看，这种不断的重复叠加起来，要么收益颇丰，要么贻害无穷。</p></blockquote><h2 id="行动指南"><a href="#行动指南" class="headerlink" title="行动指南"></a>行动指南</h2><h3 id="一、选择微习惯的策略和目标"><a href="#一、选择微习惯的策略和目标" class="headerlink" title="一、选择微习惯的策略和目标"></a>一、选择微习惯的策略和目标</h3><p>第一步选择微习惯的策略，使用一周弹性计划来确定自己使用单一微计划，还是多项微计划。当自控力较弱时应选选择单一微计划来改善自控力。如果把微习惯当作一项技能来说的话，初学者应该从单一微计划开始尝试。微习惯的每一次任务要到小不会让你在精力疲备的时候也不会产生抵抗，既使会感到它小到很荒唐。</p><blockquote><p>微步骤之小会让我们感到荒唐，这可能是社会标准、更高更大的思维习惯以及自尊心导致的。</p></blockquote><p>在习惯没有连续完成时，进行分解操作。把分解出来的第一步作为微习惯。</p><h3 id="二、挖掘微习惯的内在价值"><a href="#二、挖掘微习惯的内在价值" class="headerlink" title="二、挖掘微习惯的内在价值"></a>二、挖掘微习惯的内在价值</h3><blockquote><p>想知道习惯是否值得我们付出努力的最佳方法是先认清来源。</p></blockquote><blockquote><p>列好习惯后，看看你为什么想要实现它们，但别在这一步就停止。再问问为什么，不断地问下去，直到形成循环和重复为止，因为这时候你已经找到了核心。</p></blockquote><p>习惯的的价值要来自于自身的追求。而不是来自于外界的压力。</p><blockquote><p>来自同龄人的压力和别人对你的期待并不是我们要寻找的想法来源。</p></blockquote><h3 id="三、明确微习惯的依据，将其纳入日程"><a href="#三、明确微习惯的依据，将其纳入日程" class="headerlink" title="三、明确微习惯的依据，将其纳入日程"></a>三、明确微习惯的依据，将其纳入日程</h3><p>习惯行为不是主动的思维触发的，而是潜意识能感受到的条件触发的。比如时间、环境、事件、情绪等等。通勤坐地铁会触发我的多邻国打卡习惯，周末则是饭后。当然，饭后也会触发我抽烟的环习惯。</p><blockquote><p>培养习惯的常见依据有两种，时间和行为方式</p></blockquote><p>一个有固定依据习惯会形成得更快，没有依据的习惯会更灵活，触发习惯的概率更高。因为没有依据的习惯通常有多个不同的触发条件，模式更复杂，在大脑中形成得更慢。</p><blockquote><p>只凭借一个依据行事会让你难以获得社会机遇和发挥自主性。</p></blockquote><p>我们可以从简单的做起。培养好习惯让它有固定的时间、环境或事件来触发。然后再逐渐增加触发条件。</p><h3 id="四、建立回报机制，以奖励提升成就感"><a href="#四、建立回报机制，以奖励提升成就感" class="headerlink" title="四、建立回报机制，以奖励提升成就感"></a>四、建立回报机制，以奖励提升成就感</h3><p>习惯需要回报反馈来刺激大脑形成它，大脑会自动把与行为不相关的回报关联起来。</p><blockquote><p>我们能做的是将行为与完全不相关的回报建立关联，一段时间过后，大脑就会把这个行为和回报联系起来，这就是我们想要的！之后，大脑就不再需要这个（硬性建立起关联的）回报来促进行动了。</p></blockquote><blockquote><p>建立习惯的诀窍就是把它想象成教孩子骑自行车。刚开始，你一边让孩子蹬自行车一边向他保证你在稳稳地扶着他。可是在某个时候你把手松开后，孩子没有你的扶持也能继续骑车了。</p></blockquote><p>回报可以恢复意志力。</p><blockquote><p>通常我们会把回报看作因为做了一件好事而得到的报偿，但回报也能给你回报。</p></blockquote><p>超额完成的满足感本身是一种回报。去学会感受到这种满足，会让你的动力满满。</p><blockquote><p>你在超额完成很多工作后，可能会想奖励自己，以鼓励该行为。</p></blockquote><p>完成习惯后对更大回报的期待又是一种回报形式。</p><p>注意，不要在这个时候冲动的增加习惯的大小。</p><p>我应该为超额完成习惯设计一个奖励机制。比如在我的应用里超额完成时给出更高的爆击率反馈。</p><h3 id="五、记录与追踪完成情况"><a href="#五、记录与追踪完成情况" class="headerlink" title="五、记录与追踪完成情况"></a>五、记录与追踪完成情况</h3><p>记录自己完成一件事情，也会产生“自我效能感”。我们都感受过这种感觉，记录下来会让这种感觉更具象化，大脑会更容易形成习惯。</p><blockquote><p>不管你选择什么策略，我建议你到睡前再检查自己是否成功。如果你在白天就早早地检查完毕，完成任务的感觉会降低你继续进行额外工作的动力。</p></blockquote><p>我用 Streaks 来记录我的习惯，它可以把每个习惯的日历放在手机、电脑、平板和手表的主屏幕上（苹果生态）。</p><p><img src="/mini-habits/streaks.jpeg" alt="Streaks"></p><p>记录习惯的完成情况，可以让你对习惯的完成情况有更好的了解。及时缩小习惯，防止意志力的过多消耗。</p><p>所以在我想开发的的应用中让记录完成情况要很方便，还要有缩小习惯的功能，以及完成情况的日历视图。</p><h3 id="六、微量开始，超额完成"><a href="#六、微量开始，超额完成" class="headerlink" title="六、微量开始，超额完成"></a>六、微量开始，超额完成</h3><blockquote><p>真正让微习惯策略脱颖而出的是，你绝不会有失败的借口，绝不会害怕失败，而且绝不会感到内疚。即使你的意志力已经耗尽，微习惯的任务要求是如此之低，你总能找到方法完成。</p></blockquote><p>让习惯行为来激发动力，不要依赖动力来产成行动。前者积攒意志，后者消耗意志。如果前者遇到阻碍就缩小习惯</p><blockquote><p>微习惯绝不会阻碍你进步，就好像火花绝不可能阻碍一场大火的蔓延一样。</p></blockquote><p>超额完成让人产生的满足很愉悦，你可以在每次产生充足的动力时超额完成习惯来感受这种“自我效能感”。</p><blockquote><p>虽然我们完成这些微习惯时依赖的完全是意志力，但我们选择在达到目标后继续努力时，动力就会起作用了。</p></blockquote><h3 id="七、服从计划安排，摆脱高期待值"><a href="#七、服从计划安排，摆脱高期待值" class="headerlink" title="七、服从计划安排，摆脱高期待值"></a>七、服从计划安排，摆脱高期待值</h3><p>下意识会追求你过于困难的目标，这会扼杀你的动力。切记，不要在习惯形成之前就想着要扩大习惯的规模。</p><blockquote><p>最大的障碍是耐心。你不想成为那个每天写 50 字的人——你想让自己迅速变成每天能写出 4000 字的人，尽快实现梦想。</p></blockquote><p>急于求成是很常产生的念头。你需要等待习惯的形成，而不能急于求成。</p><blockquote><p>从潜意识层面看，超额完成目标后，大脑会设定一个新的期待值，它承载了你以前设定过的典型目标（你懂的，那些无效目标）带来的负担和压力。</p></blockquote><p>打游戏的时候我常期望一些不可能的胜利（当游戏匹配机制给你分配了不在同一水平的对手时），只少数时候它可以成功。但在游戏中并没关系，我动力充足。现实中应该运用更理性的策略，期待值要合理。</p><p>坚持每天进步一点点，比只能坚持做几次就放弃对你的未来更有帮助。</p><blockquote><p>所以，一定要提醒自己，你每天的目标并没有改变，这一点极为重要。</p></blockquote><blockquote><p>我们要把期待值和精力放到坚持目标上，而不要对任务量抱有较高的期待。</p></blockquote><h3 id="八、留意习惯养成的标志"><a href="#八、留意习惯养成的标志" class="headerlink" title="八、留意习惯养成的标志"></a>八、留意习惯养成的标志</h3><p>如果一个习惯已经形成，你会发现你不再抵触它；你会产生一种身份认同感；你不需为开始该行为寻找理由；你不再担心你不会完成它；开始行动时是非情绪化的；它很无聊。已经形成的习惯，不会让你高兴，但它对你有好处。</p><p>代表行为已成为习惯的信号有：</p><blockquote><ul><li>没有抵触情绪：该行为似乎做起来容易，不做反而更难。</li><li>身份：现在你认同该行为，而且可以信心十足地说“我常看书”或“我是个作家”。</li><li>行动时无须考虑：你不需要做出执行的决定就能开始该行为。</li><li>你不再担心了：刚开始时，你也许会担心自己漏掉一天或者早早放弃，可当行为变成习惯后，你知道你会一直做这件事，除非出现紧急情况。</li><li>常态化：习惯是非情绪化的。</li><li>它很无聊：好的习惯并不会让人兴奋，它们只是对你有好处而已。</li></ul></blockquote><p>看书 15 分钟，这是我已经养成的习惯。我每天都会看书，我会说我经常看书。每天到了看书的时候不仅会抵触，还会有一丝期待，虽然可能是因为我看的书是我想看的书。 还有多邻国打卡，累的时候一天过一次关卡。比较闲或没给事可做就会多过几个关卡。</p><p>不要一次培养过多的习惯。要培养的习惯越多，失败的风险越大。失败会消弱意志。</p><blockquote><p>微习惯策略效果很好，可是如果你在一个行为真正成为习惯之前就停止，继续添加下一组习惯，那么你可能会像个手法拙劣的杂耍艺人一样冒着让手里的橘子全部落地的风险。</p></blockquote><p>让长远对你有用的事情变成你无聊时会去做的一种习惯。养成习惯后，你不会感受到焦虑。让你的生活平淡的向着积极的方向发展。</p><h2 id="微习惯的原则"><a href="#微习惯的原则" class="headerlink" title="微习惯的原则"></a>微习惯的原则</h2><p>经常回报自己，尤其在完成微习惯之后.</p><p>保持头脑清醒。当你精力充沛时，就容易冲动，错误的估计自己的能力，增加自己的目标大小。</p><blockquote><p>你需要特别注意避免这么做，因为你每对自己提高一点要求，就需要更多意志力才能达到要求，而且就算你应付得了额外的意志力负担，也许还有同时培养多个习惯的目标。</p></blockquote><p>感到强烈抵触时，后退并缩小目标。在执行习惯时，不要让自己的精力过度消耗。这样会让你的意志力耗尽，导致习惯培养的失败。</p><blockquote><p>只要遇到抵触，我就会把任务缩小，问题就解决了。</p></blockquote><p>满意每一个进步。</p><blockquote><p>李小龙有一句名言能很好地总结这一点：“要满意，但别满足。”</p></blockquote><p>用多余精力超额完成任务，而不是制定更大目标。</p><blockquote><p>大目标在纸面上看着漂亮，但只有行动才算数。目标渺小、结果丰硕的状态比反过来好多了。</p></blockquote><blockquote><p>我们想要确保成功，而不是听成功和失败发号施令。</p></blockquote><blockquote><p>人们在设定目标时经常犯的一个错误就是没有把动力和精力水平的剧烈波动考虑在内，而是假定到了实施行动的时候，他们能维持或重新激活当前的精神和精力状态。</p></blockquote><p>绝不要小看微步骤。</p><blockquote><p>微习惯策略的核心是一个很简单的大脑错觉，但同时也是一种重视开始的生活哲理，一种认为行动优于动力的生活哲理，一种相信将每一小步积累起来便能让量变转为质变的生活哲理。</p></blockquote><p>反馈是大脑形成习惯路径的关键。通常我们训练的的习惯有着更复杂的条件和动作，形成时间较长。</p><p>不要企图用冲动来坚持一件事情，不掺杂情绪的习惯更可靠。</p><blockquote><p>冷静的头脑是建立习惯的最佳思维模式，因为它很稳定，而且可以预见。在不断取得进步的过程中，你可能会兴奋起来，但别让这种兴奋变成你实施行动的原动力。变得依赖动力或情绪正是许多个人成长计划最终失败的原因。</p></blockquote><p>绝不要自欺欺人。</p><blockquote><p>常识告诉我们，一定要突破强烈抵触情绪的阻碍，但我得说，这种做法很愚蠢。</p></blockquote><h2 id="有关习惯的其它想法"><a href="#有关习惯的其它想法" class="headerlink" title="有关习惯的其它想法"></a>有关习惯的其它想法</h2><ol><li>想要戒掉坏习惯，应该用好习惯去代替它。</li><li>微习惯也是一个让人向外迈出一小步，来突破舒适圈的过程。</li><li>自主权能促进行动，反过来失去自主权则会抑制行动。</li><li>星星之火，可以燎原。</li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;/./mini-habits/cover.jpg&quot; alt=&quot;微习惯封面&quot;&gt;&lt;/p&gt;
&lt;p&gt;这本书我是与《自控力》一起读的。都是基于相同的目的而读：学习和运用其中实际可操作的方法，为我开发的 App 设计功能帮用户能够改变自己。&lt;/p&gt;</summary>
    
    
    
    <category term="读书笔记" scheme="https://blog.esonwong.com/categories/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="笔记" scheme="https://blog.esonwong.com/tags/%E7%AC%94%E8%AE%B0/"/>
    
    <category term="读书" scheme="https://blog.esonwong.com/tags/%E8%AF%BB%E4%B9%A6/"/>
    
    <category term="摘录" scheme="https://blog.esonwong.com/tags/%E6%91%98%E5%BD%95/"/>
    
  </entry>
  
  <entry>
    <title>在 iPad 使用 VS Code 写代码</title>
    <link href="https://blog.esonwong.com/coding-on-iPad/"/>
    <id>https://blog.esonwong.com/coding-on-iPad/</id>
    <published>2023-08-29T13:54:28.000Z</published>
    <updated>2026-02-27T10:20:27.136Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/./coding-on-iPad/cover.jpeg" alt="iPad 上的 VS Code"></p><p>VS Code 推出了 tunnel 插件和服务，现在终于可以方便的在 iPad 的浏览器上打开 VS Code 了。</p><span id="more"></span><p>VS Code 可以在一台电脑上运行 VS Code Server ，并通过 Github 账号登录开启一个 tunnel 隧道生成一个网址，然后在其他设备上打开这个网址就可以使用 VS Code 了。</p><p><img src="/./coding-on-iPad/coding-on-ipad.png" alt="VS Code Server"></p><p>在服务器上也可以使用 VS Code CLI 命令行工具来启动 VS Code Server。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">code tunnel</span><br></pre></td></tr></table></figure><p>网页上使用 VS Code 的体验相当完整。我使用的插件基本上都可以使用。本址端口也可以方便的转换成一个公网地址，可以在 iPad 上访问。对于前端开发来说，可以完全在 iPad 上完成开发。</p><p>唯一的问题是 tunnel 隧道的网络延迟会不稳定，影响开发体验。</p><h2 id="ESC-键"><a href="#ESC-键" class="headerlink" title="ESC 键"></a>ESC 键</h2><p>我在 VS Code 上使用 Vim 插件，需要使用 ESC 键切换模式。但是在 iPad 大部份键盘上没有 ESC 键，<code>command + .</code> 可以代替。也可以修改修饰键映射来解决。</p><h2 id="添加到主屏幕"><a href="#添加到主屏幕" class="headerlink" title="添加到主屏幕"></a>添加到主屏幕</h2><p>在 Safari 的分享菜单中，可以添加到主屏幕，这样就可以像一个 App 一样使用了。也能得到全屏幕的体验。</p><p><img src="/./coding-on-iPad/full-screen.png" alt="full screen"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;/./coding-on-iPad/cover.jpeg&quot; alt=&quot;iPad 上的 VS Code&quot;&gt;&lt;/p&gt;
&lt;p&gt;VS Code 推出了 tunnel 插件和服务，现在终于可以方便的在 iPad 的浏览器上打开 VS Code 了。&lt;/p&gt;</summary>
    
    
    
    <category term="技术" scheme="https://blog.esonwong.com/categories/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="Web 开发" scheme="https://blog.esonwong.com/categories/%E6%8A%80%E6%9C%AF/Web-%E5%BC%80%E5%8F%91/"/>
    
    
    <category term="Web 开发" scheme="https://blog.esonwong.com/tags/Web-%E5%BC%80%E5%8F%91/"/>
    
    <category term="前端" scheme="https://blog.esonwong.com/tags/%E5%89%8D%E7%AB%AF/"/>
    
    <category term="技术" scheme="https://blog.esonwong.com/tags/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="VS Code" scheme="https://blog.esonwong.com/tags/VS-Code/"/>
    
  </entry>
  
  <entry>
    <title>在 Macbook 上运行 ChatGLM-6B</title>
    <link href="https://blog.esonwong.com/Macbook-run-ChatGLM-6B/"/>
    <id>https://blog.esonwong.com/Macbook-run-ChatGLM-6B/</id>
    <published>2023-08-13T02:36:15.000Z</published>
    <updated>2026-02-27T10:20:27.135Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/./Macbook-run-ChatGLM-6B/screenshot.png" alt="ChatGLM-6B Web"><br>我有一台 32G 内存 Macbook Pro，想要运行大语言模型看能不能替代 OpenAI 的 API。下面是我在 Macbook 上运行 ChatGLM-6B 的步骤。</p><span id="more"></span><h2 id="克隆-ChatGLM-6B-仓库"><a href="#克隆-ChatGLM-6B-仓库" class="headerlink" title="克隆 ChatGLM-6B 仓库"></a>克隆 ChatGLM-6B 仓库</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/THUDM/ChatGLM-6B</span><br></pre></td></tr></table></figure><h2 id="创建虚拟环境"><a href="#创建虚拟环境" class="headerlink" title="创建虚拟环境"></a>创建虚拟环境</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> ChatGLM-6B</span><br><span class="line">python3 -m venv .venv</span><br></pre></td></tr></table></figure><h2 id="激活虚拟环境"><a href="#激活虚拟环境" class="headerlink" title="激活虚拟环境"></a>激活虚拟环境</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">source</span> .venv/bin/activate</span><br></pre></td></tr></table></figure><h2 id="安装依赖"><a href="#安装依赖" class="headerlink" title="安装依赖"></a>安装依赖</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">pip install -r requirements.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装 PyTorch， 使用 MPS 后端来在 Mac 的 GPU 上运行</span></span><br><span class="line">pip install --pre torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/nightly/cpu</span><br></pre></td></tr></table></figure><h2 id="下载模型"><a href="#下载模型" class="headerlink" title="下载模型"></a>下载模型</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> ..</span><br><span class="line">git <span class="built_in">clone</span> https://huggingface.co/THUDM/chatglm-6b chatgml-6b-model</span><br></pre></td></tr></table></figure><h2 id="修改代码使用-MPS-后端和下载的好的模型"><a href="#修改代码使用-MPS-后端和下载的好的模型" class="headerlink" title="修改代码使用 MPS 后端和下载的好的模型"></a>修改代码使用 MPS 后端和下载的好的模型</h2><p>修改 webapp.py 文件。</p><ol><li>将 <code>.cuda()</code> 改为 <code>.to(&quot;mps&quot;)</code></li><li>将模型和 tokenizer 的路径改为 huggingface 上克隆下来的 chatglm-6b 仓库本地路径。下面我的例子中，本地路径为 <code>/Users/eson/git/chatgml-6b-model</code>。</li></ol><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="deletion">-tokenizer = AutoTokenizer.from_pretrained(&quot;THUDM/chatglm-6b&quot;, trust_remote_code=True)</span></span><br><span class="line"><span class="deletion">-model = AutoModel.from_pretrained(&quot;THUDM/chatglm-6b&quot;, trust_remote_code=True).half().cuda()</span></span><br><span class="line"><span class="addition">+tokenizer = AutoTokenizer.from_pretrained(</span></span><br><span class="line"><span class="addition">+    &quot;/Users/eson/git/chatgml-6b-model&quot;, trust_remote_code=True</span></span><br><span class="line"><span class="addition">+)</span></span><br><span class="line"><span class="addition">+model = (</span></span><br><span class="line"><span class="addition">+    AutoModel.from_pretrained(</span></span><br><span class="line"><span class="addition">+        &quot;/Users/eson/git/chatgml-6b-model&quot;, trust_remote_code=True</span></span><br><span class="line"><span class="addition">+    )</span></span><br><span class="line"><span class="addition">+    .half()</span></span><br><span class="line"><span class="addition">+    .to(&quot;mps&quot;)</span></span><br><span class="line"><span class="addition">+)</span></span><br></pre></td></tr></table></figure><h2 id="运行"><a href="#运行" class="headerlink" title="运行"></a>运行</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python webapp.py</span><br></pre></td></tr></table></figure><p>这将会在本地启动一个 web 服务，会自动打开浏览器。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;/./Macbook-run-ChatGLM-6B/screenshot.png&quot; alt=&quot;ChatGLM-6B Web&quot;&gt;&lt;br&gt;我有一台 32G 内存 Macbook Pro，想要运行大语言模型看能不能替代 OpenAI 的 API。下面是我在 Macbook 上运行 ChatGLM-6B 的步骤。&lt;/p&gt;</summary>
    
    
    
    <category term="教程" scheme="https://blog.esonwong.com/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="教程" scheme="https://blog.esonwong.com/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="技术" scheme="https://blog.esonwong.com/tags/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="AI" scheme="https://blog.esonwong.com/tags/AI/"/>
    
    <category term="Mac OS" scheme="https://blog.esonwong.com/tags/Mac-OS/"/>
    
    <category term="笔记" scheme="https://blog.esonwong.com/tags/%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
</feed>
