# OpenSay **Repository Path**: SandMo/OpenSay ## Basic Information - **Project Name**: OpenSay - **Description**: 一个开源听说软件 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-11-01 - **Last Updated**: 2026-11-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # OpenSay 免费的学生英语听说练习与模考工具。Electron + Vue 3 + TypeScript。 > 独立开源项目,与讯飞(iFLYTEK)、全真连及任何考试机构无隶属、合作或授权关系。 [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) ![Electron](https://img.shields.io/badge/Electron-45-47848F.svg?logo=electron&logoColor=white) ![Vue](https://img.shields.io/badge/Vue-3-42b883.svg?logo=vue.js&logoColor=white) ![TypeScript](https://img.shields.io/badge/TypeScript-5-3178c6.svg?logo=typescript&logoColor=white) **如果这个项目对你有帮助,欢迎点一个 [⭐ Star](https://gitee.com/SandMo/OpenSay),非常感谢 🙏** ## ✨ 作者 **砂墨** [![Bilibili](https://img.shields.io/badge/Bilibili-%E7%A0%82%E5%A2%A8-00a1d6.svg?logo=bilibili&logoColor=white)](https://space.bilibili.com/1364359571) ## 界面 | 首页 | 答题 | 报告 | | --- | --- | --- | | ![首页](docs/screenshots/home.png) | ![答题](docs/screenshots/exam.png) | ![报告](docs/screenshots/report.png) | ## 原版界面(复用) | 原版主页 | 试卷概览 | 原版答题 | 原版试音 | | --- | --- | --- | --- | | ![原版主页](docs/screenshots/legacy-main.png) | ![试卷概览](docs/screenshots/legacy-overview.png) | ![原版答题](docs/screenshots/legacy-exam.png) | ![原版试音](docs/screenshots/legacy-audition.png) | | Part B 角色扮演 | Part C 故事复述 | | --- | --- | | ![Part B](docs/screenshots/legacy-partb.png) | ![Part C](docs/screenshots/legacy-partc.png) | - 独立窗口运行 `vendor/upstream-web` 的原版构建产物 - 本地 HTTP 服务 + `shield-mock.js`,无需后端 - CEF 桥:录音、播放、文件、窗口、`stic://` 资源协议 - 示例 QTI 试卷自动生成到 `legacy-runtime/content` - 品牌文案、标题、ICP、Logo 已替换(`npm run rebrand`) - 详见 `docs/LEGACY-HOST.md` ## QTI 生成器 `src/main/qti/generator.ts` 把自有 `paper.json` 转成原版引擎可读的试卷包: - `assessmentTest.xml`(每个 section 一个 testPart) - 每个 item 的 `item.xml` - `manifest.json`(题目、分值、录音时长、音频、告警) - `read_aloud` / `role_play` / `retell` 三种题型 - 音频 provider(Legacy host 用 SAPI + lame) 自检: ```bash npm run qti:selftest ``` 示例 XML 在 `docs/examples/qti-sample/`,完整说明见 `docs/QTI-GENERATOR.md`。 ## AI 生题 | AI 生题 | AI 设置 | | --- | --- | | ![AI 生题](docs/screenshots/ai-generate.png) | ![AI 设置](docs/screenshots/ai-settings.png) | | AI 生成卷进入原版考场 | | --- | | ![AI 考场](docs/screenshots/ai-legacy.png) | - 支持任意 OpenAI 兼容接口:Base URL + API Key + 自动拉取模型 + 手动选择 - 生成朗读 / 角色扮演 / 复述三种题型 - 百度 TTS 自动合成示范音频和角色扮演问题音频 - 录音时长按音频真实时长向上取整;角色扮演回答至少保留 20 秒 - 生成 `paper.json` + QTI 包,可在原版考场直接使用 - API Key 使用系统安全存储加密,不进入普通设置文件 详见 `docs/AI-GENERATION.md`。 ## 已验证 - `npm run typecheck`:主进程 + 渲染进程通过 - `npm run build`:主进程 / preload / renderer 全部构建 - CDP 冒烟:首页、考试页路由、IPC `content.list()` 正常 - 原版主页 → 试卷概览 → 练习模式 → 原版答题页闭环 - 原版登录 → 试音 → 准备 → 答题 → 交卷(合成麦克风 + 本地 mock) - 百度 Token / ASR / TTS:应用内录音转写与 TTS 均通过 - AI 生题:mock OpenAI → 百度 TTS → QTI → 原版考场全链路通过 - 录音时长按音频向上取整:33.7s→34s、2.88s→3s、31.6s→32s - QTI 生成器自检:3 个 section / 3 个 item / 7 个 question - 原版 Part A → Part B → Part C 自然流程跑通 - 品牌替换:全量扫描无原品牌、ICP 残留 - 合成音频全链路:录音 → WAV → 保存 → 示例评分 → 报告 → 本地记录 - 打包验证:asar、`extraResources/content`、CSP 下可正常加载 - 安装包:`dist/OpenSay-0.1.0-x64.exe`(约 121.3 MB) ## 当前能力 - Electron 主进程 / preload / renderer 三层,`contextIsolation` 开启 - 内容包加载(`pack.json` + `paper.json`),zod 校验 - 自定义协议 `app-content://` / `app-media://`,支持 Range 请求 - PCM 录音(16k 单声道 WAV),适配百度 ASR - 示例评分(mock),百度 ASR/TTS 已接通并验证 - AI 生题:OpenAI 兼容模型、自动拉取模型、百度 TTS、按音频时长录音 - 百度凭据持久化:开发 `.env`、打包 `%APPDATA%/OpenSay/.env`(不入库) - 本地 JSON 存储(settings + attempts),录音按天清理 - 页面:首页 / 练习 / AI 生题 / 考试 / 报告 / 设置 / 关于 - 原版界面:独立窗口复用原版主页、试卷概览、试音、答题、交卷 ## 快速开始 ```bash npm install npm run dev ``` 如果 npm 的安全策略阻止了 Electron 安装脚本,手动补一次: ```bash node node_modules/electron/install.js ``` 常用脚本: ```bash npm run typecheck # 类型检查 npm run build # 构建到 out/ npm run build:win # 构建 Windows 安装包到 dist/ npm run rebrand # 重新执行原版构建产物去品牌 npm run qti:selftest # 生成并校验示例 QTI 包 npm run baidu:probe # 验证百度 token / ASR / TTS npm run ai:smoke # 本地 mock OpenAI + 百度 TTS 生题全链路测试 npm run mock:openai # 单独启动 mock OpenAI(可选) npm run preview # 预览构建产物 ``` > 如果项目位于 `subst` 映射盘(例如 `H:` → `F:`),`electron.vite.config.ts` > 已用 `realpathSync.native` 统一 renderer root,避免 Vite 路径不一致。 ## 目录 ``` app/ ├─ src/ │ ├─ main/ # 主进程:窗口、IPC、内容包、录音、评分、百度适配 │ ├─ preload/ # contextBridge API │ ├─ renderer/ # Vue 3 页面与样式 │ └─ shared/ # 类型与 zod schema(主/渲染共用) ├─ resources/content/ # 内置示例内容包 ├─ docs/ # 内容格式、百度接入、截图 ├─ NOTICE / UPSTREAM.md ├─ LICENSE # MIT └─ electron-builder.yml ``` ## 百度语音(可选) 复制 `.env.example` 为 `.env`: ```ini BAIDU_APP_ID=... BAIDU_API_KEY=... BAIDU_SECRET_KEY=... ``` - 未配置:示范音频用系统 `speechSynthesis`,评分为 mock - 已配置:`tts:synthesize` 走百度短文本合成,`asr:transcribe` 走 16k WAV 英语识别 - 密钥只在主进程读取;生产环境建议改由服务端代理 详见 `docs/BAIDU.md`,评分链路与厂商边界见 `docs/SCORING.md`。 ## 内容包 内置示例:`resources/content/sample/`。 用户内容目录:`%APPDATA%/opensay/content//`(打包后为 `%APPDATA%/OpenSay/content/`,以设置页显示为准)。 格式见 `docs/CONTENT.md`。当前完整支持 `read_aloud`,`role_play` / `retell` 已定义 schema,评分待接入。 ## 打包 ```powershell npm run build:win ``` 国内网络建议先设置镜像: ```powershell $env:ELECTRON_MIRROR='https://npmmirror.com/mirrors/electron/' $env:ELECTRON_BUILDER_BINARIES_MIRROR='https://npmmirror.com/mirrors/electron-builder-binaries/' npm run build:win ``` 当前未配置应用图标与代码签名,安装包使用 Electron 默认图标。 ## 已知限制 - 评分是示例实现:只用时长/节奏,**不能作为学习评价依据** - 百度 ASR 只做转写;音素级准确度、韵律需要强制对齐/GOP 或第三方 ISE - `role_play` / `retell` 在自研新 UI 中是占位页;完整流程请用原版考场 - AI 生成内容需要人工复核,尤其是答案与关键点 - 部分 OpenAI 兼容服务不支持 `/models` 或 JSON mode,可在设置页手填模型名 - 录音默认 7 天清理,暂未做“逐条删除/导出”界面 - 无自动更新、无崩溃上报、无多用户切换 - Electron 45 需要 Windows 10 及以上 ## 上游代码复用 原版**前端构建产物**已导入 `vendor/upstream-web/`,通过独立窗口复用, 来源与修改记录见 `vendor/upstream-web/UPSTREAM.md`。上游**源码快照**尚未导入; 导入时保持 `vendor/upstream/` 原样,并按 MIT 保留版权与许可声明。题库与音频单独标注来源, 存疑素材走“可替换、可下架”策略。 ## 许可证 MIT,见 `LICENSE`。第三方依赖与内容包可能使用不同许可证,以各自声明为准。