DrGitStone/JellyMusicUploader

GitHub: DrGitStone/JellyMusicUploader

这是一个 Jellyfin 插件,通过网页拖放上传音乐文件并自动管理标签和封面,简化音乐库维护。

Stars: 0 | Forks: 0

JellyMusicUploader

JellyMusicUploader

一个 Jellyfin 插件,可在网页界面中添加一个**添加音乐**按钮。只需将一个或多个 `Artist/Album/song` 文件夹拖入模态窗口,并可选择为每张专辑设置封面图片,插件即会将文件写入您的音乐媒体库文件夹并触发媒体库扫描。 **现在您终于可以从任何地方为音乐库添加音乐,无需再通过 Jellyfin 的后端操作!** 专为家庭服务器管理员设计——无需 SSH、无需 scp、无需手动导入。 只需将文件夹拖入浏览器即可。 请注意上传格式:`Artist 文件夹 > Album 名称文件夹 > Song 音轨文件` 您还可以在此过程中为专辑选择缩略图(可选),从而获得整洁的元数据体验! ## HTTP API
jellyfin-music-uploader
## 功能特点 - 兼容 **Jellyfin Media Player** 和 **Jellyfin Web UI** - 从 Jellyfin 网页界面拖放文件夹上传 - 支持一次拖放多个 Artist 文件夹 - 在上传前验证并预览文件夹结构(artist / album / track 数量 / 总大小) - 每张专辑的**封面图片选择器**——设置一次图片,它将成为该专辑及其内部所有曲目的专辑封面(通过 Jellyfin 标准的 `cover.` 约定) - **基于文件夹结构的自动标记**——每个音频文件写入后,插件会根据文件夹路径写入 `Artist`、`AlbumArtist`、`Album` 和(若缺失)`Title` 标签。解决了上传文件时 ID3 标签为空或错误的常见问题,否则 Jellyfin 的基于标签的音乐扫描器会显示为“未知艺术家” - 单文件进度、原子写入(`.part` 临时文件 → 重命名) - 批量上传完成后自动触发 Jellyfin 媒体库扫描 - 仅限管理员——浮动按钮对非管理员不可见,上传端点会拒绝非管理员令牌 - 路径遍历防护、扩展名白名单、单文件大小限制 - 单个小型 DLL——无需额外运行时依赖 Screenshot 2026-05-19 at 12 48 55 PM Screenshot 2026-05-19 at 12 49 40 PM ## 系统要求 - **Jellyfin 10.11.x**(基于 10.11.2 构建和测试) - 在 Jellyfin 中配置一个音乐媒体库,指向一个 Jellyfin 进程可写的目录 - 如需从源代码构建:**.NET 9 SDK** ## 安装说明 ### 1. 获取插件 DLL **选项 A — 下载发行版**(当有可用版本时) 如果此仓库有带标签的发行版,请从 [Releases](../../releases) 页面下载 `JellyMusicUploader.zip` 并解压。您将找到 `JellyMusicUploader.dll`、`TagLibSharp.dll` 和 `meta.json`。 **选项 B — 从源代码构建** ``` git clone https://github.com//jellyfin-music-uploader.git cd jellyfin-music-uploader dotnet build -c Release ``` 输出位于 `bin/Release/net9.0/`: - `JellyMusicUploader.dll` —— 插件本体 - `TagLibSharp.dll` —— 标签规范化所需的运行时依赖 如果需要将文件交给他人,可将这两个文件加上 `meta.json` 打包成单个 zip: ``` ( cd bin/Release/net9.0 && \ zip -j ../../../JellyMusicUploader.zip \ JellyMusicUploader.dll TagLibSharp.dll ../../../meta.json ) ``` ### 2. 将插件放入 Jellyfin 的 plugins 文件夹 Jellyfin 要求的文件夹布局是 `_/`。请创建该目录并将 `JellyMusicUploader.dll` + `meta.json` 放入其中。 **原生安装** (Debian/Ubuntu) ``` sudo mkdir -p /var/lib/jellyfin/plugins/JellyMusicUploader_0.1.0.0 sudo cp JellyMusicUploader.dll TagLibSharp.dll meta.json \ /var/lib/jellyfin/plugins/JellyMusicUploader_0.1.0.0/ sudo chown -R jellyfin:jellyfin /var/lib/jellyfin/plugins/JellyMusicUploader_0.1.0.0 sudo systemctl restart jellyfin ``` **Docker (`linuxserver/jellyfin` 及类似)** 插件文件夹位于 `/data/plugins/`。使用 `docker inspect ` 找到您主机侧的挂载点,并查看 `/config` 的绑定源。然后: ``` HOST_CONFIG=/path/to/jellyfin/config # the bind source for /config mkdir -p "$HOST_CONFIG/data/plugins/JellyMusicUploader_0.1.0.0" cp JellyMusicUploader.dll TagLibSharp.dll meta.json \ "$HOST_CONFIG/data/plugins/JellyMusicUploader_0.1.0.0/" docker restart jellyfin ``` ### 3. 配置插件 打开 **仪表板 → 插件 → Music Uploader** 并设置: | 字段 | 设置内容 | | --- | --- | | **Library Path** | 您音乐媒体库的绝对服务器端路径。对于 Docker,这是**容器内部**的路径(例如 `/data/music`),而不是主机路径。该路径必须已存在且可被 Jellyfin 写入。 | | **Max File Size (MB)** | 单个文件大小上限。`0` 表示禁用。默认 `200`。 | | **Allowed Extensions** | 以逗号分隔、小写、不带前导点号。默认值涵盖了大多数有损和无损音频格式以及封面图片格式。 | | **Trigger library scan after each batch** | 保持开启,除非有其他程序监视该文件夹。 | | **Allow overwriting** | 如果关闭,重新上传相同路径将返回 HTTP 409。 | 点击 **保存**。 ### 4. 将 JS 集成到 Jellyfin 网页客户端 这是唯一需要仔细操作的步骤。插件提供了一个 JS 文件,通过 `/musicup/frontend/js/uploader.js` 提供服务,但需要让 Jellyfin 加载它。 根据您的安装方式,有两条路径: #### 4a. 简洁方式:使用自定义 CSS 字段(适用于某些安装) 打开 **仪表板 → 通用 → 品牌 → 自定义 CSS** 并粘贴: ``` ``` 保存。在浏览器中强制刷新(Cmd-Shift-R / Ctrl-Shift-R)。 #### 4b. 可靠方式:直接编辑 `index.html` 插件的 JS 只需要在提供的 `index.html` 文件中添加一个 `#' /usr/share/jellyfin/web/index.html ``` **Docker** ``` docker exec jellyfin sh -c \ 'cp /usr/share/jellyfin/web/index.html /usr/share/jellyfin/web/index.html.bak-musicup && \ sed -i "s###" \ /usr/share/jellyfin/web/index.html' ``` 无需重启——该文件在每次页面请求时读取。只需在浏览器中**强制刷新**即可。 ## 使用方法 1. 以管理员身份登录 Jellyfin。 2. 右下角会出现 **+ 添加音乐** 按钮。 3. 点击它。模态窗口打开。 4. 从您的文件管理器中,将一个或多个 **Artist 文件夹** 拖放到拖放区域。预期的文件夹结构为 `Artist/Album/song.flac`。 您可以一次拖放多个 Artist 文件夹。 5. 模态窗口会预览它发现的内容——每个 Artist/Album 组合一行,显示曲目数量和总大小。 6. *(可选)* 点击任何行右侧的 **上传缩略图** 来为该专辑设置封面图片。一个 26×26 像素的缩略图预览会显示在旁边,还有一个小 × 用于清除它。 7. 点击 **上传**。文件会逐个上传,并显示进度条。 8. 批量上传完成后,插件会自动触发 Jellyfin 的媒体库扫描。新曲目(和您设置的任何封面)将在约 1 分钟内出现在媒体库中。 ### 文件夹结构规则 | 您拖放的内容 | 落地位置 | | --- | --- | | `Artist/Album/song.flac` | `/Artist/Album/song.flac` | | `Artist/song.flac` (无专辑文件夹) | `/Artist/Unknown Album/song.flac` | | `Artist/Album/Disc 1/song.flac` | `/Artist/Album/Disc 1/song.flac` (原样保留) | | 为某专辑选择的封面图片 | `/Artist/Album/cover.` | 封面文件遵循 Jellyfin 标准的 `cover.*` 约定——专辑封面也会自动应用到该文件夹中的所有曲目,无需为每个文件嵌入标签。 ## 标签工作原理 ### 问题所在 Jellyfin 的音乐媒体库是**基于标签的**,而不是基于文件夹的。当它扫描一个音乐文件夹时,它会读取每个文件中的 ID3 (MP3) / Vorbis (FLAC, OGG) / MP4 atom (M4A) 标签,并使用这些标签作为 Artist、AlbumArtist、Album 和 Title。它**不会**像从电影和电视剧的文件名推断那样,从文件夹结构中推断艺术家或专辑。 这很重要,因为拖放的文件通常来自标签不完善的来源: 在所有这些情况下,文件的 `artist` / `album_artist` / `album` 帧为空或错误。磁盘上的文件夹结构是 “TheBand / Ideas and Creations”,但 Jellyfin 读取文件,看到没有标签,就在媒体库界面中显示 **未知艺术家 / 未知专辑**。 您可以在任何文件上使用 `ffprobe` 验证这一点: ``` ffprobe -v error -show_entries format_tags=artist,album_artist,album,title \ -of default=noprint_wrappers=1 "/path/to/file.mp3" ``` 如果该命令没有输出,说明文件没有标签——Jellyfin 也将看不到任何内容。 ### 插件做了什么 当 **`NormalizeTagsFromFolder`** 开启(默认开启)时,插件会使用 TagLibSharp 打开它刚刚写入的每个音频文件,并设置: | 标签 | 来源 | 行为 | | --- | --- | --- | | Artist | 您拖放的顶层文件夹 (`parts[0]`) | **覆盖写入** | | AlbumArtist | 与 Artist 相同 | **覆盖写入** | | Album | 第二级文件夹,如果缺失则为 `"Unknown Album"` | **覆盖写入** | | Title | 去掉前导音轨号的文件名 | 如果为空则填充 | 因此,一个以 `TheBand/Ideas and Creations/01 You Keep Me Loving You mix # 1.mp3` 路径拖放的文件最终会带有: ``` Artist = TheBand AlbumArtist = TheBand Album = Ideas and Creations Title = You Keep Me Loving You mix # 1 (only if previously blank) ``` 前导的 `01 ` 被去掉了。它处理的其他模式包括:`01-`、`01.`、`01_`、`1-02 ` (音轨+碟片),以及任何组合(例如 `001 - `、`1-01. `)。尾部的扩展名会被移除。 ### 为什么“覆盖 Artist/Album 但仅填充 Title” 文件夹结构对于艺术家和专辑是**确定性的**——您在组织拖放内容时自己键入了这些文件夹名称,因此文件标签中之前存在的内容几乎肯定是错误或过时的。 而文件名有时是有效的曲目标题(`In your hands.mp3`),有时是垃圾(`track01.mp3`)。如果文件已经有 `Title` 标签,我们信任它——来自特定专辑的标题比从文件名猜测更可靠。如果它是空的,我们使用派生的文件名,而不是留空。 ### 何时关闭它 在插件配置页面禁用 `NormalizeTagsFromFolder` 的情况: - 您正在上传来自正确标记来源的文件(Bandcamp 发行、Discogs 标签的翻录、Beatport 下载),并且不希望任何内容被覆盖。 - 您在 MP3Tag / Picard / Mp3tag 中手动管理标签,磁盘上的文件已经是正确的。 禁用后,插件的行为就像一个纯文件移动器,Jellyfin 读取源文件嵌入的任何标签。 ## 配置参考 | 键 | 默认值 | 含义 | | --- | --- | --- | | `LibraryPath` | *空* | 绝对服务器端路径。**必填。** | | `MaxFileSizeMb` | `200` | 每个文件的大小上限(兆字节)。`0` 表示禁用。 | | `AllowedExtensions` | `mp3,flac,m4a,aac,ogg,opus,wav,wma,alac,aiff,jpg,jpeg,png,webp` | 以逗号分隔、小写、无点号。 | | `RefreshLibraryOnComplete` | `true` | 每批上传完成后触发 Jellyfin 的 `RefreshLibrary` 计划任务。 | | `AllowOverwrite` | `false` | 如果为 false,对相同相对路径的二次上传将返回 HTTP 409。 | | `NormalizeTagsFromFolder` | `true` | 写入每个音频文件后,根据文件夹结构 (`Artist/Album/song.ext`) 覆盖 Artist / AlbumArtist / Album 标签,并根据文件名设置 Title(去掉前导音轨号)。Title 仅在当前为空时设置。如果您的文件标签正确且不希望被修改,请禁用。 | ## API 参考 插件公开了这些端点,都位于 `/musicup` 下。 | 方法 | 路径 | 认证 | 描述 | | --- | --- | --- | --- | | GET | `/musicup/frontend/{**path}` | 匿名 | 提供网页客户端使用的嵌入式 JS。 | | GET | `/musicup/config` | 已认证用户 | 只读配置快照——UI 验证所需。 | | POST | `/musicup/upload` | 管理员 (`RequiresElevation`) | 多部分表单:`file` + `relativePath`。 | | POST | `/musicup/refresh` | 管理员 (`RequiresElevation`) | 触发 Jellyfin 的 `RefreshLibrary` 计划任务。 | 通过 `curl` 直接上传示例: ``` curl -X POST \ -H "X-Emby-Token: " \ -F "file=@/tmp/song.flac" \ -F "relativePath=Radiohead/OK Computer/01 Airbag.flac" \ https://your-jellyfin.example.com/musicup/upload ``` ## 安全模型 - 上传和刷新需要 `RequiresElevation` 策略(管理员用户或具有管理员作用域的 API 密钥)。 - 相对路径经过清理:没有 `..`、没有绝对路径、没有驱动器字母、没有空字节、没有保留文件名字符、没有空路径段。解析后,通过 `Path.GetFullPath` 前缀比较验证目标位置位于 `LibraryPath` 下——任何试图逃逸根目录的请求都会被 HTTP 400 拒绝。 - 文件先写入 `.part` 临时文件,成功后原子性地重命名。上传中途连接中断只会留下 `.part` 文件,而不会留下半写的 `.flac` 文件。 - 静态 `frontend` 路由仅解析 `JellyMusicUploader.Frontend.` 命名空间下的嵌入资源——无法枚举任意程序集。 ## 已知限制 - **全局媒体库扫描,而非仅音乐。** 刷新钩子执行 Jellyfin 的 `RefreshLibrary` 任务,它会扫描所有媒体库。在大型媒体库上,这可能需要几分钟;新曲目通常在扫描完全完成前就会出现,但“运行中任务”指示器会在整个扫描过程中保持显示。 - **自定义 CSS 注入不可靠。** 请参见安装步骤 4——较新的 Jellyfin 版本不会从自定义 CSS 字段注入 `` 这一行,或恢复安装程序留下的 `index.html.bak-musicup` 备份文件。 4. (可选)删除 `/data/plugins/configurations/` 下的 `JellyMusicUploader.xml` 以清除存储的设置。 5. 启动 Jellyfin。 ## 许可证 MIT — 详见 [LICENSE](LICENSE)。
标签:CMS安全, JavaScript, Jellyfin插件, TCP SYN 扫描, Web API, Web UI, 后端开发, 多人体追踪, 媒体服务器, 媒体服务器插件, 媒体管理, 封面艺术, 库扫描, 拖放上传, 插件开发, 数据可视化, 文件夹管理, 文件管理, 用户界面, 自动标签, 音乐上传, 音乐库, 音乐管理工具, 音频管理