<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>鑫鑫的个人事项记录</title><description>记录技术研究，也记录生活思考</description><link>https://cunjinjin.com/</link><templateTheme>Firefly</templateTheme><templateThemeVersion>6.15.6</templateThemeVersion><templateThemeUrl>https://github.com/CuteLeaf/Firefly</templateThemeUrl><lastBuildDate>2026年8月20日 19:12:38</lastBuildDate><item><title>欢迎来到鑫鑫的个人事项记录</title><link>https://cunjinjin.com/posts/welcome/</link><guid isPermaLink="true">https://cunjinjin.com/posts/welcome/</guid><description>这里用于记录日常、整理想法，也保存一些值得回看的生活片段。</description><pubDate>Fri, 07 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;你好，欢迎来到“鑫鑫的个人事项记录”。&lt;/p&gt;
&lt;p&gt;建立这个网站，是想为日常生活留出一块安静、有序的记录空间。今后会在这里整理近期事项、学习笔记和阶段感想。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;主要内容&lt;a href=&quot;#主要内容&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;记录近期值得留存的小事；&lt;/li&gt;
&lt;li&gt;整理学习和阅读过程中获得的新知识；&lt;/li&gt;
&lt;li&gt;回顾已经完成的计划，写下下一阶段的安排。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;所有内容都会由我本人整理，并不定期更新。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>八月中旬，把事情往回收一收</title><link>https://cunjinjin.com/posts/august-mid-review/</link><guid isPermaLink="true">https://cunjinjin.com/posts/august-mid-review/</guid><description>中途回头看一眼，比月底一口气补课更轻松。</description><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;八月过了一半以后，我开始有种很明显的感觉：事情并没有真的变多，只是有些东西一直挂着没收尾，看着就有点乱。&lt;/p&gt;
&lt;p&gt;所以这两天我没有再去加新目标，而是先把手头几件事往回理一理。中途回头看一眼，总比月底挤在一起处理轻松。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;先清掉悬着的事&lt;a href=&quot;#先清掉悬着的事&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我现在会先看这三类东西：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;已经开始、但没写完的记录；&lt;/li&gt;
&lt;li&gt;做到一半、还没有结论的事情；&lt;/li&gt;
&lt;li&gt;明明不重要，却一直占着注意力的事。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这些内容不一定大，但它们会慢慢消耗脑子里的空间。先收掉一点，后面做别的事也会顺很多。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;计划也要留空&lt;a href=&quot;#计划也要留空&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;以前我总想把计划排得满一点，后来发现，排满并不等于有效。空一点反而更容易执行，遇到临时变化也不会整张表都塌掉。&lt;/p&gt;&lt;p&gt;现在我更喜欢的方式是：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;留一个主线；&lt;/li&gt;
&lt;li&gt;留两个小目标；&lt;/li&gt;
&lt;li&gt;留一些空白给临时事情。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;这样看起来没那么热闹，但真的更像能一直做下去的节奏。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;现在最想保留的&lt;a href=&quot;#现在最想保留的&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这段时间我比较在意的是，把事情写得更具体一点。不是为了写很多，而是为了以后再看时，能知道当时到底在忙什么。&lt;/p&gt;&lt;p&gt;等八月结束再回看一次，应该就能看得更清楚：哪些是真的进展，哪些只是忙了一阵。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>我看接口日志时，最先做的不是复制请求</title><link>https://cunjinjin.com/posts/interface-diff-experiment/</link><guid isPermaLink="true">https://cunjinjin.com/posts/interface-diff-experiment/</guid><description>先把业务动作拆开，再做有控制的差分，往往比直接重放一个请求更容易看清楚真正的依赖。</description><pubDate>Fri, 14 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;看接口日志这件事，我越来越不喜欢一上来就复制请求。复制当然快，但很多时候只能说明“这个样本刚好能跑”，并不能说明我真的看懂了它。&lt;/p&gt;
&lt;p&gt;我更习惯先找一个完整动作，再慢慢拆。比如读取详情、刷新状态、提交确认、切换页面，这些动作背后通常有各自稳定的边界。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;先找一个最小动作&lt;a href=&quot;#先找一个最小动作&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我一般会从最小的一步开始，比如：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;只点一次查询；&lt;/li&gt;
&lt;li&gt;只改一个普通字段；&lt;/li&gt;
&lt;li&gt;只刷新一次状态；&lt;/li&gt;
&lt;li&gt;只上传一张测试图片。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这样做的好处是，观察对象足够单纯。出问题以后，比较容易判断是参数不对、会话失效，还是页面自己又换了一层逻辑。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;差分比猜测更可靠&lt;a href=&quot;#差分比猜测更可靠&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&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;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;请求体&lt;/td&gt;&lt;td&gt;哪个字段真的跟用户输入有关&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;响应体&lt;/td&gt;&lt;td&gt;哪个字段会影响下一步动作&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Cookie / Token&lt;/td&gt;&lt;td&gt;它们是短期会话还是长期状态&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;时间戳&lt;/td&gt;&lt;td&gt;是展示用，还是参与校验&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;很多时候，真正决定流程的不是那个最显眼的字段，而是一个看着不起眼的状态位。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;只记结论，不急着下定义&lt;a href=&quot;#只记结论不急着下定义&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我现在做分析时，会尽量把结论写得保守一点。比如“这个字段大概率是会话字段”，而不是直接断言它一定是什么。&lt;/p&gt;&lt;p&gt;这样做不是为了显得严谨，而是为了以后回头看时，知道哪些是确认过的，哪些只是当时的推断。&lt;/p&gt;&lt;p&gt;接口分析最有用的地方，不是把一切都解释得像真理，而是把那些模糊的地方先收窄，最后变成能验证、能复现的步骤。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>网页自动化里，我开始更重视页面状态而不是按钮</title><link>https://cunjinjin.com/posts/page-state-first/</link><guid isPermaLink="true">https://cunjinjin.com/posts/page-state-first/</guid><description>真正决定自动化是否稳定的，不是能不能点到按钮，而是系统是否知道自己现在处于什么状态。</description><pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;前阵子我反复碰到一个问题：按钮明明还在，自动化却突然失效了。后来我慢慢意识到，问题往往不在按钮本身，而在页面已经换了状态，只是脚本还以为它没变。&lt;/p&gt;
&lt;p&gt;所以现在我做网页自动化时，第一件事不再是“找按钮”，而是先确认页面属于哪一类状态。只要状态判断对了，后面的动作才有意义。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;先把状态说清楚&lt;a href=&quot;#先把状态说清楚&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我现在常用的方式，是把页面拆成几个固定阶段，比如：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;待登录&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;等待绑定&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;可执行&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;需要确认&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;失败待处理&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这几个状态不一定适用于所有页面，但至少能让脚本知道自己现在是在做什么，而不是只会机械点击。&lt;/p&gt;&lt;p&gt;有些页面看起来变化很多，其实真正会影响流程的点并不多。把这些关键状态先画出来，很多“偶发 bug”就会变得很具体。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;一次只做一个动作&lt;a href=&quot;#一次只做一个动作&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;以前我容易贪快，想把“判断、点击、输入、确认”一次做完。结果一旦其中一步不对，后面全乱。&lt;/p&gt;&lt;p&gt;现在我更愿意把动作拆开：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;先读状态；&lt;/li&gt;
&lt;li&gt;再做一个最小动作；&lt;/li&gt;
&lt;li&gt;再读一次状态；&lt;/li&gt;
&lt;li&gt;确认真的变了，再继续。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;这样慢一点，但出错时很好回头看。哪一步没生效，日志里会很清楚。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;异常时先停一下&lt;a href=&quot;#异常时先停一下&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;最麻烦的不是失败，而是失败以后还继续往下跑。那种情况很容易把原本还能处理的问题，弄成一团乱账。&lt;/p&gt;&lt;p&gt;我现在更在意的是：如果状态不对，就先停下来，把页面、时间点和最后一次动作留下来。对我来说，这比“硬跑到底”更有价值。&lt;/p&gt;&lt;p&gt;网页自动化做到后面，真正重要的不是动作数量，而是系统能不能一直知道自己站在哪一格上。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>AI 网页自动化：从脚本执行走向可恢复的智能体系统</title><link>https://cunjinjin.com/posts/ai-web-automation-engineering/</link><guid isPermaLink="true">https://cunjinjin.com/posts/ai-web-automation-engineering/</guid><description>网页自动化真正困难的不是点击按钮，而是让系统在页面变化、状态漂移和异常中仍能稳定完成任务。</description><pubDate>Sat, 08 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;传统网页自动化更像一条预先写好的轨道：定位元素、点击、输入、等待结果。流程固定时它很高效，但只要页面结构变化、弹窗出现或网络延迟超出预期，整条链路就可能中断。&lt;/p&gt;
&lt;p&gt;我最近关注的方向，是让自动化系统从“执行脚本”升级为一个具备 &lt;strong&gt;观察、判断、行动和校验&lt;/strong&gt; 能力的闭环。AI 的价值不在于替代所有规则，而在于处理那些难以提前枚举的页面变化。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;一个可靠的执行闭环&lt;a href=&quot;#一个可靠的执行闭环&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我把一次网页任务拆成五个阶段：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;观察&lt;/strong&gt;：获取当前 URL、可见 DOM、关键控件和页面状态；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;理解&lt;/strong&gt;：判断当前页面处于任务的哪个阶段；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;规划&lt;/strong&gt;：只生成下一步最小动作，而不是一次生成整段操作；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;执行&lt;/strong&gt;：通过浏览器驱动完成点击、输入或导航；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;校验&lt;/strong&gt;：检查页面是否出现预期状态，再决定继续、重试或回退。&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;是&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;否&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;页面观察&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;状态理解&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;生成下一步动作&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;浏览器执行&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;结果符合预期?&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;诊断与恢复&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;是&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;否&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;页面观察&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;状态理解&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;生成下一步动作&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;浏览器执行&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;结果符合预期?&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;诊断与恢复&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;这个循环看起来简单，真正的工程难点在于：系统必须知道“自己刚才做了什么”，也必须知道“页面是否真的接受了这个动作”。只有动作记录，没有结果验证，自动化就很容易在错误状态上继续运行。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;DOM 与视觉不是二选一&lt;a href=&quot;#dom-与视觉不是二选一&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;结构化 DOM 适合精确定位输入框、按钮和表格，成本低且可解释；视觉模型更适合处理 Canvas、复杂组件和缺乏语义标记的界面。实际系统中，我更倾向于分层使用：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;优先读取可访问性树和稳定属性；&lt;/li&gt;
&lt;li&gt;DOM 信息不足时，再调用视觉理解；&lt;/li&gt;
&lt;li&gt;高风险操作必须回到明确的页面状态进行二次确认；&lt;/li&gt;
&lt;li&gt;每次只执行一个可验证动作，减少错误扩散范围。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这种组合比“让模型看截图随意点击”更可靠，也比完全依赖 CSS 选择器更能适应页面变化。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;状态机比长提示词更重要&lt;a href=&quot;#状态机比长提示词更重要&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;复杂任务不能只靠一段很长的提示词维持上下文。我会把业务流程表示为显式状态，例如 &lt;code&gt;待登录&lt;/code&gt;、&lt;code&gt;资料填写中&lt;/code&gt;、&lt;code&gt;等待确认&lt;/code&gt;、&lt;code&gt;已完成&lt;/code&gt; 和 &lt;code&gt;需要人工处理&lt;/code&gt;。每个状态只允许有限的动作，并且定义清晰的进入条件和退出条件。&lt;/p&gt;&lt;p&gt;任务运行时还需要保存以下信息：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;当前目标与已经完成的步骤；&lt;/li&gt;
&lt;li&gt;最近一次页面快照和关键字段；&lt;/li&gt;
&lt;li&gt;每个动作的输入、输出与耗时；&lt;/li&gt;
&lt;li&gt;重试次数、异常原因和恢复路径；&lt;/li&gt;
&lt;li&gt;涉及提交、删除、付款等动作时的人工确认点。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这让系统具备可观测性：一次失败不再只是“运行出错”，而是可以定位到具体页面、具体状态和具体动作。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;我正在验证的方向&lt;a href=&quot;#我正在验证的方向&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;目前我更关心三个指标：任务完成率、平均恢复次数和人工接管比例。模型能力决定系统能看懂多少，而状态约束、结果校验和异常恢复决定它是否真的能长期运行。&lt;/p&gt;&lt;p&gt;一个可用于生产的 AI 网页自动化系统，最终应该像可靠的软件服务一样工作：过程可追踪、动作可审计、异常可恢复，遇到不确定情况时能够及时停下，而不是带着错误继续执行。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>AI 自动化剪辑：把模型能力接入可控的视频生产流水线</title><link>https://cunjinjin.com/posts/ai-video-production-pipeline/</link><guid isPermaLink="true">https://cunjinjin.com/posts/ai-video-production-pipeline/</guid><description>从素材理解到最终成片，一套桌面端 AI 剪辑工具需要解决时间轴、任务编排、预览一致性和确定性渲染。</description><pubDate>Fri, 07 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;最近我在研究一套桌面端 AI 自动化剪辑与画面特效工具。与“一句话生成视频”相比，我更关注一个偏工程化的问题：如何把语音识别、镜头分析、文案生成、动态排版和视频渲染组织成稳定、可调试、可重复执行的生产流程。&lt;/p&gt;
&lt;p&gt;我的设计原则是让 AI 负责理解和建议，让时间线与渲染引擎负责确定性输出。这样既能利用模型的灵活性，又不会让最终成片变成一个无法解释的黑盒。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;整体技术架构&lt;a href=&quot;#整体技术架构&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;桌面端采用 &lt;strong&gt;Electron + React&lt;/strong&gt;。Electron 负责本地文件访问、任务进程和应用生命周期，React 负责素材管理、时间线配置与任务状态界面。&lt;/p&gt;&lt;p&gt;预览与动态文案使用 &lt;strong&gt;Remotion&lt;/strong&gt;。它可以把字幕、转场、图层和动画写成组件，使视觉模板与业务参数分离。底层的裁剪、转码、音视频合成则交给 &lt;strong&gt;FFmpeg&lt;/strong&gt;，确保编码参数和输出结果可控。&lt;/p&gt;&lt;p&gt;AI 服务单独运行在 &lt;strong&gt;Python + FastAPI&lt;/strong&gt; 层：&lt;strong&gt;faster-whisper&lt;/strong&gt; 生成带时间戳的字幕，&lt;strong&gt;PySceneDetect&lt;/strong&gt; 识别场景边界，其他模型负责内容理解、文案压缩和镜头建议。&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;Electron + React 工作台&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;任务编排层&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;FastAPI AI 服务&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;faster-whisper 字幕&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;PySceneDetect 镜头&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;语义与文案分析&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;统一时间线数据&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;Remotion 实时预览&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;FFmpeg 最终渲染&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;Electron + React 工作台&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;任务编排层&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;FastAPI AI 服务&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;faster-whisper 字幕&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;PySceneDetect 镜头&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;语义与文案分析&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;统一时间线数据&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;Remotion 实时预览&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;FFmpeg 最终渲染&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;先统一时间，再谈自动化&lt;a href=&quot;#先统一时间再谈自动化&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;视频系统最容易被低估的问题是“时间”。字幕以毫秒表示，Remotion 使用帧，FFmpeg 的滤镜可能使用时间基，原始素材还可能是可变帧率。如果这些数据在不同模块之间反复换算，几帧的误差会逐步累积，最终表现为字幕漂移、转场错位或音画不同步。&lt;/p&gt;&lt;p&gt;我计划在任务层建立统一时间线模型：内部以整数毫秒保存时间，渲染前再根据目标帧率换算帧号；每段素材保留原始时间基、入点、出点和速度信息。所有 AI 输出都必须落到这份时间线上，而不是直接修改视频文件。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TimelineClip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sourceId&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sourceInMs&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sourceOutMs&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;timelineStartMs&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;playbackRate&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;number&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;effects&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;EffectConfig&lt;/span&gt;&lt;span&gt;[];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;让预览和成片保持一致&lt;a href=&quot;#让预览和成片保持一致&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;交互预览追求低延迟，最终渲染追求稳定与画质，两者天然存在差异。我的思路是让 Remotion 和 FFmpeg 共享同一份时间线与效果参数：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Remotion 提供快速画面预览和动态文字编排；&lt;/li&gt;
&lt;li&gt;FFmpeg 负责素材预处理、音频标准化和最终编码；&lt;/li&gt;
&lt;li&gt;对关键视觉效果建立基准帧，自动比较预览与输出；&lt;/li&gt;
&lt;li&gt;每次渲染保存参数快照，使成片可以复现。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;对于字幕，不只要识别文字，还要处理断句、停顿、每行字数和画面安全区。faster-whisper 给出词级时间戳后，系统还需要进行语义分组，再根据模板约束生成字幕片段。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;任务编排与失败恢复&lt;a href=&quot;#任务编排与失败恢复&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;长视频处理不适合用一个同步接口从头跑到尾。我会把流程拆成独立任务：探测素材、抽取音频、语音识别、镜头切分、语义分析、预览代理生成、最终渲染。每个节点都有输入摘要、进度、输出文件和错误信息。&lt;/p&gt;&lt;p&gt;这样某一步失败时，只需要重跑对应节点；用户修改文案后，也不必重新做语音识别和镜头检测。对桌面工具来说，这种可恢复能力比单次演示速度更重要。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;当前研究重点&lt;a href=&quot;#当前研究重点&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;现在主要在验证镜头切分与语义段落的对齐、字幕时间轴清洗、模板参数化，以及不同硬件环境下的渲染调度。我的目标不是堆叠模型，而是形成一套清晰的媒体处理中间层：输入可分析、过程可干预、效果可复用、输出可复现。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>我的日常记录方式</title><link>https://cunjinjin.com/posts/how-i-take-notes/</link><guid isPermaLink="true">https://cunjinjin.com/posts/how-i-take-notes/</guid><description>用简单的方法整理每天的事项，让记录真正服务于生活。</description><pubDate>Thu, 06 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;记录不一定需要复杂的工具。对我来说，能够长期坚持的方法，通常都有三个特点：容易开始、内容清楚、方便回顾。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;当天记录&lt;a href=&quot;#当天记录&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;把需要处理的事情写成简短清单，完成后及时标记。遇到值得记住的想法，也先用一句话保存下来。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;每周整理&lt;a href=&quot;#每周整理&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;每周找一个固定时间回顾记录，删除已经没有意义的内容，把真正重要的部分整理成更完整的笔记。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;定期回看&lt;a href=&quot;#定期回看&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;记录的价值不只是“写下来”，更在于以后还能找到。清晰的标题、日期和分类，可以让回顾变得更轻松。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>八月事项整理</title><link>https://cunjinjin.com/posts/august-plan/</link><guid isPermaLink="true">https://cunjinjin.com/posts/august-plan/</guid><description>把本月需要关注的生活、学习和整理事项放在一份清晰的清单里。</description><pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;新的月份，先把需要关注的事情分成几个小部分。计划不追求排得很满，更重要的是清楚、可执行。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;生活&lt;a href=&quot;#生活&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;整理近期照片和文件；&lt;/li&gt;
&lt;li&gt;保持规律作息；&lt;/li&gt;
&lt;li&gt;给重要事项预留充足时间。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;学习&lt;a href=&quot;#学习&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;完成正在阅读的内容；&lt;/li&gt;
&lt;li&gt;把零散笔记整理成主题；&lt;/li&gt;
&lt;li&gt;每周做一次简短回顾。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;网站&lt;a href=&quot;#网站&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;持续补充真实的个人记录；&lt;/li&gt;
&lt;li&gt;检查文章分类和页面显示；&lt;/li&gt;
&lt;li&gt;保持页面内容简洁、准确。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content:encoded></item><item><title>网络协议分析笔记：从请求重放到可验证的接口模型</title><link>https://cunjinjin.com/posts/web-protocol-analysis-notes/</link><guid isPermaLink="true">https://cunjinjin.com/posts/web-protocol-analysis-notes/</guid><description>在合法授权环境中，通过流量观察、状态建模与差分实验理解 Web 客户端和服务端之间的真实交互。</description><pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;所谓“网络逆向”，在我的学习语境里更接近 &lt;strong&gt;协议分析与兼容性研究&lt;/strong&gt;：在自己拥有或获得授权的系统中，观察客户端与服务端如何交换数据，再把零散请求整理成可验证的接口模型。&lt;/p&gt;
&lt;p&gt;网页上的一次点击，背后可能包含鉴权、业务请求、异步轮询、资源上传和状态确认。只复制其中一个请求，往往无法复现完整行为。真正重要的是找出请求之间的依赖关系。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;从业务动作建立观察样本&lt;a href=&quot;#从业务动作建立观察样本&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我会先选择最小业务动作，例如“读取一条记录”或“修改一个非关键字段”，然后在开发者工具或测试代理中保存完整会话。分析时重点关注：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;请求方法、路径、查询参数和内容类型；&lt;/li&gt;
&lt;li&gt;Cookie、Token、时间戳和一次性标识的作用范围；&lt;/li&gt;
&lt;li&gt;响应中的业务状态码、分页游标和错误结构；&lt;/li&gt;
&lt;li&gt;前一个响应是否为后一个请求提供必要参数；&lt;/li&gt;
&lt;li&gt;页面是否还通过 WebSocket 或轮询接收状态变化。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;一次只改变一个输入变量，可以避免把偶然相关误判为协议规则。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;用差分实验寻找关键字段&lt;a href=&quot;#用差分实验寻找关键字段&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;面对参数较多的请求，我倾向于做受控差分：保持环境一致，仅修改一个业务字段，然后比较 URL、请求体、请求头和响应结果。经过多轮实验，可以把字段分成几类：&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;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;业务字段&lt;/td&gt;&lt;td&gt;随用户输入变化&lt;/td&gt;&lt;td&gt;建立明确的数据类型与校验规则&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;会话字段&lt;/td&gt;&lt;td&gt;登录后保持一段时间&lt;/td&gt;&lt;td&gt;交给会话管理模块维护&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;临时字段&lt;/td&gt;&lt;td&gt;每次请求或短周期变化&lt;/td&gt;&lt;td&gt;追踪它的生成与失效条件&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;展示字段&lt;/td&gt;&lt;td&gt;只影响前端呈现&lt;/td&gt;&lt;td&gt;与核心业务模型分离&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;这种分类能把“抓到一个请求”推进到“理解一组状态转换”。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;重放不是终点，建模才是&lt;a href=&quot;#重放不是终点建模才是&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;请求能够重放，只说明当前样本有效。为了验证理解是否正确，还要覆盖正常、边界和失败三类场景，并记录服务端返回的可观察状态。&lt;/p&gt;&lt;p&gt;我通常把分析结果整理成一份接口契约：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;operation&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;updateProfile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;precondition&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;session is valid&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;displayName&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;success&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;profile version increments&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;conflict&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;current version is returned&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这份契约比某段一次性脚本更有价值，因为它可以继续生成测试用例、Mock 服务和兼容层，也能帮助定位前后端对状态理解不一致的问题。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;保留证据链与安全边界&lt;a href=&quot;#保留证据链与安全边界&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;协议分析应当限定在自有系统、公开接口或明确授权范围内。我会对测试环境、样本时间、客户端版本和操作步骤做记录，同时对会话凭据和个人信息进行脱敏，不在文章或仓库中保存真实 Token。&lt;/p&gt;&lt;p&gt;这项工作的技术含量不在于“隐藏得多深”，而在于能否用可重复的实验，把一个黑盒交互还原成边界清晰、行为稳定、能够被验证的系统模型。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>x86 逆向分析：从调用约定到运行时行为验证</title><link>https://cunjinjin.com/posts/x86-reverse-engineering-lab/</link><guid isPermaLink="true">https://cunjinjin.com/posts/x86-reverse-engineering-lab/</guid><description>以自编译实验程序为样本，结合静态阅读和动态调试理解 x86 程序的控制流、数据流与调用边界。</description><pubDate>Mon, 03 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;最近重新整理 x86 逆向分析的学习方法。相比记忆大量指令，我更关注三个问题：数据从哪里来、经过哪些转换、最终影响了哪个分支。只要控制流和数据流能够对应起来，汇编代码就不再是一串孤立的助记符。&lt;/p&gt;
&lt;p&gt;本文以自己编译的实验程序为样本，记录一套从静态阅读到动态验证的方法。所有实验都在隔离环境中进行，只用于软件学习、调试和兼容性研究。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;先识别程序边界&lt;a href=&quot;#先识别程序边界&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;拿到一个实验样本后，我会先确认文件格式、目标架构、入口点、导入函数和主要代码段，再观察是否包含调试符号、异常处理信息和明显的字符串引用。&lt;/p&gt;&lt;p&gt;这个阶段并不急于给函数命名，而是先建立全局轮廓：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;哪些函数负责输入与输出；&lt;/li&gt;
&lt;li&gt;哪些区域频繁访问堆、栈或全局数据；&lt;/li&gt;
&lt;li&gt;哪些分支决定关键返回值；&lt;/li&gt;
&lt;li&gt;外部库调用在哪里形成行为边界。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;调用约定是阅读函数的坐标系&lt;a href=&quot;#调用约定是阅读函数的坐标系&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;理解调用约定后，才能正确判断参数从哪里传入、返回值在哪里产生、哪些寄存器需要由调用方或被调用方保存。&lt;/p&gt;&lt;p&gt;在 32 位 x86 中，经常能从栈帧附近看到参数与局部变量的访问；在 x86-64 中，前几个参数更多通过寄存器传递。编译器优化还可能省略传统帧指针，因此不能只依赖固定的函数序言模式。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;push&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ebp&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;mov&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ebp&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;esp&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;sub&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;esp&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;20h&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;mov&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;eax&lt;/span&gt;&lt;span&gt;, [&lt;/span&gt;&lt;span&gt;ebp&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;test&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;eax&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;eax&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;jz&lt;/span&gt;&lt;span&gt;   short invalid_input&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这段代码透露出一个清晰的数据关系：函数读取第一个栈参数，对它进行零值判断，并把控制流分成正常路径和异常路径。阅读时我会把这些关系先翻译成接近伪代码的表达，再继续追踪每条路径。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;用数据流约束控制流&lt;a href=&quot;#用数据流约束控制流&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;遇到复杂函数时，从入口顺着所有跳转阅读很容易迷失。我更倾向于从关键结果反向追踪：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;找到影响返回值或关键内存写入的指令；&lt;/li&gt;
&lt;li&gt;追踪相关寄存器最后一次定义的位置；&lt;/li&gt;
&lt;li&gt;标记参与计算的参数、局部变量和常量；&lt;/li&gt;
&lt;li&gt;再检查哪些条件跳转能够改变这条数据链。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;这种方式可以快速识别真正有意义的基本块，把日志、错误处理和编译器生成的辅助代码暂时放到次要位置。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;静态假设必须经过动态验证&lt;a href=&quot;#静态假设必须经过动态验证&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;反编译结果是高质量的推测，不是最终事实。动态调试的作用，是在关键基本块设置断点，用不同输入观察寄存器、标志位、栈和内存的实际变化。&lt;/p&gt;&lt;p&gt;我会给每次实验保留简短记录：输入条件、命中的路径、关键地址、前后状态和结论。如果结果与静态推断不一致，就回到调用方检查参数来源，或确认是否存在间接调用、结构体偏移和符号扩展等细节。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;从单个函数走向行为模型&lt;a href=&quot;#从单个函数走向行为模型&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;最终目标不是把每条汇编都翻译一遍，而是形成程序行为模型：输入经过哪些校验，状态如何迁移，错误如何传播，输出由哪些条件共同决定。&lt;/p&gt;&lt;p&gt;当函数签名、数据结构和控制流逐步稳定后，再统一命名并写出伪代码。这个过程虽然比“直接看反编译结果”慢一些，却能让结论有证据支撑，也更容易在新版本样本中重新定位相同逻辑。&lt;/p&gt;&lt;/section&gt;</content:encoded></item></channel></rss>