Skip to content

Repository files navigation

BDMV → Emby Builder

BDMV → Emby Builder 只读分析 Blu-ray BDMV,根据 MPLS 播放关系识别电影、剧集和附加内容,并生成适合 Emby 扫描的派生媒体目录。完整单 M2TS 可以直接复制或硬链接;确属同一逻辑视频的分段和裁切范围则无损重封装,不重新编码视频、音频或字幕。

本项目源于作者的个人使用需求。 开发目的是在保留原始 BDMV 的同时,更方便地生成符合 Emby 命名和目录习惯的媒体库。代码公开在 GitHub,主要用于留存项目,也希望能为有类似需求的用户提供参考或直接使用。项目将随作者自身需求不定期更新,目前没有固定的维护计划或功能路线图。

真实原盘的扫描、规划和构建目前只在 macOS 上验证过;代码和自动化测试包含 Linux、Windows 兼容处理,但尚未在这两个系统上完成真实 BDMV 与 libbluray 工作流验证。

本项目是非官方工具,与 Emby LLC 或 Blu-ray Disc Association 没有隶属、授权或背书关系。

功能

  • 递归发现单张或多张 BDMV,读取 META、MPLS、PlayItem、Entry Mark、连接条件、多角度、SubPath 和 SubPlayItem;
  • 离线选择电影主标题、拆分剧集 episode,并收集同盘或纯特典盘中的附加内容;
  • 支持一集一个 M2TS、一集跨多个 M2TS,以及有充分 playlist/章节证据时一个 M2TS 包含多集的结构;
  • 排除重复 playlist、菜单循环和明显的交互导航结构;
  • 支持直接复制、硬链接和无损重封装三种处理策略;
  • 输出可审核的计划、dry-run、构建结果和状态文件;
  • 写入前检查路径、文件身份、硬链接能力和剩余空间,写入后检查时长、轨道和时间线;
  • 不访问在线元数据服务,不移动、重命名或修改源 BDMV。

程序不执行 BD-J 菜单,也不能稳定取得花絮的自然语言名称。无法充分证明的逻辑边界会保持整体或产生警告,不会使用作品名、盘号或固定 playlist ID 特判。

系统要求

  • Python 3.11 或更高版本;
  • FFmpeg 和 FFprobe;
  • 普通完整 playlist 需要多段或裁切重封装时,FFmpeg 必须支持 libbluray 的 bluray protocol。

项目没有第三方 Python 运行时依赖。建议安装到项目内虚拟环境:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e .
bdmv-emby-builder --help

macOS 可通过 Homebrew 安装带 libbluray 的构建:

brew install ffmpeg-full

仅当当前 shell 没有找到 ffmpeg-full 时,才需要调整 PATH。也可以使用环境变量或 TOML 指定程序位置:

export BDMV_EMBY_FFMPEG="/path/to/ffmpeg"
export BDMV_EMBY_FFPROBE="/path/to/ffprobe"

Linux 和 Windows 需要自行安装带 libbluray 的 FFmpeg 构建。无论使用哪个平台,都应先检查实际生效的程序:

bdmv-emby-builder doctor

涉及普通 playlist 重封装时,检查结果中的 bluray_protocol 应为 true

快速开始

复制 config.example.toml 为本地任务文件,例如 task.toml

[task]
source = "/absolute/path/to/BDMV_LIBRARY"
destination = "/absolute/path/to/EmbyLibrary"

[[disc]]
path = "Movie/MAIN_DISC"
disc_type = "movie"
processing = "copy_remux"

[[disc]]
path = "Movie/BONUS_DISC"
disc_type = "bonus"
title = "Movie Name"

推荐执行顺序:

# 检查环境
bdmv-emby-builder doctor --config task.toml

# 生成计划,不写媒体
bdmv-emby-builder plan --config task.toml --out plan.json

# 解析最终 copy / hardlink / remux 动作,不写媒体
bdmv-emby-builder build plan.json --results dry-run-results.json

# 先构建一个任务并播放确认
bdmv-emby-builder build plan.json --execute \
  --only JOB_ID --results one-job-results.json

# 执行完整计划
bdmv-emby-builder build plan.json --execute \
  --results build-results.json

# 检查目标库状态
bdmv-emby-builder status "/absolute/path/to/EmbyLibrary"

可选的 scan 命令用于导出更底层的只读结构:

bdmv-emby-builder scan "/absolute/path/to/BDMV_LIBRARY" --out scan.json

plan.json 是程序生成的审核产物,不是人工配置文件。重新规划后应重新执行 dry-run,不要手工修改计划后继续构建。

配置

每个 TOML 文件描述一次任务。[task] 保存本次输入和输出;每个 [[disc]] 保存一张盘需要人工指定的类别、作品归属和处理策略。

[task]

字段 必填 说明
source 单张盘根目录或包含多张盘的根目录;其下应能发现 BDMV,不能直接指向 BDMV 本身
destination Emby 派生媒体根目录,不能位于 source

建议使用绝对路径。命令行位置参数可以临时覆盖这两个字段。

[[disc]]

字段 必填 说明
path 多盘任务需要 相对于 task.source 的盘目录;单盘任务可以省略
disc_type movieseriesbonusignore
title 覆盖作品目录名,或把主盘、特典盘和多版本归入同一作品
edition 同作品、同分辨率存在多个剪辑时使用的版本标签
processing copy_remuxhardlink_remuxhardlink_only
hardlink_only_failure block_discskip_job,仅影响 hardlink_only
season 仅限 series;覆盖季号,0 表示 Specials
episode_start 仅限 series;指定该盘第一集集号

disc_type 表示盘的主要用途,不限制盘内只能存在一种内容:

  • movie:选择一部电影主标题,其余有效内容进入 extras 候选;
  • series:识别一个或多个 episode,其余有效内容进入 extras 候选;
  • bonus:不选择正片,全部有效内容按 extras 规则筛选;
  • ignore:忽略该盘。

配置不接受 playlist ID、单条花絮名称或单独的输出文件名。程序负责技术规划,用户负责确认作品归属、季号、多版本以及无法从 BDMV 判断的内容语义。

作品标题按以下优先级确定:

  1. [[disc]].title
  2. 命令行 --title
  3. BDMV META 日文标题;
  4. META 英文或其他标题;
  5. 盘目录名。

季号按 [[disc]].season、命令行 --season、META/目录中的明确季标、默认第 1 季依次确定。默认季号会在计划中标记为低置信度;同一作品、季和 edition 的多张盘会连续编号,必要时可用 episode_start 修正起始集数。

[settings]

所有设置均可省略。

字段 默认值 说明
extra_min_seconds 60 附加内容候选最低时长
container "m2ts" 输出容器,可选 m2tsmkv
extras_folder "extras" 本次任务统一使用的 Emby 附加内容目录
remux_backend "auto" autobluray 或显式接受限制的 concat
copy_boundary_tolerance_seconds 0.1 判断 PlayItem 是否完整覆盖 M2TS 的边界误差
duration_tolerance_seconds 2.0 成品相对 MPLS 逻辑时长的允许误差
minimum_free_space_bytes 5368709120 目标卷固定最小剩余空间
free_space_margin_ratio 0.05 目标文件系统容量预留比例
batch_space_check true 执行前检查整批任务空间
hardlink_only_failure "block_disc" hardlink_only 失败时整盘阻塞或逐项跳过
ffmpeg "ffmpeg" FFmpeg 命令或路径
ffprobe "ffprobe" FFprobe 命令或路径

识别规则

主标题优先采用本盘 FFmpeg/libbluray 的相关标题结果;不可用时才回退到本盘最长有效候选并产生警告。对于 BDMV META 标题具有连续编号的电影合集,程序会比较无歧义同行盘的本地选择;如果相同 playlist 编号在目标盘上也对应合理长候选但与本盘结果冲突,只记录审核提示,不自动覆盖本盘选择。编号连续、至少两张同行盘支持且覆盖全部同行盘 80% 以上时标为强提示;能形成唯一建议但不满足这些条件时标为弱提示。该提示本身不会增加构建阻塞,实际可执行性仍由所选处理模式、源文件完整性和安全校验决定。计划会按所选模式处理本盘主标题,并把符合附加内容筛选条件的其他有效长候选写入 extras/,供用户播放后在派生目录中更名或移动。

剧集拆分优先使用原盘明确关系,包括完整独立 PlayItem、连续覆盖主标题的独立单集 playlist,以及具有可靠 Entry Mark、连接条件和时长旁证的 PlayItem/章节分组。多角度、逻辑连续连接、重复 clip、无法证明安全的 SubPath 或边界证据不足时不会拆分。

程序会对满足严格条件的短时静音、静态系统卡进行复核。电影硬链接模式只有在计划和构建阶段都能重新证明时才允许排除;低置信度的短 extras 只增加人工复核提示,不会自动删除。该功能不使用 OCR。

完整识别约束见处理与重封装设计

处理策略

模式 完整单 M2TS 分段或裁切内容 适合场景
copy_remux 逐字节复制 无损重封装 默认;希望派生库与原盘文件身份独立
hardlink_remux 同文件系统优先硬链接,失败时复制 无损重封装 希望减少一对一文件的额外空间占用
hardlink_only 只允许硬链接 不处理 只接受零额外媒体数据的一对一映射

重封装使用 stream copy,主要消耗磁盘读写,CPU 占用通常远低于转码。

hardlink_only 默认在同盘任一已规划输出无法硬链接时阻塞整盘。设置 hardlink_only_failure = "skip_job" 后,只跳过无法硬链接的已规划输出,不会降级为复制或重封装。若主标题本身无法可靠识别,规划仍会直接失败。

硬链接成品与源 M2TS 共享文件内容。删除或重命名一侧目录项不会删除另一侧,但原地修改任一文件会同时影响两边;应把硬链接媒体视为只读。

输出与附加内容

电影和剧集使用 Emby 常见目录结构:

EmbyMovies/
└── Movie Name/
    ├── Movie Name - 1080p.m2ts
    └── extras/
        └── Bonus Disc - PL00004-P01 - 000042.m2ts

EmbyTV/
└── Series Name/
    ├── Season 01/
    │   ├── Series Name - S01E01 - 1080p.m2ts
    │   └── Series Name - S01E02 - 1080p.m2ts
    └── extras/

分辨率标签来自选中正片的实际视频流。

附加内容必须人工复核

程序默认把识别出的附加内容统一写入作品目录下的 extras/,文件名仅由盘标题、playlist/分段编号和时长组成。这个文件名用于稳定定位来源,不表示程序已经判断出内容类别。

BDMV 通常不能可靠说明一段内容是预告、访谈、OP/ED、广播内容还是幕后花絮。构建完成后,用户应逐项播放确认,并仅在 Emby 派生目录中自行更名或移动到合适的分类目录。

extras_folder 可以把整个任务的附加内容改为 Emby 支持的其他目录,例如 specialsshortsscenesfeaturettesbehind the scenesdeleted scenesinterviewstrailers,但不会逐条自动分类。需要参与剧集刮削和播放顺序的正式 Special 应人工放入 Season 00Specials,并按 S00E01 等格式命名。具体规则以 Emby 电影命名剧集命名文档为准。

审核与安全

执行前至少确认:

  • warnings、正片/episode/extras 数量和 playlist_selection
  • main_selection_evidence 中的本盘选择、合理长候选及跨盘提示;
  • 季号、集号、多版本归属和输出路径;
  • playlist_segment、源 M2TS、in/out 范围;
  • dry-run 中的最终 operation 和预计空间;
  • 标记为 content_review 的附加内容。

scanplan 和未加 --executebuild 不写媒体。实际构建只在目标根中创建文件,默认不覆盖已有成品;使用 --overwrite 前应先确认目标。媒体先写入随机临时文件,校验通过后再原子替换。构建结果和目标目录中的 .bdmv-emby-state.json 会保留主标题选择证据;status 同时展示该证据,并检查缺失、内容变化及硬链接身份。

任务 TOML、scan、plan、results 和 state 通常包含绝对路径、目录名和媒体库清单,应视为本地隐私数据,不要未经检查上传。更完整的边界见隐私与安全

原始 BDMV 是源归档,Emby 目录是派生数据。两者位于同一块硬盘时不构成备份;确认输出前不要删除原盘,正式备份应位于独立存储介质。

已知限制

  • 自动主标题选择、同盘多部长片、多剪辑版和复杂多角度内容仍需人工审核;
  • 花絮自然语言名称和语义类别通常不能从 BDMV 稳定获得;
  • M2TS 对章节及丰富轨道元数据的表达有限,章节主要保存在计划和状态中;
  • 重新规划不会自动删除旧计划不再引用的派生文件;
  • 真实原盘工作流目前只在 macOS 验证,Linux 和 Windows 用户应先用少量内容测试。

许可证

本项目采用 MIT License

About

Safely copy, hardlink, or losslessly remux BDMV playlists into an Emby-ready M2TS library.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages