Kopuz
Kopuz 是一款使用 Rust 和 Dioxus 框架构建的现代、轻量级音乐播放器应用。 它提供了一个简洁且响应式的界面,用于管理和欣赏您的本地音乐收藏。
English | Türkçe | Português de Portugal | മലയാളം
关于名称
kopuz 是一种古老的突厥弦乐器,通常被认为是许多中亚鲁特琴的祖先。 它传统上由吟游诗人和萨满使用。
吉尔吉斯人的 komuz 并非同一种乐器,但很可能是 kopuz 的后裔。 哈萨克人的 kobyz 也与之相关,不过它是用弓拉奏而非拨弦的。 相比之下,图瓦/雅库特的 xomus(口弦)尽管名称相似,但与之无关。
在突厥传说中,kopuz 与传奇吟游诗人 Dede Korkut 有关, 但这属于神话而非历史。
概述
Kopuz 允许您扫描本地目录中的音频文件,从您的 Jellyfin 或 Subsonic(Navidrome 等) 服务器流媒体播放,或连接 YouTube Music、SoundCloud 或 Spotify 作为流媒体后端, 自动将所有内容组织成可浏览的库。您可以按艺术家、专辑、流派进行导航, 或探索您的自定义播放列表。该应用专为性能和桌面集成而构建,利用了 Rust 的强大功能。
库、播放列表、收藏和设置存储在一个本地 SQLite
数据库(kopuz.db)中;UI 实时读取该数据库,因此更改会立即显示。每个
媒体源都拥有自己的凭据和自己的收藏。
功能
- 主题定制:包含动态主题支持,可自定义视觉外观。您还可以从零开始构建自己的自定义主题,并完全控制颜色变量。
- 原生集成:与 Linux (MPRIS)、macOS (Now Playing / Remote Command Center) 和 Windows (System Media Transport Controls) 上的系统媒体控件集成。
- 迷你播放器:一个紧凑的播放器覆盖层,可从底部栏切换,以提供更小的正在播放视图。
- 最小化到托盘:可选择关闭到系统托盘图标而不是退出,以便播放继续在后台运行。在 设置 中切换。 在 Linux 上需要 appindicator 库(参见安装说明)。
- Discord RPC:内置 RPC 支持!!!
- 多后端:从您的 Jellyfin 或 Subsonic 兼容服务器(Navidrome 效果极佳)流媒体,连接 YouTube Music、SoundCloud 或 Spotify,或者仅指向本地文件夹。您可以随意混合搭配。每个源都通过一个统一的
MediaSource层暴露,并且 UI 会根据每个源的功能(搜索、下载、电台、发现、收藏同步等)进行适配,而不是硬编码每个服务的行为。 - YouTube Music:完整的流媒体后端,带有 Spotify 风格的 发现 页面(推荐歌曲、播放列表、专辑、艺术家和心情),丰富的 艺术家资料(横幅、热门歌曲、专辑、单曲、相关艺术家),专辑/播放列表浏览,以及 混合电台(从任何曲目“启动电台”)。 使用您的账户登录以访问您的音乐库、喜欢的音乐和播放列表 - 或者 以匿名方式运行(无需登录)以浏览、搜索和播放公开 曲目。参见 YouTube Music 设置。
- SoundCloud:支持搜索、曲目播放(渐进式 MP3 和 Go+ AAC/HLS)、将您的喜欢的曲目作为收藏、只读播放列表以及 点赞/取消点赞的流媒体后端。通过隔离配置文件中的一次性浏览器登录添加。参见 SoundCloud 设置。
- Spotify:您的已保存曲目、专辑和播放列表、发现页面、 搜索和在线收听记录,通过 Spotify 官方 Web Playback SDK 或您拥有的任何 Spotify Connect 设备进行播放。需要 Premium 和一次性 应用设置。参见 Spotify 设置。
- 歌词支持:享受实时同步和纯文本歌词,并配有 自动滚动功能以跟随您的音乐。
- 收藏:在本地标记曲目或与您 Jellyfin/Subsonic 服务器同步收藏。
- 播放列表:创建和管理您自己的播放列表,一次添加单个曲目或 整个专辑,并将播放列表同步到您的服务器。
- 流派浏览:按流派浏览本地和服务器 音乐库。
- 文件类型徽章:本地曲目在曲目行中显示一个小格式徽章(MP3、FLAC、WAV、 等),以便您一眼查看源格式。
- 搜索:跨艺术家、专辑和曲目进行搜索,具有实时结果, 以及一个快速搜索覆盖层,您可以从任何地方打开以跳转 直达您所需的内容。
- 自定义界面字体:为界面使用您自己的字体,让 Kopuz 呈现您想要的样子。
- 收听日志:在本地跟踪播放次数,以便您可以查看自己最常听的内容。
- Scrobbling:向 ListenBrainz 发送 Scrobble。对于 Jellyfin 用户, 如果您使用多个客户端,建议使用 jellyfin-plugin-listenbrainz。
- 语言支持:界面支持阿拉伯语、巴西葡萄牙语、荷兰语、 英语、欧洲葡萄牙语、菲律宾语、法语、德语、希腊语、希伯来语、 匈牙利语、印度尼西亚语、意大利语、日语、韩语、马拉雅拉姆语、波兰语、罗马尼亚语、 俄语、简体中文、西班牙语、瑞典语、泰米尔语、Toki Pona、土耳其语、 乌克兰语、越南语和 Sitelen Pona,并提供了简化的新语言添加体验。
- 高性能:繁重的后台处理和优化的库 扫描器确保应用即时打开、运行流畅,并快速跳过之前 已索引的文件。
- 自动清理:重新扫描时自动从您的 库中移除缺失或已删除的曲目。
- 流畅导航:享受精致的界面,在浏览不同视图和页面时,滚动位置会 正确重置。
- 减少动画:无障碍设置,如果您更喜欢更平静的界面, 可以减弱动态效果。
- 均衡器:内置 10 段均衡器,带有预设和自定义设置, 以微调您的声音。
- 交叉淡化:混合曲目过渡,以实现更平滑的自动播放 原生桌面构建中的歌曲。浏览器播放目前使用常规曲目切换。
- 通道模式:在
Stereo、Mono、Left only、Right only和Swap L/R输出模式之间切换。 - yt-dlp 集成:通过 yt-dlp 直接从 YouTube 和其他支持的网站下载音频。选择您的输出格式(最佳音频、MP3、FLAC、Opus、WAV 或 MP4 视频)。不建议使用 FLAC,因为 yt-dlp 是对有损音频进行重新封装,而不是从无损源解码。支持 SponsorBlock、章节分割、cookies、速率限制等。需要您的系统上已安装
yt-dlp。 - 元数据设置:设置中的专用元数据部分允许您控制艺术家图片的来源。在 专辑封面(使用第一张专辑封面作为艺术家照片,默认)或 艺术家照片(直接从您的 Jellyfin 或 Subsonic 服务器获取实际的艺术家图片)之间进行选择。切换到艺术家照片模式时,一旦您打开艺术家页面,图片就会在后台从服务器获取。如果艺术家在您的服务器上没有专用照片,则使用其第一张专辑封面作为回退,以确保永远不会显示空白。
安装
Cargo (crates.io)
使用 Cargo 直接安装:
cargo install --locked kopuz
NixOS / Nix
直接运行而无需安装:
nix run github:temidaradev/kopuz
安装到你的配置文件:
nix profile add github:temidaradev/kopuz
在 NixOS 上,使用 flake:
[!TIP] 这比
nix profile更受推荐,因为它将 Kopuz 作为带有图标和.desktop条目的正式系统应用进行安装。
将 Kopuz 添加到你的 flake.nix 输入中:
{
inputs.kopuz.url = "github:temidaradev/kopuz";
}
然后将其传递到系统配置中,并添加 Cachix substituter,以便 下载预构建的二进制文件而不是进行编译:
{
nix.settings = {
substituters = ["https://kopuz.cachix.org" ];
trusted-public-keys = ["kopuz.cachix.org-1:J2X3AnAYhKTJW5S3aCLoA1ckonQXVNZMQvhZA0YAufw="];
};
}
然后安装该包:
{pkgs, kopuz, ...}: let
kopuzPkg = kopuz.packages.${pkgs.stdenv.hostPlatform.system}.default
in {
environment.systemPackages = [kopuzPkg];
}
AUR (Arch Linux)
使用您偏好的辅助工具从 AUR 安装:
yay -S kopuz-bin
# or
paru -S kopuz-bin
Flatpak(推荐)
Kopuz 即将在 Flathub 上提供。在此期间,您可以通过我们预构建的 Flatpak 仓库安装它,或自行从源代码构建。
选项 1:安装预构建版本(推荐)
flatpak install --user --or-update \
https://kopuz-org.github.io/kopuz-flatpak/com.temidaradev.kopuz.flatpakref
选项 2:从源清单构建
要求
确保已安装 Rust 和 Dioxus CLI。如果可用,我们建议通过发行版的包管理器安装
dioxus-cli。如果未为你的发行版打包,你可以使用 Cargo 作为备选方案进行安装:
cargo install --locked dioxus-cli
然后构建并安装 Kopuz:
git clone https://github.com/temidaradev/kopuz
cd kopuz
dx build --release --package kopuz
flatpak-builder --user --install --force-clean \
build-dir packaging/flatpak/com.temidaradev.kopuz.json
flatpak run com.temidaradev.kopuz
您也可以点击该文件,并使用应用提供商打开它,例如 KDE Discover。
AppImage
[!IMPORTANT] AppImage 需要您的系统上已安装
webkit2gtk-4.1和gtk3。 这些依赖项未捆绑。系统托盘图标此外 还需要 appindicator 库(例如libayatana-appindicator);没有 它 Kopuz 可以正常运行,但不会显示托盘图标。在大多数具有现代桌面环境的发行版中,这些已经存在。 如果尚未安装,您需要手动安装它们。
在基于 Arch 的发行版中,如果 AppImage 因 WebKitNetworkProcess
错误而崩溃,请通过以下方式运行:
LD_LIBRARY_PATH=/usr/lib ./kopuz_*.AppImage
或一次性创建符号链接(需要 sudo):
sudo mkdir -p /usr/libexec/webkit2gtk-4.1
sudo ln -s /usr/lib/webkit2gtk-4.1/WebKitNetworkProcess /usr/libexec/webkit2gtk-4.1/
sudo ln -s /usr/lib/webkit2gtk-4.1/WebKitWebProcess /usr/libexec/webkit2gtk-4.1/
sudo ln -s /usr/lib/webkit2gtk-4.1/WebKitGPUProcess /usr/libexec/webkit2gtk-4.1/
从源码构建
依赖项
使用 Nix
[!TIP] Nix 是 Kopuz 的主要开发方式,也是 在跨系统一致的纯、可复现环境中获取构建依赖项的推荐方法。
# Using Nix3 CLI
nix develop
如果你是 Direnv 用户,请使用提供的 .envrc:
# Using Direnv
direnv allow
如果你希望在开发环境中继续使用你的 usershell,则推荐安装 Direnv。
[!NOTE] 系统托盘图标(用于 minimize to tray)在运行时依赖于 appindicator 库。它已包含在下方列出的软件包 依赖项中。如果没有该库,托盘图标将不会显示,并且关闭窗口会直接退出应用而不是将其隐藏 - Kopuz 仍可正常运行。 Nix 开发环境已提供该库。
基于 Arch Linux 的系统
sudo pacman -S rust cargo dioxus-cli base-devel cmake pkgconf opus alsa-lib xdotool webkit2gtk-4.1 gtk3 libsoup3 openssl libayatana-appindicator
基于 Debian 的系统
sudo apt install rustc cargo build-essential cmake pkg-config libopus-dev libasound2-dev libxdo-dev libwebkit2gtk-4.1-dev libgtk-3-dev libsoup-3.0-dev libssl-dev libayatana-appindicator3-1
cargo install dioxus-cli
基于 Fedora 的系统
sudo dnf groupinstall "Development Tools" "Development Libraries"
sudo dnf install rust cargo cmake pkgconf-pkg-config opus-devel alsa-lib-devel libxdo-devel webkit2gtk4.1-devel gtk3-devel libsoup3-devel openssl-devel libayatana-appindicator-gtk3
cargo install --locked dioxus-cli
基于 openSUSE 的系统
sudo zypper install rust cargo cmake pkg-config libopus-devel alsa-devel xdotool webkit2gtk3-soup2-devel gtk3-devel libsoup3-devel libopenssl-devel libayatana-appindicator3-1
cargo install --locked dioxus-cli
开发 Kopuz
安装 Bazelisk,它会读取
仓库中固定的 .bazelversion。在 macOS 上:
brew install bazelisk
克隆仓库并构建桌面端二进制文件:
git clone https://github.com/Kopuz-org/kopuz
cd kopuz
bazel build //:kopuz
使用单独的调试数据库运行:
KOPUZ_DB_PATH=kopuz-debug.db bazel run //:kopuz
构建优化后的二进制文件:
bazel build --config=release //:kopuz
首次调用 Bazel 会下载固定的 Bazel 和 Rust 工具链,以及 Cargo.lock 和 Cargo.Bazel.lock 中记录的第三方 crate。
构建的二进制文件可通过稳定的 bazel-bin/crates/kopuz/kopuz
符号链接访问。
测试单个 crate 或完整的工作区:
bazel test //crates/db:db_test
bazel test //:tests
使用拒绝警告的方式运行 Clippy:
bazel build \
--aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect \
--output_groups=clippy_checks \
--@rules_rust//rust/settings:clippy_flag=-Dwarnings \
//crates/...
在不更改文件的情况下检查格式:
bazel build \
--aspects=@rules_rust//rust:defs.bzl%rustfmt_aspect \
--output_groups=rustfmt_checks \
//crates/...
应用 rustfmt:
bazel run @rules_rust//:rustfmt -- //crates/...
Cargo 清单仍然是依赖项版本和特性的权威来源。
在修改清单或 Cargo.lock 之后,重新生成 Bazel 的解析锁:
CARGO_BAZEL_REPIN=1 bazel build //crates/config:config
Tailwind 的输出已提交,因为 Dioxus 将其作为应用资源使用。 每当 UI 类发生变化时,请重新生成它:
npm ci
npx @tailwindcss/cli -i ./tailwind.css \
-o ./crates/kopuz/assets/tailwind.css
Bazel 目标用于构建和运行原生 Rust 可执行文件。Dioxus 仍然负责桌面安装程序和移动项目生成,因此在生成这些产物时,请在 Bazel 构建/测试门控之后使用现有的包装器:
just build
just android-patch
just ios-build-sim
macOS
隔离说明: 如果您下载的是 .dmg,macOS 可能会阻止它。运行
一次以清除隔离标志:
xattr -d com.apple.quarantine /Applications/Kopuz.app
Kopuz 将文件存储在哪里?
您的设置、扫描的曲库、播放列表和收藏项都保存在配置目录中的单个
SQLite 数据库中,kopuz.db。专辑封面和
已下载的音轨则保留在缓存目录的磁盘上。(调试构建使用单独的
kopuz-debug.db,因此 dx serve 绝不会触及您的真实数据。您可以
使用 KOPUZ_DB_PATH 环境变量来覆盖数据库位置。)
在 macOS 上:
~/Library/Application Support/com.temidaradev.kopuz/kopuz.db- 设置、 曲库、播放列表、收藏项~/Library/Caches/com.temidaradev.kopuz/covers/- 缓存的专辑封面~/Library/Caches/com.temidaradev.kopuz/offline_tracks/- 已下载的音轨
在 Linux 上(XDG 规范):
~/.config/kopuz/kopuz.db- 设置、曲库、播放列表、收藏项~/.cache/kopuz/covers/- 缓存的专辑封面~/.cache/kopuz/offline_tracks/- 已下载的音轨
在 Windows 上(AppData):
%APPDATA%\temidaradev\kopuz\config\kopuz.db- 设置、曲库、播放列表、 收藏项%LOCALAPPDATA%\temidaradev\kopuz\cache\covers\- 缓存的专辑封面%LOCALAPPDATA%\temidaradev\kopuz\cache\offline_tracks\- 已下载的音轨
[!NOTE] 从旧版本升级?首次启动时,Kopuz 会将您现有的
library.json和playlists.json导入到kopuz.db中,并保留*.json.bak备份。之后,旧的 JSON 文件将不再被读取。
如果封面未显示或曲库看起来异常,只需删除缓存文件夹 并点击重新扫描即可。
YouTube Music 设置
Kopuz 可以使用 YouTube Music 作为流媒体后端。从 设置 → 媒体服务器 → 添加 → YouTube Music 中添加它。
选择模式
设置对话框提供两种方法:
-
通过浏览器登录 - kopuz 会在一个 隔离的浏览器配置文件(全新的独立会话;绝不会影响您的正常浏览)中打开 Google 登录页面, 等待您完成登录,并提取会话 Cookie。 请选择要使用的已安装 Chromium 系列浏览器(Chrome、Chromium、Brave、 Edge、Vivaldi 或 Helium)。这将解锁您的音乐库、喜欢的音乐、 播放列表和关注的艺术家。
-
不登录继续(匿名) - 无需登录,无需 Cookie。您可以 浏览、搜索、打开艺术家/专辑/播放列表页面、启动混合电台并播放 公开曲目。喜欢的音乐、音乐库播放列表以及关注/点赞功能 将被禁用(这些视图会显示“登录以启用”的提示)。Music Premium 专属 曲目无法在匿名模式下播放。
Premium 曲目
Music Premium 锁定的曲目在主路径
返回 UNPLAYABLE 时,会回退到本地
yt-dlp 解析,因此安装 yt-dlp 有助于处理这些情况。匿名
模式完全无法播放 Premium 专属内容。
SoundCloud 设置
Kopuz 可以使用 SoundCloud 作为流媒体后端。从 设置 → 媒体 服务器 → 添加 → SoundCloud 中添加。
无需输入 URL 或密码。Kopuz 会在一个
隔离的浏览器配置文件(全新的独立会话;绝不会影响您的正常浏览)中打开 soundcloud.com/signin,
等待您完成登录,并提取会话的 oauth_token。
请选择要使用的已安装 Chromium 系列浏览器(Chrome、Chromium、Brave、
Edge、Vivaldi 或 Helium)。
登录成功后,您可以进行搜索、跟踪播放进度(渐进式 MP3 以及 Go+ AAC/HLS 流)、将喜欢的曲目作为收藏夹、只读访问您的播放列表,以及执行点赞/取消点赞操作。移除来源会清理其独立的配置文件。
Spotify 设置
Spotify 在 Kopuz 中与其他所有后端的工作方式不同,因此需要一些一次性设置。Kopuz 通过官方 Web API 访问您的曲库,而音频本身则由运行在您机器上浏览器中的 Spotify 官方 Web Playback SDK 播放。Kopuz 驱动该播放器并在其自身 UI 中显示所有内容,但它从不接触音频流,也从不要求您的密码。
开始之前
您需要三样东西:
-
Spotify Premium。 Web Playback SDK 拒绝在免费账户上流式传输。 浏览您的曲库在没有 Premium 的情况下仍然有效,但播放无效。
-
您自己的 Spotify 客户端。 Kopuz 不提供 Client ID,您需要花大约两分钟创建一个并粘贴进去。
-
已安装受支持的浏览器。 macOS 上的 Chrome、Edge、Brave、Chromium、Vivaldi、 Helium 或 Safari。Firefox 在此不可用:SDK 在 Firefox 中存在一个长期存在的 bug, 播放会在几秒后停止,因此 Kopuz 不会选择它。
[!NOTE] 要在 Helium 中使用 Spotify 后端,您需要将 Widevine 文件 放置在正确的位置。参见 此处 以获取更多信息。在 NixOS 上使用 hjem,可以通过添加
hjem.users.your-username = { xdg.config.files."net.imput.helium/WidevineCdm/latest-component-updated-widevine-cdm".text = '' {"Path":"${pkgs.widevine-cdm}/share/google/chrome/WidevineCdm"} ''; };到您的配置中来实现。
1. 创建你的 Spotify 应用
-
打开 developer.spotify.com/dashboard 并使用你想要用于听歌的账户登录。
-
点击 Create app。名称和描述可以是任意内容,它们仅对你可见。
-
在 Redirect URIs 中,精确添加以下内容,末尾不要加斜杠:
http://127.0.0.1:8898/callback
Spotify 会逐字符比较此字符串,因此这里的拼写错误是导致登录失败的最常见原因。
- 在 Which API/SDKs are you planning to use? 下,同时勾选 Web API 和 Web Playback SDK。
- 保存,然后打开应用的 Settings 并复制 Client ID。你不需要 Client Secret,Kopuz 使用 PKCE 代替。
- 前往应用的 User Management,添加每个将登录的 Spotify 账户的显示名称和电子邮件, 包括你自己的。
[!IMPORTANT] 新创建的应用处于 Spotify 的 Development Mode。这意味着最多 五个列出的用户可以登录,应用所有者需要 Premium,并且某些 API 功能受到限制(参见下文 What Spotify limits )。这是 Spotify 的政策,而非 Kopuz 的限制。
2. 在 Kopuz 中添加源
前往 Settings → Media servers → Add → Spotify,将你的 Client ID 粘贴到 Spotify Client ID 字段中,然后保存。
Kopuz 会在你的默认浏览器中打开 Spotify 的授权页面。批准它,然后
重定向会返回到 Kopuz 在 127.0.0.1:8898 上运行的一个小监听器,仅用于
那几秒钟。确保在你登录时没有其他程序占用端口 8898。之后源就准备好了,Kopuz 会自行
刷新令牌。
3. 播放音乐
你的音乐可以从两个地方输出,你可以随时在它们之间切换。
应用内播放器(默认)。 首次点击播放时,Kopuz 会在受支持的浏览器中打开一个小型播放器标签页。该标签页负责实际的播放,因为 DRM 播放仅在真实浏览器中有效。将其保留在后台并忽略即可。所有操作仍由 Kopuz 控制:播放/暂停、跳转、音量、上一首/下一首、您的队列以及系统媒体键。当您退出 Kopuz 时,该标签页会自动关闭。
浏览器在您与页面交互之前会阻止声音,因此如果第一首曲目在那里毫无动静,请在该标签页中任意位置点击一次。Kopuz 会等待该操作,然后开始播放曲目。
Spotify Connect 设备。 底部栏中的设备按钮会列出您周围的任何 Spotify Connect 目标:您的手机、桌面应用、扬声器、电视。选择其中一个,Kopuz 会将播放直接发送到该设备,完全不涉及浏览器标签页。进度、播放状态和当前曲目在 Kopuz 中保持同步,您的操作系统媒体小组件也会随之更新。选择 kopuz (this app) 可返回应用内播放器。
值得了解的设置
这两项均位于 Settings → Media servers 下的 Spotify 行中:
- Spotify 播放浏览器。 哪个浏览器获得播放器标签页。自动 会选取它找到的第一个已安装的支持浏览器。
- Spotify 播放设备。 当 Kopuz 启动时,如果 Spotify 已在其他地方播放,Kopuz 应如何处理。其他设备(默认值) 意味着 Kopuz 接管该会话并仅与其同步,而不是将播放权从该设备夺走。此应用 意味着 Kopuz 始终在本地播放。
您将获得的内容
已保存的曲目显示为收藏,已保存的专辑显示为您的曲库,并且您的 播放列表可供浏览。有一个发现页面,包含循环播放、跳回 继续播放和全时最爱,支持跨曲目/专辑/艺术家搜索,点赞和 取消点赞,以及像任何其他 来源一样向 Last.fm、Libre.fm 和 ListenBrainz 发送播放记录。
Spotify 的限制
这里的大多数粗糙边缘都来自 Spotify 的开发模式,而不是来自 Kopuz:
- Search returns at most ten results per type. Development Mode apps get a hard cap on the search endpoint.
- Playlists are read-only. You can browse and play them, but creating and editing playlists is not available for Spotify sources.
- Playlists you only follow may look empty. Spotify only exposes the tracks of playlists you own or collaborate on. Editorial playlists (Discover Weekly, Release Radar, and friends) are off limits to third-party apps entirely.
- No downloads, no tag editing, no radio for Spotify tracks.
- No equalizer, crossfade, or gapless on Spotify audio. The browser owns that audio pipeline, so Kopuz's own audio features do not apply to it.
故障排除
- “Spotify playback needs Chrome, Edge, Brave, Chromium, Vivaldi, Helium, or Safari” 表示未找到上述任何浏览器。请安装其中一个,然后在 Settings → Media servers 下选择它。
- Sign-in never completes. 请逐字符检查 Spotify 应用中的 redirect URI,并确保没有其他程序正在使用端口 8898。
- Sign-in is refused for a friend's account. 请先在您的应用下的 User Management 中添加该用户。Development Mode 总共允许五个用户。
- Auth errors after the app has been closed for a while. Kopuz 会在启动时刷新 token,因此请等待片刻。如果问题依旧,请移除 Spotify 源并重新添加。
- The Discover page is empty. 如果您在更新 Kopuz 之前已登录,您的 token 可能早于 Discover 所需的 scopes。请退出登录并重新登录。
- A track plays in the tab but Kopuz looks frozen, or the other way around. 手动关闭播放器标签页会断开设备连接。在 Kopuz 中再次按下播放,它将打开一个新的标签页。
Logs & Debugging
Kopuz 通过 tracing 记录日志。大部分内容
可直接从应用本身访问 - Settings → Logs 包含 Open logs folder、
Export logs 以及一个 Enable Performance Tracing 开关 - 因此用户无需
终端即可发送有用的报告。
Where the files live
所有文件都位于日志目录中(Open logs folder 按钮会直接 跳转到此处):
- Linux:
~/.cache/kopuz/logs/ - macOS:
~/Library/Caches/com.temidaradev.kopuz/logs/ - Windows:
%LOCALAPPDATA%\temidaradev\kopuz\cache\logs\
| 文件 | 说明 |
|---|---|
latest.log | 当前会话。跨度计时 + 事件;实时日志。 |
kopuz-<timestamp>.log | 之前的会话,在启动时归档(保留最近 10 个)。重启永远不会擦除之前的运行记录。 |
crash-<timestamp>.txt | 仅在崩溃时(Rust panic)写入:消息、回溯、最近的日志尾部、应用/操作系统版本。 |
kopuz-trace.json | 性能跟踪 - 仅在启用跟踪时(见下文)。每次运行都会覆盖。 |
时间戳为 UTC YYYY-MM-DD_HH-MM-SS,因此文件按时间顺序排序。
故障排查速查表
应用崩溃 → 会自动生成一个 crash-<timestamp>.txt。请用户
提供 设置 → 日志 → 导出日志(将 latest.log + 最新的
崩溃报告打包到一个文件中),或 打开日志文件夹 并获取最新的
crash-*.txt。
性能问题(冻结 / 加载缓慢 / 卡顿) → 请用户执行以下操作:
- 设置 → 日志 → 启用“性能跟踪”,然后重启应用 (该开关会发出警告 - 跟踪记录器仅在启动时设置一次)。
- 复现缓慢的操作。
- 退出应用(这会干净地刷新跟踪数据)。
- 设置 → 日志 → 打开日志文件夹 并发送
kopuz-trace.json(或 导出日志)。
在 speedscope.app 或 ui.perfetto.dev 打开 trace。关键路径(YouTube 流 解析、浏览/搜索/分页、混合电台、库扫描、下载、播放 切换、按组件渲染)被记录为命名 span,并且 worker-thread 的工作嵌套在启动它的 action 之下,因此 trace 显示 时间确切地花在哪里。之后将其关闭 - 它会增加开销并在长会话期间增大 trace 文件。
Power-user env vars
终端运行的 verbosity 日志级别由 env vars 控制:
# Verbose (debug-level) logs for a session
KOPUZ_DEBUG=1 kopuz
# Fine-grained, per-module (overrides KOPUZ_DEBUG); standard tracing directive syntax
KOPUZ_LOG="server::ytmusic=trace,kopuz=debug" kopuz
# Deep render-tree profiling: Dioxus's own per-component render/diff spans
# (enable the trace toggle in Settings first; this just controls what's recorded)
KOPUZ_LOG="info,dioxus_core=trace" kopuz
RUST_LOG 同样有效;KOPUZ_LOG 具有优先权。
性能跟踪 仅通过 设置 → 日志 → 启用性能跟踪(然后重启)来启用——没有对应的环境变量;UI 是唯一的事实来源。默认关闭 → 零开销。
调试构建在 设置 → 日志 中增加了一个 触发崩溃 按钮,用于测试崩溃报告路径。它在发布构建中被编译排除。
优化
Kopuz 旨在即使面对大型曲库也能保持流畅。以下是我们在底层所做的:
-
跳过已索引的内容 - 扫描器维护一个
HashSet,记录它已经见过的每个路径,因此重新扫描仅处理新文件。如果你有 10,000 首曲目,然后添加了 5 首新的,Kopuz 不会重新读取其他 9995 首。这在 HDD 上尤其能带来巨大差异。 -
并行启动加载 - 启动时,曲库、配置、播放列表和收藏项均使用
tokio::join!并行加载。在此更改之前,所有内容都是顺序加载的,你会盯着一个空白窗口看一会儿。现在几乎是瞬间完成。 -
专辑封面缓存 - 封面图像仅提取一次并保存到磁盘(Linux 上为
~/.cache/kopuz/covers/,macOS 上为~/Library/Caches/)。我们还在内存中缓存 macOS 的当前播放封面对象,以便在进度条更新时不必每次都重新解码图像。 -
图像懒加载 - 搜索结果、曲目行和流派视图中的专辑封面均使用
loading="lazy",这样在浏览大型曲库时就不会一次性加载数百张图像。 -
非阻塞 I/O - 所有繁重的工作(元数据解析、文件扫描、 保存库状态)都在
spawn_blocking个线程上运行,因此 UI 永远不会 冻结。即使在执行完整的库扫描期间,主线程也保持响应。 -
更智能的排序 - 我们在库视图中使用
sort_by_cached_key而不是普通的sort_by_key,这避免了在每次比较时重新计算排序键(例如.to_lowercase())。这也许是个小事,但在数千首曲目中会累积起来。 -
用于封面的 HTTP 缓存 - 自定义的
artwork://协议使用Cache-Control: public, max-age=31536000提供图像, 因此 Webview 不会重新请求它已经拥有的封面。
总体而言,这些更改将重新扫描时间降低了_显著_,并且应用程序 感觉响应快得多,特别是对于超过 5000 首曲目的库。内存 使用量也保持在合理范围内,因为我们不会在内存中保留解码后的图像 超过必要的时间。
技术栈
- Dioxus: UI 框架
- Symphonia: 音频解码库
- Cpal: 音频 I/O 库
- Lofty: 元数据解析
- SQLite / sqlx: 带有编译时检查查询的本地存储
- TailwindCSS: 基于 CSS 的样式框架
加密货币捐赠
- Solana: "2fapJYRztnTRLpJbmyEUnsuZ36AzLK2JrMmmLEfDqKpN"
- Bitcoin: "bc1qz94yz9xvufa6hxlvjzaajgd2zyfu86arn68hu4"
- Monero: "86mz3HxTrKyYpuvx78m6pufbXdwAnoyoZBztz6HyYrnM1XP5YVrMy9jTVRY5vzgGtkizACLpFwHEdafKTMoj6y8mAVgvWMz"
- Ethereum: "0xa490D50470cdFf837B6663F7f6cBe50B157224e5"
- USDT on Solana Chain: "GYmnAcrA5MbF6cUxT2m5d5cwdfr14qSY9WFYRwXxaibW"
致谢
- Logo 设计:Lucas Amorim - 他的 Instagram 账号