Repository navigation
FastETS v1.0.6 — 完成度 75% 的真正根因修好了
易听说(讯飞 E听说 / ets100)作业自动化助手 · Python + pywebview · macOS / Windows
⚠️ 免责声明 / Disclaimer(请先读这一段)
本软件仅供学习、研究与技术原理探究使用。
-
仅用于学习原理
FastETS 是一个技术研究项目,用于学习 E听说(讯飞)客户端与云端接口的通信原理、语音合成流程与自动化编排方法。任何使用者仅可将本软件用于学习原理,并须在使用结束后 24 小时内删除本软件及其全部副本(包括源码、编译产物、缓存、录制的音频与克隆音色数据)。 -
滥用与我无关
使用本软件造成的任何后果,包括但不限于账号被封禁、成绩异常、学校处罚、学术诚信问题或第三方索赔,均由使用者自行承担,与本软件的作者、贡献者、维护者及发布平台完全无关。本软件作者不对任何形式的滥用行为负责,也不为任何违规使用提供技术支持。 -
必须保证正常练习
使用者必须保证自己仍然进行正常、真实的英语练习。本软件不能、也不应替代你真实的听说训练。请在完成作业后自行对照原文复述与订正,把工具当作「参考答案生成器」与「朗读练习器」,而不是「刷分器」。 -
账号与数据
你必须拥有科大讯飞 E听说平台的合法、正版使用权限。本软件不会收集、上传或共享你的账号数据到任何第三方服务器;账号口令、Token 与录制的音频仅保存在你本机的应用数据目录中。请自行承担使用本软件所带来的账号安全风险(包括但不限于与官方客户端异地登录导致的顶号)。 -
声音与授权
你只克隆你自己或已获得明确授权的声音。声音克隆得到的音色数据仅用于你本人的练习,请勿用于冒充他人。
首次启动本程序时同样会弹出上述免责声明,必须阅读并同意后才能使用。
下载
| 文件 | 平台 |
|---|---|
FastETS-macOS-arm64.zip |
macOS Apple Silicon(M1/M2/M3/M4) |
FastETS-macOS-x64.zip |
macOS Intel |
FastETS-Windows-x64.zip |
Windows 64 位 |
ffmpeg 与 Speex 编码器已随包附带,无需另外安装。macOS 解压后得到 FastETS.app(首次运行请在「系统设置 → 隐私与安全性」中允许打开);Windows 解压后直接运行 FastETS.exe。
快速上手
- 首次启动会强制显示免责声明,阅读并同意。
- 「账号」页 → 填手机号与密码登录(有多个年级/班级时会让你选)。
- 「声音」页 → 选一种声音来源:
- 直接使用默认声音(最省事):填一个音色 ID,或点「获取音色列表」从服务商的系统音色里挑一个,不需要克隆;
- 克隆我的声音:自行录好中文与英文样本并「导入音频文件」→ 「克隆声音」。
⚠️ 程序不再提供麦克风录制,请用系统录音工具录好再导入;- MiniMax 需要在「设置」页填 API Key,且账号套餐必须开通声音克隆(否则会明确提示
your current token plan not support model, voice_clone); - 也可以改用 OpenAI 兼容端点(含本地 GPT-SoVITS / CosyVoice 等)。
- 完全免密钥:选
edge(Edge TTS)或 macOS 上的macos(系统朗读),不需要任何 API Key;主服务失败会自动切到备用源。
- 「设置」页:先保持「演练模式」勾选,确认流程无误后再取消。
- 「复述/表达答案」选择
第一个/随机/手动(手动会在朗读时弹出答案列表)。
- 「复述/表达答案」选择
- 「作业」页 → 「拉取作业」→ 勾选 → 「开始完成」。
- 作业状态选「全部状态」才能看到已完成、已达标的作业。
- 任何作业都可以点「重做」重新提交。
v1.0.6 变更内容
本版是 FastETS 的第一个正式版(不再是 pre-release)。
完成度卡在 75% 的真正原因找到了:发出去的 order 是整卷的连续题号,而服务端要的是「这道题在它自己那个资源包里是第几题」。
服务端把一次作答记成 资源包(entity) + 包内题号(order) 一条记录,order 每个资源包都要从 1 重新开始。FastETS 之前把 order 发成了整份卷子里的连续题号(而且是按大题名累加的),于是:
| 资源包 | 大题 | 题数 | 之前发的 order | 服务端期望 | 命中 |
|---|---|---|---|---|---|
| 665159 | 朗读词组 | 1 | 1 | 1 | ✓ |
| 665160 | 朗读词组 | 1 | 2 | 1 | ✗ |
| 665161 | 朗读词组 | 1 | 3 | 1 | ✗ |
| 665162 | 朗读句子 | 1 | 1 | 1 | ✓ |
| 665163 | 朗读句子 | 1 | 2 | 1 | ✗ |
| 665164 | 交际应答 | 5 | 1–5 | 1–5 | ✓✓✓✓✓ |
| 665165 | 复述 | 1 | 1 | 1 | ✓ |
| 665166 | 表达 | 1 | 1 | 1 | ✓ |
命中 9/12 = 75%——和 2026-10-25 三次真实提交(09:08 / 19:42 / 20:06)测到的完成度一模一样:那三个包的答案永远对不上,重做多少次都没用,官方 App 里也就永远是「未完成」。
- 修法:界面上的卷子序号和发出去的
order分开算。order现在取包内题号(资源包自带的xh/xth,没有就按顺序 1、2、3…),每个资源包从 1 重新开始。按同一份作业离线回放,12 条记录(entity, order)两两不同 → 命中 12/12 = 100%。 - 顺带纠正 v1.0.4:那一版把
serial_id当成「包内第几条」来递增,对完成度没有任何影响(v1.0.4 实测仍是 75%)。serial_id的真正含义是「这道题里的第几段录音」(逐句跟读一题分句提交,每句 0、1、2…),已改回。 - 怎么验证:升级后重做一次这份作业,看官方 App 里的完成度。如果还是 75%,把
fastets.log里ETS params /m/audio/sync-v2那几行发我——日志里能直接看到每次提交的entity_id/order,能一眼看出还有哪条对不上。
v1.0.5 变更内容
- 没见过的题型不再「整包只记一条」:程序认识的题型只有 7 种(
collector.read/picture/dialogue/role/3q5a/choose/fill),其余结构(比如某些课后作业、单词作业)以前会整个资源包当成一道题提交,服务端只落库 1 条,完成度自然上不去。现在只要资源包里带一份条目列表(question/sublist/exam_info/items/list/word/words),就拆成「一个条目一道题」;条目里的答案列表按备选答案处理,朗读只读其中一份;题号优先取seq/xh/xth/num/no/index。已知题型完全不受影响。 - 遇到新题型会留下线索:日志里会打一行
未识别的题型结构 <type>(<大题名>),已按通用规则拆成 N 道题。把这行发给我,就能照着真实结构写精确解析,而不是一直靠通用规则猜。 - 说明:v1.0.4 里提到的
collector.repeat_essay/collector.repeat_dialogue/collector.word这几个类型名没有可核实的出处(本地缓存、三个公开实现、公开检索里都查不到),v1.0.5 因此改成按数据结构兜底,而不是按名字硬编码。
v1.0.4 变更内容
- 完成度卡在 75% 的根因修好了:服务端把一次作答存成 「资源包 + 包内第几条」 一条记录。旧实现把
serial_id写成「这道题的第几句」,于是一个资源包里的 5 道交际应答题全部挤在0/1两个编号上,服务端只落库 2 条——12 道题只记下 9 条,完成度正好 75%,官方 App 里始终显示「未完成」。现在每个资源包各有一个编号游标,包内每交一条录音就 +1、换包归零,所以同一包里的每道题都有独立记录(实测作业的交际应答包 5 道题 →serial_id0/1/2/3/4)。⚠️ v1.0.6 实测:这一版的改动对完成度没有影响,真正的原因是order发成了整卷题号,见 v1.0.6。 - 交际应答按「一份备选答案」朗读:这类题目的
std是若干份备选回答(实测一份作业里有 36~45 份),不是一段要照读的长文本。现在它们和其它多答案题型一样进入候选池:朗读时按你在设置里选的方式(第一个 / 随机 / 手动)只读其中一份,每题只录一条音;「解析」预览里也逐条列出所有备选答案,不再用斜杠挤成一行。 - 日志不再记录明文密码:以前 debug 日志会把
/user/login的请求参数整个写进fastets.log,里面包含你的明文密码。现在password/token/code等字段在写日志前一律掩码。 - 钥匙串读不到时的提示更直白:程序文件被替换后旧钥匙串条目会读不出来(OSStatus -25293)。这时账号页会直接说明「请重新登录一次以重建」,日志里仍保留 ASCII 错误码方便排查。
v1.0.3 变更内容
上一版说的「ETS 评分服务异常」其实是误判:真实原因已经查到并修好了。
- 「所有题都失败」真正的根因修好了:
m/audio/sync-v2里要带的resource_id不是固定的 55,而是这份作业自己的资源 id(来自作业列表顶层的resource_id,实测(新教材)8年级(上)U3A是240)。发错 id 时,附件全都上传成功、sync-v2也照常发出,但服务端按 id 去找评测服务配置时找不到,于是每一题都返回远程获取ets服务失败,作业在官方 App 里始终显示未完成——和你手机上显示的一模一样。现在这个 id 会从作业列表一路透传到每一道题,真实账号实测 12/12 全部提交成功,0 失败。 - 答题耗时不再为 0:随包附带的 ffmpeg 没有 ffprobe,原来探测音频时长总是静默失败返回 0,于是每条提交里的
use_time都是 0。改成解析 ffmpeg 自己的输出后,use_time会带上这道题的真实秒数。 - 「停止」按钮现在真的停得下来:以前按下停止只是把界面上的状态改成「已取消」,后台任务照跑不误——Pacer 的停止标志和任务的取消标志是两套,从没接上。现在两者共用同一个事件标志,等待中的睡眠会被立刻唤醒,任务状态也不会再被改回「完成」。
- Token 过期自动续期:登录拿到的 token 只能用一段时间,过期后所有接口都报「ets的token过期」。现在遇到这种情况会自动用记住的密码重新登录一次并重放请求,不用手动重登。
- 账号密码搬进系统凭据库:
- macOS:新建一个 FastETS 专属钥匙串(
~/Library/Application Support/FastETS/fastets.keychain-db),条目的访问控制列表只信任 FastETS 这一个可执行文件——别的程序(包括命令行security find-generic-password)读它会被直接拒绝,就算拿到钥匙串口令也不行,只有系统管理员另行授权才可能拿到。程序全程关闭钥匙串交互,不会弹出任何对话框。 - Windows:用 DPAPI(
CryptProtectData)加密,只对当前 Windows 用户可解。 - 旧版本留在
state.json里的明文密码会在启动时自动迁移进凭据库,并从文件里抹掉;「退出登录」会连凭据库里的条目一起删掉。 - 账号页会显示当前凭据存在哪儿。
- 说明:GitHub 的 CI 沙箱里钥匙串不可用,自检会打印原因并跳过这一项(不影响构建);本机实测(ad-hoc 签名的 App 二进制自建自读)通过。
- macOS:新建一个 FastETS 专属钥匙串(
v1.0.2 变更内容
- 「远程获取ets服务失败」不再直接判为整题失败:v1.0.2 里这类错误会自动重试(默认 2 次,间隔 4 秒),仍失败则记为「已提交但 ETS 评分未确认」,不计入失败。注意:v1.0.3 已查明真正的根因是
resource_id填错(见上一节),修好之后这个错误本身就不会再出现了;这里的重试与「未确认」状态保留下来,作为真正偶发的服务端故障的兜底。 - 复述 / 表达可以挑示例答案来读:这类题的题干本身不是要朗读的内容,程序现在会从作业资源里解析出全部示例答案(实测一份作业里复述 6 份、表达 10 份),朗读时按你设置的方式挑一份:第一个 / 随机 / 手动。手动模式下程序会弹出答案列表让你点一份,选中后立刻朗读。
- macOS 自带朗读可用:新增
macos语音源,直接调用系统/usr/bin/say(可指定系统音色与语速),不需要任何 API Key。主语音服务失败时会自动改用它作为备用(默认开启),Windows 不提供此方式。 - Edge TTS 免密钥语音:新增
edge语音源,edge-tts已进依赖并打进安装包,同样不需要 API Key,可与 macOS 系统朗读互相兜底。
v1.0.1 修复内容
- 提交作业彻底修好:上一版每一道题都会失败,根因是 ffmpeg 6.0 起删除了
libspeex编码器,随包附带的 ffmpeg 根本产不出 ETS100 需要的spx附件。
现在 FastETS 自带一个静态链接 libspeex 1.2.1 的小工具(speexenc_raw),产出的帧与 ffmpeg 5.x 的libspeex逐字节相同:同一份 libspeex 源码、同样的quality=8/ CBR /complexity=3/ 每帧 320 采样,末帧同样补零,编译时关闭自动向量化以对齐 ffmpeg 的浮点结果。实测一段 17 秒录音(852 帧 / 59640 字节)与 ffmpeg 5.1 的 sha256 完全一致;自检里也有一条test_speex_matches_ffmpeg,本机存在带libspeex的 ffmpeg 时会自动逐字节比对。
万一该工具缺失,提交不再中断:会省略 spx 附件,mp3 与评测 XML 照常上传,分数不受影响,并在日志里给出明确提示。 - Windows 上的 spx 附件修好:Windows 的 C 运行时默认把 stdin/stdout 当文本流,PCM 里出现
0x1A会被当成文件结束、输出里的0x0A会被改写成0x0D 0x0A,结果 Windows 版产出的spx是空的或被截断。内置编码器现在会先切到二进制模式;自检里也把「有编码器却编码失败」从跳过改成报错,避免再被掩盖。 - 日志不再刷
[object Object]:进度事件以前把整个对象塞进了 message,现在统一归一化成文本,并带上阶段标签(下载 / 合成 / 上传 / 回传 / 克隆 …)。 - 声音克隆不再「没有音频数据」:取消麦克风录制,改为导入音频文件;导入后立刻探测并显示格式、时长、采样率与平均音量,文件太小、无法识别、录到静音都会给出具体原因;上游报错会带上 MiniMax 的
trace_id与原始响应。 - 可以直接用默认声音:新增「直接使用默认声音」模式,不必克隆即可开工;MiniMax 可拉取 300+ 个系统音色供挑选。克隆失败或尚未克隆时会自动回落到默认音色,不会卡住流程。
- 新的应用图标:macOS 与 Windows 都换上了新的渐变波形图标。
本版特性
- 复刻 ETS100 签名协议:登录 / 设备绑定 / 畅言登录 / 账号列表 / 作业列表 / OSS 凭证 / 成绩回传。
- 题型全覆盖:听选信息、逐句跟读、朗读、短文朗读、回答问题、听后选择、听后记录、信息转述,以及整卷模拟考试。
- 逐句跟读按句切分,逐句合成与回传。
- 声音:可克隆自己的音色,也可直接使用服务商的默认音色。
- 拟人节奏:按朗读词数推算等待、随机抖动、大题间隔,降低被限流的概率。
- 重做:不达标、进行中、已达标均可重做。
- 演练模式:只上传音频、不提交成绩。
已知限制
- 官方接口若调整版本号、签名规则或响应结构,需要同步更新。
- 云端登录可能让官方客户端被顶号,建议先在工具里完成操作,再打开官方 App。
- 声音克隆需要服务商账号具备相应权限(MiniMax 需完成实名并在套餐中开通声音克隆;未开通时程序会明确报错,可改用默认音色)。
- 端到端真实提交已在真实账号上跑通:v1.0.3 用真实账号提交了一份完整作业,12/12 全部成功,服务端记录了得分(作业分数 5.7/10)。当时完成度只有 75%,v1.0.6 已定位并修复其根因(
order必须是包内题号,见上一节),修复后的完成度需要你用新版本再跑一次来确认。 - macOS 系统朗读仅在 macOS 可用,Windows 请用
edge或其它服务。 - macOS 凭据存放在 FastETS 专属钥匙串里,条目只信任 FastETS 可执行文件;重新构建或移动应用程序后可执行文件路径会变,旧条目将读不到(此时重新登录一次即可,程序会重建条目)。
许可
MIT © FastETS contributors
构建与测试由 GitHub Actions 自动完成:Ubuntu / macOS / Windows 三套自检全部通过(CI run 40192628926)之后才发布本次正式版。