feat: rename project to TamaASR 1.0.0

Migrate internal identifiers, installation paths, packaging metadata, and repository references while preserving package upgrades from meloasr.

AI-assisted-by: Codex
AI-model: gpt-5.6-sol
AI-reasoning-effort: medium
Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
2026-09-01 20:55:14 +08:00
co-authored by Codex
parent 39ddfd8eaa
commit 2100ebab6b
41 changed files with 227 additions and 208 deletions
+8 -8
View File
@@ -106,9 +106,9 @@ jobs:
- name: 构建 deb 与 rpm - name: 构建 deb 与 rpm
env: env:
MELOASR_VERSION: ${{ needs.update-flake-lock.outputs.version }} TAMA_ASR_VERSION: ${{ needs.update-flake-lock.outputs.version }}
MELOASR_DEB_ARCH: ${{ matrix.deb_arch }} TAMA_ASR_DEB_ARCH: ${{ matrix.deb_arch }}
MELOASR_ELECTRON_APP_DIR: ${{ matrix.electron_app_dir }} TAMA_ASR_ELECTRON_APP_DIR: ${{ matrix.electron_app_dir }}
run: | run: |
pnpm install --frozen-lockfile pnpm install --frozen-lockfile
pnpm run package:deb pnpm run package:deb
@@ -165,17 +165,17 @@ jobs:
env: env:
CACHIX_CACHE_NAME: ${{ vars.CACHIX_CACHE_NAME }} CACHIX_CACHE_NAME: ${{ vars.CACHIX_CACHE_NAME }}
run: | run: |
nix build ".#packages.${{ matrix.system }}.meloasr" nix build ".#packages.${{ matrix.system }}.tama-asr"
store_path="$(readlink -f result)" store_path="$(readlink -f result)"
cachix push "$CACHIX_CACHE_NAME" "$store_path" cachix push "$CACHIX_CACHE_NAME" "$store_path"
cachix pin --keep-revisions 1 "$CACHIX_CACHE_NAME" \ cachix pin --keep-revisions 1 "$CACHIX_CACHE_NAME" \
"meloasr-${{ matrix.system }}" "$store_path" "tama-asr-${{ matrix.system }}" "$store_path"
printf '%s\n' "$store_path" > "meloasr-${{ matrix.system }}.txt" printf '%s\n' "$store_path" > "tama-asr-${{ matrix.system }}.txt"
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
with: with:
name: nix-build-${{ matrix.system }} name: nix-build-${{ matrix.system }}
path: meloasr-${{ matrix.system }}.txt path: tama-asr-${{ matrix.system }}.txt
publish-release: publish-release:
name: 创建 GitHub Release name: 创建 GitHub Release
@@ -218,7 +218,7 @@ jobs:
with: with:
tag_name: v${{ needs.update-flake-lock.outputs.version }} tag_name: v${{ needs.update-flake-lock.outputs.version }}
target_commitish: ${{ needs.update-flake-lock.outputs.commit_sha }} target_commitish: ${{ needs.update-flake-lock.outputs.commit_sha }}
name: MeloASR ${{ needs.update-flake-lock.outputs.version }} name: TamaASR ${{ needs.update-flake-lock.outputs.version }}
body_path: release-notes.md body_path: release-notes.md
files: release/* files: release/*
fail_on_unmatched_files: true fail_on_unmatched_files: true
+2 -2
View File
@@ -87,8 +87,8 @@ jobs:
env: env:
CACHIX_CACHE_NAME: ${{ vars.CACHIX_CACHE_NAME }} CACHIX_CACHE_NAME: ${{ vars.CACHIX_CACHE_NAME }}
run: | run: |
nix build ".#packages.${{ matrix.system }}.meloasr" nix build ".#packages.${{ matrix.system }}.tama-asr"
store_path="$(readlink -f result)" store_path="$(readlink -f result)"
cachix push "$CACHIX_CACHE_NAME" "$store_path" cachix push "$CACHIX_CACHE_NAME" "$store_path"
cachix pin --keep-revisions 1 "$CACHIX_CACHE_NAME" \ cachix pin --keep-revisions 1 "$CACHIX_CACHE_NAME" \
"meloasr-${{ matrix.system }}" "$store_path" "tama-asr-${{ matrix.system }}" "$store_path"
+3 -3
View File
@@ -1,8 +1,8 @@
# MeloASR 维护约定 # TamaASR 维护约定
## 项目范围 ## 项目范围
MeloASR 是仅面向 Linux 的 Fcitx5 桌面语音输入工具。项目名为 `MeloASR`,分发包名为 `meloasr`,当前版本为 `0.1.17`。 TamaASR 是仅面向 Linux 的 Fcitx5 桌面语音输入工具。项目名为 `TamaASR`,分发包名为 `tama-asr`,当前版本为 `1.0.0`。
不得恢复 Windows、PowerShell 或 Tauri 输出路径。发行版差异只能存在于依赖说明和打包配置,不能进入语音输入核心逻辑。 不得恢复 Windows、PowerShell 或 Tauri 输出路径。发行版差异只能存在于依赖说明和打包配置,不能进入语音输入核心逻辑。
@@ -44,7 +44,7 @@ MeloASR 是仅面向 Linux 的 Fcitx5 桌面语音输入工具。项目名为 `M
## Fcitx5 与本地协议 ## Fcitx5 与本地协议
- Socket:`$XDG_RUNTIME_DIR/meloasr/fcitx5.sock`;目录 `0700`,Socket `0600`; - Socket:`$XDG_RUNTIME_DIR/tama-asr/fcitx5.sock`;目录 `0700`,Socket `0600`;
- JSONL 协议版本:2; - JSONL 协议版本:2;
- `sessionId` 隔离轮次,`revision` 单调递增; - `sessionId` 隔离轮次,`revision` 单调递增;
- `text` 永远是当前完整文本; - `text` 永远是当前完整文本;
+7
View File
@@ -2,6 +2,13 @@
本项目遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 的格式。 本项目遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 的格式。
## [1.0.0] - 2026-09-01
### 变更
- 项目更名为 TamaASR,分发包名改为 `tama-asr`,并迁移应用标识、Fcitx5 addon、本地 Socket、持久会话、桌面入口及安装路径。
- 将仓库地址更新为 <https://github.com/Melorise/TamaASR>,并为 deb、RPM 和 Arch 包声明替换旧包的关系。
## [0.1.17] - 2026-09-01 ## [0.1.17] - 2026-09-01
### 变更 ### 变更
+3 -3
View File
@@ -1,8 +1,8 @@
# MeloASR 维护约定 # TamaASR 维护约定
## 项目范围 ## 项目范围
MeloASR 是仅面向 Linux 的 Fcitx5 桌面语音输入工具。项目名为 `MeloASR`,分发包名为 `meloasr`,当前版本为 `0.1.17`。 TamaASR 是仅面向 Linux 的 Fcitx5 桌面语音输入工具。项目名为 `TamaASR`,分发包名为 `tama-asr`,当前版本为 `1.0.0`。
不得恢复 Windows、PowerShell 或 Tauri 输出路径。发行版差异只能存在于依赖说明和打包配置,不能进入语音输入核心逻辑。 不得恢复 Windows、PowerShell 或 Tauri 输出路径。发行版差异只能存在于依赖说明和打包配置,不能进入语音输入核心逻辑。
@@ -44,7 +44,7 @@ MeloASR 是仅面向 Linux 的 Fcitx5 桌面语音输入工具。项目名为 `M
## Fcitx5 与本地协议 ## Fcitx5 与本地协议
- Socket:`$XDG_RUNTIME_DIR/meloasr/fcitx5.sock`;目录 `0700`,Socket `0600`; - Socket:`$XDG_RUNTIME_DIR/tama-asr/fcitx5.sock`;目录 `0700`,Socket `0600`;
- JSONL 协议版本:2; - JSONL 协议版本:2;
- `sessionId` 隔离轮次,`revision` 单调递增; - `sessionId` 隔离轮次,`revision` 单调递增;
- `text` 永远是当前完整文本; - `text` 永远是当前完整文本;
+3 -3
View File
@@ -1,4 +1,4 @@
# MeloASR # TamaASR
大模型的进步推动了自然语言处理的进化,语音输入正在成为主流。在其它桌面平台下,微信输入法,豆包输入法,千问输入法等支持语音输入甚至以此为卖点的新兴中文输入法层出不穷。 大模型的进步推动了自然语言处理的进化,语音输入正在成为主流。在其它桌面平台下,微信输入法,豆包输入法,千问输入法等支持语音输入甚至以此为卖点的新兴中文输入法层出不穷。
而在linux下,相关领域却长期空白,现有实现主要聚焦于以下几种类型: 而在linux下,相关领域却长期空白,现有实现主要聚焦于以下几种类型:
@@ -11,7 +11,7 @@ api调用——调用各大ai厂商的语音转文字api。显然,该方案最
因此,本项目使用了一种全新的思路:在后台运行一个electron应用,并在里面登录千问,元宝等网页版对话作为后端,实时抓取语音输入到输入框中的结果,并传递给fcitx5,从而让linux用户也用上高质量的语音输入。 因此,本项目使用了一种全新的思路:在后台运行一个electron应用,并在里面登录千问,元宝等网页版对话作为后端,实时抓取语音输入到输入框中的结果,并传递给fcitx5,从而让linux用户也用上高质量的语音输入。
简而言之,MeloASR 是面向 Linux/Fcitx5 的桌面语音输入工具。应用使用受支持网页平台自身的录音、流式识别、纠错、断句和标点能力,并把网页编辑器中的当前完整文本实时同步到活动的 Fcitx5 InputContext。 简而言之,TamaASR 是面向 Linux/Fcitx5 的桌面语音输入工具。应用使用受支持网页平台自身的录音、流式识别、纠错、断句和标点能力,并把网页编辑器中的当前完整文本实时同步到活动的 Fcitx5 InputContext。
当前后端: 当前后端:
@@ -31,7 +31,7 @@ api调用——调用各大ai厂商的语音转文字api。显然,该方案最
网页后端适配器 网页后端适配器
→ Electron 后端窗口与登录会话 → Electron 后端窗口与登录会话
→ 会话状态机 → 会话状态机
→ $XDG_RUNTIME_DIR/meloasr/fcitx5.sock → $XDG_RUNTIME_DIR/tama-asr/fcitx5.sock
→ Fcitx5 常驻 addon → Fcitx5 常驻 addon
→ 当前应用的 preedit / commit → 当前应用的 preedit / commit
``` ```
+3 -3
View File
@@ -1,5 +1,5 @@
{ {
description = "MeloASR — web-backed voice input for Fcitx5"; description = "TamaASR — web-backed voice input for Fcitx5";
inputs.nixpkgs.url = "github:Melorise/nixpkgs/nixos-unstable"; inputs.nixpkgs.url = "github:Melorise/nixpkgs/nixos-unstable";
@@ -12,13 +12,13 @@
let pkgs = import nixpkgs { inherit system; }; let pkgs = import nixpkgs { inherit system; };
in { in {
default = pkgs.callPackage ./packaging/nix/package.nix { }; default = pkgs.callPackage ./packaging/nix/package.nix { };
meloasr = self.packages.${system}.default; tama-asr = self.packages.${system}.default;
}); });
apps = forAllSystems (system: { apps = forAllSystems (system: {
default = { default = {
type = "app"; type = "app";
program = "${self.packages.${system}.default}/bin/meloasr"; program = "${self.packages.${system}.default}/bin/tama-asr";
}; };
}); });
+10 -10
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
project(meloasr-fcitx5 VERSION 0.1.17 LANGUAGES CXX) project(tama-asr-fcitx5 VERSION 1.0.0 LANGUAGES CXX)
include(GNUInstallDirs) include(GNUInstallDirs)
include(CTest) include(CTest)
@@ -8,16 +8,16 @@ find_package(Fcitx5Core 5.0 REQUIRED)
find_package(Fcitx5Utils 5.0 REQUIRED) find_package(Fcitx5Utils 5.0 REQUIRED)
find_package(nlohmann_json 3.2 REQUIRED) find_package(nlohmann_json 3.2 REQUIRED)
add_library(meloasr MODULE voiceinput.cpp) add_library(tama-asr MODULE voiceinput.cpp)
target_compile_features(meloasr PRIVATE cxx_std_20) target_compile_features(tama-asr PRIVATE cxx_std_20)
target_compile_options(meloasr PRIVATE -Wall -Wextra -Wpedantic) target_compile_options(tama-asr PRIVATE -Wall -Wextra -Wpedantic)
target_link_libraries(meloasr PRIVATE Fcitx5::Core Fcitx5::Utils nlohmann_json::nlohmann_json) target_link_libraries(tama-asr PRIVATE Fcitx5::Core Fcitx5::Utils nlohmann_json::nlohmann_json)
set_target_properties(meloasr PROPERTIES PREFIX "lib") set_target_properties(tama-asr PROPERTIES PREFIX "lib")
set(MELOASR_LIBRARY_PATH "${FCITX_INSTALL_ADDONDIR}/libmeloasr") set(TAMA_ASR_LIBRARY_PATH "${FCITX_INSTALL_ADDONDIR}/libtama-asr")
configure_file(meloasr.conf.in meloasr.conf @ONLY) configure_file(tama-asr.conf.in tama-asr.conf @ONLY)
install(TARGETS meloasr LIBRARY DESTINATION "${FCITX_INSTALL_ADDONDIR}") install(TARGETS tama-asr LIBRARY DESTINATION "${FCITX_INSTALL_ADDONDIR}")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/meloasr.conf" DESTINATION "${FCITX_INSTALL_PKGDATADIR}/addon") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tama-asr.conf" DESTINATION "${FCITX_INSTALL_PKGDATADIR}/addon")
if(BUILD_TESTING) if(BUILD_TESTING)
add_executable(protocolsession_test protocolsession_test.cpp) add_executable(protocolsession_test protocolsession_test.cpp)
+4 -4
View File
@@ -1,4 +1,4 @@
# MeloASR Fcitx5 addon # TamaASR Fcitx5 addon
该 addon 作为 Fcitx5 常驻 Module 工作,不需要切换到独立输入法。 该 addon 作为 Fcitx5 常驻 Module 工作,不需要切换到独立输入法。
@@ -18,8 +18,8 @@ fcitx5 -r
安装文件: 安装文件:
```text ```text
~/.local/lib/fcitx5/libmeloasr.so ~/.local/lib/fcitx5/libtama-asr.so
~/.local/share/fcitx5/addon/meloasr.conf ~/.local/share/fcitx5/addon/tama-asr.conf
``` ```
本地协议使用 `$XDG_RUNTIME_DIR/meloasr/fcitx5.sock`,目录权限 `0700`,Socket 权限 `0600`。协议版本为 2,支持 `configure` 动态快捷键和 `activate` 悬浮球启动请求。 本地协议使用 `$XDG_RUNTIME_DIR/tama-asr/fcitx5.sock`,目录权限 `0700`,Socket 权限 `0600`。协议版本为 2,支持 `configure` 动态快捷键和 `activate` 悬浮球启动请求。
+1 -1
View File
@@ -17,4 +17,4 @@ rm -f -- \
"${HOME}/.local/lib/fcitx5/libvoiceinput.so" \ "${HOME}/.local/lib/fcitx5/libvoiceinput.so" \
"${HOME}/.local/share/fcitx5/addon/voiceinput.conf" "${HOME}/.local/share/fcitx5/addon/voiceinput.conf"
echo "已安装 MeloASR Fcitx5 插件,请重启 Fcitx5。" echo "已安装 TamaASR Fcitx5 插件,请重启 Fcitx5。"
-14
View File
@@ -1,14 +0,0 @@
[Addon]
Name=MeloASR
Name[zh_CN]=MeloASR
Comment=Connect MeloASR web backends to the active input context
Comment[zh_CN]=将 MeloASR 网页后端连接到当前输入上下文
Type=SharedLibrary
Library=@MELOASR_LIBRARY_PATH@
Category=Module
Version=0.1.17
OnDemand=False
Configurable=False
[Addon/Dependencies]
0=core:5.0.0
+14
View File
@@ -0,0 +1,14 @@
[Addon]
Name=TamaASR
Name[zh_CN]=TamaASR
Comment=Connect TamaASR web backends to the active input context
Comment[zh_CN]=将 TamaASR 网页后端连接到当前输入上下文
Type=SharedLibrary
Library=@TAMA_ASR_LIBRARY_PATH@
Category=Module
Version=1.0.0
OnDemand=False
Configurable=False
[Addon/Dependencies]
0=core:5.0.0
+17 -17
View File
@@ -35,7 +35,7 @@ namespace {
constexpr int kProtocolVersion = 2; constexpr int kProtocolVersion = 2;
constexpr std::size_t kMaxBufferBytes = 1024 * 1024; constexpr std::size_t kMaxBufferBytes = 1024 * 1024;
#define MELOASR_DIAGNOSTIC_INFO if (!diagnosticLogging_) {} else FCITX_INFO() #define TAMA_ASR_DIAGNOSTIC_INFO if (!diagnosticLogging_) {} else FCITX_INFO()
class VoiceInputAddon final : public fcitx::AddonInstance { class VoiceInputAddon final : public fcitx::AddonInstance {
public: public:
@@ -53,7 +53,7 @@ public:
fcitx::EventType::InputContextFocusOut, fcitx::EventType::InputContextFocusOut,
fcitx::EventWatcherPhase::PostInputMethod, fcitx::EventWatcherPhase::PostInputMethod,
[this](fcitx::Event &event) { [this](fcitx::Event &event) {
MELOASR_DIAGNOSTIC_INFO << "MeloASR:InputContext focusOut,取消当前会话 active=" TAMA_ASR_DIAGNOSTIC_INFO << "TamaASR:InputContext focusOut,取消当前会话 active="
<< session_.active() << " awaiting=" << awaitingStart_; << session_.active() << " awaiting=" << awaitingStart_;
cancelForContext(static_cast<fcitx::InputContextEvent &>(event).inputContext()); cancelForContext(static_cast<fcitx::InputContextEvent &>(event).inputContext());
}); });
@@ -68,7 +68,7 @@ public:
fcitx::EventType::InputContextReset, fcitx::EventType::InputContextReset,
fcitx::EventWatcherPhase::PostInputMethod, fcitx::EventWatcherPhase::PostInputMethod,
[this](fcitx::Event &event) { [this](fcitx::Event &event) {
MELOASR_DIAGNOSTIC_INFO << "MeloASR:InputContext reset,取消当前会话 active=" TAMA_ASR_DIAGNOSTIC_INFO << "TamaASR:InputContext reset,取消当前会话 active="
<< session_.active() << " awaiting=" << awaitingStart_; << session_.active() << " awaiting=" << awaitingStart_;
cancelForContext(static_cast<fcitx::InputContextEvent &>(event).inputContext()); cancelForContext(static_cast<fcitx::InputContextEvent &>(event).inputContext());
}); });
@@ -79,7 +79,7 @@ public:
auto *context = static_cast<fcitx::InputContextEvent &>(event).inputContext(); auto *context = static_cast<fcitx::InputContextEvent &>(event).inputContext();
if (context == focusedInputContext_) focusedInputContext_ = nullptr; if (context == focusedInputContext_) focusedInputContext_ = nullptr;
if (context == inputContext_) { if (context == inputContext_) {
MELOASR_DIAGNOSTIC_INFO << "MeloASR:InputContext destroyed,取消当前会话"; TAMA_ASR_DIAGNOSTIC_INFO << "TamaASR:InputContext destroyed,取消当前会话";
sendControl("request-cancel"); sendControl("request-cancel");
resetLocalState(false); resetLocalState(false);
} }
@@ -118,7 +118,7 @@ private:
if (action == VoiceKeyAction::Start) { if (action == VoiceKeyAction::Start) {
event.filterAndAccept(); event.filterAndAccept();
MELOASR_DIAGNOSTIC_INFO << "网页语音输入:快捷键按下 held=" << held_ TAMA_ASR_DIAGNOSTIC_INFO << "网页语音输入:快捷键按下 held=" << held_
<< " awaiting=" << awaitingStart_ << " awaiting=" << awaitingStart_
<< " active=" << session_.active(); << " active=" << session_.active();
if (!ensureConnected()) { if (!ensureConnected()) {
@@ -132,7 +132,7 @@ private:
if (action == VoiceKeyAction::Stop) { if (action == VoiceKeyAction::Stop) {
event.filterAndAccept(); event.filterAndAccept();
MELOASR_DIAGNOSTIC_INFO << "网页语音输入:快捷键松开 awaiting=" << awaitingStart_ TAMA_ASR_DIAGNOSTIC_INFO << "网页语音输入:快捷键松开 awaiting=" << awaitingStart_
<< " active=" << session_.active(); << " active=" << session_.active();
held_ = false; held_ = false;
if (awaitingStart_ || session_.active()) sendControl("request-stop"); if (awaitingStart_ || session_.active()) sendControl("request-stop");
@@ -143,7 +143,7 @@ private:
if (event.key().check(FcitxKey_Escape)) { if (event.key().check(FcitxKey_Escape)) {
event.filterAndAccept(); event.filterAndAccept();
MELOASR_DIAGNOSTIC_INFO << "MeloASR:录音中收到 Escape,取消当前会话"; TAMA_ASR_DIAGNOSTIC_INFO << "TamaASR:录音中收到 Escape,取消当前会话";
sendControl("request-cancel"); sendControl("request-cancel");
clearPreedit(); clearPreedit();
resetLocalState(false); resetLocalState(false);
@@ -151,7 +151,7 @@ private:
} }
// 用户开始键盘输入时,立即取消语音会话,并让该按键继续交给原输入法。 // 用户开始键盘输入时,立即取消语音会话,并让该按键继续交给原输入法。
MELOASR_DIAGNOSTIC_INFO << "MeloASR:录音中收到其它按键,取消当前会话 key=" TAMA_ASR_DIAGNOSTIC_INFO << "TamaASR:录音中收到其它按键,取消当前会话 key="
<< event.key().toString() << " rawKey=" << event.rawKey().toString() << event.key().toString() << " rawKey=" << event.rawKey().toString()
<< " repeat=" << event.rawKey().states().test(fcitx::KeyState::Repeat); << " repeat=" << event.rawKey().states().test(fcitx::KeyState::Repeat);
sendControl("request-cancel"); sendControl("request-cancel");
@@ -163,7 +163,7 @@ private:
if (!context || !context->hasFocus()) return false; if (!context || !context->hasFocus()) return false;
if (!context->inputPanel().clientPreedit().empty() || if (!context->inputPanel().clientPreedit().empty() ||
!context->inputPanel().preedit().empty()) { !context->inputPanel().preedit().empty()) {
FCITX_WARN() << "MeloASR:当前输入法存在未提交文本,本轮未启动"; FCITX_WARN() << "TamaASR:当前输入法存在未提交文本,本轮未启动";
return false; return false;
} }
inputContext_ = context; inputContext_ = context;
@@ -179,12 +179,12 @@ private:
if (probe > 0 || (probe < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))) { if (probe > 0 || (probe < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))) {
return true; return true;
} }
MELOASR_DIAGNOSTIC_INFO << "网页语音输入:检测到失效的 Electron Socket,立即重连"; TAMA_ASR_DIAGNOSTIC_INFO << "网页语音输入:检测到失效的 Electron Socket,立即重连";
handleDisconnect(); handleDisconnect();
} }
const char *runtimeDir = std::getenv("XDG_RUNTIME_DIR"); const char *runtimeDir = std::getenv("XDG_RUNTIME_DIR");
if (!runtimeDir || !*runtimeDir) return false; if (!runtimeDir || !*runtimeDir) return false;
const std::string socketPath = std::string(runtimeDir) + "/meloasr/fcitx5.sock"; const std::string socketPath = std::string(runtimeDir) + "/tama-asr/fcitx5.sock";
const int fd = ::socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); const int fd = ::socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (fd < 0) return false; if (fd < 0) return false;
sockaddr_un address{}; sockaddr_un address{};
@@ -267,11 +267,11 @@ private:
awaitingStart_ || session_.active()) return; awaitingStart_ || session_.active()) return;
fcitx::Key candidate(message["shortcut"].get<std::string>()); fcitx::Key candidate(message["shortcut"].get<std::string>());
if (!candidate.isValid() || !candidate.hasModifier()) { if (!candidate.isValid() || !candidate.hasModifier()) {
FCITX_WARN() << "MeloASR:拒绝无效快捷键"; FCITX_WARN() << "TamaASR:拒绝无效快捷键";
return; return;
} }
trigger_ = std::move(candidate); trigger_ = std::move(candidate);
MELOASR_DIAGNOSTIC_INFO << "MeloASR:快捷键已更新为 " << trigger_.toString(); TAMA_ASR_DIAGNOSTIC_INFO << "TamaASR:快捷键已更新为 " << trigger_.toString();
return; return;
} }
if (type == "activate") { if (type == "activate") {
@@ -285,7 +285,7 @@ private:
if (!message.contains("sessionId") || !message["sessionId"].is_string()) return; if (!message.contains("sessionId") || !message["sessionId"].is_string()) return;
session_.start(message["sessionId"].get<std::string>()); session_.start(message["sessionId"].get<std::string>());
awaitingStart_ = false; awaitingStart_ = false;
MELOASR_DIAGNOSTIC_INFO << "网页语音输入:会话开始,clientPreedit=" TAMA_ASR_DIAGNOSTIC_INFO << "网页语音输入:会话开始,clientPreedit="
<< inputContext_->capabilityFlags().test(fcitx::CapabilityFlag::Preedit); << inputContext_->capabilityFlags().test(fcitx::CapabilityFlag::Preedit);
// 新会话尚无文本;重复发布空 preedit 会使部分 frontend 立刻 reset。 // 新会话尚无文本;重复发布空 preedit 会使部分 frontend 立刻 reset。
return; return;
@@ -293,7 +293,7 @@ private:
if (type == "cancel") { if (type == "cancel") {
const std::string incoming = message.value("sessionId", std::string()); const std::string incoming = message.value("sessionId", std::string());
if (!incoming.empty() && !session_.matches(incoming)) return; if (!incoming.empty() && !session_.matches(incoming)) return;
MELOASR_DIAGNOSTIC_INFO << "MeloASR:收到 Electron cancel,sessionIdEmpty=" TAMA_ASR_DIAGNOSTIC_INFO << "TamaASR:收到 Electron cancel,sessionIdEmpty="
<< incoming.empty() << " message=" << incoming.empty() << " message="
<< message.value("message", std::string()); << message.value("message", std::string());
clearPreedit(); clearPreedit();
@@ -306,7 +306,7 @@ private:
const std::int64_t incomingRevision = message["revision"].get<std::int64_t>(); const std::int64_t incomingRevision = message["revision"].get<std::int64_t>();
if (!session_.accept(message.value("sessionId", std::string()), incomingRevision)) return; if (!session_.accept(message.value("sessionId", std::string()), incomingRevision)) return;
currentText_ = message["text"].get<std::string>(); currentText_ = message["text"].get<std::string>();
MELOASR_DIAGNOSTIC_INFO << "网页语音输入:收到 " << type << " revision=" TAMA_ASR_DIAGNOSTIC_INFO << "网页语音输入:收到 " << type << " revision="
<< incomingRevision << " bytes=" << currentText_.size(); << incomingRevision << " bytes=" << currentText_.size();
setPreedit(currentText_); setPreedit(currentText_);
if (type == "finish") { if (type == "finish") {
@@ -374,7 +374,7 @@ private:
} }
void handleDisconnect() { void handleDisconnect() {
MELOASR_DIAGNOSTIC_INFO << "MeloASR:Electron Socket 断开,取消当前会话 active=" TAMA_ASR_DIAGNOSTIC_INFO << "TamaASR:Electron Socket 断开,取消当前会话 active="
<< session_.active() << " awaiting=" << awaitingStart_; << session_.active() << " awaiting=" << awaitingStart_;
clearPreedit(); clearPreedit();
resetLocalState(false); resetLocalState(false);
+4 -4
View File
@@ -1,10 +1,10 @@
{ {
"name": "meloasr", "name": "tama-asr",
"productName": "MeloASR", "productName": "TamaASR",
"version": "0.1.17", "version": "1.0.0",
"private": true, "private": true,
"packageManager": "pnpm@11.21.0", "packageManager": "pnpm@11.21.0",
"author": "MeloASR contributors", "author": "TamaASR contributors",
"description": "基于网页语音识别后端和 Fcitx5 的 Linux 实时语音输入工具", "description": "基于网页语音识别后端和 Fcitx5 的 Linux 实时语音输入工具",
"main": "dist/main/index.js", "main": "dist/main/index.js",
"scripts": { "scripts": {
+7 -5
View File
@@ -1,11 +1,13 @@
# Linux 分发打包 # Linux 分发打包
MeloASR 0.1.17 的系统包由两部分组成: TamaASR 1.0.0 的系统包由两部分组成:
- Electron 应用安装到 `/opt/meloasr`,命令入口为 `/usr/bin/meloasr`; - Electron 应用安装到 `/opt/tama-asr`,命令入口为 `/usr/bin/tama-asr`;
- Fcitx5 常驻 addon 由目标发行版中的 CMake/Fcitx5 开发包编译,并安装到该环境报告的 addon 目录。 - Fcitx5 常驻 addon 由目标发行版中的 CMake/Fcitx5 开发包编译,并安装到该环境报告的 addon 目录。
安装包同时提供桌面入口、项目图标和 `/etc/xdg/autostart/meloasr.desktop`,因此安装后的默认行为是随桌面会话启动。设置页关闭自启动时,应用需要在用户级 autostart 目录写入覆盖项,不能删除系统包所属文件。 安装包同时提供桌面入口、项目图标和 `/etc/xdg/autostart/tama-asr.desktop`,因此安装后的默认行为是随桌面会话启动。设置页关闭自启动时,应用需要在用户级 autostart 目录写入覆盖项,不能删除系统包所属文件。
`tama-asr` 1.0.0 的 deb、RPM 和 Arch 元数据均声明替换旧 `meloasr` 包;通过对应发行版的包管理器安装新包时,旧应用、Fcitx5 addon 和桌面文件会一并卸载。
## 统一构建契约 ## 统一构建契约
@@ -15,7 +17,7 @@ deb、rpm 和 Arch 配置期望项目提供:
pnpm run build:linux:dir pnpm run build:linux:dir
``` ```
该命令应在 `release/linux-unpacked/` 生成可直接运行的 Electron 目录,并且主程序名必须是 `meloasr`。仓库提供的 `electron-builder.yml` 只生成这一中间目录;deb/rpm/Arch 的系统文件仍由各自脚本管理,避免用安装钩子复制未被包管理器追踪的 Fcitx5 文件。 该命令应在 `release/linux-unpacked/` 生成可直接运行的 Electron 目录,并且主程序名必须是 `tama-asr`。仓库提供的 `electron-builder.yml` 只生成这一中间目录;deb/rpm/Arch 的系统文件仍由各自脚本管理,避免用安装钩子复制未被包管理器追踪的 Fcitx5 文件。
主项目可将脚本定义为: 主项目可将脚本定义为:
@@ -40,7 +42,7 @@ pnpm run build:linux:dir
packaging/deb/build-deb.sh packaging/deb/build-deb.sh
``` ```
产物位于 `packaging/out/meloasr_0.1.17_<arch>.deb`。依赖名称按 Debian/Ubuntu 系列填写,但尚未在各发行版完成安装验证。 产物位于 `packaging/out/tama-asr_1.0.0_<arch>.deb`。依赖名称按 Debian/Ubuntu 系列填写,但尚未在各发行版完成安装验证。
## rpm ## rpm
+17 -14
View File
@@ -1,16 +1,19 @@
pkgname=meloasr pkgname=tama-asr
pkgver=0.1.17 pkgver=1.0.0
pkgrel=1 pkgrel=1
pkgdesc='Web-backed voice input for Fcitx5' pkgdesc='Web-backed voice input for Fcitx5'
arch=('x86_64') arch=('x86_64')
url='https://github.com/Melorise/MeloASR' url='https://github.com/Melorise/TamaASR'
license=('MPL2') license=('MPL2')
depends=('fcitx5' 'gtk3' 'nss' 'libxss' 'mesa' 'alsa-lib') depends=('fcitx5' 'gtk3' 'nss' 'libxss' 'mesa' 'alsa-lib')
conflicts=('meloasr')
provides=('meloasr')
replaces=('meloasr')
makedepends=('nodejs' 'pnpm' 'cmake' 'gcc' 'nlohmann-json') makedepends=('nodejs' 'pnpm' 'cmake' 'gcc' 'nlohmann-json')
source=("${pkgname}-${pkgver}.tar.gz::${url}/archive/refs/tags/v${pkgver}.tar.gz") source=("${pkgname}-${pkgver}.tar.gz::${url}/archive/refs/tags/v${pkgver}.tar.gz")
sha256sums=('SKIP') sha256sums=('SKIP')
_source_dir="MeloASR-${pkgver}" _source_dir="TamaASR-${pkgver}"
build() { build() {
cd "${srcdir}/${_source_dir}" cd "${srcdir}/${_source_dir}"
@@ -31,17 +34,17 @@ check() {
package() { package() {
cd "${srcdir}/${_source_dir}" cd "${srcdir}/${_source_dir}"
install -d "${pkgdir}/opt/meloasr" install -d "${pkgdir}/opt/tama-asr"
cp -a release/linux-unpacked/. "${pkgdir}/opt/meloasr/" cp -a release/linux-unpacked/. "${pkgdir}/opt/tama-asr/"
install -Dm755 packaging/assets/meloasr-wrapper "${pkgdir}/usr/bin/meloasr" install -Dm755 packaging/assets/tama-asr-wrapper "${pkgdir}/usr/bin/tama-asr"
install -Dm644 packaging/assets/meloasr.desktop \ install -Dm644 packaging/assets/tama-asr.desktop \
"${pkgdir}/usr/share/applications/meloasr.desktop" "${pkgdir}/usr/share/applications/tama-asr.desktop"
install -Dm644 packaging/assets/meloasr-autostart.desktop \ install -Dm644 packaging/assets/tama-asr-autostart.desktop \
"${pkgdir}/etc/xdg/autostart/meloasr.desktop" "${pkgdir}/etc/xdg/autostart/tama-asr.desktop"
install -Dm644 packaging/assets/meloasr.metainfo.xml \ install -Dm644 packaging/assets/tama-asr.metainfo.xml \
"${pkgdir}/usr/share/metainfo/meloasr.metainfo.xml" "${pkgdir}/usr/share/metainfo/tama-asr.metainfo.xml"
install -Dm644 src/assets/logo.png \ install -Dm644 src/assets/logo.png \
"${pkgdir}/usr/share/pixmaps/meloasr.png" "${pkgdir}/usr/share/pixmaps/tama-asr.png"
DESTDIR="${pkgdir}" cmake --install build/fcitx5 DESTDIR="${pkgdir}" cmake --install build/fcitx5
} }
+2 -2
View File
@@ -4,8 +4,8 @@
```bash ```bash
curl --fail --location --remote-name \ curl --fail --location --remote-name \
https://github.com/Melorise/MeloASR/releases/download/v0.1.17/PKGBUILD https://github.com/Melorise/TamaASR/releases/download/v1.0.0/PKGBUILD
makepkg --syncdeps --cleanbuild makepkg --syncdeps --cleanbuild
``` ```
`PKGBUILD` 会根据 `pkgver` 直接下载 GitHub Release 标签对应的源码归档,无需手动下载、重命名或放置源码包。源码地址固定为 `https://github.com/Melorise/MeloASR/archive/refs/tags/v${pkgver}.tar.gz`,因此同一份 `PKGBUILD` 可以重复构建该版本。 `PKGBUILD` 会根据 `pkgver` 直接下载 GitHub Release 标签对应的源码归档,无需手动下载、重命名或放置源码包。源码地址固定为 `https://github.com/Melorise/TamaASR/archive/refs/tags/v${pkgver}.tar.gz`,因此同一份 `PKGBUILD` 可以重复构建该版本。
@@ -1,12 +0,0 @@
[Desktop Entry]
Type=Application
Name=MeloASR
Comment=Start MeloASR when signing in
Comment[zh_CN]=登录桌面后启动 MeloASR
Exec=meloasr --autostart
Icon=meloasr
Terminal=false
X-GNOME-Autostart-enabled=true
X-KDE-autostart-after=panel
NoDisplay=true
-2
View File
@@ -1,2 +0,0 @@
#!/bin/sh
exec /opt/meloasr/meloasr --ozone-platform=x11 "$@"
@@ -0,0 +1,11 @@
[Desktop Entry]
Type=Application
Name=TamaASR
Comment=Start TamaASR when signing in
Comment[zh_CN]=登录桌面后启动 TamaASR
Exec=tama-asr --autostart
Icon=tama-asr
Terminal=false
X-GNOME-Autostart-enabled=true
X-KDE-autostart-after=panel
NoDisplay=true
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
exec /opt/tama-asr/tama-asr --ozone-platform=x11 "$@"
@@ -1,10 +1,10 @@
[Desktop Entry] [Desktop Entry]
Type=Application Type=Application
Name=MeloASR Name=TamaASR
Comment=Web-backed voice input for Fcitx5 Comment=Web-backed voice input for Fcitx5
Comment[zh_CN]=基于网页后端的 Fcitx5 语音输入工具 Comment[zh_CN]=基于网页后端的 Fcitx5 语音输入工具
Exec=meloasr Exec=tama-asr
Icon=meloasr Icon=tama-asr
Terminal=false Terminal=false
Categories=Utility;Accessibility; Categories=Utility;Accessibility;
StartupNotify=false StartupNotify=false
@@ -1,21 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application"> <component type="desktop-application">
<id>io.github.meloasr.MeloASR</id> <id>io.github.melorise.TamaASR</id>
<name>MeloASR</name> <name>TamaASR</name>
<summary>Web-backed voice input for Fcitx5</summary> <summary>Web-backed voice input for Fcitx5</summary>
<summary xml:lang="zh-CN">基于网页后端的 Fcitx5 语音输入工具</summary> <summary xml:lang="zh-CN">基于网页后端的 Fcitx5 语音输入工具</summary>
<metadata_license>CC0-1.0</metadata_license> <metadata_license>CC0-1.0</metadata_license>
<project_license>MPL-2.0</project_license> <project_license>MPL-2.0</project_license>
<description> <description>
<p>MeloASR connects supported web speech-recognition backends to the active Fcitx5 input context.</p> <p>TamaASR connects supported web speech-recognition backends to the active Fcitx5 input context.</p>
<p xml:lang="zh-CN">MeloASR 将支持的网页语音识别后端连接到当前 Fcitx5 输入上下文。</p> <p xml:lang="zh-CN">TamaASR 将支持的网页语音识别后端连接到当前 Fcitx5 输入上下文。</p>
</description> </description>
<url type="homepage">https://github.com/Melorise/MeloASR</url> <url type="homepage">https://github.com/Melorise/TamaASR</url>
<launchable type="desktop-id">meloasr.desktop</launchable> <launchable type="desktop-id">tama-asr.desktop</launchable>
<provides> <provides>
<binary>meloasr</binary> <binary>tama-asr</binary>
</provides> </provides>
<releases> <releases>
<release version="1.0.0" date="2026-09-01"/>
<release version="0.1.17" date="2026-09-01"/> <release version="0.1.17" date="2026-09-01"/>
<release version="0.1.16" date="2026-08-26"/> <release version="0.1.16" date="2026-08-26"/>
<release version="0.1.15" date="2026-08-26"/> <release version="0.1.15" date="2026-08-26"/>
+4 -4
View File
@@ -2,9 +2,9 @@
set -euo pipefail set -euo pipefail
project_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)" project_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)"
version="${MELOASR_VERSION:-0.1.17}" version="${TAMA_ASR_VERSION:-1.0.0}"
arch="${MELOASR_DEB_ARCH:-$(dpkg --print-architecture)}" arch="${TAMA_ASR_DEB_ARCH:-$(dpkg --print-architecture)}"
app_dir="${1:-${MELOASR_ELECTRON_APP_DIR:-${project_dir}/release/linux-unpacked}}" app_dir="${1:-${TAMA_ASR_ELECTRON_APP_DIR:-${project_dir}/release/linux-unpacked}}"
work_dir="${project_dir}/packaging/out/deb-root" work_dir="${project_dir}/packaging/out/deb-root"
output_dir="${project_dir}/packaging/out" output_dir="${project_dir}/packaging/out"
@@ -21,4 +21,4 @@ sed \
mkdir -p "${output_dir}" mkdir -p "${output_dir}"
dpkg-deb --root-owner-group --build "${work_dir}" \ dpkg-deb --root-owner-group --build "${work_dir}" \
"${output_dir}/meloasr_${version}_${arch}.deb" "${output_dir}/tama-asr_${version}_${arch}.deb"
+5 -3
View File
@@ -1,11 +1,13 @@
Package: meloasr Package: tama-asr
Version: @VERSION@ Version: @VERSION@
Section: sound Section: sound
Priority: optional Priority: optional
Architecture: @ARCH@ Architecture: @ARCH@
Maintainer: MeloASR contributors Maintainer: TamaASR contributors
Installed-Size: @INSTALLED_SIZE@ Installed-Size: @INSTALLED_SIZE@
Depends: fcitx5, libc6, libstdc++6, libgtk-3-0, libnss3, libxss1, libgbm1, libasound2 | libasound2t64 Depends: fcitx5, libc6, libstdc++6, libgtk-3-0, libnss3, libxss1, libgbm1, libasound2 | libasound2t64
Conflicts: meloasr
Replaces: meloasr
Description: Web-backed voice input for Fcitx5 Description: Web-backed voice input for Fcitx5
MeloASR hosts supported web speech-recognition backends and sends their TamaASR hosts supported web speech-recognition backends and sends their
live corrected text to the active Fcitx5 input context. live corrected text to the active Fcitx5 input context.
+3 -3
View File
@@ -1,5 +1,5 @@
appId: io.github.meloasr.MeloASR appId: io.github.melorise.TamaASR
productName: MeloASR productName: TamaASR
asar: true asar: true
directories: directories:
@@ -16,6 +16,6 @@ extraResources:
linux: linux:
target: target:
- dir - dir
executableName: meloasr executableName: tama-asr
icon: src/assets/logo.png icon: src/assets/logo.png
category: Utility category: Utility
+12 -12
View File
@@ -16,7 +16,7 @@ let
pnpm = pnpm_11; pnpm = pnpm_11;
in in
stdenv.mkDerivation (finalAttrs: { stdenv.mkDerivation (finalAttrs: {
pname = "meloasr"; pname = "tama-asr";
version = (builtins.fromJSON (builtins.readFile ../../package.json)).version; version = (builtins.fromJSON (builtins.readFile ../../package.json)).version;
src = ../..; src = ../..;
@@ -67,24 +67,24 @@ stdenv.mkDerivation (finalAttrs: {
installPhase = '' installPhase = ''
runHook preInstall runHook preInstall
appDir="$out/share/meloasr/app" appDir="$out/share/tama-asr/app"
mkdir -p "$appDir" "$out/bin" "$out/share/applications" \ mkdir -p "$appDir" "$out/bin" "$out/share/applications" \
"$out/share/pixmaps" "$out/share/metainfo" \ "$out/share/pixmaps" "$out/share/metainfo" \
"$out/etc/xdg/autostart" "$out/etc/xdg/autostart"
cp package.json "$appDir/" cp package.json "$appDir/"
cp -r dist "$appDir/" cp -r dist "$appDir/"
install -Dm644 packaging/assets/meloasr.desktop \ install -Dm644 packaging/assets/tama-asr.desktop \
"$out/share/applications/meloasr.desktop" "$out/share/applications/tama-asr.desktop"
install -Dm644 packaging/assets/meloasr-autostart.desktop \ install -Dm644 packaging/assets/tama-asr-autostart.desktop \
"$out/etc/xdg/autostart/meloasr.desktop" "$out/etc/xdg/autostart/tama-asr.desktop"
install -Dm644 packaging/assets/meloasr.metainfo.xml \ install -Dm644 packaging/assets/tama-asr.metainfo.xml \
"$out/share/metainfo/meloasr.metainfo.xml" "$out/share/metainfo/tama-asr.metainfo.xml"
install -Dm644 src/assets/logo.png \ install -Dm644 src/assets/logo.png \
"$out/share/pixmaps/meloasr.png" "$out/share/pixmaps/tama-asr.png"
cmake --install build/fcitx5 cmake --install build/fcitx5
makeWrapper ${electron}/bin/electron "$out/bin/meloasr" \ makeWrapper ${electron}/bin/electron "$out/bin/tama-asr" \
--add-flags "$appDir" --add-flags "$appDir"
runHook postInstall runHook postInstall
@@ -92,9 +92,9 @@ stdenv.mkDerivation (finalAttrs: {
meta = { meta = {
description = "Web-backed voice input for Fcitx5"; description = "Web-backed voice input for Fcitx5";
homepage = "https://github.com/Melorise/MeloASR"; homepage = "https://github.com/Melorise/TamaASR";
license = lib.licenses.mpl20; license = lib.licenses.mpl20;
mainProgram = "meloasr"; mainProgram = "tama-asr";
platforms = lib.platforms.linux; platforms = lib.platforms.linux;
}; };
}) })
+7 -7
View File
@@ -2,8 +2,8 @@
set -euo pipefail set -euo pipefail
project_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)" project_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)"
version="${MELOASR_VERSION:-0.1.17}" version="${TAMA_ASR_VERSION:-1.0.0}"
app_dir="${1:-${MELOASR_ELECTRON_APP_DIR:-${project_dir}/release/linux-unpacked}}" app_dir="${1:-${TAMA_ASR_ELECTRON_APP_DIR:-${project_dir}/release/linux-unpacked}}"
stage_dir="${project_dir}/packaging/out/rpm-root" stage_dir="${project_dir}/packaging/out/rpm-root"
top_dir="${project_dir}/packaging/out/rpmbuild" top_dir="${project_dir}/packaging/out/rpmbuild"
@@ -14,19 +14,19 @@ command -v rpmbuild >/dev/null || {
rm -rf -- "${stage_dir}" "${top_dir}" rm -rf -- "${stage_dir}" "${top_dir}"
"${project_dir}/packaging/scripts/stage-linux.sh" "${app_dir}" "${stage_dir}" "${project_dir}/packaging/scripts/stage-linux.sh" "${app_dir}" "${stage_dir}"
addon_file="$(find "${stage_dir}/usr" -type f -path '*/fcitx5/libmeloasr.so' \ addon_file="$(find "${stage_dir}/usr" -type f -path '*/fcitx5/libtama-asr.so' \
-printf '/usr/%P\n' -quit)" -printf '/usr/%P\n' -quit)"
if [[ -z "${addon_file}" ]]; then if [[ -z "${addon_file}" ]]; then
echo "未在安装根目录中找到 Fcitx5 addon。" >&2 echo "未在安装根目录中找到 Fcitx5 addon。" >&2
exit 1 exit 1
fi fi
mkdir -p "${top_dir}"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} mkdir -p "${top_dir}"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
tar -C "${stage_dir}" -czf "${top_dir}/SOURCES/meloasr-root.tar.gz" . tar -C "${stage_dir}" -czf "${top_dir}/SOURCES/tama-asr-root.tar.gz" .
rpmbuild -bb \ rpmbuild -bb \
--define "_topdir ${top_dir}" \ --define "_topdir ${top_dir}" \
--define "meloasr_version ${version}" \ --define "tama_asr_version ${version}" \
--define "meloasr_addon_file ${addon_file}" \ --define "tama_asr_addon_file ${addon_file}" \
"${project_dir}/packaging/rpm/meloasr-binary.spec" "${project_dir}/packaging/rpm/tama-asr-binary.spec"
find "${top_dir}/RPMS" -type f -name '*.rpm' -exec cp -f {} "${project_dir}/packaging/out/" \; find "${top_dir}/RPMS" -type f -name '*.rpm' -exec cp -f {} "${project_dir}/packaging/out/" \;
@@ -1,19 +1,21 @@
Name: meloasr Name: tama-asr
Version: %{meloasr_version} Version: %{tama_asr_version}
Release: 1%{?dist} Release: 1%{?dist}
Summary: Web-backed voice input for Fcitx5 Summary: Web-backed voice input for Fcitx5
License: MPL-2.0 License: MPL-2.0
URL: https://github.com/Melorise/MeloASR URL: https://github.com/Melorise/TamaASR
Source0: meloasr-root.tar.gz Source0: tama-asr-root.tar.gz
Requires: fcitx5 Requires: fcitx5
Requires: gtk3 Requires: gtk3
Requires: nss Requires: nss
Requires: libXScrnSaver Requires: libXScrnSaver
Requires: mesa-libgbm Requires: mesa-libgbm
Obsoletes: meloasr < 1.0.0
Provides: meloasr = %{version}-%{release}
%description %description
MeloASR hosts supported web speech-recognition backends and sends their live TamaASR hosts supported web speech-recognition backends and sends their live
corrected text to the active Fcitx5 input context. corrected text to the active Fcitx5 input context.
%prep %prep
@@ -26,47 +28,50 @@ tar -C %{buildroot} -xzf %{SOURCE0}
%files %files
%defattr(-,root,root,-) %defattr(-,root,root,-)
/opt/meloasr /opt/tama-asr
/usr/bin/meloasr /usr/bin/tama-asr
%{meloasr_addon_file} %{tama_asr_addon_file}
/usr/share/applications/meloasr.desktop /usr/share/applications/tama-asr.desktop
/usr/share/pixmaps/meloasr.png /usr/share/pixmaps/tama-asr.png
/usr/share/metainfo/meloasr.metainfo.xml /usr/share/metainfo/tama-asr.metainfo.xml
/usr/share/fcitx5/addon/meloasr.conf /usr/share/fcitx5/addon/tama-asr.conf
/etc/xdg/autostart/meloasr.desktop /etc/xdg/autostart/tama-asr.desktop
%changelog %changelog
* Tue Sep 01 2026 MeloASR contributors - 0.1.17-1 * Tue Sep 01 2026 TamaASR contributors - 1.0.0-1
- Rename the package and replace the legacy meloasr package on upgrade.
* Tue Sep 01 2026 TamaASR contributors - 0.1.17-1
- Replace the application and tray icons; use one icon for ready and one for all not-ready states. - Replace the application and tray icons; use one icon for ready and one for all not-ready states.
* Wed Aug 26 2026 MeloASR contributors - 0.1.16-1 * Wed Aug 26 2026 TamaASR contributors - 0.1.16-1
- Migrate dependency installation and build commands from npm to pnpm. - Migrate dependency installation and build commands from npm to pnpm.
* Wed Aug 26 2026 MeloASR contributors - 0.1.15-1 * Wed Aug 26 2026 TamaASR contributors - 0.1.15-1
- Download the Arch package source directly from the matching GitHub release tag. - Download the Arch package source directly from the matching GitHub release tag.
* Wed Aug 26 2026 MeloASR contributors - 0.1.14-1 * Wed Aug 26 2026 TamaASR contributors - 0.1.14-1
- Cache the active web editor for the duration of each speech session. - Cache the active web editor for the duration of each speech session.
* Mon Aug 24 2026 MeloASR contributors - 0.1.13-1 * Mon Aug 24 2026 TamaASR contributors - 0.1.13-1
- Create the settings renderer only when it is opened and destroy it on close. - Create the settings renderer only when it is opened and destroy it on close.
* Sun Aug 23 2026 MeloASR contributors - 0.1.12-1 * Sun Aug 23 2026 TamaASR contributors - 0.1.12-1
- Disable Electron GPU acceleration for background web renderers. - Disable Electron GPU acceleration for background web renderers.
* Sun Aug 23 2026 MeloASR contributors - 0.1.11-1 * Sun Aug 23 2026 TamaASR contributors - 0.1.11-1
- Release only the selected speech backend renderer. - Release only the selected speech backend renderer.
- Keep the overlay as a non-interactive session status indicator. - Keep the overlay as a non-interactive session status indicator.
* Sun Aug 23 2026 MeloASR contributors - 0.1.10-1 * Sun Aug 23 2026 TamaASR contributors - 0.1.10-1
- Restore the Nix npm configuration hook before building the application. - Restore the Nix npm configuration hook before building the application.
* Sun Aug 23 2026 MeloASR contributors - 0.1.9-1 * Sun Aug 23 2026 TamaASR contributors - 0.1.9-1
- Fix multi-architecture package staging and RPM addon file ownership. - Fix multi-architecture package staging and RPM addon file ownership.
- Fix Nix derivation configuration phase. - Fix Nix derivation configuration phase.
* Sun Aug 23 2026 MeloASR contributors - 0.1.8-1 * Sun Aug 23 2026 TamaASR contributors - 0.1.8-1
- Fix Fcitx5 addon compatibility with Ubuntu 24.04. - Fix Fcitx5 addon compatibility with Ubuntu 24.04.
* Sun Aug 23 2026 MeloASR contributors - 0.1.7-1 * Sun Aug 23 2026 TamaASR contributors - 0.1.7-1
- Initial package - Initial package
+15 -15
View File
@@ -2,9 +2,9 @@
set -euo pipefail set -euo pipefail
project_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)" project_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)"
app_dir="${1:-${MELOASR_ELECTRON_APP_DIR:-${project_dir}/release/linux-unpacked}}" app_dir="${1:-${TAMA_ASR_ELECTRON_APP_DIR:-${project_dir}/release/linux-unpacked}}"
stage_dir="${2:-${project_dir}/packaging/out/root}" stage_dir="${2:-${project_dir}/packaging/out/root}"
addon_build_dir="${MELOASR_ADDON_BUILD_DIR:-${project_dir}/packaging/out/fcitx5-build}" addon_build_dir="${TAMA_ASR_ADDON_BUILD_DIR:-${project_dir}/packaging/out/fcitx5-build}"
if [[ "${app_dir}" != /* ]]; then if [[ "${app_dir}" != /* ]]; then
app_dir="${project_dir}/${app_dir}" app_dir="${project_dir}/${app_dir}"
@@ -16,30 +16,30 @@ if [[ ! -d "${app_dir}" ]]; then
exit 1 exit 1
fi fi
if [[ ! -x "${app_dir}/meloasr" ]]; then if [[ ! -x "${app_dir}/tama-asr" ]]; then
echo "Electron 解包目录中没有可执行文件 meloasr:${app_dir}" >&2 echo "Electron 解包目录中没有可执行文件 tama-asr:${app_dir}" >&2
exit 1 exit 1
fi fi
install -d \ install -d \
"${stage_dir}/opt/meloasr" \ "${stage_dir}/opt/tama-asr" \
"${stage_dir}/usr/bin" \ "${stage_dir}/usr/bin" \
"${stage_dir}/usr/share/applications" \ "${stage_dir}/usr/share/applications" \
"${stage_dir}/usr/share/pixmaps" \ "${stage_dir}/usr/share/pixmaps" \
"${stage_dir}/usr/share/metainfo" \ "${stage_dir}/usr/share/metainfo" \
"${stage_dir}/etc/xdg/autostart" "${stage_dir}/etc/xdg/autostart"
cp -a "${app_dir}/." "${stage_dir}/opt/meloasr/" cp -a "${app_dir}/." "${stage_dir}/opt/tama-asr/"
install -Dm755 "${project_dir}/packaging/assets/meloasr-wrapper" \ install -Dm755 "${project_dir}/packaging/assets/tama-asr-wrapper" \
"${stage_dir}/usr/bin/meloasr" "${stage_dir}/usr/bin/tama-asr"
install -Dm644 "${project_dir}/packaging/assets/meloasr.desktop" \ install -Dm644 "${project_dir}/packaging/assets/tama-asr.desktop" \
"${stage_dir}/usr/share/applications/meloasr.desktop" "${stage_dir}/usr/share/applications/tama-asr.desktop"
install -Dm644 "${project_dir}/packaging/assets/meloasr-autostart.desktop" \ install -Dm644 "${project_dir}/packaging/assets/tama-asr-autostart.desktop" \
"${stage_dir}/etc/xdg/autostart/meloasr.desktop" "${stage_dir}/etc/xdg/autostart/tama-asr.desktop"
install -Dm644 "${project_dir}/packaging/assets/meloasr.metainfo.xml" \ install -Dm644 "${project_dir}/packaging/assets/tama-asr.metainfo.xml" \
"${stage_dir}/usr/share/metainfo/meloasr.metainfo.xml" "${stage_dir}/usr/share/metainfo/tama-asr.metainfo.xml"
install -Dm644 "${project_dir}/src/assets/logo.png" \ install -Dm644 "${project_dir}/src/assets/logo.png" \
"${stage_dir}/usr/share/pixmaps/meloasr.png" "${stage_dir}/usr/share/pixmaps/tama-asr.png"
cmake -S "${project_dir}/linux/fcitx5" -B "${addon_build_dir}" \ cmake -S "${project_dir}/linux/fcitx5" -B "${addon_build_dir}" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
+2 -2
View File
@@ -5,7 +5,7 @@ export const qianwenDefinition: BackendDefinition = Object.freeze({
label: '千问', label: '千问',
url: 'https://www.qianwen.com/', url: 'https://www.qianwen.com/',
origins: Object.freeze(['https://www.qianwen.com']), origins: Object.freeze(['https://www.qianwen.com']),
partition: 'persist:meloasr-qianwen', partition: 'persist:tama-asr-qianwen',
editorSelector: '[data-slate-editor="true"][contenteditable="true"], [role="textbox"][contenteditable="true"]' editorSelector: '[data-slate-editor="true"][contenteditable="true"], [role="textbox"][contenteditable="true"]'
}); });
@@ -14,7 +14,7 @@ export const yuanbaoDefinition: BackendDefinition = Object.freeze({
label: '元宝', label: '元宝',
url: 'https://yuanbao.tencent.com/', url: 'https://yuanbao.tencent.com/',
origins: Object.freeze(['https://yuanbao.tencent.com']), origins: Object.freeze(['https://yuanbao.tencent.com']),
partition: 'persist:meloasr-yuanbao', partition: 'persist:tama-asr-yuanbao',
editorSelector: '.ql-editor[contenteditable="true"], [contenteditable="true"][role="textbox"]' editorSelector: '.ql-editor[contenteditable="true"], [contenteditable="true"][role="textbox"]'
}); });
+2 -2
View File
@@ -5,7 +5,7 @@ import path from 'node:path';
import { resolveAutoStartAction } from './auto-start-policy'; import { resolveAutoStartAction } from './auto-start-policy';
export class AutoStartService { export class AutoStartService {
private readonly filePath = path.join(os.homedir(), '.config', 'autostart', 'meloasr.desktop'); private readonly filePath = path.join(os.homedir(), '.config', 'autostart', 'tama-asr.desktop');
apply(enabled: boolean): void { apply(enabled: boolean): void {
const action = resolveAutoStartAction(app.isPackaged, enabled); const action = resolveAutoStartAction(app.isPackaged, enabled);
@@ -15,7 +15,7 @@ export class AutoStartService {
fs.writeFileSync(this.filePath, [ fs.writeFileSync(this.filePath, [
'[Desktop Entry]', '[Desktop Entry]',
'Type=Application', 'Type=Application',
'Name=MeloASR', 'Name=TamaASR',
'Hidden=true', 'Hidden=true',
'' ''
].join('\n'), { mode: 0o644 }); ].join('\n'), { mode: 0o644 });
+2 -2
View File
@@ -54,13 +54,13 @@ export class BackendManager extends EventEmitter {
skipTaskbar: true, skipTaskbar: true,
width: 1280, width: 1280,
height: 840, height: 840,
title: `${definition.label} · MeloASR`, title: `${definition.label} · TamaASR`,
backgroundColor: '#ffffff', backgroundColor: '#ffffff',
icon: path.join(app.getAppPath(), 'dist', 'assets', 'logo.png'), icon: path.join(app.getAppPath(), 'dist', 'assets', 'logo.png'),
webPreferences: { webPreferences: {
partition: definition.partition, partition: definition.partition,
preload: path.join(__dirname, '..', 'preload', 'backend.js'), preload: path.join(__dirname, '..', 'preload', 'backend.js'),
additionalArguments: [`--meloasr-backend=${id}`], additionalArguments: [`--tama-asr-backend=${id}`],
nodeIntegration: false, nodeIntegration: false,
contextIsolation: true, contextIsolation: true,
sandbox: true, sandbox: true,
+1 -1
View File
@@ -8,7 +8,7 @@ const MAX_LINE_BYTES = 1024 * 1024;
export function defaultSocketPath(env: NodeJS.ProcessEnv = process.env): string { export function defaultSocketPath(env: NodeJS.ProcessEnv = process.env): string {
if (!env.XDG_RUNTIME_DIR) throw new Error('缺少 XDG_RUNTIME_DIR,无法创建 Fcitx5 本地 Socket'); if (!env.XDG_RUNTIME_DIR) throw new Error('缺少 XDG_RUNTIME_DIR,无法创建 Fcitx5 本地 Socket');
return path.join(env.XDG_RUNTIME_DIR, 'meloasr', 'fcitx5.sock'); return path.join(env.XDG_RUNTIME_DIR, 'tama-asr', 'fcitx5.sock');
} }
export class JsonLineDecoder { export class JsonLineDecoder {
+5 -5
View File
@@ -9,7 +9,7 @@ import { SettingsWindow } from './settings-window';
import { TrayController } from './tray-controller'; import { TrayController } from './tray-controller';
import type { BackendStatusPayload, Point } from '../shared/contracts'; import type { BackendStatusPayload, Point } from '../shared/contracts';
app.setName('MeloASR'); app.setName('TamaASR');
app.disableHardwareAcceleration(); app.disableHardwareAcceleration();
app.commandLine.appendSwitch('disable-gpu'); app.commandLine.appendSwitch('disable-gpu');
const singleInstance = app.requestSingleInstanceLock(); const singleInstance = app.requestSingleInstanceLock();
@@ -18,7 +18,7 @@ if (!singleInstance) {
app.quit(); app.quit();
} else { } else {
void app.whenReady().then(bootstrap).catch((error) => { void app.whenReady().then(bootstrap).catch((error) => {
console.error('[MeloASR 启动失败]', error); console.error('[TamaASR 启动失败]', error);
app.quit(); app.quit();
}); });
} }
@@ -36,8 +36,8 @@ async function bootstrap(): Promise<void> {
const overlay = new OverlayController(settings); const overlay = new OverlayController(settings);
await overlay.create(); await overlay.create();
const sessions = new SessionController(backends, bridge, overlay); const sessions = new SessionController(backends, bridge, overlay);
const repositoryUrl = process.env.MELOASR_REPOSITORY_URL?.trim() || const repositoryUrl = process.env.TAMA_ASR_REPOSITORY_URL?.trim() ||
'https://github.com/Melorise/MeloASR'; 'https://github.com/Melorise/TamaASR';
const settingsWindow = new SettingsWindow(settings, backends, overlay, sessions, repositoryUrl); const settingsWindow = new SettingsWindow(settings, backends, overlay, sessions, repositoryUrl);
registerIpc({ settings, autoStart, bridge, backends, overlay, sessions, settingsWindow }); registerIpc({ settings, autoStart, bridge, backends, overlay, sessions, settingsWindow });
const tray = new TrayController( const tray = new TrayController(
@@ -164,7 +164,7 @@ function registerIpc(services: Services): void {
if (typeof payload?.backend !== 'string' || !backends.senderIsActive(event, payload.backend)) return; if (typeof payload?.backend !== 'string' || !backends.senderIsActive(event, payload.backend)) return;
if (!settings.get().diagnosticLogging) return; if (!settings.get().diagnosticLogging) return;
const { backend, stage, ...details } = payload; const { backend, stage, ...details } = payload;
console.info(`[MeloASR 网页诊断] backend=${backend} stage=${stage || 'unknown'} ${JSON.stringify(details)}`); console.info(`[TamaASR 网页诊断] backend=${backend} stage=${stage || 'unknown'} ${JSON.stringify(details)}`);
}); });
} }
+3 -3
View File
@@ -72,7 +72,7 @@ export class SessionController extends EventEmitter {
cancel(message = '语音输入已取消'): void { cancel(message = '语音输入已取消'): void {
if (!['starting', 'recording', 'stopping'].includes(this.state)) return; if (!['starting', 'recording', 'stopping'].includes(this.state)) return;
console.warn(`[MeloASR 会话取消] state=${this.state} reason=${message}`); console.warn(`[TamaASR 会话取消] state=${this.state} reason=${message}`);
this.generation += 1; this.generation += 1;
this.stopRequestedDuringStart = false; this.stopRequestedDuringStart = false;
this.backends.activePage()?.webContents.send('backend-control', { this.backends.activePage()?.webContents.send('backend-control', {
@@ -104,7 +104,7 @@ export class SessionController extends EventEmitter {
} }
backendError(message: string): void { backendError(message: string): void {
console.error(`[MeloASR 后端错误] state=${this.state} reason=${message}`); console.error(`[TamaASR 后端错误] state=${this.state} reason=${message}`);
if (this.bridge.activeSession) this.bridge.cancel(); else this.bridge.rejectStart(message); if (this.bridge.activeSession) this.bridge.cancel(); else this.bridge.rejectStart(message);
this.state = 'idle'; this.state = 'idle';
this.mirroredText = ''; this.mirroredText = '';
@@ -127,7 +127,7 @@ export class SessionController extends EventEmitter {
} }
private notify(message: string): void { private notify(message: string): void {
if (Notification.isSupported()) new Notification({ title: 'MeloASR', body: message }).show(); if (Notification.isSupported()) new Notification({ title: 'TamaASR', body: message }).show();
} }
private emitState(): void { private emitState(): void {
+1 -1
View File
@@ -37,7 +37,7 @@ export class SettingsWindow {
minWidth: 560, minWidth: 560,
minHeight: 560, minHeight: 560,
show: false, show: false,
title: 'MeloASR 设置', title: 'TamaASR 设置',
autoHideMenuBar: true, autoHideMenuBar: true,
icon: path.join(app.getAppPath(), 'dist', 'assets', 'logo.png'), icon: path.join(app.getAppPath(), 'dist', 'assets', 'logo.png'),
webPreferences: { webPreferences: {
+2 -2
View File
@@ -30,7 +30,7 @@ export class TrayController {
create(): void { create(): void {
this.tray = new Tray(trayImage('loading')); this.tray = new Tray(trayImage('loading'));
this.tray.setToolTip('MeloASR · 正在加载'); this.tray.setToolTip('TamaASR · 正在加载');
this.tray.on('click', () => void this.settingsWindow.show()); this.tray.on('click', () => void this.settingsWindow.show());
this.refresh(); this.refresh();
} }
@@ -42,7 +42,7 @@ export class TrayController {
: status.login === 'logged-out' ? 'login-required' : status.login === 'logged-out' ? 'login-required'
: status.detail.startsWith('加载失败') ? 'error' : 'loading'; : status.detail.startsWith('加载失败') ? 'error' : 'loading';
this.tray.setImage(trayImage(state)); this.tray.setImage(trayImage(state));
this.tray.setToolTip(`MeloASR · ${status.detail}`); this.tray.setToolTip(`TamaASR · ${status.detail}`);
this.tray.setContextMenu(Menu.buildFromTemplate([ this.tray.setContextMenu(Menu.buildFromTemplate([
{ label: '设置', click: () => void this.settingsWindow.show() }, { label: '设置', click: () => void this.settingsWindow.show() },
{ label: '打开登录/调试页面', click: () => void this.settingsWindow.openDebug() }, { label: '打开登录/调试页面', click: () => void this.settingsWindow.openDebug() },
+2 -2
View File
@@ -5,8 +5,8 @@ import { shouldClickMicrophoneOnCancel } from './speech-session-state';
import { shouldFinishAfterStop } from './stop-completion'; import { shouldFinishAfterStop } from './stop-completion';
const backendId = process.argv const backendId = process.argv
.find((argument) => argument.startsWith('--meloasr-backend=')) .find((argument) => argument.startsWith('--tama-asr-backend='))
?.slice('--meloasr-backend='.length) ?? ''; ?.slice('--tama-asr-backend='.length) ?? '';
const adapter = getBackendWebAdapter(backendId); const adapter = getBackendWebAdapter(backendId);
let editorObserver: MutationObserver | undefined; let editorObserver: MutationObserver | undefined;
+2 -2
View File
@@ -3,11 +3,11 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="viewport" content="width=device-width,initial-scale=1">
<title>MeloASR 设置</title> <title>TamaASR 设置</title>
<link rel="stylesheet" href="settings.css"> <link rel="stylesheet" href="settings.css">
</head> </head>
<body> <body>
<header><img src="../assets/logo.png" alt=""><div><h1>MeloASR</h1><span>设置</span></div></header> <header><img src="../assets/logo.png" alt=""><div><h1>TamaASR</h1><span>设置</span></div></header>
<main> <main>
<section> <section>
<h2>语音后端</h2> <h2>语音后端</h2>
+1 -1
View File
@@ -3,7 +3,7 @@ import test from 'node:test';
import { JsonLineDecoder, defaultSocketPath } from '../src/main/fcitx-bridge'; import { JsonLineDecoder, defaultSocketPath } from '../src/main/fcitx-bridge';
test('Socket 路径只使用当前用户运行时目录', () => { test('Socket 路径只使用当前用户运行时目录', () => {
assert.equal(defaultSocketPath({ XDG_RUNTIME_DIR: '/run/user/1000' }), '/run/user/1000/meloasr/fcitx5.sock'); assert.equal(defaultSocketPath({ XDG_RUNTIME_DIR: '/run/user/1000' }), '/run/user/1000/tama-asr/fcitx5.sock');
assert.throws(() => defaultSocketPath({}), /XDG_RUNTIME_DIR/); assert.throws(() => defaultSocketPath({}), /XDG_RUNTIME_DIR/);
}); });