自建Emby教程

Build your own Emby

Posted by PYQ on February 1, 2025

TL; DR:折腾了一圈最终还是没使用自建Emby进行观影🤣

Why Emby

为什么需要Emby

关于Emby的wiki—终点站Emby

  • 不想/愿意为国内流媒体商付钱
  • 对画质等有较高要求
  • 喜欢海报墙
  • 热爱观影
  • 想要有自己的影视库,并分享给朋友家人
  • 喜欢折腾
  • ……

为什么需要自建Emby

之前一直使用公费服(比如最近跑路的Miskaf服),虽然体验一般,但勉强能用,不过对网络要求也很高(即使是大服也很难满足所有人的网络环境)。最近因为跑路事件,陆陆续续加了好几个公益、公费和付费的TG群,发现它们各有各的缺点:

  1. 公益服:基本封车或者门槛很高,需要蹲开注,甚至有些还需要邀请码,难以轻易加入。
  2. 公费服:价格便宜,通常每月10元以下,但体验很一般,高峰期卡顿严重,资源更新也不及时。
  3. 付费服:区别于公费服,价格更高,基本每月20-30元,甚至还有几百块的白名单服务。虽然不知道具体体验如何,但注册这些服务通常需要购买一年的机场订阅,而我自己并不缺机场。
  4. 跑路风险:无论是公益、公费还是付费服,都存在跑路的风险。虽然服务好的话价格也能接受,但谁也无法保证能看多久,万一跑路就亏了。
  5. “饭圈”氛围:部分服群组有一种“饭圈”的感觉,氛围不太喜欢,我只想单纯地观影,不想参与这些。
  6. 信息安全:使用别人的服务,难免会担心个人信息和观影记录的安全性。

除了上述Emby服的共通缺点,还有一些其他原因让我思考是否需要自建Emby:

  1. 资源获取能力:我真的需要花钱去买Emby服吗?毕竟那些资源我自己也能找到,只是需要一个更好的管理和播放方式。
  2. 资源偏好:很多Emby服里的资源我并不感兴趣,自建Emby可以根据自己的喜好整理媒体库。

After build my own Emby

架构

我个人采用了以下方案,尽量做到成本最低:

  • 夸克网盘:我有88VIP赠送的会员(闲鱼上大概6元左右一年),包含6T空间,播放速度尚可,资源丰富且更新快(我主要使用夸克吧网盘资源收藏(夸克))。对于持续更新的剧集,转存一次后可以自动同步更新。为什么不使用热门的115网盘和阿里云盘?115太贵,我个人用不到那么大空间;阿里云盘则吃相太难看,对第三方的限制太大。
  • Alist:由于CloudDrive2不支持夸克网盘,因此需要使用Alist的WebDAV功能来挂载夸克资源。
  • CloudDrive2:将夸克网盘的资源(通过WebDAV)挂载到本地。虽然也可以使用Rclone,但大家都说CloudDrive2速度更快。
  • AutoSymlink:扫描CloudDrive2挂载后的资源,生成对应的.strm文件,并实时同步到Emby。.strm文件的作用是加快刮削速度,同时减少对网盘的直接刮削,避免触发风控。
  • Emby Server:前面所有的组件/服务都是为它服务的。Emby Server负责整理电影和剧集媒体库,并提供播放服务。
  • Emby Client
    • PC:使用Emby破解版。
    • iPhone/iPad:使用SenPlayer。

搭建Emby的架构大同小异,上述组件/服务具有很大的灵活性。例如:

  • 资源存储可以使用热门的115网盘,也可以直接使用硬盘(效果最好,但成本会更高)。
  • 如果使用115网盘或阿里云盘,可以跳过Alist,直接使用CloudDrive2。
  • 其他组件也可以根据需求替换或调整,比如使用Rclone代替CloudDrive2。

所有服务均部署在RackNerd的一台VPS上,服务器仅运行上述服务,全部使用容器,完全手动管理,未安装任何面板或其他辅助工具。服务器配置如下:

  • 1 GB 内存(稍显不足,但勉强够用吧)
  • 1 CPU 核心(对CPU要求几乎没有)
  • 20 GB 高速SSD存储(影视资源约3.7TB,服务器存储已使用77.4%,存储空间略显紧张)
  • 4000 GB 月流量(完全用不完)
  • 1 Gbps 带宽(共享带宽,线路质量较差,高峰期很影响体验,对网络环境要求很高)
  • 1 个IPv4 地址

日常资源占用情况如下图所示,自建的服务器只给了三四个账号,也没有测试过多人同时观看的负载:

自建Emby后的体验

最初搭建Emby时,看到精美的海报墙和精心整理的影视库,内心充满了成就感。然而,随着播放时频繁的卡顿,热情逐渐消退。到现在(大约搭建好半个月后),除了在添加夸克资源时顺便同步一下Emby,几乎不再直接通过Emby观影了。 主要原因还是服务器线路质量太差,晚上高峰期基本无法流畅观看,白天的体验也一般,勉强算是“能看”而已。当然,想要优化也有不少办法(说白了就是加钱 : )):

  1. 加钱升级服务器:购买更好的服务器,比如一台性能强劲但线路一般的作为Emby服务器,再搭配一台线路优秀但性能一般的作为中转服务器。
  2. 加钱购置NAS等设备:虽然我对NAS不太了解,但从折腾Emby的过程中来看,要想获得最佳体验,还是需要使用硬盘和一台闲置的电脑作为服务器,直接在本地或通过局域网共享播放。
  3. 更换组件/服务:或许将夸克换成115网盘,再通过302挂载,体验会更好?

折腾了这么久,最后却没有通过Emby进行观影,我到底收获了什么呢?

  1. 知识积累:对Emby的相关知识有了更深入的了解,能够对各种公益服/付费服做出自己的判断。
  2. 媒体库整理:借此机会整理并形成了自己的媒体库。
  3. Emby练手:会搭建自己的Emby了,并借此机会开始接触VPS(虽然是程序员,但之前一直使用虚拟机;VPS折腾起来确实费时费力,但也挺有趣)。
  4. 帮助朋友:一些朋友的网络环境使用Emby体验还不错,也算是发挥了作用。

最终,我还是选择了直接通过夸克观看,或者下载后使用PotPlayer等软件进行播放。

How to build your own Emby

准备环境

以下是一个用于准备环境的脚本,它会创建所需的目录并配置Docker的挂载标志:

cloud_media/strm存储支持CloudDrive2直接挂载的网盘的资源(自己的架构暂未用到,如果想使用CloudDrive2挂载多个网盘资源可以这样建,但一般也不会挂载多个吧,维护多费劲呀);webdav_media/webdav_strm存储夸克的资源。

Clouddrive 使用 fuse3 来挂载云存储服务,使用fuse3在Docker容器中挂载云存储服务时,需要在主机系统上启用共享挂载。这可以通过在Docker服务配置中设置MountFlags选项或在主机系统上使用mount –make-shared命令来实现。这是因为FUSE3需要共享挂载才能正常工作,如果没有共享挂载,挂载将会失败并显示“权限被拒绝”的错误。通过启用共享挂载,FUSE3挂载可以在Docker容器和主机系统之间共享,从而实现对云存储服务的无缝访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash

# 创建所需的目录
echo "Creating required directories..."
mkdir -p /media/docker/alist
mkdir -p /media/docker/clouddrive/Config
mkdir -p /media/docker/movie/{cloud_media,webdav_media,strm,webdav_strm}
mkdir -p /media/docker/auto_symlink/config
mkdir -p /media/docker/movie/cloud_media/clouddrive
mkdir -p /media/docker/movie/webdav_media/clouddrive
mkdir -p /media/docker/movie/emby/config

# 启用 MountFlags 共享,用于支持 Fuse3 挂载
echo "Enabling shared mount flags for Docker..."
sudo mkdir -p /etc/systemd/system/docker.service.d/
sudo cat <<EOF > /etc/systemd/system/docker.service.d/clear_mount_propagation_flags.conf
[Service]
MountFlags=shared
EOF
sudo systemctl restart docker.service

echo "Environment setup completed."

启动容器

以下是docker-compose.yml文件的内容,用于启动所有服务(服务器需要能拉取镜像(不管是使用国外服务器还是配置镜像源的方式),或者可以使用docker load -i导入镜像的tar包):

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
version: "3"

services:
  alist:
    image: xhofe/alist-aria2:latest
    container_name: alist
    restart: always
    environment:
      - PUID=0
      - PGID=0
      - UMASK=022
      - TZ=Asia/Shanghai
    ports:
      - "5244:5244"
      - "6800:6800"
    volumes:
      - /media/docker/alist:/opt/alist/data

  clouddrive:
    image: cloudnas/clouddrive2
    container_name: clouddrive
    restart: unless-stopped
    environment:
      - CLOUDDRIVE_HOME=/Config
    ports:
      - "8097:19798"
    volumes:
      - /media/docker/movie/cloud_media:/media:shared
      - /media/docker/movie/webdav_media:/webdav_media:shared
      - /media/docker/clouddrive/Config:/Config
    privileged: true
    pid: host
    devices:
      - /dev/fuse:/dev/fuse

  auto_symlink:
    image: shenxianmq/auto_symlink:latest
    container_name: auto_symlink
    restart: unless-stopped
    environment:
      - TZ=Asia/Shanghai
    ports:
      - "8095:8095"
    volumes:
      - /media/docker/movie/cloud_media/clouddrive:/media/docker/movie/cloud_media/clouddrive:rslave
      - /media/docker/movie/webdav_media/clouddrive:/media/docker/movie/webdav_media/clouddrive:rslave
      - /media/docker/movie/strm:/media/docker/movie/strm
      - /media/docker/movie/webdav_strm:/media/docker/movie/webdav_strm
      - /media/docker/auto_symlink/config:/app/config
    user: "0:0"

  emby-local:
    image: amilys/embyserver
    container_name: emby-local
    restart: unless-stopped
    environment:
      - UID=0
      - GID=0
      - GIDLIST=0
      - TZ=Asia/Shanghai
    ports:
      - "8096:8096"
    volumes:
      - /media/docker/movie/emby/config:/config
      - /media/docker/movie/cloud_media/clouddrive:/media/docker/movie/cloud_media/clouddrive:rslave
      - /media/docker/movie/webdav_media/clouddrive:/media/docker/movie/webdav_media/clouddrive:rslave
      - /media/docker/movie/webdav_strm:/webdav_strm
      - /media/docker/movie/strm:/strm
    privileged: true
    devices:
      - /dev/dri:/dev/dri

运行以下命令来准备环境并启动所有服务:

1
2
3
4
5
6
7
8
# 赋予脚本执行权限
chmod +x setup.sh

# 执行脚本
./setup.sh

# 启动容器
docker-compose up -d

以下是各个服务的访问端口:

应用 端口
Alist 5244
CloudDrive2 8097
AutoSymlink 8095
Emby Server 8096

Alist

Alist 的初始管理员用户名为 admin,密码可以通过以下命令查看日志输出获取:

1
docker logs alist

或者直接通过容器内命令获取密码:

1
docker exec -it alist ./alist -password

关于如何添加存储(如夸克网盘、阿里云盘等),请参考 Alist 官方文档添加账号 部分。

缓存设置建议: 在添加存储时,推荐将 缓存过期时间 设置为 -1,这样可以实时获取存储的目录列表,实现资源实时更新的特性。如果设置为 0,表示缓存永不过期,需要手动在页面右下角点击刷新按钮来刷新缓存。

以下是 Alist 的 WebDAV 配置参数:

参数
链接 http[s]://domain:port/dav/
主机 domain:port
路径 dav
协议 httphttps
端口 同 Web 端口(默认 5244)
账号 同 Alist 登录账号
密码 同 Alist 登录密码

CloudDrive2

CloudDrive2基础会员最大网盘数只能支持2,最大挂载数只能支持1,不支持文件变更通知。不过会员也很便宜。

添加网盘资源。

将网盘资源挂载到本地。

挂载成功后可以在主机/media/docker/movie/webdav_media/quark文件夹中看到相应的目录和文件。

默认账号:admin;默认密码:password。在首次登录时,你可以使用这些凭据进行登录。为了安全起见,建议登录后立即更改密码。AutoSymlink配置见下图,全局设置中需检查是否进行同样的设置,否则会同步失败。

Image 1 Image 2
Image 3

这里把定时同步关闭了,因为开启的时候出现了每天都会全部生成一次strm的情况,导致Emby重新刮削。虽然作者在issue中说解决了,但还是发生了,我不知道哪里出问题了。于是直接把定时同步关了,有更新的时候如果着急就手动同步,不急的话Emby也会实时监控更新,反正是自用不需要那么高的实时性。

添加同步任务后可以通过常用工具—手动同步生成strm文件,通过日志可以查看生成进度和状态。由于没有购买CloudDrive2的会员,因此不能自动实时更新,只能通过在手动添加资源后选择手动同步,以及设置Emby通知实现。

Emby

Emby刮削正确性百分之90和文件命名有关,Emby中的媒体主要可分为电影和电视节目两大类,因此推荐将电影的资源放在一个文件夹,而电视剧、动漫、纪录片等多集的资源放在一个文件夹。命名规范可参考万剑归宗之刮削大法!史上最全从Emby命名规则到刮削设置一条龙图文教程!。对刮削后不正确的元数据,则需要手动的去刮削元数据来纠正(因此如果想减少此项任务的工作量,请尽可能的规范自己资源的命名,在每次添加资源的时候就做好命名)。

刮削不出来元数据?大概率是网络的问题,需要魔法或者修改一下host文件。

Emby一定要关闭转码,否则可能会对服务器造成宕机:设置->用户->编辑->配置->播放,取消勾选视频转码选项

添加媒体库,这里展示电影和剧集两种类型的媒体库设置,尽可能的去保证刮削出来的海报等元数据精美。首选图像下载语言选择英文是因为英文的往往自动刮削出来的更精美,文字更少。要求更高的可以将不同语言的资源放在不同的文件夹,再选择对应的语言。

电影

Image 1 Image 2
Image 3 Image 4

剧集

Image 1 Image 2
Image 3 Image 4
Image 5 Image 6

Reference

搭建Emby的过程中主要参考了下面两位的文章:

  1. 一文讲清本地部署emby+cd2+alist+strm+302重定向,实现畅快观影(完善配置中)
  2. alist-clouddrive2-auto_symlink-emby-nginx实现emby播放115直链