@pls-compile-owo/fisheye 0.3.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/README.md +12 -0
- package/fisheye.mjs +9 -34
- package/lib/audio.mjs +645 -0
- package/lib/bili.mjs +19 -18
- package/lib/budget.mjs +117 -0
- package/lib/env.mjs +1 -0
- package/lib/i18n.mjs +131 -0
- package/lib/retry.mjs +209 -0
- package/lib/stages.mjs +34 -13
- package/lib/util.mjs +9 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
本项目遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 规范与 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
4
4
|
|
|
5
|
+
## [0.4.2] - 2026-11-14
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `lib/env.mjs` 缺少 `execFileSync` 导入:`onPath()` 失败导致 PATH 上的 ffmpeg/python 永远无法被识别(影响 `resolveTool` 的 PATH 兜底)。
|
|
10
|
+
- `selftest`:PATH 上的 python 无法执行(如 Windows 商店占位符)时降级为跳过而不是失败。
|
|
11
|
+
|
|
12
|
+
## [0.4.1] - 2026-11-14
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- 音频转写能力探测(`lib/audio.mjs`):检测 whisper.cpp,`selftest` 显示音频转写是否可用;不可用时优雅提示安装方式。
|
|
17
|
+
- README 环境变量表补充 `FISHEYE_WHISPER` / `FISHEYE_WHISPER_MODEL`。
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- 首次运行(`out/`、`cache/` 目录不存在)时字幕缓存写入与视频下载不再报 ENOENT。
|
|
22
|
+
|
|
23
|
+
## [0.4.0] - 2026-11-14
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- B站 API 请求自动重试:网络错误 / 超时 / 5xx / 429 自动重试,指数退避 + 抖动;4xx 不重试(`lib/retry.mjs`)。
|
|
28
|
+
- token 预算估算可配置:`FISHEYE_TOKENS_PER_GRID` / `FISHEYE_TOKENS_PER_SUBS` / `FISHEYE_TOKENS_PER_FINE` 覆盖单张成本,`FISHEYE_TOKEN_MODEL`(gpt / qwen / gemini / 数字)按模型 tokenizer 修正(`lib/budget.mjs`)。
|
|
29
|
+
- CLI 中英双语:`FISHEYE_LANG=en` 输出英文,默认中文(`lib/i18n.mjs`)。
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- `lib/bili.mjs` 的请求统一走 `fetchWithRetry`(函数签名与返回值不变)。
|
|
34
|
+
- `lib/stages.mjs` 的预算估算改用 `lib/budget.mjs`(默认值与旧 COST 一致)。
|
|
35
|
+
|
|
5
36
|
## [0.3.0] - 2026-11-14
|
|
6
37
|
|
|
7
38
|
### Changed
|
package/README.md
CHANGED
|
@@ -68,6 +68,18 @@ npm link # 可选:装成全局命令
|
|
|
68
68
|
|
|
69
69
|
> ⚠️ 这个文件已被 `.gitignore` 排除,**永远不要提交**。
|
|
70
70
|
|
|
71
|
+
### 环境变量
|
|
72
|
+
|
|
73
|
+
| 变量 | 说明 |
|
|
74
|
+
|---|---|
|
|
75
|
+
| `FISHEYE_LANG` | CLI 输出语言:`zh`(默认)/ `en` |
|
|
76
|
+
| `FISHEYE_TOKENS_PER_GRID` / `FISHEYE_TOKENS_PER_SUBS` / `FISHEYE_TOKENS_PER_FINE` | 单张拼图 / 字幕带 / 精读帧的 token 估算覆盖(默认 1200 / 1000 / 1300) |
|
|
77
|
+
| `FISHEYE_TOKEN_MODEL` | 按模型 tokenizer 修正估算:`gpt`(1.0)/ `qwen`(1.35)/ `gemini`(0.8)/ 数字 |
|
|
78
|
+
| `FISHEYE_WHISPER` | whisper.cpp 可执行文件路径(音频转写,可选;不装则跳过) |
|
|
79
|
+
| `FISHEYE_WHISPER_MODEL` | whisper 模型文件(ggml-*.bin,可选) |
|
|
80
|
+
| `FISHEYE_HOME` | 数据目录(cache/out 位置,默认项目目录) |
|
|
81
|
+
| `FFMPEG` / `PYTHON` / `BILI_CRED` | 工具与登录态路径覆盖 |
|
|
82
|
+
|
|
71
83
|
### 依赖路径(一般不用管)
|
|
72
84
|
|
|
73
85
|
fisheye 按这个顺序找 ffmpeg / python / 凭证:
|
package/fisheye.mjs
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import path from 'node:path'
|
|
19
19
|
import { PKG_DIR, WS, CFG_FILE, FFMPEG, CRED } from './lib/env.mjs'
|
|
20
20
|
import { parseTime, num, pageNum } from './lib/util.mjs'
|
|
21
|
+
import { t } from './lib/i18n.mjs'
|
|
21
22
|
import { stageAuto, stageGrid, stageSubs, stageSelftest, stageRefine, stageGrab, stageLocal } from './lib/stages.mjs'
|
|
22
23
|
|
|
23
24
|
const IS_SELFTEST = process.argv[2] === 'selftest'
|
|
@@ -27,28 +28,11 @@ const IS_LOCAL = process.argv[2] === 'local'
|
|
|
27
28
|
|
|
28
29
|
if (!IS_SELFTEST) {
|
|
29
30
|
if (!FFMPEG) {
|
|
30
|
-
console.error(
|
|
31
|
-
|
|
32
|
-
安装方式(任选其一):
|
|
33
|
-
1. 装到 PATH:https://ffmpeg.org/download.html (Windows 用 gyan.dev 的 build)
|
|
34
|
-
2. 放项目里:把 ffmpeg 可执行文件放到 ${path.join(PKG_DIR, 'bin')}/
|
|
35
|
-
3. 设环境变量:FFMPEG=<ffmpeg 完整路径>
|
|
36
|
-
4. 写配置:${CFG_FILE} 里加 {"ffmpeg": "<完整路径>"}`)
|
|
31
|
+
console.error(t('err.ffmpeg.missing', { binDir: path.join(PKG_DIR, 'bin'), cfgFile: CFG_FILE }))
|
|
37
32
|
process.exit(2)
|
|
38
33
|
}
|
|
39
34
|
if (!IS_LOCAL && !CRED) {
|
|
40
|
-
console.error(
|
|
41
|
-
|
|
42
|
-
创建 ${path.join(WS, 'credentials.json')},内容:
|
|
43
|
-
{
|
|
44
|
-
"sessdata": "<B站 SESSDATA>",
|
|
45
|
-
"bili_jct": "<bili_jct>",
|
|
46
|
-
"buvid3": "<buvid3>"
|
|
47
|
-
}
|
|
48
|
-
获取方法:浏览器登录 B站 → F12 → Application → Cookies → bilibili.com,
|
|
49
|
-
复制这三个值。或用环境变量 BILI_CRED=<文件路径> 指向已有文件。
|
|
50
|
-
|
|
51
|
-
(也可以只跑 selftest 先看环境是否就绪:node fisheye.mjs selftest)`)
|
|
35
|
+
console.error(t('err.cred.missing', { credPath: path.join(WS, 'credentials.json') }))
|
|
52
36
|
process.exit(2)
|
|
53
37
|
}
|
|
54
38
|
}
|
|
@@ -71,7 +55,7 @@ const opt = (name, dflt) => {
|
|
|
71
55
|
if (stage === 'local') {
|
|
72
56
|
const fileArg = argv[1]
|
|
73
57
|
if (!fileArg || fileArg.startsWith('--')) {
|
|
74
|
-
console.error('
|
|
58
|
+
console.error(t('err.local.usage'))
|
|
75
59
|
process.exit(2)
|
|
76
60
|
}
|
|
77
61
|
try {
|
|
@@ -81,25 +65,16 @@ if (stage === 'local') {
|
|
|
81
65
|
to: parseTime(opt('to', null), 'to')
|
|
82
66
|
})
|
|
83
67
|
} catch (error) {
|
|
84
|
-
console.error(
|
|
68
|
+
console.error(t('err.local.failed', { message: error?.message ?? error }))
|
|
85
69
|
process.exit(1)
|
|
86
70
|
}
|
|
87
71
|
process.exit(0)
|
|
88
72
|
}
|
|
89
73
|
if (!stage || (stage !== 'selftest' && !bvid)) {
|
|
90
74
|
if (rawBvid && stage !== 'selftest') {
|
|
91
|
-
console.error(
|
|
75
|
+
console.error(`${t('err.bvFormat', { raw: rawBvid })}\n`)
|
|
92
76
|
}
|
|
93
|
-
console.log('
|
|
94
|
-
console.log(' node fisheye.mjs auto <BV> [--budget 20000] [--density 6] ← 推荐:自动规划并铺网')
|
|
95
|
-
console.log(' node fisheye.mjs refine <BV> --template ← 生成精读决策模板')
|
|
96
|
-
console.log(' node fisheye.mjs refine <BV> --decisions <file.json> ← 按模型判断精读')
|
|
97
|
-
console.log(' node fisheye.mjs refine <BV> ← 几何兜底(零 token)')
|
|
98
|
-
console.log(' node fisheye.mjs grid <BV> [--chunk 60] [--grid 3x3]')
|
|
99
|
-
console.log(' node fisheye.mjs subs <BV> [--count 12] [--band auto|0.22]')
|
|
100
|
-
console.log(' node fisheye.mjs grab <BV> <t1,t2,t3> ← 手动指定时间点')
|
|
101
|
-
console.log(' node fisheye.mjs local <视频文件> [--grid 3x3] [--from t] [--to t] ← 看本地视频(mp4/mkv/...)')
|
|
102
|
-
console.log(' node fisheye.mjs selftest [--deep] ← 自检(依赖/凭证/API/缓存/磁盘)')
|
|
77
|
+
console.log(t('usage'))
|
|
103
78
|
process.exit(2)
|
|
104
79
|
}
|
|
105
80
|
// 顶层错误兜底:不要把堆栈直接甩给用户
|
|
@@ -133,9 +108,9 @@ try {
|
|
|
133
108
|
opt('band', 'auto'),
|
|
134
109
|
{ page, range })
|
|
135
110
|
} else if (stage === 'grab') await stageGrab(bvid, argv[2] ?? '', { page })
|
|
136
|
-
else { console.error('
|
|
111
|
+
else { console.error(t('err.unknownStage', { stage })); process.exit(2) }
|
|
137
112
|
} catch (e) {
|
|
138
|
-
console.error(
|
|
113
|
+
console.error(t('err.fatal', { message: e.message }))
|
|
139
114
|
if (process.env.FISHEYE_DEBUG) console.error(e.stack)
|
|
140
115
|
process.exit(1)
|
|
141
116
|
}
|