Repository navigation
Releases
v2.3.0
Full Changelog: v2.2.1...v2.3.0
MAGI v2.2.1
MAGI v2.2.1 — 把「视频没法看」修掉
2.2.0 有一个能把视频彻底变废的回归:鼠标指针在画面上划过就快进/倒退,靠左竖滑还会一路改亮度。 这一版修掉它,另外补了两处相关的东西。
根因
两个播放器(libVLC 覆盖层 VideoOverlay、libVLC 不可用时的内置 <video> 回退层 VideoPlayer)都犯同一个错:手势处理里没有判断「鼠标是否按下」。
React 的 onPointerMove 挂的是 pointermove,指针只是划过、没有任何按键时也会连续触发。而手势状态里 x0 / y0 初始值是 0,于是 dx = clientX - 0 直接等于屏幕横坐标——鼠标随便挪一下就是几百像素的「位移」,一超过 14px 阈值就被判成「拖动进度」。竖向同理,左侧三分之一的竖滑被判成调亮度。
更糟的是 pointerup 只在真正按下后才来,所以这个错误的 seek 模式会一直挂着,直到你点一下鼠标才把累积的 dx 一次性提交——就是你看到的「视频自己跳走」。
修法
- 手势判定抽成纯模块
src/video/gestureCore.ts,两个播放器共用。第一条规则就写在函数第一行:if (!g.down) return { type: 'ignore' }。没按下 = 什么都不许改。 - 起判阈值 8px,防手抖误触。
- 方向判定改对:原来是「谁的位移先超过 14px 谁赢」,斜着划一下就被判成 seek;现在要求横向幅度 大于纵向的 1.2 倍 才算拖动进度。
- 状态复位统一走
gestureUp(),pointerup/pointercancel都覆盖,手势不会残留到下一次。 - 删掉
onDoubleClick:它和pointerup里的双击分区逻辑重复,双击一次会跳两次。 - 新增
npm run test:gesture:28 条断言,纯 node 跑(--experimental-strip-types),不需要 Electron 也不需要浏览器。CI 已接入,回归会当场变红。
顺带
- 内核降级不再静默:libVLC 加载失败时会退回内置
<video>播放器(画面、手势都不同),以前一点提示都没有,用户只会觉得播放器坏了。现在右下角有角标「未加载 libVLC · 已退回内置播放器」,悬停能看到该检查哪个路径。 - 自己遇到这个问题时先看一眼:如果视频是内置播放器(能看到左上角标题栏是网页样式、底部控制条也不一样),说明
resources/vlc/libvlc.dll或开发期的vendor/vlc/不在。跑一次node scripts/fetch-vlc.mjs就回来了。
现在的鼠标行为
| 操作 | 结果 |
|---|---|
| 不按键,随便划过 | 什么都不发生(只会把控制条唤出来) |
| 按下 + 横向拖 | 拖动进度,松手提交 |
| 按下 + 竖向拖(右侧) | 音量 |
| 按下 + 竖向拖(左侧三分区) | 亮度(仅内置播放器,libVLC 层没有这一项) |
| 单击 | 显示 / 隐藏控制条 |
| 双击左 / 右三分区 | −10s / +10s |
| 双击中间 | 全屏切换 |
| 按住不动 600ms | 2x 快进,松开恢复 |
验证
npm run test:gesture→ 28 / 28 通过npx tsc --noEmit→ 0 errorvite build→ 通过- 未做:Electron 内的端到端手势验收(本机沙箱里 GPU 进程起不来,CDP 连上后 renderer 立刻崩)。
scripts/probe-gesture.mjs已经写好,在有桌面会话的机器上npm run probe:gesture可以直接跑那套 AI 验收。
MAGI v2.2.0 — 音乐换 foobar 范式,视频换 libVLC
MAGI v2.2.0 — 音乐换 foobar 范式,视频换 libVLC
破坏性变更。 这一版把「整合」时期留下的两条技术债一次性砍了:音乐层不再是 folia-major 的源码移植,视频层不再随包塞一个 mpv.exe。阅读器(EPUB / TXT)一行没动。
为什么非砍不可:folia 那一层是把上游 1039 个文件按 import 闭包原样搬进来的,它的在线账号、歌词 provider、封面 CDN 在纯本地场景全是空实现,任何一处 noop 兜不住就整块崩——这就是「整合之后一堆 bug」的来源。mpv 则是另一个方向的债:115 MB 的可执行文件随包分发,靠命名管道传 JSON,还得为它单独维护一套「找不到就降级」的分支。
音乐:foobar2000 / MusicBee 范式
src/folia/ 整体删除,src/music/ 从零写。取值取向是桌面音乐管理器,不是网页播放器:信息密度优先,动效让位。
- 左侧媒体库树 —— 全部 / 最近添加 / 最常播放 / 从未播放,加上按 艺术家 / 专辑 / 流派 / 年份 / 文件夹 五种维度实时聚合。聚合是从曲目数组现算的,不落索引,导入完立刻就有。分组默认收起,点标题展开。
- 右侧多列表格 ——
# / 标题 / 艺术家 / 专辑 / 年份 / 时长 / 规格,每一列都能点表头排序。#列默认按专辑内曲序而不是文件名(foobar 语义);「规格」列把 codec + 采样率 + 位深 + 声道压成一行FLAC 44.1k 24bit,一眼看出无损还是转码。 - 底部传输条 —— 扁平一条,常驻,是全应用唯一的
<audio>元素宿主,所以切页面不会断音、也不会出现两条进度互相打架。顶部一条细线就是进度条,直接拖拽 seek。 - 队列跟随筛选 —— 双击某一行时,队列用的是当前筛选后的列表,不是全库。在「2024 年」里双击第一首,下一首就是同一年的下一首。
视觉参数都是按桌面软件的密度调的:行高 27px、数字等宽、斑马纹、播放中那行用强调色而不是换背景。屏外行用 content-visibility: auto 跳过渲染,53 首和 5000 首的滚动开销差别很小。
视频:libVLC 3.0.21
electron/mpv.cjs → electron/vlc.cjs,用 koffi(N-API 预编译绑定)直接 FFI 加载 libvlc.dll——不需要 MSVC,不需要 node-gyp,Windows 上 npm i 完就能跑。
窗口结构沿用上一版那套(因为它是对的):videoWin(focusable: false,只负责提供一个 HWND)+ overlayWin(透明覆盖,承载控制条 UI)。libvlc_media_player_set_hwnd() 把 vout 挂进前者,原生子窗口永远画在网页内容之上,所以 UI 必须放在另一个窗口里。
状态回推改了做法:不再解析 libvlc_event_t——那是带 union 的 C 结构体,跨 FFI 读字段极易错位,一个字段偏移错了就是整块状态乱跳。改成 10Hz 轮询 get_state / get_time / get_length / audio_get_volume,稳定、可预期,代价可以忽略。
硬解默认 --avcodec-hw=d3d11va;--file-caching=1200 + --drop-late-frames + --skip-frames 保证本地大码率片源不追帧。
这一版踩到的三个坑(都记进 README 了):
| 症状 | 根因 | 修法 |
|---|---|---|
open 返回 false,media-new-failed |
libvlc_media_new_path 在 Windows 上不认 D:/x.mp4 这种正斜杠路径,直接返回 NULL |
toVlcPath() 统一归一反斜杠 |
| 视频跑到独立窗口里去了 | set_hwnd 写在 play() 之后,VLC 已经建好 vout |
顺序固定为 new_path → new_player → set_hwnd → play |
| 插件加载失败 / 解码器缺失 | --plugin-path 在 libvlc 3.x 已废弃,传了也没用 |
改走环境变量 VLC_PLUGIN_PATH + dll 同级 plugins/ |
另外 libvlc_media_player_set_aspect_ratio 是 2.x 的 API,3.0 里根本没这个符号,比例控制要拆成 video_set_aspect_ratio + video_set_crop_geometry + video_set_scale 三件套。
体积
| 2.1.1 | 2.2.0 | |
|---|---|---|
| 直接依赖 | 34 | 8 |
node_modules 顶层项 |
1000+ | 437 |
渲染层产物 dist/ |
数十 MB | 0.85 MB(3 files) |
| 安装包 | 146 MB | 138 MB |
dist/ 这一项差了两个数量级,主要是 pixi + three + folia 的样式与字体资源一起走了。
安装包反而小了 8 MB,这点和直觉相反:解压后的 libVLC(180 MB)确实比 mpv.exe(115 MB)大,但 VLC 那堆小 DLL 在 NSIS 里压缩率极高,而 mpv 是一个已经压过的 115 MB 单文件、几乎压不动。真正省下来的是 folia 那层渲染资源。
libVLC 不入库(解压后 180 MB,超 GitHub 单文件上限),自建时先跑 node scripts/fetch-vlc.mjs,它会按 清华 → 中科大 → 官方 三镜像回退下载 3.0.21 并解压到 vendor/vlc/,electron-builder 自动复制成包内 resources/vlc。
验收
三个无头 CDP 探针,跑在真实运行的应用里,不是静态 DOM 断言。
视频 11 项(开发版与生产打包版都跑了一遍):
available=true engine=libvlc 3.0.21
open=true (620ms / 生产版 455ms) time advancing=YES
seek → 120s 生效 volume=45 → 0.42 mute=true rate=1.5
pause → resume 正常 轨道列表 1 video / 1 audio
aspect: fit / fill / 16:9 三态切换正常
snapshot → 1376×768 真实视频帧(确认 vout 真的在画,不是黑窗)
close → buffered/width/height 全部归零
console errors = 0
音乐全项:.mu-page 渲染、58 行、7 列表头齐全、点「时长」排序后 0:01 → 7:12、展开专辑分组筛出 2 行、双击播放 currentId=b2 playing=true queue=2、传输条暂停/继续、音量 0.42、进度 seek 生效。注入的测试曲目跑完自动清理,残留 0。
整体冒烟 8 项:标题、preload 桥接 25 个方法、左侧三分区、canvas=0、#root 挂载、语言包 IPC、控制台无错误、无未捕获异常。
tsc --noEmit 与 vite build 均 exit 0。
其余
- 顺带修掉几处过期配置:
release.yml里还在拉便携 mpv、产物目录还写着../nr_out;tsconfig.json的@/*还指向被删掉的src/folia/*;LICENSE的第三方声明还写着「因移植 folia 而必须 AGPL」——现在删了移植层,继续用 AGPL 是选择而不是义务,声明里如实改了。 - 许可证不变:AGPL-3.0-or-later。libVLC 是 LGPL-2.1+,以未修改的独立 DLL 随包分发、运行时 FFI 加载,可按 LGPL 要求自行替换。
- folia 带走的还有 14 种可视化与 Lattice 歌曲墙。它们依赖在线歌词 provider 与账号态,本地跑起来只有空壳——想要可视化的话,Web Audio 那条通路还留着(
src/lib/visualizer.ts),只是暂时没有消费者。 - 这一版起有了真正的 CI:
ci.yml在每次 push / PR 上跑node --check electron/*.cjs+tsc --noEmit+vite build;release.yml在推v*标签时自动拉 libVLC、构建 NSIS 与 portable、发 Release。下面这个包就是它产出的。 - 顺手记一个 CI 上的坑:
unzipper的Extract()在 GitHub runner 上解 74 MB 的 VLC zip 会抛Premature close,本地却正常。改成优先调 Windows 自带的bsdtar(必须显式写System32\tar.exe——CI 的 bash 步骤里PATH首位是 Git Bash 的/usr/bin,那里是 GNU tar,不认 zip)。
MAGI v2.1.1 — 补齐 folia 播放页(封面 / 歌词 / 桌面播放形式)
MAGI v2.1.1 — 补上 folia 的播放页(封面 / 歌词 / 桌面播放形式)
v2.1.0 把 folia 的播放层搬进来了,但只搬到了「歌曲墙」那一档:currentView === 'player' 的整块播放页从没进过闭包。所以点开一首歌只有海报墙,没有大封面、没有歌词、也不是 folia 的桌面播放形式。这一版把缺的那一块补齐。
修了什么
- 播放页(
player档)补齐 —— 闭包新增PlayerPanel.tsx+buildPlayerPanelModel.ts(闭包从 4 个入口长到 6 个,340 个文件 / 64925 行),外加UnifiedPanel的 MAGI 适配层src/media/MagiPlayerPanel.tsx。 - 歌曲封面出来了 —— folia 的封面位只有一个,就在
UnifiedPanel侧栏里(img alt="Art",512px 请求尺寸 / 320px 展示)。之前侧栏被AnimatePresence {isOpen && …}挡着,封面根本没渲染。现在进播放页默认展开侧栏:大封面 + 五个标签页(封面 / 在线歌词 / 控制 / 队列 / 账户)+ 歌名 / 艺人 / 专辑。 - 歌词出来了 —— 根因不在音频数据,而在视图档位:可视化器画不画歌词只认
resolveVisualizerShowText,它的唯一放行条件是useAppViewStore.view === 'player',而这个 store 在 v2.1.0 里从没被写过(恒为'home'),于是showText恒为false,歌词浮层直接返回shouldRenderOverlay: false。现在 MAGI 的nowPlayingOpen/playView会同步进useAppViewStore.view(并给该 store 补了 module-level 的setView,对齐它自己已有的导出风格)。 - 「桌面播放形式」回来了 —— 分层按 folia 原样:可视化器
z-0全屏铺底(封面取色背景 + 逐字大歌词 + 底部后续行预览)→ 歌曲墙z-10(只在lattice档出现)→ 侧栏z-60。
现在的交互
| 操作 | 结果 |
|---|---|
| 点底部播放条胶囊 | 进播放页:可视化器铺底 + 侧栏大封面(folia 的默认档) |
| 播放条 / 侧栏里的「歌曲墙」 | 进 Lattice 海报墙(叠在可视化器之上) |
侧栏右下 × |
收起侧栏,只剩纯可视化器(歌照样唱、歌词照样走) |
验收
无头 CDP 探针(静态服 dist/ → Edge headless + Emulation.setDeviceMetricsOverride 1600×900),走真实路径(对 [data-ponder="player-bar"] 派发真点击,而不是直接改 store):
B/PLAYER view=player isPanelOpen=true panel=1 coverVisible=true(320×320)
tabs=[cover,onlineLyrics,controls,queue,account]
panelTitle=少女☆歌劇 レヴュースタァライト | アメリカ民謡研究会 | 永遠に違うよ。
visActiveLine=僕の今日まで glowWordCount=15 (主歌词行真的画出来了)
D/NOPANEL view=player isPanelOpen=false visActiveLine=抱きしめて glowWordCount=15
C/LATTICE view=lattice lattice=1 panel=0
E/CLOSED view=home playerSurface=0
14 种可视化模式巡览:全部有 canvas;封面作为画内图像出现的只有 monet(莫奈),其余模式的封面走侧栏与背景取色 —— 与上游一致。
探针踩到的坑:假的音源播不动,
<audio>.currentTime钉在 0,而GlowWord的词态迁移靠useMotionValueEvent(currentTime, 'change'),值不变就一次都不触发,所有词卡在waiting初态(DOM 里有、肉眼看不见)。探针里把currentTime换成可拨动的墙钟才验出真结果 —— 这不是产品缺陷。
其余
- 版本号 2.1.0 → 2.1.1;README 的音频段补上「播放页 / 歌曲墙」两档说明与第三处移植改动。
tsc --noEmit0 error。- 构建与打包参数不变:
CODEBUDDY_SAFE_DELETE_ENABLED=0,每个 target 用全新输出目录、串行跑。
MAGI v2.1.0 - folia 一比一移植 + 内嵌 mpv 真 HDR 视频
MAGI v2.1.0 — folia 一比一移植 + 内嵌 mpv 真 HDR 视频
这一版把上一版"参考 folia 做的形态"整个换掉了:音频播放界面现在是folia-major 的源码本身。
音频:folia 一比一移植
不再仿写,而是按 import 闭包整体搬运 —— 把 folia-major 的播放相关代码 1039 个文件原样复制进 src/folia/,再用别名 @ → src/folia 让 folia 内部的 @/xxx 与相对引用原样成立(folia 的 src/ ≡ MAGI 的 src/folia/)。没有重写一行 UI 代码,所以界面、动效、状态机、样式都与上游一致。
- 底部播放条:folia 原版 Folium 胶囊进度条,全局常驻;首页态收成一条细进度胶囊,悬停展开
- Lattice 全屏舞台:大封面海报墙 + 世界层 + 逐行歌词 + 铬层工具 + 播放队列,framer-motion 转场
- 逐字歌词:pixi 8 渲染,标准 LRC 与增强型逐字都支持(同名
.lrc或 ID3 内嵌),带歌词快慢微调与译文字幕叠加 - 14 种可视化模式:
cadenzacappellacladdaghclassicdioramafumelumieremonetpartitapendolosonnetstilltemperatilt,另有 6 种背景模式;每种独立分包按需加载 - 样式用 Tailwind 4 分层引入并跳过 preflight,避免 reset 冲掉既有的手写样式
移植时的两处必要改动:① folia 的 3 处 Web Worker 路径在 MAGI 里被禁用(打包后渲染层走
file://,Worker 脚本加载不可靠;这三处在 MAGI 都是死代码——元数据改由主进程提供,歌词解析改为同步就地计算,automix 分析退回主线程跑同一套数学)。② folia 依赖file-type@^21的./core导出,MAGI 的music-metadata@12带的是file-type@22,已改为根导入。
视频:内嵌 mpv,真 HDR
Chromium 的 <video> 在 Windows 上拿不到 HDR 色彩直通,所以视频改由随包分发的便携 mpv(v0.41.0 + libplacebo v7.375.0)解码:
- 真 HDR 直通:
--vo=gpu-next --gpu-api=d3d11 --target-colorspace-hint=yes,并走--hwdec=auto-safe硬解 - 全格式:mpv/FFmpeg 支持的容器与编码基本都能放,不再受 Chromium 内核限制
- 窗口结构:mpv 用
--wid嵌进一个专用的原生视频窗口(原生子窗口永远画在网页内容之上,UI 压不住它),控制 UI 由另一个透明覆盖窗口承载,两层尺寸位置始终跟随主窗口 —— 观感仍是「视频在 MAGI 里」 - 通信:mpv JSON IPC over Windows 命名管道,
observe_property实时回推 时间轴 / 时长 / 缓冲 / 暂停 / 音量 / 静音 / 倍速 / 分辨率 / EOF - 控制 UI:左右拖动快进快退(OSD 提示)、双击左右 ±10s、双击中间全屏、长按 2 倍速、滚轮调音量;控制栏 3 秒无操作自动隐藏;倍速 0.5x–2x;画面比例(适应/裁剪/拉伸);截图保存;外挂
.srt/.vtt/.ass(自动优先挂中文字幕)+ 内封字幕轨道选择、字号位置可调;队列连播、断点续播、播完自动下一集;键盘 空格 / ←→ / ↑↓ / F / M / Esc - 降级:机器上找不到 mpv 会自动退回 Chromium
<video>播放器,功能不丢、只是没有 HDR 直通
说明
- 安装包体积明显变大(安装版 146 MB / 便携版 125 MB)是因为 115 MB 的 mpv 随包分发。从源码自建时按 README「打包」一节把 mpv 放到
resources/mpv/即可;不放也能构建,视频会降级。 mpv.exe超过 GitHub 单文件 100 MB 上限,因此不入库(.gitignore已排除resources/mpv/),但随下面两个安装包分发。
文件
| 文件 | 说明 |
|---|---|
MAGI Setup 2.1.0.exe |
NSIS 安装版,可选安装目录、建桌面快捷方式 |
MAGI-portable-2.1.0.exe |
免安装单文件 |
Windows x64。 当前仅构建 Windows 安装包。
MAGI v2.0.0
MAGI v2.0.0 — 从阅读器到影音综合体
项目正式改名 NovelReader → MAGI(书 / 乐 / 影三区一体),本次是第 2 个大版本。
🎵 新增:音乐播放(Folia 形态)
- 本地音乐库:单文件导入 / 递归扫描文件夹;ID3v2 / FLAC / Vorbis / MP4 元数据(标题、艺人、专辑、年份、流派、Hi-Res 标识)与内嵌封面
- 常驻底部播放条:封面 + 传输控制 + 进度拖拽 + 顺序 / 随机 / 单曲 + 音量
- 全屏播放台:大封面 + 环形频谱 + 逐字歌词 + 播放队列 + 歌词快慢微调 + 睡眠定时
- 歌词:同名
.lrc或 ID3 内嵌,标准 LRC 与增强型逐字均支持 - 断点续播:每首歌记住位置;队列 / 音量 / 模式跨会话保留
- 支持 Windows SMTC 媒体键(Media Session)
🎬 新增:视频播放(Vivid Player 形态)
- 视频库:单文件 / 文件夹导入,断点进度显示
- 手势播放器:左右拖动快进快退(OSD 提示)、左上上下拖动调亮度、右上上下拖动调音量、双击左右 ±10s、双击中间全屏、长按 2 倍速、滚轮缩放 + 缩放后拖动平移
- 字幕:外挂
.srt/.vtt/.ass(支持视频名.zh-cn.srt多语言标记)+ 内封字幕轨道,字号 / 位置 / 底色可调 - 播放控制:倍速 0.5x–2x、画面比例、截图保存、画中画、队列连播、断点续播
- 控制栏 3 秒自动隐藏;键盘空格 / ←→ / ↑↓ / F / M / Esc
📖 保留并增强
- 阅读器:EPUB / TXT、双阅读模式、多主题、目录 / 书签 / 标注 / 进度
- 文献查阅中心:划词即查 + 搜索台 + 学术文献库 + 本地词库
- GPT-SoVITS 语音朗读
- 左侧分区导航(书架 / 音乐 / 视频),旧书库数据完全兼容
🛠 工程
- 主进程本地媒体 HTTP 服务:
127.0.0.1随机端口 + Range 支持 + CORS + 导入路径白名单(音视频拖动进度必需) music-metadata元数据解析(ESM 动态 import)- 新增模块:
lib/lrc.ts、lib/subtitle.ts、lib/visualizer.ts、lib/mediaImport.ts、lib/useAudioEngine.ts、lib/audioGraph.ts
📦 安装
| 文件 | 说明 |
|---|---|
MAGI Setup 2.0.0.exe |
安装版(NSIS),可改安装目录、建桌面快捷方式 |
MAGI-portable-2.0.0.exe |
免安装单文件,双击即用 |
仅构建 Windows x64。macOS / Linux 可自行 npm run dist。
NovelReader v1.1.1
NovelReader v1.1.1
一个纯修复版本:修掉「查阅中心 / 文献库在书库页完全看不到」的入口缺失问题。
🐛 修复:文献查阅功能「装了但看不见」
1.1.0 里功能代码是全的(百度百科 / 萌娘百科联网链、主进程 lookup 代理、内置词库都在包里),但书库页(Home)压根没有渲染任何入口 —— 之前的代码只导入了图标、解构了 setLookupOpen / setLiteratureOpen,JSX 里一个按钮都没写,属于死代码。
结果就是:打开应用停在书库页时,看起来和旧版一模一样,唯一入口只剩阅读器顶部悬浮栏里两个没有文字的图标(而且悬浮栏平时是隐藏的,鼠标移动才出现)。
本版修复:
- 书库页新增常驻入口条,不随书籍列表滚动,两张带图标 + 标题 + 说明的卡片:
- 查阅中心 —— 划词即查 · 联网 + 本地词库
- 文献库 —— 学术文献 · 引用生成
- 即使不打开任何书,也能直接从首页进入这两个面板。
🌐 补齐英文语言包
英文词典整块缺少 research / lookup / literature 共 37 个 key,之前切到 English 界面会直接显示 research、tabLookup 这种原始 key 名。本版已补全。
📦 下载
| 文件 | 说明 |
|---|---|
NovelReader-portable-1.1.1.exe |
免安装便携版,双击即用,适合先试 |
NovelReader Setup 1.1.1.exe |
安装版(NSIS),支持覆盖安装升级 |
两个包内容一致,按习惯选一个即可。
✅ 验证
tsc --noEmit零错误vite build通过- 打包产物
app.asar已确认包含新入口的 JS / CSS 与中英文案
💡 入口速查
| 场景 | 位置 |
|---|---|
| 书库页(首页) | 顶部常驻入口条 → 查阅中心 / 文献库 |
| 阅读中 | 顶部悬浮栏(鼠标移到顶部出现)→ 查阅 / 文献 图标 |
| 选中正文文字 | 划词浮条 → 查阅 / 收藏 |
NovelReader v1.1.0 — 文献查阅中心 + 大文件 EPUB 支持
NovelReader v1.1.0
沉浸式桌面小说阅读器 · Electron + React + EPUB.js · 免费开源 · 无需登录
🆕 文献查阅中心(本次主打)
阅读时选中任意文字 → 底部浮条弹出 查阅 / 收藏,一键调出资料卡片。
- 三 Tab 查阅面板
- 查阅:本地词库命中 + 联网摘要,可收藏为笔记、复制、打开原文、译成中/英
- 收藏:所有查阅结果的收藏夹
- 本地词库:搜索 / 新增 / 导入 JSON / 导出 JSON / 恢复内置(内置 16 条文学·出版·学术词条,断网可用)
- 学术文献库:录入文献(标题/作者/年份/来源/链接/标签/备注),按标签筛选,一键生成并复制 GB/T 7714-2015 或 APA 7th 著录,可关联到某本书、导入导出 JSON
- 离线兜底:无网络时自动降级到本地词库,不阻塞阅读
数据源(已实测)
| 数据源 | 状态 |
|---|---|
| 百度百科 openapi | ✅ 200 / 约 280ms |
| 萌娘百科(站内 API) | ✅ 200 / 约 1s(轻小说·ACG·角色名极准) |
| MyMemory 翻译 | ✅ 200 / 约 730ms |
联网链按「可达源优先、被墙源降为末位兜底」排序,避免每次查阅先干等超时。
🐛 大文件 EPUB 加载修复
彻底解决 数百 MB ~ GB 级 EPUB 无法导入/打开 的问题。
- 旧行为:导入与打开都把整本书读成 base64 → EPUB.js 底层 JSZip 在内存里整包解压(600MB 解压后数 GB)→ 渲染进程 OOM / 卡死。
- 新方案:主进程用
unzipper流式解压到临时目录(内存 O(1)),再起本地 HTTP 服务暴露解压目录,EPUB.js 走目录模式按需读取单文件,不再创建 JSZip。 - 实测:657.6 MB / 394 章的书,流式解压 7.7s,EPUB.js 解析 0.2s,394 章全部正常。
📦 下载
| 文件 | 说明 |
|---|---|
NovelReader Setup 1.1.0.exe |
安装版(推荐) |
NovelReader-portable-1.1.0.exe |
便携版,双击即用,无需安装 |
Windows 10 / 11 x64。
✨ 完整功能
- 📚 书架管理:导入 EPUB / TXT,封面墙展示,删除后可从原路径重新导入
- 📖 双阅读模式:竖向滚动 / 横向翻页,一键切换
- 🎨 多主题、字体 / 字号 / 行距 / 边距可调
- 📑 目录、书签、标注、阅读进度自动保存
- 🔊 GPT-SoVITS 本地 AI 语音朗读:逐句朗读、自动续读下一章
- 🔍 文献查阅中心:划词查询、笔记收藏、学术文献库
- 🌐 中英双语界面
NovelReader v1.0.0
??????:Windows NSIS ???? portable ???????