跳过正文
  1. 文章/

在 Plex 中整理本地讲座视频并添加 Metadata

·502 字·3 分钟
作者
Yang Hu

如何将本地讲座/课程视频(没有 TMDB/TVDB 收录的)在 Plex 中整理成结构清晰的电视节目,并通过 Plex API 写入自定义描述文字。

示例是 Jonathan Biss 的 Exploring Beethoven’s Piano Sonatas——Curtis 音乐学院与 Coursera 合作的 5 部分课程,存储在 Synology NAS 上。

问题
#

Plex 默认的 metadata 爬虫依赖 TMDB 或 TVDB。没有收录的本地讲座视频要么显示成一堆无封面的乱列表,要么被错误匹配到不相关的节目。

解决方案:将课程当作**电视节目(TV Show)**处理,使用 Plex 的 Personal Media Shows 代理,再通过 Plex API 推送自定义 metadata。

第一步:按 Season/Episode 结构整理文件
#

Plex 的 TV Show 扫描器要求文件名包含 SxxExx

1
2
3
4
5
6
7
Exploring Beethoven's Piano Sonatas/
├── Season 01/
│   ├── Exploring Beethoven's Piano Sonatas - S01E01 - Lecture 1, Part 1.mp4
│   ├── Exploring Beethoven's Piano Sonatas - S01E01 - Lecture 1, Part 1.en.srt
│   └── ...
├── Season 02/
└── ...

每个"讲"对应一个 Season,每个"Part"对应一集。字幕文件放在视频旁边,命名加 .en.srt 后缀,Plex 会自动识别为英文字幕。

用一个 shell 脚本批量重命名和移动文件,支持 --dry-run 预览:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash
BASE="/volume1/data/media/courses/Exploring Beethoven's Piano Sonatas"
SHOW="Exploring Beethoven's Piano Sonatas"
DRY_RUN=false
[[ "$1" == "--dry-run" ]] && DRY_RUN=true

for file in "$BASE"/*.mp4; do
    filename=$(basename "$file")
    S=$(echo "$filename" | sed 's/^\([0-9]*\) - .*/\1/')
    E=$(echo "$filename" | sed 's/^[0-9]* - \([0-9]*\) - .*/\1/')
    TITLE=$(echo "$filename" | sed 's/^[0-9]* - [0-9]* - //' | sed 's/ ([^)]*)\.[^.]*$//')
    SS=$(printf "%02d" "$S"); EE=$(printf "%02d" "$E")
    mkdir -p "$BASE/Season $SS"
    mv "$file" "$BASE/Season $SS/${SHOW} - S${SS}E${EE} - ${TITLE}.mp4"
done

# 将字幕从 srts/ 子文件夹移到对应 Season 目录
for file in "$BASE/srts"/*.srt; do
    filename=$(basename "$file")
    S=$(echo "$filename" | sed 's/^\([0-9]*\) - .*/\1/')
    E=$(echo "$filename" | sed 's/^[0-9]* - \([0-9]*\) - .*/\1/')
    TITLE=$(echo "$filename" | sed 's/^[0-9]* - [0-9]* - //' | sed 's/ ([^)]*)\.[^.]*$//')
    SS=$(printf "%02d" "$S"); EE=$(printf "%02d" "$E")
    mv "$file" "$BASE/Season $SS/${SHOW} - S${SS}E${EE} - ${TITLE}.en.srt"
done

第二步:配置 Plex 资料库
#

在 Plex 中新建资料库:

  • 类型: 电视节目(TV Shows)
  • 文件夹: 指向节目根目录(或 courses/ 父目录)
  • 高级 → 代理: Personal Media Shows
  • 高级: 勾选"优先使用本地 metadata"

保存后扫描,Plex 会自动从文件名识别出所有季和集。

第三步:通过 Plex API 写入描述文字
#

Personal Media Shows 不会从任何地方拉取描述。可以在 Plex UI 里手动编辑,但有多季时用 API 批量推送更方便。

获取 Plex Token
#

Plex Web → 播放任意视频 → “…” → “获取信息” → “查看 XML”,URL 中有 X-Plex-Token=XXXXX

核心 API 调用
#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import urllib.request, urllib.parse, json

BASE = "http://plex.nas:32400"
TOKEN = "your-token-here"

def plex_get(path, params=None):
    url = BASE + path
    if params:
        url += "?" + urllib.parse.urlencode(params)
    req = urllib.request.Request(url)
    req.add_header("X-Plex-Token", TOKEN)
    req.add_header("Accept", "application/json")
    with urllib.request.urlopen(req) as r:
        return json.loads(r.read())

# 列出所有资料库
sections = plex_get("/library/sections")

# 列出某个资料库的所有节目(key=7)
shows = plex_get("/library/sections/7/all")

# 更新节目描述(type=2)或季描述(type=3)
def set_summary(section_key, rating_key, item_type, summary):
    params = {
        "type": item_type,
        "id": rating_key,
        "summary.value": summary,
        "summary.locked": 1,
    }
    url = f"{BASE}/library/sections/{section_key}/all?" + urllib.parse.urlencode(params)
    req = urllib.request.Request(url, method="PUT")
    req.add_header("X-Plex-Token", TOKEN)
    urllib.request.urlopen(req)

summary.locked=1 可以防止 Plex 在下次刷新 metadata 时覆盖你写入的文字。

完整脚本逻辑
#

脚本自动发现节目和所有季,然后逐一推送预先写好的描述:

1
2
3
4
5
6
7
section_key, show_key = find_show(base_url, token, SHOW_TITLE)
seasons = get_seasons(base_url, token, show_key)

set_summary(section_key, show_key, 2, SHOW_SUMMARY)           # 节目级描述
for season in seasons:
    idx = season["index"]
    set_summary(section_key, season["ratingKey"], 3, SEASON_SUMMARIES[idx])

注意事项
#

  • 如果 Plex 自动匹配了错误的节目,可以在 UI 中"修正匹配 → 无",或将资料库代理切换为 Personal Media Shows 后重新扫描。
  • Plex 显示的节目标题可能和文件夹名不同(取决于之前匹配到了什么)。在搜索前先通过 API(/library/sections/{key}/all)确认实际标题。
  • 海报图片:在节目根目录放一张 poster.jpg,Plex 会自动读取。