chore: 发布 0.0.7 - 更新主界面截图、新增微信反馈群、精简配置文档
This commit is contained in:
1 parent
2def8cdaf9
commit
241d83762c
14 files changed
+56
-196
No files matched your search
@@ -170,7 +170,7 @@ SayIt/
|
||||
| 语音识别 | Qwen3-ASR + vLLM / 豆包 ASR / 千问 ASR / sherpa-onnx |
|
||||
| AI 润色 | DeepSeek / 通义千问 / Azure OpenAI / Ollama |
|
||||
| 部署 | Docker Compose、NVIDIA Container Toolkit |
|
||||
| 开发 | 整个项目使用 Claude Opus 4.6 开发 |
|
||||
| 开发 | 整个项目使用 Claude Opus 开发 |
|
||||
|
||||
## 开发
|
||||
|
||||
@@ -195,6 +195,18 @@ cd backend && uvicorn app.main:app --port 8000
|
||||
|
||||
前置要求:Python 3.10+、NVIDIA GPU + CUDA
|
||||
|
||||
## 交流反馈
|
||||
|
||||
有任何问题、建议或想法,欢迎扫码加入用户反馈微信群,一起交流:
|
||||
|
||||
<div align="center">
|
||||
|
||||
<img src="docs/images/readme/SayIt%20用户反馈微信群.jpg" width="240" alt="SayIt 用户反馈微信群">
|
||||
|
||||
*微信扫码加入 SayIt 用户反馈群*
|
||||
|
||||
</div>
|
||||
|
||||
## 贡献
|
||||
|
||||
欢迎提交 Bug 报告和功能建议!请阅读 [贡献指南](./CONTRIBUTING.md)。
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sayit-tauri",
|
||||
"version": "0.0.5",
|
||||
"version": "0.0.7",
|
||||
"description": "SayIt - Voice to Text Desktop App (Tauri)",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
Generated
+1
-1
@@ -3763,7 +3763,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sayit"
|
||||
version = "0.0.5"
|
||||
version = "0.0.7"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bzip2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "sayit"
|
||||
version = "0.0.5"
|
||||
version = "0.0.7"
|
||||
authors = ["Liu Qianglong", "Claude"]
|
||||
edition = "2021"
|
||||
|
||||
|
||||
@@ -246,7 +246,11 @@ pub fn check_for_updates() -> Result<Value, String> {
|
||||
/// 下载更新安装包到临时目录
|
||||
#[tauri::command]
|
||||
pub async fn download_update(url: String) -> Result<String, String> {
|
||||
let client = reqwest::Client::new();
|
||||
// 必须带 User-Agent:生产环境 AWS WAF 的 NoUserAgent_HEADER 规则会拦截无 UA 的请求(403)
|
||||
let client = reqwest::Client::builder()
|
||||
.user_agent(concat!("SayIt/", env!("CARGO_PKG_VERSION")))
|
||||
.build()
|
||||
.map_err(|e| format!("初始化下载客户端失败: {}", e))?;
|
||||
let resp = client
|
||||
.get(&url)
|
||||
.timeout(std::time::Duration::from_secs(300))
|
||||
|
||||
@@ -178,11 +178,21 @@ fn main() {
|
||||
hook.start(app.handle(), &ptt_str, &hf_str);
|
||||
|
||||
// 设置窗口图标(用 ICO 文件,包含多尺寸帧,Windows 自动选最合适的)
|
||||
// 并根据启动方式决定是否显示主窗口:
|
||||
// 开机自启会带 --minimized 参数 → 保持隐藏,静默停留在托盘
|
||||
// 用户手动打开则正常显示(窗口配置为 visible:false,需显式 show)
|
||||
let launched_minimized = std::env::args().any(|arg| arg == "--minimized");
|
||||
if let Some(main_window) = app.get_webview_window("main") {
|
||||
let ico_bytes = include_bytes!("../icons/icon.ico");
|
||||
if let Ok(icon) = tauri::image::Image::from_bytes(ico_bytes) {
|
||||
let _ = main_window.set_icon(icon);
|
||||
}
|
||||
if !launched_minimized {
|
||||
let _ = main_window.show();
|
||||
let _ = main_window.set_focus();
|
||||
} else {
|
||||
log::info!("Launched with --minimized, staying hidden in tray");
|
||||
}
|
||||
}
|
||||
|
||||
// 系统托盘图标
|
||||
@@ -261,14 +271,26 @@ fn main() {
|
||||
{
|
||||
use tauri_plugin_autostart::ManagerExt;
|
||||
let storage: tauri::State<Storage> = app.state();
|
||||
let autostart = app.autolaunch();
|
||||
let already_set = storage.get("autoLaunchInitialized", None);
|
||||
if already_set.is_null() || already_set.as_str() == Some("") {
|
||||
// 首次运行,注册开机自启并标记
|
||||
let autostart = app.autolaunch();
|
||||
// 首次运行,注册开机自启并标记(新注册已带 --minimized 参数)
|
||||
let _ = autostart.enable();
|
||||
let flag = serde_json::json!("true");
|
||||
let _ = storage.set("autoLaunchInitialized", &flag);
|
||||
let _ = storage.set("autoLaunchArgsMigrated", &flag);
|
||||
log::info!("Auto-launch enabled on first run");
|
||||
} else {
|
||||
// 老用户迁移:旧自启项不带 --minimized 参数,重新注册一次以写入新参数
|
||||
let migrated = storage.get("autoLaunchArgsMigrated", None);
|
||||
if migrated.as_str() != Some("true") {
|
||||
if autostart.is_enabled().unwrap_or(false) {
|
||||
let _ = autostart.disable();
|
||||
let _ = autostart.enable();
|
||||
log::info!("Auto-launch re-registered with --minimized arg");
|
||||
}
|
||||
let _ = storage.set("autoLaunchArgsMigrated", &serde_json::json!("true"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,7 +306,7 @@ fn main() {
|
||||
// .plugin(tauri_plugin_process::init())
|
||||
.plugin(tauri_plugin_autostart::init(
|
||||
tauri_plugin_autostart::MacosLauncher::LaunchAgent,
|
||||
None,
|
||||
Some(vec!["--minimized"]),
|
||||
))
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
// Store
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"productName": "SayIt",
|
||||
"version": "0.0.5",
|
||||
"version": "0.0.7",
|
||||
"identifier": "com.sayit.app",
|
||||
"build": {
|
||||
"frontendDist": "../dist",
|
||||
@@ -20,7 +20,7 @@
|
||||
"minHeight": 600,
|
||||
"decorations": false,
|
||||
"center": true,
|
||||
"visible": true
|
||||
"visible": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
|
||||
@@ -22,7 +22,7 @@ export const DEFAULTS: Record<string, unknown> = {
|
||||
selectedMic: '', // 设备 ID,空字符串 = 系统默认
|
||||
|
||||
// ── AI 校对 ──
|
||||
aiEnabled: false, // 是否开启 AI 校对。可选: true | false
|
||||
aiEnabled: true, // 是否开启 AI 校对。可选: true | false
|
||||
aiPromptAppend: '', // 全局附加 prompt
|
||||
|
||||
// ── AI 供应商 ──
|
||||
|
||||
@@ -6,7 +6,7 @@ export const BUILTIN_APP_RULES: AppPromptRule[] = [
|
||||
appId: 'teams',
|
||||
name: 'Teams',
|
||||
builtin: true,
|
||||
enabled: true,
|
||||
enabled: false,
|
||||
priority: 100,
|
||||
presetId: 'intent',
|
||||
promptAppend: '适合即时协作聊天。优先输出可以直接发送的短消息,语气自然、清晰、简洁,避免邮件腔。',
|
||||
@@ -20,7 +20,7 @@ export const BUILTIN_APP_RULES: AppPromptRule[] = [
|
||||
appId: 'outlook',
|
||||
name: 'Outlook',
|
||||
builtin: true,
|
||||
enabled: true,
|
||||
enabled: false,
|
||||
priority: 95,
|
||||
presetId: 'intent',
|
||||
promptAppend: '适合工作邮件草稿。语气正式、完整,必要时自然分段,但不要编造收件人、称呼或任何事实。',
|
||||
@@ -34,7 +34,7 @@ export const BUILTIN_APP_RULES: AppPromptRule[] = [
|
||||
appId: 'kiro',
|
||||
name: 'Kiro',
|
||||
builtin: true,
|
||||
enabled: true,
|
||||
enabled: false,
|
||||
priority: 90,
|
||||
presetId: 'faithful',
|
||||
promptAppend: '面向开发工具输入。保留代码、命令、文件名、路径、英文标识符和 Markdown 结构,不要把技术词改写成普通中文。',
|
||||
@@ -48,7 +48,7 @@ export const BUILTIN_APP_RULES: AppPromptRule[] = [
|
||||
appId: 'vscode',
|
||||
name: 'VSCode',
|
||||
builtin: true,
|
||||
enabled: true,
|
||||
enabled: false,
|
||||
priority: 85,
|
||||
presetId: 'faithful',
|
||||
promptAppend: '面向 VSCode 编辑区。保留代码、命令、文件名、API、英文术语和 Markdown 结构,不要过度润色技术内容。',
|
||||
@@ -62,7 +62,7 @@ export const BUILTIN_APP_RULES: AppPromptRule[] = [
|
||||
appId: 'cursor',
|
||||
name: 'Cursor',
|
||||
builtin: true,
|
||||
enabled: true,
|
||||
enabled: false,
|
||||
priority: 80,
|
||||
presetId: 'faithful',
|
||||
promptAppend: '面向 Cursor 编辑区。保留代码、命令、路径、技术名词和英文标识符,不要擅自解释或补全技术内容。',
|
||||
@@ -76,7 +76,7 @@ export const BUILTIN_APP_RULES: AppPromptRule[] = [
|
||||
appId: 'notepad',
|
||||
name: '记事本',
|
||||
builtin: true,
|
||||
enabled: true,
|
||||
enabled: false,
|
||||
priority: 70,
|
||||
presetId: 'intent',
|
||||
promptAppend: '面向 Windows 记事本,适合随手记录的纯文本。输出纯文本,不要使用 Markdown 标记或特殊格式符号。',
|
||||
|
||||
@@ -39,7 +39,7 @@ function normalizeAppPromptRule(raw: unknown, fallback?: AppPromptRule): AppProm
|
||||
appId,
|
||||
name,
|
||||
builtin: value.builtin === true || fallback?.builtin === true,
|
||||
enabled: typeof value.enabled === 'boolean' ? value.enabled : fallback?.enabled ?? true,
|
||||
enabled: typeof value.enabled === 'boolean' ? value.enabled : fallback?.enabled ?? false,
|
||||
priority,
|
||||
presetId: String(value.presetId ?? fallback?.presetId ?? '').trim() || undefined,
|
||||
promptAppend: String(value.promptAppend ?? fallback?.promptAppend ?? '').trim(),
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
# SayIt AI 润色供应商
|
||||
|
||||
SayIt 有两个核心功能:语音转文本(ASR)和 AI 文本润色。ASR 部分可以参考 [豆包语音识别凭证获取](豆包ASR凭据获取.md) 和 [阿里云千问语音识别](aliyun.md)。
|
||||
|
||||
AI 润色功能可以去除口癖词(嗯、啊、那个)、修正语音识别错误、自动分段排版等,都可以通过 Prompt 自定义控制。
|
||||
|
||||
SayIt 已对接国内常用的 AI 服务商(通义千问、DeepSeek、豆包等),同时支持 OpenAI 兼容格式,可以接入其他供应商或第三方中转。
|
||||
|
||||
## 1. 最佳实践
|
||||
|
||||
**推荐 DeepSeek deepseek-v4-flash 作为默认选择。** 质量最好、价格极低、速度可接受。
|
||||
|
||||
DeepSeek V4 Flash(2026 年 4 月发布)是 284B 参数的 MoE 模型,13B 激活参数,支持 1M 上下文。关闭思考模式后速度接近旧版 deepseek-chat,但质量明显更好,价格还更便宜(输入 1 元/百万 Token,输出 2 元/百万 Token)。
|
||||
|
||||
如果对延迟极度敏感(需要 <500ms),可以用通义千问 qwen3.6-flash,速度最快但质量略逊。
|
||||
|
||||
| 供应商 | 模型 | 短文本 | 长文本 | 每月成本 |
|
||||
| --------------| -------------------| -----------| ------------| ----------|
|
||||
| **DeepSeek** | deepseek-v4-flash | **803ms** | **2089ms** | ~1.5 元 |
|
||||
| 通义千问 | qwen3.6-flash | 393ms | 1308ms | ~3.8 元 |
|
||||
|
||||
> 月成本按每天 100 次、每次约 100 字估算。V4 Flash 默认开启 thinking,会导致延迟飙升到 2~7 秒。SayIt 已在代码中自动关闭思考模式,无需用户手动配置。
|
||||
|
||||
## 2. 如何选择AI模型
|
||||
|
||||
- **速度**:总耗时由 TTFT(Time To First Token,首个字生成时间)和 TPS(每秒 Token 数)决定。语音转写场景下,总耗时超过 1~2 秒会有明显等待感。
|
||||
- **质量**:能否准确执行 Prompt 指令——去口癖、识别自我修正、格式化列表、纠正专有名词大小写等。
|
||||
- **价格**:V4 Flash 的自动 prompt 缓存机制让重复 system prompt 的场景成本极低。
|
||||
|
||||
## 3. 实测数据
|
||||
|
||||
以下数据是 2026 年 5 月实测的,使用非流式请求(和 SayIt 实际调用方式一致),每条用例跑了 3 次取中位数。
|
||||
|
||||
### 速度
|
||||
|
||||
| 供应商 | 模型 | 短文本 | 中等文本 | 长文本(~200字) |
|
||||
| ----------| -------------------------------| --------| ----------| ------------------|
|
||||
| DeepSeek | deepseek-v4-flash(关闭思考) | 803ms | 971ms | 2089ms |
|
||||
| 通义千问 | qwen3.6-flash | 393ms | 489ms | 1308ms |
|
||||
|
||||
|
||||
### 质量
|
||||
|
||||
两家都能正确去口癖、识别列表结构、纠正专有名词大小写(DeepSeek、ChatGPT、OpenAI 等)。V4 Flash 在专有名词纠正和格式化方面更稳定,输出更简洁。
|
||||
|
||||
|
||||
## 4. 关于豆包
|
||||
|
||||
豆包的语音识别(ASR)是目前中文场景下最好的,SayIt 推荐使用豆包 ASR。但豆包的 AI 文本模型(lite 和 mini 都测了)延迟极不稳定,中长文本经常超过 10 秒,不适合语音转写的润色场景。建议 ASR 用豆包,AI 润色用 DeepSeek 或通义千问。
|
||||
|
||||
## 5. 价格参考
|
||||
|
||||
| 供应商 | 模型 | 输入(百万Token) | 输出(百万Token) |
|
||||
| ----------| ----------------------| -------------------| -------------------|
|
||||
| DeepSeek | deepseek-v4-flash | 1 元 | 2 元 |
|
||||
| 通义千问 | qwen3.6-flash | 1.8 元 | 10.8 元 |
|
||||
| 豆包 | doubao-seed-2-0-mini | 0.2 元 | 2 元 |
|
||||
|
||||
|
||||
|
||||
## 6. 配置指南
|
||||
|
||||
> 建议直接使用官方 API。第三方中转站延迟普遍更高。
|
||||
|
||||
### DeepSeek(推荐)
|
||||
|
||||
- API 地址:`https://api.deepseek.com`
|
||||
- 模型:`deepseek-v4-flash`
|
||||
- 获取 API Key:[platform.deepseek.com](https://platform.deepseek.com/api_keys)
|
||||
- **注意**:SayIt 会自动在请求中添加 `thinking: {type: "disabled"}` 关闭思考模式以降低延迟
|
||||

|
||||
|
||||
### 通义千问
|
||||
|
||||
- API 地址:`https://dashscope.aliyuncs.com/compatible-mode`
|
||||
- 模型:`qwen3.6-flash`
|
||||
- 获取 API Key:[百炼平台](https://bailian.console.aliyun.com/?spm=a2c4g.11186623.0.0.60905ec6iyaRqr&tab=model#/api-key)
|
||||

|
||||
|
||||
### 豆包(火山方舟)
|
||||
- API 地址:`https://ark.cn-beijing.volces.com/api/v3`
|
||||
- 模型:`doubao-seed-2-0-mini-260215`
|
||||

|
||||
@@ -1,95 +0,0 @@
|
||||
# SayIt ASR 语音识别配置
|
||||
|
||||
SayIt 支持三种语音识别模式:
|
||||
|
||||
- **云端 API**:调用云服务商的语音识别接口,准确率最高,适合大多数个人用户
|
||||
- **本地推理**:使用本地模型离线识别,不需要网络,但准确率和速度不如云端
|
||||
- **服务器模式**:自己部署后端服务,适合团队或有定制需求的场景
|
||||
|
||||
对个人用户来说,**云端 API 是最推荐的方式**,下面主要介绍这个。
|
||||
|
||||
## 1. 最佳实践
|
||||
|
||||
中文语音识别准确率最高的是**豆包流式语音识别 2.0**(Seed-ASR-2.0),其次是阿里的**千问 ASR**(qwen3-asr-flash)。
|
||||
|
||||
SayIt 对豆包和千问 ASR 都做了流式优化——按住说话时,音频会实时发送给服务端,松手后只需要等待最后一小段音频的处理时间,通常几百毫秒就能拿到结果。
|
||||
|
||||
另外 SayIt 还支持**千问 3.5 Omni** 多模态模型,这类模型原生支持音频输入、文本输出,可以在转录的同时执行 Prompt 指令(比如去口癖、翻译等),相当于 ASR + AI 润色一步到位。
|
||||
|
||||
| 供应商 | 模型 | 特点 | 价格 |
|
||||
| --------------| --------------------------| --------------------------| -------------------------|
|
||||
| **豆包** | Seed-ASR-2.0 | 中文准确率最高,推荐首选 | 1.00 元/小时 |
|
||||
| **阿里千问** | qwen3-asr-flash-realtime | 流式识别,速度极快 | 1.19 元/小时 |
|
||||
| **阿里千问** | qwen3.5-omni-flash | ASR + AI 一步到位 | 按 Token 计费(见下方) |
|
||||
|
||||
|
||||
## 2. 使用豆包语音识别
|
||||
|
||||
SayIt 支持使用字节跳动「豆包流式语音识别模型 2.0」作为语音识别引擎。豆包 ASR 是目前中文语音识别准确率最高的模型,推荐使用。
|
||||
|
||||
1. 注册 / 登录火山引擎
|
||||
|
||||
打开[火山引擎语音服务控制台](https://console.volcengine.com/speech/service/10038),用手机号注册或登录即可。已有账号的直接登录,没有账号会引导你先注册。
|
||||
[图片]
|
||||
|
||||
|
||||
2. 完成实名认证
|
||||
|
||||
火山引擎的 API 服务需要先做实名认证,没认证的话后面创建应用会卡住。进入[实名认证页面](https://console.volcengine.com/user/authentication/detail/),按页面提示走完就行。
|
||||
[图片]
|
||||
|
||||
|
||||
3. 创建应用并获取 APP ID
|
||||
|
||||
进入[应用管理页面](https://console.volcengine.com/speech/app1),点击「创建应用」。填写应用名称和简介(随便写就行),关键一步:一定要勾选「豆包流式语音识别模型 2.0 小时版」,不然后面用不了。
|
||||
[图片]
|
||||
|
||||
|
||||
4. 获取APP ID 和 Access Token
|
||||
|
||||
进入 [API 服务中心页面](https://console.volcengine.com/speech/service/10038),点击「豆包流式语音识别模型2.0」(配图是旧版界面)。页面上会显示你的 APP ID,鼠标放到 Access Token 上面,点击小眼睛图标,可以看到 Access Token 信息。
|
||||
[图片]
|
||||
|
||||
记录下来这两个信息填到 SayIt 软件中。选择 语音引擎 - 云 API 模式 - 选择ASR供应商为豆包 ASR,填写凭证信息后可以保存测试。
|
||||
[图片]
|
||||
|
||||
|
||||
豆包开通试用后,半年内有 20 小时的[免费额度](https://www.volcengine.com/docs/6561/1359369?lang=zh)。超出免费额度后,按量计费:豆包流式语音识别模型 2.0 — 1 元/小时。[后付费价格详情](https://www.volcengine.com/docs/6561/1359370?lang=zh)
|
||||
|
||||
|
||||
## 3. 阿里千问 ASR
|
||||
|
||||
阿里百炼平台提供了两个语音识别模型,都可以在 SayIt 中使用。
|
||||
|
||||
**qwen3-asr-flash / qwen3-asr-flash-realtime**
|
||||
|
||||
纯语音识别模型,中文准确率仅次于豆包。有两个版本:
|
||||
- **qwen3-asr-flash**:非流式,录完再发,速度也很快
|
||||
- **qwen3-asr-flash-realtime**:流式,边录边发,松手后几乎立刻出结果,体验极佳
|
||||
|
||||
两者准确率一样,推荐使用流式版本。适合搭配独立的 AI 润色供应商使用(比如通义千问或 DeepSeek 做文本校对)。
|
||||
|
||||
**qwen3.5-omni-flash**
|
||||
|
||||
多模态模型,可以直接接收音频输入并输出文本。和普通 ASR + AI 润色的两步流程不同,Omni 模型一步完成,可以在 System Prompt 中直接控制输出格式(比如去口癖、翻译、列表排版等)。
|
||||
|
||||
适合不想分别配置 ASR 和 AI 润色的用户,配置更简单。
|
||||
|
||||
**配置方式**
|
||||
|
||||
在 SayIt 设置中选择千问 ASR 系列,需要填写 API Key。
|
||||
|
||||
- 获取 API Key:[阿里百炼平台](https://bailian.console.aliyun.com/cn-beijing?tab=model#/api-key)
|
||||
|
||||
## 4. 价格
|
||||
|
||||
下面是各个模型按需使用的价格参考。
|
||||
|
||||
| 模型 | 价格 | 免费额度 |
|
||||
| ---------------------------------------| -----------------| ------------------------|
|
||||
| 豆包 Seed-ASR-2.0 | 1.00 元/小时 | 20 小时(半年内) |
|
||||
| 千问 qwen3-asr-flash(非流式) | 0.79 元/小时 | 10 小时(90天内) |
|
||||
| 千问 qwen3-asr-flash-realtime(流式) | 1.19 元/小时 | 10 小时(90天内) |
|
||||
| 千问 qwen3.5-omni-flash | 约 2.3 元/小时* | 100 万 Token(90天内) |
|
||||
|
||||
*Omni 按 Token 计费(每秒音频 ≈ 25 token),2.3 元为粗略估算。详见[千问价格文档](https://help.aliyun.com/zh/model-studio/model-pricing#95f0464a10q5c)。
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 244 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 43 KiB |
Reference in new issue
Block a user