Bump APP_VERSION to 1.0.0 / BUILD_NUMBER to 1; refresh README to clarify project direction and add quarantine-removal guidance for the unsigned release artifact; add USAGE.md as the end-user walkthrough; add MIT LICENSE.
7.5 KiB
OpenLess
OpenLess 是一个原生 macOS 语音输入应用:把光标放在任意输入框,按下全局快捷键说话,OpenLess 会录音、转写、轻度整理,并把结果插入当前输入位置。插入失败时会自动复制到剪贴板,尽量保证“用户说过的话不丢”。
项目方向
OpenLess 只做一件事:把语音变成可用的书面文字,落到当前光标位置。
- 不做问答、不做任务执行、不做项目分析。
- 不做对话上下文累积,每次输入都是独立的整理请求。
- 输入语音 → 转写 → 整理 → 插入当前输入框。失败时复制到剪贴板。
- 围绕这条主路径完善体验:模式选择、词典、历史、菜单栏、首页报告。
当前状态(v1.0)
- 原生 Swift / SwiftUI / AppKit,SwiftPM 项目;macOS 15+。
- macOS 26+ 使用 Liquid Glass 效果,旧系统回退到系统 material。
- 默认是切换式录音:按一次开始,再按一次结束;录音中按
Esc取消。 - 接入火山引擎流式 ASR 和 Ark / DeepSeek 兼容 Chat Completions 进行润色。
- 4 种输出模式:原文、轻度润色、清晰结构、正式表达。
- 主窗口按「首页 / 历史记录 / 词典 / 设置」组织;菜单栏常驻;底部有微型状态胶囊。
- 词典支持作为 ASR 热词注入和润色阶段的语义判断。
下载与安装(普通用户)
到 Releases 下载 OpenLess-1.0.0.zip,解压得到 OpenLess.app,拖到 应用程序。
重要: 1.0 是开发期 ad-hoc 签名构建(未做 Apple Developer ID 签名和 notarization)。直接打开会被 Gatekeeper 拦下提示“无法验证开发者”。需要在终端中移除隔离属性:
xattr -dr com.apple.quarantine /Applications/OpenLess.app
之后就可以双击启动。首次启动需要在 系统设置 → 隐私与安全:
- 授予 OpenLess 麦克风权限。
- 授予 OpenLess 辅助功能权限。
- 退出 OpenLess 并重新打开(辅助功能授权对全局快捷键生效需要重启进程)。
- 从 Dock 打开 OpenLess 首页 → 「设置」 → 填入火山引擎 ASR 和 Ark 凭据。
完整的端用户使用步骤见 USAGE.md。
从源码构建(开发者)
# 库 / 测试构建
swift build
swift test
# 完整 .app 构建(release,ad-hoc 签名,默认重置 TCC)
./scripts/build-app.sh
# 保留已授予的 TCC 权限
RESET_TCC=0 ./scripts/build-app.sh
# 启动
open build/OpenLess.app
# 实时日志
tail -f ~/Library/Logs/OpenLess/OpenLess.log
启动参数(在 AppDelegate.runLaunchActions 处理):
open build/OpenLess.app --args --open-settings
open build/OpenLess.app --args --start-recording
凭据
凭据保存在本机 Keychain(service = com.openless.app)。开发期同时维护一份明文 JSON 兜底,用于在 Keychain 不可用时回退:
~/.openless/credentials.json # 0600,目录 0700
仓库本身不包含任何 API Key、Token 或 Endpoint 之外的私有信息。
需要配置的字段:
- 火山引擎 ASR:APP ID、Access Token、Resource ID。
- Ark 润色:API Key、Model ID、Endpoint。
提示词处理原则
OpenLess 的润色模型只做文本整理,不做问答、不做任务执行、不做项目分析。每次语音输入都会作为独立请求发送,提示词会明确告诉模型:
- 本次输入与历史对话隔离。
- 原始转写只是待整理文本。
- 即使原文里有问题或命令,也不要回答或执行。
- 只输出整理后的正文,不添加“我整理如下”等引导语。
例如用户说:“我们这个应用还有哪些功能没有完成”,正确输出应是:
我们这个应用还有哪些功能没有完成?
而不是直接替用户列出清单。
竞品文本和长期改写样例会按“原始文本 -> 目标整理结果 -> 改写规律”的方式沉淀,后续接入向量数据库后,只检索相似改写样例作为参考,不把样例当作当前对话上下文。规范见 docs/polish-reference-corpus.md,示例见 Examples/polish-reference-examples.sample.jsonl。
词典
词典用于处理用户自己的专有名词、产品名、人名和新词。当前支持:
- 手动添加正确词、分类和备注;暂不要求用户维护易错词或上下文点。
- 将启用词条作为火山 ASR
context.hotwords注入,优先在识别阶段识别正确。 - 将词典包裹后注入后期润色模型,明确告诉模型根据整句语义自动判断:如果
Cloud在当前语境下明显指向 AI 产品Claude,就修正为Claude;如果确实是在说云服务 Cloud,则保留原词。 - 从历史输出中自动学习类似
Claude、ChatGPT、OpenLess的候选正确词,后续作为 ASR 热词和后期语义判断候选。
主窗口按「首页 / 历史记录 / 词典 / 设置」组织;词典页点击“新建”会弹出独立编辑窗口,首页会展示口述时长、总字数、平均每分钟字数、估算节省时间和词典参与记录。
架构概览
SwiftPM 工作区,1 个可执行 + 8 个库。库与库之间无相互依赖,全部只依赖 OpenLessCore,由 OpenLessApp 统一在 DictationCoordinator 里编排。
OpenLessCore // Pure value types: DictationSession, PolishMode, HotkeyBinding,
// AudioConsumer protocol, RawTranscript/FinalText, errors.
OpenLessHotkey // CGEventTap-based modifier-key monitor. Requires Accessibility.
OpenLessRecorder // AVAudioEngine → 16 kHz mono Int16 PCM, 推送到 AudioConsumer.
OpenLessASR // 火山引擎 streaming ASR over WebSocket.
OpenLessPolish // Ark / Doubao chat-completions 客户端 + 模式驱动 prompts。
OpenLessInsertion // AX focused-element 优先;剪贴板 + Cmd+V 兜底;最后 copy-only。
OpenLessPersistence // CredentialsVault (Keychain), HistoryStore, DictionaryStore,
// UserPreferences。
OpenLessUI // SwiftUI 胶囊视图 + 状态枚举(不接窗口)。
OpenLessApp // AppDelegate, 菜单栏, 设置窗口, 胶囊窗口, DictationCoordinator。
录音 → 转写 → 润色 → 插入的状态机由 Sources/OpenLessApp/DictationCoordinator.swift 单一拥有,详见 CLAUDE.md。
1.0 之后的规划
下面这些功能在需求文档里有规划,但 1.0 没有发布:
- 按住说话模式(hold-to-talk):当前仅支持切换式。
- 本地 ASR:当前仅接入火山引擎云端 ASR。
- 常用片段 Snippets:尚无 UI 和触发逻辑。
- 历史增强:复制按钮、搜索、重新润色、重新插入。
- 粘贴上一条快捷键。
- 多屏定位:胶囊按当前焦点所在屏幕显示。
- Developer ID 签名 + Notarization + Sparkle 自动更新。
维护者:发布前检查
- 确认没有提交
.build/、build/、.DS_Store、~/.openless/credentials.json或临时截图。 - 保留
Resources/Brand/openless-app-icon-source.jpg、Resources/AppIcon.png、Resources/AppIcon.icns。 - 运行
./scripts/build-app.sh,确认build/OpenLess.app可启动。 - 在一台干净 macOS 机器上验证权限引导、快捷键、录音、ASR、润色、插入和剪贴板兜底。
- 用
ditto -c -k --keepParent build/OpenLess.app build/OpenLess-<version>.zip打包,确保 ad-hoc 签名和扩展属性保留。 - 正式分发前请完成 Developer ID 签名和 notarization。
许可
MIT