OCS Firefox AbortError 修复记录:学习通跳转下一节后不自动播放
能跳转,但下一节就是不播
最近用 Firefox 挂学习通,OCS 网课助手又出了个让人摸不着头脑的问题。
一节视频放完,OCS 会正常跳到下一节,说明自动跳转没坏。但新视频就是停在那里不播放,尤其是在标签页放到后台的时候。更神奇的是,我只要回到页面,手动按一下播放按钮,视频马上就能正常播放。
当时用的是 Firefox 157.0、Tampermonkey 5.5.0、OCS 5.1.0,后两者已经更新到最新版。我先怀疑 Firefox 的后台标签页行为,又排查了 Global Speed(已经对学习通禁用),调整相关设置后仍然没解决。
既然手动点播放立刻有效,那就先别折腾自动跳转了,应该去看看 OCS 是怎么启动下一节视频的。
控制台里的 AbortError
打开 Firefox 开发者工具(F12),在下一节视频尝试自动播放时,控制台里能看到:
DOMException: The fetching process for the media resource was aborted by the user agent at the user's request.
沿调用栈查到 OCS 启动视频的位置。网页里的 HTMLMediaElement.play() 会返回一个 Promise;如果这次媒体加载或播放请求被中断,就可能得到 AbortError。它并不意味着视频以后都不能播放,事实上我手动点一下就能播。
另外,这个错误和 NotAllowedError 不是一回事。后者通常是浏览器不允许自动播放,重试多少次也不该拿来绕过浏览器的权限判断。
本机测试下来,遇到这种临时 AbortError 时,隔一会儿重试 play(),下一节就能继续自动播放。至于为什么 Firefox 会中断那一次请求,是学习通切换视频源的时序问题,还是后台加载行为导致的,我还没法确定。
顺手给 OCS 提了个 PR
先用一个临时 Tampermonkey 脚本验证了重试思路,确认在我这台机器上有效。随后把修复写进 OCS 的学习通播放流程,提交到了上游:
ocsjs/ocsjs PR #345:fix(cx): retry transient AbortError when starting next chapter video
改动主要是:只有 play() 抛出 AbortError 才重试,延迟依次为 700、1200、2000、3500 毫秒,最多重试四次。如果视频已经开始播放、播放结束,或者播放器节点被移除,就不再继续尝试。还处理了暂停事件与播放请求同时触发的问题,避免几个请求互相打架。
对于 NotAllowedError 等其他错误,仍然交给原来的错误处理逻辑,没有修改网站请求或学习进度的处理。
PR 还加了六项自动化测试,包括成功播放、重试恢复、重试耗尽、禁止自动播放、播放器移除和其他请求已成功启动等情况。测试通过了,不过PR 的正式实现还没有在完整的真实课程跳转中做过人工验收;我实际在学习通验证有效的是前面提到的临时脚本。
截至 2026 年 10 月 11 日写这篇记录时,PR #345 还没合并。
等不及合并的话,先装临时脚本
如果你也遇到「能自动跳到下一节,但视频不播放;手动点一下却正常」的问题,可以先试试我用过的临时补丁:
OCS Firefox AbortError 临时修复脚本(.user.js)
Firefox 装好并启用 Tampermonkey 后,直接打开这个链接,通常就能进入脚本安装页面。如果只显示 JS 源码,就打开 Tampermonkey 管理面板,新建脚本,把链接里的代码复制进去保存。
然后刷新学习通课程页面,保留原来的 OCS 脚本,测试下一节能否自动播放。不需要自己编译 OCS,也不用关掉 Firefox 的自动播放限制。
这个脚本只在 *.chaoxing.com 上运行,等网页或 OCS 调用视频 play() 并碰到临时 AbortError 后才重试,不会绕过 NotAllowedError,也不会改动课程进度。
不过它的实现方式是修改页面里的 HTMLMediaElement.prototype.play,影响范围比上游 PR 更大,适合拿来临时救急。等 PR 合并、对应版本正式发布并确认已经修好后,就把这个临时脚本关掉或删掉。
如果装了仍没用,先检查 Tampermonkey 有没有在学习通页面启用脚本,再打开 F12 看具体报错。如果现在报的是 NotAllowedError,那就不是这次要修的加载中断问题了。
AI 辅助说明:这次排障分析、临时补丁、PR 代码与测试,以及本文的整理,都使用了 ChatGPT 辅助。我提供了故障现象和复现环境,在自己的 Firefox 上验证临时修复效果,并通过自己的 GitHub 账号提交了 PR。错误的底层触发原因尚未完全查明。