你可能以为版本号从 2024 增加到 2025 表示这是一个很大的更新。实际上并非如此。版本号 X.Y.Z 目前仅表示它是 X 年 Y 月的第 Z 个版本。
新功能
pakku 2025.2.1 主要更新了用户脚本功能,现在可以写异步的回调函数了。
异步回调函数可以用来处理用户脚本的回调函数之间的依赖关系:假设一个 tweak_before_pakku
回调函数的执行过程依赖于弹幕的元信息(需要通过 tweak_proto_view
回调函数读取),就可以让前者延迟返回,直到后者被调用。异步回调函数也可以用来实现其他目的,比如请求网络 API 等等。
下面的例子是一个删除所有投票弹幕及其结果的用户脚本:
let votes_resolve = null;
let votes_promise = new Promise(resolve => votes_resolve = resolve);
tweak_proto_view(view => {
let votes_res = view.commandDms.filter(d => d.command === '#VOTE#').map(d => {
let extra = JSON.parse(d.extra);
return {
time_begin_ms: d.stime,
time_end_ms: d.stime + extra.duration + 2000,
option_texts: extra.options.map(o => o.desc),
};
});
votes_resolve(votes_res);
view.commandDms = view.commandDms.filter(d => d.command !== '#VOTE#');
});
tweak_before_pakku(async chunk => {
let votes = await votes_promise;
chunk.objs = chunk.objs.filter(d => {
for(let v of votes) {
if(
d.time_ms >= v.time_begin_ms &&
d.time_ms <= v.time_end_ms &&
v.option_texts.includes(d.content)
)
return false;
}
return true;
});
});
需要注意,这个例子主要用来炫技,实际使用时更建议根据弹幕 Protobuf 新增的 dmFrom
字段来判断投票弹幕:
tweak_proto_view(view=>{
view.commandDms = view.commandDms.filter(d => d.command !== '#VOTE#');
});
tweak_before_pakku(chunk=>{
chunk.objs = chunk.objs.filter(
dm => dm.extra.proto_dmfrom !== 2 // DmFromType.DmFromCmd
);
});
另外,回调函数现在新增了第二个参数 env
。它表示执行时的一些环境信息,包括当前视频(env.ingress
)、当前弹幕分片的编号(env.segidx
)和 pakku 设置(env.config
)。
上述更新都是向前兼容的,所以应该不需要修改现有的脚本(如果并非异步而且没有接收 env
参数的话)。更新后的具体用法参见 用户脚本文档。
其他改进
- (2025.2.1)用户脚本不再排队执行,以减少主线程被播放器阻塞导致的时间开销
- (2025.2.1)在用户脚本运行完毕后再销毁 Web Worker(#298)
- (2025.2.1)用户脚本编辑器的类型速查加入了语法高亮
- (2014.12.2)改进了自动弹幕优选功能处理弹幕权重的计算逻辑
- (2014.12.2)WebAssembly 程序提前释放不再需要的弹幕信息,以减少内存占用
- (2014.12.2)在合并弹幕时避免复制弹幕信息,以减少内存占用和时间开销
Bug 修复
- (2025.2.1)用户脚本涉及 tweak_proto_view 时 ArrayBuffer 大小可能出错
- (2025.2.1)当弹幕分块数量估计不准确时,视频末尾的空白分块没有返回给播放器,导致弹幕列表不显示
- (2014.12.2)播放器更新后,弹幕信息显示框无法识别 UP 主弹幕
- (2014.12.2)WebAssembly 程序出错时只在控制台提示而不抛出异常