用Python+Watchdog构建Emby Server智能推送系统:从零到Docker化部署

每次下载新影片后,你是否还在反复刷新Emby页面等待它出现在媒体库?作为资深影音爱好者,我花了三个周末时间研究出一套完全自动化的解决方案——当Emby Server检测到新文件时,系统会自动解析影片信息并通过Telegram推送通知到手机,整个过程无需人工干预。最令人惊喜的是,整个系统可以打包成仅69.5MB的Docker镜像,部署只需一条命令。

1. 系统架构设计原理

这个自动化系统的核心在于事件驱动架构。当Emby Server完成新影片的元数据刮削后,会在媒体库目录生成.nfo描述文件。我们的系统通过Watchdog模块监听这些.nfo文件的创建事件,触发后续处理流程。

整个工作流可以分为四个关键阶段:

  1. 文件监听层:Watchdog实时监控指定目录的文件系统事件
  2. 数据解析层:使用ElementTree解析.nfo文件获取基础元数据
  3. 信息增强层:通过TMDB API补充高清海报和详细演职员信息
  4. 通知推送层:格式化消息内容并通过Telegram Bot API发送
# 简化的核心事件处理逻辑
from watchdog.events import FileSystemEventHandler

class EmbyHandler(FileSystemEventHandler):
    def on_created(self, event):
        if event.src_path.endswith('.nfo'):
            metadata = parse_nfo(event.src_path)
            enriched_data = fetch_tmdb_data(metadata)
            send_telegram_notification(enriched_data)

这种设计有三大优势:

  • 低延迟:文件创建事件触发后平均300ms内完成处理
  • 低开销:仅在有新文件时才激活处理逻辑
  • 可扩展:各层功能独立,方便后续添加其他通知渠道

2. 环境准备与依赖配置

2.1 基础环境要求

推荐使用Python 3.10+环境以获得最佳兼容性。以下是必需的核心依赖:

pip install watchdog requests python-dotenv

注:v2.x版本已移除对xmllint的依赖,使镜像体积减少70%

2.2 关键API凭证获取

需要提前准备三个关键凭证:

服务 获取方式 环境变量名
Telegram Bot 与@BotFather对话创建 BOT_TOKEN
Telegram频道 将Bot添加为频道管理员,访问https://api.telegram.org/bot<TOKEN>/getUpdates获取 CHAT_ID
TMDB API 注册开发者账号申请API Key TMDB_API

提示:TMDB API申请时需要提供应用描述,可填写"用于个人媒体库信息管理"

3. 核心代码实现解析

3.1 文件监控服务

使用Watchdog的Observer模式实现持久化监听:

from watchdog.observers import Observer

observer = Observer()
observer.schedule(EmbyHandler(), path=MEDIA_PATH, recursive=True)
observer.start()

try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    observer.stop()
observer.join()

关键参数说明:

  • recursive=True 监控所有子目录
  • MEDIA_PATH 应设置为Emby媒体库的挂载路径
  • 使用KeyboardInterrupt优雅退出

3.2 元数据增强处理

.nfo文件仅包含基础信息,通过TMDB API获取高清海报和演职员详情:

def fetch_tmdb_data(title, year):
    params = {
        'api_key': TMDB_API,
        'query': title,
        'year': year,
        'language': 'zh-CN'
    }
    response = requests.get('https://api.tmdb.org/3/search/movie', params=params)
    if response.status_code == 200:
        return response.json().get('results', [])[0]
    return None

处理时需注意:

  • 中文搜索需设置language=zh-CN
  • 剧集需使用/search/tv端点
  • 建议添加异常处理和重试逻辑

4. Docker化部署实战

4.1 镜像构建优化

基于Alpine的极简镜像配置:

FROM python:3.10-alpine

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
CMD ["python", "watchdog_emby.py"]

构建命令:

docker build -t emby-watchdog .

对比:从Ubuntu基础镜像改为Alpine后,体积从231MB降至69.5MB

4.2 容器运行配置

典型部署命令示例:

docker run -d --name=emby-notifier \
  -v "/media/movies:/media" \
  -e BOT_TOKEN="xxx" \
  -e CHAT_ID="xxx" \
  -e TMDB_API="xxx" \
  -e MEDIA_PATH="/media" \
  -e LOG_PATH="/var/log/emby_notifier.log" \
  emby-watchdog

挂载点注意事项:

  • 主机媒体库路径应与Emby Server配置一致
  • 日志文件建议挂载到持久化存储
  • 可使用--restart=unless-stopped确保服务持续运行

5. 高级功能扩展思路

基础功能稳定后,可以考虑添加这些增强特性:

  • 多语言支持:根据.nfo语言自动切换通知语言
  • 质量过滤:仅推送符合特定分辨率/编码格式的影片
  • 用户偏好:基于交互式命令设置个人关注类型
  • 统计报表:每周自动生成媒体库更新周报

一个实用的消息模板改进示例:

def format_message(metadata):
    return f"""
🎬 新影片入库通知
————————————
📌 标题:{metadata['title']}
⭐ 评分:{metadata['vote_average']}/10
🗓️ 年份:{metadata['release_date'][:4]}
👥 主演:{', '.join(metadata['cast'][:3])}
————————————
{metadata['overview']}
"""

实际部署后发现,系统在Raspberry Pi 4上也能稳定运行,CPU占用率长期低于5%。最惊喜的是某次自动推送帮我发现了一部错放在纪录片分类的动作片,这种意外收获正是自动化带来的附加价值。

更多推荐