功能台里挂着两扇门,其中一扇后面就是这台翻译机。它是这座档案室里第一个「不用人守着也能干活」的项目——上游本来只是一个等人叫唤的技能,四天之后,它变成了一间自己推进的线上书房。
整理时间:2026-09-16 | 更新:2026-09-17 本次更新:D 方案(脚本直连 API)上线——第 4 节的吞吐数字按实测修正,新增第 7 节,复盘由七条扩为十条,末尾「下一步」重写。 开发周期:四天(09-14 → 09-17)| 线上:https://trs.andrew-li.top 上游引擎:
deusyu/translate-book(Rainman Translate Book,MIT 许可)| 本项目:Andrew-li777/translate-book说明:下文所有数字(块数、耗时、内存、成品体积)都来自项目自己的迭代记录与验证结果,非估算。
0. 起点:一个「要人叫才动」的技能
上游项目本质是一个 Agent Skill,不是服务。它解决的是一个很具体的问题:整本书怎么用 LLM 翻完而不崩。
输入(PDF / DOCX / EPUB)
│
▼
Calibre ebook-convert → HTMLZ → HTML → Markdown
│
▼
切块 chunk0001.md, chunk0002.md, …
│ manifest.json 记录每块哈希
▼
并行子代理(默认 8 并发)
│ 每个子代理:读 1 块 → 翻译 → 写 output_chunk*.md
▼
校验(manifest 哈希比对,源↔译文 1:1 对应)
│
▼
合并 → Pandoc → HTML(带目录)→ Calibre → DOCX / EPUB / PDF
它做对了三件关键的事:
- 一块一个独立子代理、一个全新上下文窗口——避免了「一本书塞进一次会话」必然出现的上下文堆积和输出截断。
- manifest 用 SHA-256 记录每块哈希——防止陈旧或损坏的译文被合并进成品。
- 断点续译 + 邻块上下文——每块能看到相邻块的只读片段,用于代词和实体消解。
但这三条都属于「引擎素质」。它还有四个缺口,全都指向同一件事——它只在你叫它的时候才动:
| 缺口 | 后果 |
|---|---|
| 无 Web 界面 | 每次翻译都要登服务器敲命令 |
| 无任务队列 | 传一本书、等它、再传下一本,无法排队 |
| 无增量状态 | 中断即从头,8 并发跑一半断了全白费 |
| 依赖人工触发 | 想翻 200 页的书就得全程守着 |
一句话:上游解决了「翻译质量」,没解决「谁来按按钮」。
这四天要做的事,就是给它补上后半句——然后在最后一天,把补上的东西再换掉一次。
1. 架构:不是重写引擎,是给它装一套自动化
第一个决策最重要:不重写引擎,只外包它的调度权。
浏览器 → Cloudflare(HTTPS) → Origin Rule(Hostname→8080) → Caddy(按 Host 分流)
├→ :8788 translate-web
└→ :8787 scan
这样拆成三段,每段的职责边界必须干净:
| 层 | 位置 | 职责 | 明确不做什么 |
|---|---|---|---|
| 引擎 | book/scripts/(11 个脚本 + .venv) |
转换、切块、合并、构建成品 | 不碰网络、不碰队列、不知道 Web 存在 |
| 网站 | web/(FastAPI 单页 + systemd) |
上传、展示、任务编排、SSE 进度 | 不做翻译,LLM 工作全部交给外部 |
| 驱动 | Hermes cron(3 分钟一轮) | 只做「翻译 3 块 + 翻译书名」 | 不做队列扫描、不做合并构建 |
核心收益:任何一个环节都可以独立替换。Web 挂了翻译照跑;cron 挂了可以手动补跑;引擎升级不动 Web。
其中「网站不做翻译」这一条是反直觉的。最自然的写法是在 FastAPI 里内嵌一个后台翻译任务,但那样会把 LLM 长任务和 Web 请求生命周期绑在一起——重启服务就杀翻译,而这台机器只有 3.8GB 内存,Web 和重型解析抢内存是常态。所以 Web 只是个观察窗口 + 任务编排器,真正的翻译发生在别处。
当时写下「任何一个环节都可以独立替换」时,它只是一句设计信念。第四天它被兑现了一次:驱动层自己也被整个换掉,而 Web 和引擎都没动(见第 7 节)。
2. 移植:先让它在别人的服务器上活下来
上游跑在开发机上,本项目的运行环境是:Debian 12 / root / Python 3.11 / 3.8GB RAM + 2GB swap。移植过程中踩了三个坑,每一个都值得记下来。
坑一:仓库根本下载不下来
GitHub 直连超时,ghproxy 镜像也超时。这不是代码问题,是中国网络环境下单点镜像的必然结果。
解法:写一个多镜像脚本,按 github.com → ghproxy → ghfast.top 顺序依次尝试,任一成功即返回。最终 ghfast.top 拉下 11.8MB。
教训:别把「下载」当成命令,把它当成一个需要重试策略的步骤。
坑二:root 身份下 PDF 导出崩溃
merge_and_build.py 生成 HTML / DOCX / EPUB 全部正常,只有 PDF 失败。根因是 Calibre 的 ebook-convert 底层用 Qt WebEngine,而 Qt WebEngine 又基于 Chromium——以 root 身份运行会触发 Chromium 沙箱崩溃。
解法:在 calibre_html_publish.py 顶部加一行,把它做成永久修复而不是外部环境变量:
import os
os.environ.setdefault("QTWEBENGINE_DISABLE_SANDBOX", "1")
写在代码里而不是写在启动脚本里,是因为「任何方式运行都不用再记得加环境变量」。把坑焊死在代码里,而不是记在文档里。
坑三:并发从 8 降到 3
上游默认 8 并发子代理。这台机器上:每个子代理 = 一个独立的 agent 运行时进程,而 delegation.max_concurrent_children 本身就硬限制为 3。
进一步实测:内存安全线约 3.05GB,已见过 2.96GB 峰值。6 并发必 OOM。
所以 3 并发不是保守选择,而是同时踩在「配置硬上限」和「内存安全上限」上的唯一可行值。
移植结束时的验证:standard-alice.epub → 37 块;合并产出 HTML / DOCX(9.9MB) / EPUB(10MB) / PDF(12.5MB) 全部成功;真译一块 43 秒、17k tokens 输入、质量优秀。
3. 最难的一段:3 分钟窗口
把引擎跑通只是第一天的事。真正的难题出现在让它自动跑起来的时候:
⚠️ 核心约束:Hermes cron 单次会话有 3 分钟硬中断。扣掉启动、加载 skill、队列开销,每轮有效翻译时间只有约 150 秒。
而实测出现过单块翻译最坏 268 秒——比整个窗口还长。直接把翻译丢给 cron,等于每轮都在赌。
解法不是「让翻译更快」,而是按「谁受时间限制」重新分工:
| 工作类型 | 谁做 | 为什么 |
|---|---|---|
| 队列扫描 / pick / 记录 / 进度 / merge 请求 | consumer.py(脚本,毫秒级) |
纯机械操作,不受窗口影响 |
| 翻译 chunk + 翻译书名 | cron agent(delegate_task 3 块并行) |
必须用 LLM,且是唯一被窗口限制的部分 |
| 合并构建(分钟级) | Web 后台线程(60 秒 watcher) | 太慢,放 cron 里必被掐断 |
这是整个项目最重要的一条设计原则:不要把「慢的构建步骤」放进有时限的调度器里。
断点续译:靠幂等,不靠记忆
分工解决了「谁做」,但没解决「被掐断了怎么办」。答案是让每一步都幂等,而且只认一个事实来源:
- 一个 chunk 的
output_chunk{i}.md文件存在 = 这块已翻译。 这是唯一事实来源,run_state.json只记录、不决策。 consumer.py pick时如果发现 output 已存在就自动补记录(record_only)——即使上一轮在 3 分钟边界被打断,下一轮也只会「补登记」,绝不重译。- merge 前检查
run_state是否全部 done;术语表变化时只精确重置受影响的块,不动已译部分。
这样就出现了一个很好的性质:最坏情况不是「白干一轮」,而是「这一轮只完成了两块」。268 秒那块在窗口内没写完,下一轮它已经落盘,直接跳过。
顺手修掉的一个死循环
pick 一开始有个隐蔽 bug:output 文件已存在(比如上一轮中断前刚好写完),但 run_state 还没来得及记录 → 下一轮 pick 仍然认为它「未译」→ 无限重译同一块。
根因是把两套状态当成了两套真相。 修法就是上面的 record_only:以文件为准,状态只是它的影子。
这一节绕来绕去,都在和同一个对手周旋:3 分钟。而它最终不是被优化掉的,是被整个绕开的——见第 7 节。
4. 规模化验证:200 块,无人值守跑完全书
机制对不对,得用真实的书来验。选了一本真实技术书——Bioinformatics Data Skills(Vince Buffalo,200 页级 PDF)。
上传 PDF → convert → 200 个 chunk
→ cron 每 5 分钟 × 3 块自动翻译
→ 无人值守 5.5 小时
→ 200 / 200 全部译完
→ 自动合并 → 5 格式成品
成品体积:PDF 10.1MB / DOCX 7.0MB / EPUB 5.8MB / HTML 1.28MB / Markdown 1.13MB。抽查第 9 章(Range 数据类型)的译文质量不错,代码块和图片引用完整保留。
一个 0 字节空块差点让整书失败
200 块全部译完,任务状态却卡在 failed——卡在 merge。
根因很朴素:chunk0200 是 convert 从 PDF 末尾空白页生成的 0 字节合法空块,子代理的译文自然也是空的;而 merge 的校验逻辑把「空输出」一律当成「这块没翻译」,于是拒绝合并。
⚠️ 教训:空 chunk 是合法产物,不是失败。 校验逻辑必须区分两种空——「源本来就空」和「源非空但输出为空」。后者才是事故,前者是 PDF 的正常结构。
修法是给 manifest.py 和 merge_and_build.py 打 source_empty 补丁,容忍源为空的块。补丁后重跑 merge,退出码 0,状态修正为 done。
整本书、200 块、5.5 小时的工作量,卡在最后一块的 0 字节上。 这类问题的特征很清楚:它不在主流程里,它在主流程的边界条件里。
提速:5 分钟 → 3 分钟,以及一个反直觉的结果
5.5 小时还是太长。瓶颈不在模型也不在磁盘,而在调度间隔:cron 间隔必须 ≥ 窗口时长(否则两轮会重叠,子代理并发翻倍直接 OOM),所以 5 分钟是安全但浪费的选择。
把 cron 间隔从 5 分钟压到 3 分钟——刚好等于窗口,不重叠:
| 配置 | 理论吞吐 | 200 块 |
|---|---|---|
| 5min × 3 块 | 36 块/h | 5.5h(实测) |
| 3min × 3 块 | 60 块/h | 7h45m(实测,仅 26 块/h) |
结果和算出来的相反。 理论吞吐从 36 涨到 60 块/h(1.67 倍),而 200 块的实测从 5.5 小时变成 7 小时 45 分——更慢了。
教训:「把参数算对」和「让系统跑快」是两件事。 至于为什么反而更慢,文档只给了数字、没给根因,这里就不替它下结论了。
还有一个更值得注意的事实:这个更慢的数字,当时并没有被发现。它是第四天为了给新方案建基线才被测准的——下一节就讲这件事。
5. 三个让「自动化」变成「产品」的小闭环
引擎能无人值守跑完一本书之后,剩下的三处设计决定了它是一台机器还是一个能用的产品。
术语表:改一个词,全书重译
专有名词是机器翻译最容易翻车的地方。所以每本书有独立术语表,而保存动作本身就是一次全链路触发:
PUT /api/books/{name}/glossary
→ 内容哈希变化
→ 算出 affected_chunks
→ 已完成书重置为 ready
→ 轮询引擎下一轮自动接手重译
实测有效:给《爱丽丝》注入术语后,重译块里出现了「爱丽丝」「白兔先生」——术语表真实影响翻译,不是摆设。
服务端校验也不客气:缺 target 字段或 alias == source 直接 400;gender 等必填项由后端补默认值。把校验做在写入端,比做在读取端便宜。
SSE:秒级进度,但保留轮询兜底
进度一开始是 15 秒轮询,体验很钝。换成 SSE 之后:
GET /api/jobs/{id}/stream,每 2 秒读一次progress.json,有变化才推- 约 16 秒一次心跳(
: ping)防中间层断连 - 终态推送
done后主动关闭 X-Accel-Buffering: no防止反向代理缓冲住事件流
但轮询没有删掉,保留为兜底。实测 SSE 断线时 15 秒轮询能自动恢复,两套机制不冲突。同理,上传成功后立刻建立 SSE,done 事件刷新书库——实时是体验,兜底是可靠性,两者不该二选一。
顺带一提:这套 SSE 只读 progress.json,所以后来换掉翻译引擎时,它一行都没改。接口选对了,替换就是免费的。
访客模式:把「一刀切」换成「双模式」
最初整站是 Caddy 层的 basic auth,意味着任何人打开都是 401——包括你自己在手机上随手看看。
后来的两个提交把它改成应用层双模式:
| 身份 | 判定 | 权限 |
|---|---|---|
| 游客 | 无 Authorization 头 |
只读白名单:书库列表、详情、章节对照、全文搜索、封面、静态资源 |
| 管理员 | Basic 凭据 bcrypt 校验通过 | 全功能:上传、下载、术语表、删除、回收站 |
游客规则的实现细节值得一提——它不是黑名单,是白名单:
- 文件端点按扩展名放行(
.md.txt.csv与图片、.html),内部.json/.yml一律不给 /api/jobs/(任务详情、SSE)和/api/trash严格拒绝/download/对游客一律拒绝
而且游客点击下载/上传/删除时弹登录框,而不是裸 403——前端直接拦住,别让人看到权限报错才明白自己没登录。凭据比对用常量时间比较(hmac.compare_digest)防时序攻击,另加按前缀独立计数的限流。
一句话:权限设计的重心不在「能不能看到」,而在「越界时给出什么反应」。
6. 网络与运维这一关
两次 521,两个不同的原因
trs.andrew-li.top 上线后公网 HTTPS 一直 521(源站不可达),而 scan 正常。同一个 Caddy、同一台机器,两次原因完全不同:
- 第一次:Cloudflare 猜不出源站端口,默认回源 443/80,而服务器上唯一监听的是 Caddy 的 8080 → 521。
- 第二次:配置 Origin Rule 时,匹配字段误用了 「URI 完整」——而 URI 匹配的是 URL 路径(
/),永远不可能匹配到域名 → 规则形同不存在,仍然 521。
⚠️ 关键:Origin Rule 的匹配字段必须选 Hostname(Host 头),端口重写固定到 8080,Host 头保持原样,让 Caddy 按域名分流。
这两次踩坑的价值在于:第一次是知识盲区,第二次是「以为改对了」。错误信息一模一样,根因毫无关系。
服务自愈
translate-web.service 用 systemd 管理:Restart=on-failure + 开机自启 + 崩溃自愈。重启网关这类操作要走延迟定时器(systemd-run --user),因为直接 systemctl restart 会把自己的会话一起杀掉。
7. 第四天:把调度器整个拆掉
前三天做的所有事,都建立在同一个前提上:翻译必须发生在 cron 的 3 分钟窗口里。第四天,这个前提被推翻了。
先测准基线,才知道要绕开什么
准备新方案时,项目做了一件很值钱的事:把原方案的实测吞吐测准了。结果是 26 块/h——而不是之前按参数推导出来的 60 块/h。
| 方案 | 配置 | 吞吐 | 200 块 |
|---|---|---|---|
| cron(原现状) | 3min × 3 块 | 26 块/h 实测 | 7h45m 实测 |
| 每轮 6 块 | 5min × 6 块 | 72 块/h 理论 | ❌ 不可行:并发上限 3,6 个子代理必 OOM |
| 脚本直连 | systemd 守护,3 并发 | ~110 块/h 实测 | ~2h(据实测外推) |
理论 60、实测 26——差了 2.3 倍。差距不在模型,在调度器自己:每轮 cron 都要冷启动一次 agent 会话、加载 skill,再等子代理起来。这些开销不在参数表里。
教训:参数推导只能给出上限,实测才给出答案。 而讽刺的是,真正把这个数字测准的动机,不是为了知道现状有多慢,而是为了给下一个方案建基线——基线不测,你就不知道该绕开什么。
实现:一个守护进程,替换执行器
translate_direct.py 由 translate-direct.service 常驻,整体是「复用队列、只换执行器」:
主循环(每 10 秒轮询一遍队列):
① consumer.pick() → 取本批 3 块(原队列逻辑原样复用)
② ThreadPool(3) 并发直调 API → 写 output_chunk{i}.md
③ fix_images() → 补回缺失的图片引用
④ consumer.finish() → 记录 + 进度
⑤ 全书完成 → request_merge() → 交 Web watcher 构建
关键参数都写死在脚本顶部、不散落:BATCH=3、单请求 TIMEOUT=180s、RETRIES=3、指数退避 15 秒、轮询间隔 10 秒。API 通道是 https://developer.amd.com.cn/radeon/api/v1/chat/completions,模型 DeepSeek-V4-Flash,key 从环境变量读,不硬编码。
队列、状态、进度、watcher 全部原样复用——所以换成它之后,Web 上的 SSE 进度无缝可见,前端一行代码没改。第 1 节那句「任何一个环节都可以独立替换」,到这里才真正兑现。
顺带一个跨期闭环:这条直连通道,正是本刊 第 002 期 里介绍的 AMD 开发者平台免费 API。那篇文章的结论是「平台入口开得好就直连」——这一次,被直连的不再是一个客户端工具,而是整条流水线本身。
A/B 测试意外测出了一个吞吐杀手
新方案最大的风险是质量一致性,所以原计划是做 10 块 A/B 对比(旧译文 vs 新译文)。结果这个测试暴露了一件完全没预料到的事:
reasoning_effort |
单块耗时 | 结果 |
|---|---|---|
none |
47–65s | ✅ 快且稳 |
minimal |
180s | ❌ 超时 |
medium |
141–144s | ⚠️ 慢——白烧 1536 个 reasoning token |
xhigh |
>180s | ❌ 超时 |
一个 3KB 的小 chunk,medium 要花 141–144 秒,none 只要 47–65 秒,而质量等同(文档原话:章节标题甚至比原来翻得更准)。
教训:翻译是直译任务,不需要推理。 thinking effort 对翻译是纯负收益——默认改成
none,单这一项就是 2.7 倍提速。这个参数平时没人会盯,是 A/B 测试顺手照出来的。
结果
| 指标 | cron | 脚本直连 |
|---|---|---|
| 吞吐 | 26 块/h 实测 | ~110 块/h 实测 |
| 单块耗时 | — | 47–65s |
| 常驻内存 | 子代理峰值 ~1GB | 10.8M(systemd MemoryMax=1G) |
| 时间窗口 | 3 分钟硬中断 | 无 |
| 译文质量 | 基线 | A/B 相当 |
| 成品 | — | 5 格式全生成 |
实测样本是一本 37 块规模的测试书:全书 22 分钟。速度约 4–6 倍、内存省约 800MB,而且不再有任何时间窗口。
两个只有直连才会踩的坑
坑一:合并永远不触发。 37 块全译完,任务停在 merging,成品却一直不生成。
根因:consumer.finish() 在「全部译完」时只把状态置为 merging,不写 merge_request.json;而 Web 的 merge watcher 要求 status == merging 且 merge_request.json 存在 两个条件同时成立。缺后者 → 永不触发。
修法:全部译完之后显式再调一次 request_merge();已卡住的任务手动补一个文件即可恢复。
教训:两个组件各自都「做对了一半」,合起来就是死锁。 状态机和触发条件是两份契约,得放在一起审。
坑二:直连会丢图片。 merge 报错——output_chunk0003.md 的图片引用与源不一致,少了 images/000002.png、images/000036.png。
根因:插图密集的长 chunk,模型会把整块  引用全部丢弃。而 merge 有图片校验,缺图即拒绝合并。
解法是新增 fix_images.py 做确定性后处理:逐行比对源 chunk 与 output 的图片引用,缺失的按源原样补回。
⚠️ 最值得记的一点:prompt 约束不是保证。 skill 蓝图里明明写着「必须原样保留图片引用」,直连时模型照样丢。而且这个坑只有直连才会踩——走
delegate_task时子代理手里有read_file工具,会自己回读源文件核对,所以从不丢图。
同一份 prompt,换个执行路径就失效了。 这就是那条更普遍的原则:凡是「模型应该做对」的事,都要有确定性脚本兜底。
双引擎互斥
新引擎上线后,cron 没有删掉,而是降级为兜底:cron 的 prompt 里加了守卫——主引擎活着时 cron 只待命;主引擎挂了,cron 自动接管翻译。
一个能自动跑完长任务的系统,最后该保留的不是速度,是「主路径死了还有一条路」。
8. 复盘:十条被验证的原则
四天里所有的关键决策,收敛成十条:
1. 「引擎 + 界面 + 调度」三段式是这个场景的最优解。 上游引擎一行没改照样用,Web 只做编排,调度层只做最小的 LLM 工作——最后连调度层都能整个换掉而不牵动其他两层。
2. 机械操作和 LLM 工作必须彻底分离。 这是 3 分钟窗口下唯一站得住的分工。脚本毫秒级、不受窗口影响;LLM 工作才是有时限的那部分。
3. 慢的构建步骤不能放进有时限的调度器。 merge 分钟级 → 交给 Web 后台线程。到最后这一步做得更彻底:连调度器本身都绕开了。
4. 文件系统即数据库。 任务队列、进度、术语表、翻译状态全是 JSON 文件,不用 SQL/Redis。零依赖、崩溃可读、任何脚本都能直接读写——在 3.8GB 的内存上,没有多余服务可以跑。代价是并发写要用原子写(写临时文件 + rename)。
5. 幂等是断点续译的前提。 所有步骤可重入,且「一个 output 文件 = 唯一的已翻译事实」。状态记录只用来加速,不用来决策。
6. 空 chunk 是合法产物。 校验必须区分「源空」与「源非空但输出空」。边界条件不是主流程的边角料,它就是失败发生的地方。
7. 骨架和 JS 必须同步交付——最大的一次前端事故。 全选、删除所选、上传按钮、任务折叠、回收站全都无反应。根因不是逻辑写错,而是 index.html 有完整的 UI 骨架,app.js 根本没有对应的函数——功能从上线那一刻起就是死的。
第 7 条最值得记:它不报错、不崩溃、没有任何日志,只是静静地什么都不做。 加 HTML 骨架时必须同步加 JS,并且双向 grep 核对函数名——这是唯一能拦住它的办法。
8. 参数推导不等于实测吞吐。 60 块/h 是算出来的,26 块/h 是跑出来的。调度器的冷启动开销不写在任何参数表里——理论值和实测值差 2.3 倍,而且这个差距在换掉调度器之前一直被当成 60。
9. 让直译任务做推理是纯浪费。 同一个模型,reasoning_effort 从 medium 改成 none:2.7 倍提速、质量不变、超时消失。不是所有 LLM 调用都需要「想」,翻译就不需要。
10. prompt 约束不是保证,确定性后处理才是。 同一份「必须保留图片引用」的 prompt,一条执行路径从不丢图、另一条全丢——差别只在于前者有工具兜底。凡是「模型应该做对」的事,都要有脚本接住。
9. 现状与下一步
今天的样子(四天后的稳定态):
- 上传 PDF / DOCX / EPUB(≤100MB)→ 后台转换 → 守护进程持续直连翻译 → 自动合并 → 5 格式成品一键下载
- 双引擎:脚本直连为主引擎,cron 降级为自动接管的兜底
- 藏书网格、任务队列(SSE 秒级进度)、章节对照阅读(左右同步滚动)、全文搜索(译文 / 原文 / 全部)、回收站、可收起侧栏
- 游客只读参观 + 管理员全功能
- 视觉上沿用功能台的同一套设计令牌(
--paper/--ink/--accent/--line),所以它嵌进博客的功能台时不像外来物
下一步,按文档里的优先级:
- 跑一本真实长书,验长期稳定性——新引擎目前只在 37 块规模上验过,200 块级别还是外推。这是唯一还没被证明的一环。
- 图片修复从「追加到末尾」改为「按源行号插回原位」——当前实现为了稳健先把引用补到文末,位置准确率还有余量。
- 对照阅读细化(锚点跳转、字数 / 进度统计)
- 上传文件名清洗(超长与特殊字符,目前靠文件系统上限兜底)
更远的方向:翻译记忆(已译句子缓存,长系列书提速)、术语表批量导入导出、多用户与各自书库、浏览器内 EPUB 阅读器、翻译风格预设、双语对照导出、CI 回归、整栈 Docker 化、搜索换 SQLite FTS5、任务失败与磁盘水位告警。
四天里最大的收获其实不是那 4–6 倍。是发现「算出来的数字」和「跑出来的数字」之间隔着一整个调度器——而只有先把基线诚实地测出来,才看得见那个该被拆掉的东西。
参考链接
- 上游引擎:
deusyu/translate-book(Rainman Translate Book,MIT,灵感来自wizlijun/claude_translater) - 本项目仓库:https://github.com/Andrew-li777/translate-book
- 在线访问:https://trs.andrew-li.top(游客可只读参观)
- 姊妹服务 scan(视频解析):https://scan.andrew-li.top
- 直连通道来源:本刊 第 002 期 · 免费大模型 API 实战地图(AMD 路线)
- 项目文档:仓库内
迭代文档/(版本演进 / 问题记录 / 经验总结 / 架构与流程图 / 优化升级方向 / 未来发展)
本文记录 translate-book 从 Agent Skill 到线上翻译文库的移植与自动化过程,2026-09-17 补充「脚本直连 API」引擎上线后的实测数据;所有性能数字与成品体积取自项目验证记录,200 块规模下的新引擎耗时为据实测外推而非实测。线上服务的功能与权限以实际部署为准。