6 Commits

Author SHA1 Message Date
91270
856a6777c7 Merge pull request #133 from Mayfly777w/master
迅雷字幕提供额外匹配选项
2026-01-11 23:21:02 +08:00
Mayfly777w
60ff15c57a 迅雷字幕提供额外匹配选项
迅雷字幕提供额外匹配选项,可以以元数据中的系列名和季集信息来作为匹配对象
影视/电影做了特殊处理,可以正常匹配
2026-01-01 22:25:42 +08:00
Meiam
0761c11a69 新增(Jellyfin): 为 Shooter 和 Thunder 插件添加图标并配置编译输出 2025-12-23 13:49:52 +08:00
Meiam
72ca0c5c39 docs: 恢复 README.md 中被误删的广告位内容 2025-12-22 20:10:56 +08:00
Meiam
2c02096298 docs: 深度美化 README.md 排版并更新特性说明 2025-12-22 20:08:26 +08:00
Meiam
2e622cda22 chore: 从版本库中移除 GEMINI.md (保留本地文件) 2025-12-22 19:37:48 +08:00
9 changed files with 151 additions and 175 deletions

BIN
.gitignore vendored

Binary file not shown.

View File

@@ -1,9 +1,13 @@
using MediaBrowser.Common;
using Emby.Web.GenericEdit;
using MediaBrowser.Common;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Plugins;
using MediaBrowser.Model.Serialization;
using System;
using System.ComponentModel;
using System.IO;
namespace Emby.MeiamSub.Thunder
@@ -12,10 +16,10 @@ namespace Emby.MeiamSub.Thunder
/// <summary>
/// 插件入口
/// </summary>
public class Plugin : BasePlugin, IHasThumbImage
public class Plugin : BasePluginSimpleUI<PluginConfiguration>, IHasThumbImage
{
public Plugin(IApplicationPaths applicationPaths)
public Plugin(IApplicationPaths applicationPaths, IApplicationHost applicationHost) : base(applicationHost)
{
Instance = this;
}
@@ -40,6 +44,10 @@ namespace Emby.MeiamSub.Thunder
/// </summary>
public ImageFormat ThumbImageFormat => ImageFormat.Gif;
/// <summary>
/// 获取插件选项
/// </summary>
public PluginConfiguration Options => this.GetOptions();
public static Plugin Instance { get; private set; }
@@ -64,4 +72,21 @@ namespace Emby.MeiamSub.Thunder
return stream;
}
}
/// <summary>
/// 插件配置类
/// </summary>
public class PluginConfiguration : EditableOptionsBase
{
public override string EditorTitle => "MeiamSub Thunder Options";
[Description("勾选此项后,使用元数据中的剧集名称和季集编号搜索字幕")]
public bool EnableUseMetadata { get; set; }
public PluginConfiguration()
{
// 默认值
EnableUseMetadata = false;
}
}
}

View File

@@ -1,16 +1,20 @@
using Emby.MeiamSub.Thunder.Model;
using MediaBrowser.Common;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Base;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
@@ -34,6 +38,9 @@ namespace Emby.MeiamSub.Thunder
protected readonly ILogger _logger;
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
private readonly IServiceRoot _serviceRoot;
private Plugin MainPlugin { get; set; }
public int Order => 100;
@@ -46,11 +53,14 @@ namespace Emby.MeiamSub.Thunder
#endregion
#region
public ThunderProvider(ILogManager logManager, IJsonSerializer jsonSerializer, IHttpClient httpClient)
public ThunderProvider(ILogManager logManager, IJsonSerializer jsonSerializer, IHttpClient httpClient, IApplicationHost applicationHost)
{
_logger = logManager.GetLogger(GetType().Name);
_jsonSerializer = jsonSerializer;
_httpClient = httpClient;
_serviceRoot = new ServiceRoot(applicationHost);
MainPlugin = _serviceRoot.GetService<IApplicationHost>().Plugins.OfType<Plugin>().FirstOrDefault();
_logger.Info("{0} Init", new object[1] { Name });
}
#endregion
@@ -80,6 +90,30 @@ namespace Emby.MeiamSub.Thunder
/// <returns></returns>
private async Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitlesAsync(SubtitleSearchRequest request)
{
// 修改人Mayfly777w
// 修改时间2026-01-01
// 备注:如果勾选采用元数据中的剧集名来作为字幕搜索匹配,则使用,否则默认用文件名
string MovieName;
if (MainPlugin.Options.EnableUseMetadata)
{
if (request.ContentType == VideoContentType.Episode)
{
MovieName = $"{request.SeriesName} S{request.ParentIndexNumber}E{request.IndexNumber}";
}
else if (request.ContentType == VideoContentType.Movie)
{
MovieName = request.Name;
}
else
{
MovieName = Path.GetFileName(request.MediaPath);
}
}
else
{
MovieName = Path.GetFileName(request.MediaPath);
}
// 修改人: Meiam
// 修改时间: 2025-12-22
// 备注: 增加异常处理
@@ -88,7 +122,7 @@ namespace Emby.MeiamSub.Thunder
{
var language = NormalizeLanguage(request.Language);
_logger.Info("{0} Search | Target -> {1} | Language -> {2}", Name, Path.GetFileName(request.MediaPath), language);
_logger.Info("{0} Search | Target -> {1} | Language -> {2}", Name, MovieName, language);
if (language != "chi")
{
@@ -105,7 +139,7 @@ namespace Emby.MeiamSub.Thunder
HttpRequestOptions options = new HttpRequestOptions
{
Url = $"https://api-shoulei-ssl.xunlei.com/oracle/subtitle?name={Path.GetFileName(request.MediaPath)}",
Url = $"https://api-shoulei-ssl.xunlei.com/oracle/subtitle?name={MovieName}",
UserAgent = $"{Name}",
TimeoutMs = 30000,
AcceptHeader = "*/*",

View File

@@ -1,68 +0,0 @@
# MeiamSubtitles 项目文档
## 项目概览
**MeiamSubtitles** 是一套为 **Emby****Jellyfin** 媒体服务器开发的 C# 字幕插件。它支持从 **迅雷影音****射手网** 自动下载中文字幕,并利用文件哈希匹配技术确保字幕的精确度。
## 项目结构
解决方案 `MeiamSubtitles.sln` 包含以下核心项目:
* **Emby 插件:**
* `Emby.MeiamSub.Shooter`: 射手网字幕提供程序 (目标框架: `netstandard2.1`)。
* `Emby.MeiamSub.Thunder`: 迅雷看看字幕提供程序 (目标框架: `netstandard2.1`)。
* **Jellyfin 插件:**
* `Jellyfin.MeiamSub.Shooter`: 射手网字幕提供程序 (目标框架: `net9.0`)。
* `Jellyfin.MeiamSub.Thunder`: 迅雷看看字幕提供程序 (目标框架: `net9.0`)。
* *注: Jellyfin 插件遵循现代 .NET 架构,通过 `PluginServiceRegistrator` 使用依赖注入来管理服务 (如 `IHttpClientFactory`)。*
* **开发工具:**
* `Emby.MeiamSub.DevTool`: 控制台应用程序,用于开发调试,特别是验证各平台字幕匹配所需的哈希计算逻辑。
## 编译与开发
### 环境要求
* .NET 9 SDK (用于编译 Jellyfin 插件)
* .NET Framework / .NET Core (支持 .NET Standard 2.1)
### 编译命令
在根目录下执行以下命令编译整个解决方案:
```bash
dotnet build MeiamSubtitles.sln
```
### 编译产出
项目配置了 `PostBuild` 事件,编译后的 DLL 文件会自动复制到:
1. 各项目目录下的 `..\Release`
2. 解决方案根目录下的 `Release``Debug` 文件夹。
### 开发调试工具
可以使用 `Emby.MeiamSub.DevTool` 在本地测试哈希算法:
```bash
cd Emby.MeiamSub.DevTool
dotnet run
```
*注:测试时需在 `Program.cs` 中修改对应的视频文件路径。*
## 安装指南
### 手动安装 (Emby/通用)
1. 编译项目或下载已发布的版本。
2. 将生成的 `.dll` 文件复制到服务器的插件目录:
* **Windows:** `Emby-Server\Programdata\Plugins\``Emby-Server\System\Plugins\`
* **Linux:** `/opt/emby-server/system/plugins``/var/lib/emby/plugins`
* **群晖 (Synology):** `/var/packages/EmbyServer/var/plugins`
3. 重启 Emby 服务。
### Jellyfin 安装
Jellyfin 支持通过插件存储库安装:
* **存储库 URL:** `https://github.com/91270/MeiamSubtitles.Release/raw/main/Plugin/manifest-stable.json`
***控制台 -> 插件 -> 存储库** 中添加此链接。
## 核心技术
* **C# / .NET:** 核心开发语言 (Jellyfin: .NET 9, Emby: .NET Standard 2.1)。
* **依赖注入 (Jellyfin)**: 使用 `IHttpClientFactory` 管理 HTTP 请求,符合 Jellyfin 现代插件架构。
* **异步编程**: 核心 I/O 操作 (文件哈希) 采用异步模式 (`ReadExactlyAsync`),防止阻塞服务器线程。
* **依赖库版本**:
* **Emby**: `MediaBrowser.Server.Core` (v4.9.1.90)
* **Jellyfin**: `Jellyfin.Controller` (v10.11.5)
* **哈希算法:** 实现了射手网和迅雷特定的 MD5/SHA1 哈希计算逻辑,用于视频内容的精确匹配。

View File

@@ -15,6 +15,12 @@
<PackageReference Include="Jellyfin.Controller" Version="10.11.5" />
</ItemGroup>
<ItemGroup>
<None Update="thumb.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="Copy $(TargetDir)$(TargetFileName) $(SolutionDir)$(ConfigurationName)\$(TargetFileName) /y&#xD;&#xA;" />
</Target>

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -15,6 +15,12 @@
<PackageReference Include="Jellyfin.Controller" Version="10.11.5" />
</ItemGroup>
<ItemGroup>
<None Update="thumb.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="Copy $(TargetDir)$(TargetFileName) $(SolutionDir)$(ConfigurationName)\$(TargetFileName) /y&#xD;&#xA;" />
</Target>

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

175
README.md
View File

@@ -1,133 +1,106 @@
# MeiamSubtitles
Emby & Jellyfin 中文字幕插件,支持 **迅雷影音**、**射手网** 字幕自动下载与精准 Hash 匹配。
# 🎬 MeiamSubtitles
[![.NET Status](https://img.shields.io/badge/.NET-Standard%202.1%20%7C%209.0-blueviolet.svg)](#)
[![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20Win%20%7C%20OSX-brightgreen.svg)](#)
[![LICENSE](https://img.shields.io/badge/license-Apache%202-blue)](#)
[![Star](https://img.shields.io/github/stars/91270/Emby.MeiamSub?label=Star%20this%20repo)](https://github.com/91270/Emby.MeiamSub)
[![Fork](https://img.shields.io/github/forks/91270/Emby.MeiamSub?label=Fork%20this%20repo)](https://github.com/91270/Emby.MeiamSub/fork)
[![博客](https://img.shields.io/badge/博客-Meiam's%20Home-brightgreen.svg)](https://www.592.la/)
**MeiamSubtitles** 是一款专为 **Emby****Jellyfin** 媒体服务器打造的中文字幕下载插件。它集成了 **迅雷影音****射手网** 的强大搜索能力支持精准的视频哈希Hash匹配让您的媒体库自动补全高质量字幕。
&nbsp;
---
## 给个星星! ⭐️
<p align="left">
<img src="https://img.shields.io/badge/.NET-Standard%202.1%20%7C%209.0-blueviolet.svg" alt=".NET Status">
<img src="https://img.shields.io/badge/Platform-Linux%20%7C%20Win%20%7C%20OSX-brightgreen.svg" alt="Platform">
<img src="https://img.shields.io/badge/license-Apache%202-blue" alt="LICENSE">
<a href="https://github.com/91270/Emby.MeiamSub"><img src="https://img.shields.io/github/stars/91270/Emby.MeiamSub?label=Star%20this%20repo" alt="Star"></a>
<a href="https://www.592.la/"><img src="https://img.shields.io/badge/博客-Meiam's%20Home-brightgreen.svg" alt="博客"></a>
</p>
如果你喜欢这个项目或者它帮助你, 请给 Star~(辛苦咯)
## 📣 广告时间
如果你能赞助稳定 Google Drive 团队盘用于媒体库插件测试, 请于我联系 91270#QQ.COM
> **搬瓦工 $99 年付**建站神器重出江湖THE PLAN V1 传家宝套餐18机房随意切换。
> **循环优惠码**`BWHCCNCXVV` (6.77%)
> **[直达通道 (传家宝套餐)](https://bwh88.net/aff.php?aff=117&pid=87)**
&nbsp;
## ✨ 核心特性
## 广告时间 📣
- **🚀 精准匹配**: 支持迅雷看看 (CID) 和射手网 (Hash) 双重校验逻辑,确保字幕与视频内容完美同步。
- **⚡ 极致性能**: 核心采样算法全面采用**异步 I/O (Async/Await)** 模式,在大规模媒体库扫描时不会阻塞服务器线程。
- **🌐 广泛兼容**: 深度适配 **Jellyfin 10.11+****Emby v4.9+**,支持 `zho``chi` 等多种国际化语言代码映射。
- **🛡️ 稳定可靠**: 针对射手网 API 的老化问题增加了防御性校验,能有效处理乱码返回,保证系统长效稳定。
- **📝 详尽日志**: 记录哈希计算耗时与接口原始响应,让问题排查不再是黑盒。
搬瓦工 $99 年付, 建站神器重出江湖THE PLAN V1 传家宝套餐18机房随意切换
## 📦 项目组件说明
循环优惠码BWHCCNCXVV6.77%
| 组件名称 | 适用平台 | 目标框架 | 说明 |
| :--- | :--- | :--- | :--- |
| **Emby.MeiamSub.Thunder** | Emby | .NET Standard 2.1 | 迅雷看看字幕插件 |
| **Emby.MeiamSub.Shooter** | Emby | .NET Standard 2.1 | 射手影音字幕插件 |
| **Jellyfin.MeiamSub.Thunder** | Jellyfin | .NET 9.0 | 迅雷看看字幕插件 (现代 DI 架构) |
| **Jellyfin.MeiamSub.Shooter** | Jellyfin | .NET 9.0 | 射手影音字幕插件 (现代 DI 架构) |
| **Emby.MeiamSub.DevTool** | 开发调试 | .NET 8.0 | 哈希算法测试与 API 模拟工具 |
[直达通道(传家宝套餐)](https://bwh88.net/aff.php?aff=117&pid=87)
---
&nbsp;
## 🚀 快速安装
## 功能介绍
### 第一步:获取插件
前往 [GitHub Releases](https://github.com/91270/Emby.MeiamSub/releases) 下载最新版本的发布包。
- [x] **迅雷影音**: 支持通过文件 Hash (CID) 精准匹配字幕
- [x] **射手网**: 支持通过文件 Hash 精准匹配字幕。
- [x] **高性能**: 核心哈希计算采用异步 I/O (Async/Await) 模式,避免阻塞服务器线程。
- [x] **稳定性**: 内置重试机制与异常处理Jellyfin 版本采用现代化的依赖注入架构。
> **🔔 推荐建议**:在媒体库设置中**不勾选**本插件作为默认自动下载器。建议仅在手动“搜索字幕”时使用,以获得更精准的人工筛选体验
## 项目说明
### 第二步:部署插件
| # | 模块功能 | 项目名称 | 说明 |
|---|---|---|---|
| 1 | Emby 插件 | `Emby.MeiamSub.Thunder` | 迅雷看看字幕插件 (.NET Standard 2.1) |
| 2 | Emby 插件 | `Emby.MeiamSub.Shooter` | 射手影音字幕插件 (.NET Standard 2.1) |
| 3 | Jellyfin 插件 | `Jellyfin.MeiamSub.Thunder` | 迅雷看看字幕插件 (.NET 9.0) |
| 4 | Jellyfin 插件 | `Jellyfin.MeiamSub.Shooter` | 射手影音字幕插件 (.NET 9.0) |
| 5 | 开发工具 | `Emby.MeiamSub.DevTool` | 哈希算法测试与调试工具 |
#### 🔹 方式 AJellyfin 存储库安装 (强烈推荐)
Jellyfin 用户可直接添加官方存储库,实现一键安装与自动更新:
1. 控制台 -> **插件** -> **存储库** -> 点击“添加”。
2. 输入名称 `MeiamSub` 和 URL
`https://github.com/91270/MeiamSubtitles.Release/raw/main/Plugin/manifest-stable.json`
3. 在“目录”中找到插件并安装,重启服务即可。
## 使用插件
#### 🔹 方式 B手动安装 (Emby/通用)
将下载的 `.dll` 文件Jellyfin 用户请下载 `.zip` 并解压完整目录)放入服务器的 `plugins` 文件夹:
首先下载已编译好的插件 [Release 下载](https://github.com/91270/Emby.MeiamSub/releases)。
- **Windows**: `AppData\Local\jellyfin\plugins``Emby-Server\programdata\plugins`
- **Linux/Docker**: `/config/plugins``/var/lib/emby/plugins`
- **群晖/威联通**: 对应套件安装目录下的 `plugins` 文件夹
**注意**:建议在媒体库设置中**不勾选**本插件作为默认下载器,仅在手动“编辑字幕”或“搜索字幕”时使用,以获得最佳体验。
---
## 常见问题排查 (FAQ)
## 常见问题排查 (FAQ)
如果您在搜索字幕时遇到“未找到结果”,请按以下步骤排查:
<details>
<summary><b>1. 为什么在 Jellyfin 10.11+ 中搜不到字幕?</b></summary>
新版 Jellyfin 采用了三位字母的语言代码(如 <code>zho</code>)。请确保您已升级至本插件的 <b>v1.0.13.0</b> 或更高版本,该版本已完美解决语言映射兼容性。
</details>
### 1. 语言代码识别
- **现象**: 在 Jellyfin 10.11+ 中搜索不到字幕。
- **原因**: 新版 Jellyfin 可能会传递三位字母代码 (如 `zho`)
- **解决**: 本插件最新版已修复该问题,支持 `zho``chi``zh-CN` 等多种映射。请确保您使用的是最新版本的 DLL。
<details>
<summary><b>2. 为什么射手网有时候返回结果为空?</b></summary>
由于射手网 API 维护状态不佳,对于部分冷门资源或 Hash 不匹配的文件API 可能会返回非法数据。插件目前已增加防御逻辑,会自动忽略这些无效返回以保护服务器稳定
</details>
### 2. 射手网 API 状态
- **现象**: 部分电影能搜到,部分完全搜不到。
- **原因**: 射手网 API 年久失修,对于无资源或 Hash 不匹配的文件API 可能返回异常内容(如乱码)
- **表现**: 插件已增加防御性校验,若检测到 API 返回异常,会自动过滤并返回空结果以保证系统稳定。
<details>
<summary><b>3. 安装本插件后会影响 Open Subtitles 吗?</b></summary>
不会。本插件已将优先级 (Order) 调整为 100低优先级并在代码层面优化了并发逻辑确保官方插件能优先获取请求机会
</details>
### 3. 如何反馈问题
如果遇到确定有字幕但搜不到的情况,请查看服务器日志并提供以下关键信息:
- 搜索开始时的 `Target` 文件名
- 接口返回的 `ResponseBody` 内容。
- 计算得到的 `FileHash` 值。
<details>
<summary><b>4. 如何提供有效的错误反馈?</b></summary>
如果确定有字幕但搜不到,请在 Issue 中提供日志里的 <code>Target</code> 文件名、计算出的 <code>FileHash</code> 以及 <code>ResponseBody</code> 内容
</details>
## Jellyfin 安装 (推荐)
---
Jellyfin 用户可以通过添加插件存储库实现一键安装和自动更新:
## 🤝 贡献与感谢
1. 打开 Jellyfin 控制台 -> **插件** -> **存储库**
2. 点击添加,输入名称 (如 MeiamSub) 和以下 URL
```
https://github.com/91270/MeiamSubtitles.Release/raw/main/Plugin/manifest-stable.json
```
3. 保存后在插件目录中找到 **MeiamSub.Thunder** 和 **MeiamSub.Shooter** 进行安装。
4. 重启 Jellyfin 服务。
欢迎通过提交 Issue 或 Pull Request 来完善本项目
### 手动安装 (Emby / 通用)
- **开发守则**: 遵循异步命名规范,所有修改请标注 `修改人: Meiam`
- **致谢**: 感谢 [Emby.Subtitle.Subscene](https://github.com/nRafinia/Emby.Subtitle.Subscene) 提供的灵感与参考。
将下载的 `.dll` 文件复制到服务器的插件目录,然后重启服务。
---
#### Windows
```bash
# 路径可能因安装方式不同而异
Emby-Server\Programdata\Plugins\
# 或
Emby-Server\System\Plugins\
```
## ⭐️ 给个星星
#### Linux / Docker
```bash
# 常见路径
/opt/emby-server/system/plugins
# 或
/var/lib/emby/plugins
```
如果你喜欢这个项目,请给一个 **Star**!这对我非常重要。
#### 群晖 (Synology)
如果你有稳定的 Google Drive 团队盘资源可供媒体库插件测试,欢迎联系:`91270#QQ.COM`
```bash
/var/packages/EmbyServer/var/plugins
# 或
/var/packages/EmbyServer/target/system/plugins
```
#### 威联通 (QNAP)
```bash
# 其中`CACHEDEV{num}_DATA`的名称取决于你的qpkg安装位置
/share/CACHEDEV1_DATA/.qpkg/EmbyServer/programdata/plugins
/share/CACHEDEV1_DATA/.qpkg/EmbyServer/system/plugins
```
&nbsp;
## 贡献
欢迎提交 Issue 反馈问题,或提交 Pull Request 贡献代码。
* **开发分支**: `master`
* **代码风格**: 请遵循现有的 C# 代码风格,异步方法请使用 `Async` 后缀。
## 致谢
[Emby.Subtitle.Subscene](https://github.com/nRafinia/Emby.Subtitle.Subscene)
---
*Powered by Meiam*