chore: 发布 0.0.7 - 更新主界面截图、新增微信反馈群、精简配置文档

This commit is contained in:
crosswk committed 2026-07-03 11:12:05 +08:00
1 parent 2def8cdaf9
commit 241d83762c
14 files changed
+56 -196

No files matched your search

+13 -1
View File
@@ -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
View File
@@ -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": {
+1 -1
View File
@@ -3763,7 +3763,7 @@ dependencies = [
[[package]]
name = "sayit"
version = "0.0.5"
version = "0.0.7"
dependencies = [
"base64 0.22.1",
"bzip2",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "sayit"
version = "0.0.5"
version = "0.0.7"
authors = ["Liu Qianglong", "Claude"]
edition = "2021"
+5 -1
View File
@@ -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))
+25 -3
View File
@@ -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
+2 -2
View File
@@ -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": {
+1 -1
View File
@@ -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 标记或特殊格式符号。',
+1 -1
View File
@@ -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(),
-83
View File
@@ -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"}` 关闭思考模式以降低延迟
![alt text](DeepSeek获取API.png)
### 通义千问
- 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)
![alt text](百炼获取API.png)
### 豆包(火山方舟)
- API 地址:`https://ark.cn-beijing.volces.com/api/v3`
- 模型:`doubao-seed-2-0-mini-260215`
![alt text](豆包获取API.png)
-95
View File
@@ -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