版本:SPlayer Next v1.1.0(Windows 11 x64,安装版),已登录网易云账号,开着「启用听歌打卡」,「NCM 听歌打卡方式」选「原版日志接口」。dev 分支(4c60335d09)同样的写法,见下。
现象:播放模式设成「单曲循环」,一首网易云的歌连着放了约 30 分钟(时长 3:56,约 7 遍),网易云手机客户端的听歌排行里这首歌只多了 1 次。
原因(读代码得到,并把两段原样切出来跑过):
- 单曲循环时,渲染层在
ended 之后只做 seek(0) 加 play(),不重新 load:dev 分支 src/core/player/events.ts 第 52–55 行 finishCurrentTrack。
- 主进程收到
ended 时调 neteaseScrobble.onEnded(),里面 progress.end() 清掉了计时载荷,并把 current 置为 null:dev 分支 electron/main/services/neteaseScrobble.ts 第 120–125 行。
- 之后没有
load,onTrackLoaded 不会再被调,载荷一直是空的:playProgress 的 maybeFire 在 payload == null 时直接返回;onPosition 里「跳回阈值之前就 rearm」那一段要求 current 不为空,也进不去。所以单曲循环从第二遍起一次都不报。
列表循环不受影响:每一遍都经过 nextTrack → loadTrack → player:load → onTrackLoaded。
复现:从 v1.1.0 安装包的 out/main/index.js 原样取出 createPlayProgress(第 2925–2992 行)和网易云打卡那一段(第 5702–5773 行),把 Date.now 换成假时钟、callNetease 换成计数,模拟一首 236 秒的歌每秒一个 position 事件、放完发 ended:
| 模式 |
放了几遍 |
上报几次 |
上报时刻(秒) |
单曲循环(ended 后不重新 load,只重新 play) |
8 |
1 |
118 |
列表循环(每遍都 load) |
8 |
8 |
118, 355, 592, 829, 1066, 1303, 1540, 1777 |
同样受影响的:Last.fm 的 scrobble 走同一个 createPlayProgress,它的 onEnded 也把 current 置空(v1.1.0 out/main/index.js 第 3026–3030 行),单曲循环下应该也只报第一遍(这一条只读了代码,没跑)。
建议:单曲循环重新开始播放时,让主进程把这一轮当作重新加载。比如渲染层单曲循环那条路走一次轻量的「重新开始」IPC,主进程据此对当前曲目重新 onTrackLoaded;或者 onEnded 先留住上一首的载荷,紧接着同一曲目从 0 开始播放时 load 回去。
版本:SPlayer Next v1.1.0(Windows 11 x64,安装版),已登录网易云账号,开着「启用听歌打卡」,「NCM 听歌打卡方式」选「原版日志接口」。dev 分支(
4c60335d09)同样的写法,见下。现象:播放模式设成「单曲循环」,一首网易云的歌连着放了约 30 分钟(时长 3:56,约 7 遍),网易云手机客户端的听歌排行里这首歌只多了 1 次。
原因(读代码得到,并把两段原样切出来跑过):
ended之后只做seek(0)加play(),不重新load:dev 分支src/core/player/events.ts第 52–55 行finishCurrentTrack。ended时调neteaseScrobble.onEnded(),里面progress.end()清掉了计时载荷,并把current置为null:dev 分支electron/main/services/neteaseScrobble.ts第 120–125 行。load,onTrackLoaded不会再被调,载荷一直是空的:playProgress的maybeFire在payload == null时直接返回;onPosition里「跳回阈值之前就rearm」那一段要求current不为空,也进不去。所以单曲循环从第二遍起一次都不报。列表循环不受影响:每一遍都经过
nextTrack→loadTrack→player:load→onTrackLoaded。复现:从 v1.1.0 安装包的
out/main/index.js原样取出createPlayProgress(第 2925–2992 行)和网易云打卡那一段(第 5702–5773 行),把Date.now换成假时钟、callNetease换成计数,模拟一首 236 秒的歌每秒一个position事件、放完发ended:ended后不重新load,只重新play)load)同样受影响的:Last.fm 的 scrobble 走同一个
createPlayProgress,它的onEnded也把current置空(v1.1.0out/main/index.js第 3026–3030 行),单曲循环下应该也只报第一遍(这一条只读了代码,没跑)。建议:单曲循环重新开始播放时,让主进程把这一轮当作重新加载。比如渲染层单曲循环那条路走一次轻量的「重新开始」IPC,主进程据此对当前曲目重新
onTrackLoaded;或者onEnded先留住上一首的载荷,紧接着同一曲目从 0 开始播放时load回去。