@pls-compile-owo/fisheye 0.8.1 → 0.8.3
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 +17 -0
- package/lib/danmaku.mjs +8 -1
- package/package.json +1 -1
- package/test/golden/ad-truth/BV1WhaA6hE7s.json +14425 -0
- package/test/golden/fixtures/BV1kr4y1x7DU.json +3 -2
- package/test/golden.test.mjs +29 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
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.8.3] - 2026-11-14
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- 广告段检测:片头/片尾 60s 内的低置信度段不再判为广告(片头低弹幕是正常现象,首次人工真值样本 BV1WhaA6hE7s 暴露的误报)。
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- 广告段真值样本(`test/golden/ad-truth/`):人工标注广告段 + golden 测试验证覆盖率 ≥80% 且无片头片尾误报。
|
|
14
|
+
|
|
15
|
+
## [0.8.2] - 2026-11-14
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **广告段检测在稀疏弹幕视频上误报**:弹幕密度低于 0.2 条/秒时密度统计不可靠(艺术短片《利马》127 条/856s 被误标 3 段「低互动段」),改为直接跳过检测(宁漏勿错)。
|
|
20
|
+
- golden fixture 补充人工真值标注(利马三段确认非广告)。
|
|
21
|
+
|
|
5
22
|
## [0.8.1] - 2026-11-14
|
|
6
23
|
|
|
7
24
|
### Added
|
package/lib/danmaku.mjs
CHANGED
|
@@ -6,6 +6,10 @@ export const AD_SEGMENT_SIGNAL = /金主|恰饭|商单|硬广|软广|赞助|推
|
|
|
6
6
|
|
|
7
7
|
export function detectAdSegments(danmaku, duration, bucketSec = 30, stepSec = 10) {
|
|
8
8
|
if (!danmaku?.length || duration < 120) return []
|
|
9
|
+
// 弹幕太稀疏(如艺术短片 127 条 / 856s ≈ 0.15 条/s)时密度统计不可靠:
|
|
10
|
+
// 中位数本身极低,「低于中位数 45%」的段落只会是「观众不爱发弹幕的正常段落」。
|
|
11
|
+
// 低于 0.2 条/秒直接不判广告(宁漏勿错,低互动段标签也会误导)。
|
|
12
|
+
if (danmaku.length / duration < 0.2) return []
|
|
9
13
|
const dens = []
|
|
10
14
|
for (let s = 0; s + bucketSec <= duration; s += stepSec) {
|
|
11
15
|
let n = 0
|
|
@@ -27,7 +31,7 @@ export function detectAdSegments(danmaku, duration, bucketSec = 30, stepSec = 10
|
|
|
27
31
|
if (!long.length) return []
|
|
28
32
|
|
|
29
33
|
const hits = danmaku.filter((d) => AD_SEGMENT_SIGNAL.test(d.text))
|
|
30
|
-
|
|
34
|
+
const out = long.map((sp) => {
|
|
31
35
|
const near = hits.filter((h) => h.t >= sp.from - 20 && h.t <= sp.to + 20)
|
|
32
36
|
// dens 是「30s 窗、10s 步长」的滑窗,同一条弹幕会被相邻 3 个桶各计一次。
|
|
33
37
|
// 分母必须用「实际桶数」而不是 (时长/bucketSec),否则 ratio 虚高约 3 倍
|
|
@@ -45,6 +49,9 @@ export function detectAdSegments(danmaku, duration, bucketSec = 30, stepSec = 10
|
|
|
45
49
|
keywords: near.slice(0, 3).map((h) => h.text),
|
|
46
50
|
}
|
|
47
51
|
})
|
|
52
|
+
// 片头/片尾 60s 内的「低置信度」段丢弃:开头结尾弹幕本来就少,不是广告信号。
|
|
53
|
+
// 高置信度(有广告关键词)不受此限——片头口播广告仍是广告。
|
|
54
|
+
return out.filter((s) => s.confidence === 'high' || (s.from >= 60 && s.to <= duration - 60))
|
|
48
55
|
}
|
|
49
56
|
|
|
50
57
|
// 按时间桶聚合,找「观众最激动」的时段。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pls-compile-owo/fisheye",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Token-budget-aware video understanding for AI agents: official subtitles -> burned-in subtitle band -> danmaku highlights -> adaptive keyframe grids -> targeted refine.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|