配合 jellyfin 和 yt-dlp 下视频到威联通 NAS

yt-dlp 是新一代视频下载神器,开源、支持各大平台、并且有海量的参数设置项。也许出于降低曝光度考虑,yt-dlp 没有官方界面,也没有 RPC 接口,这就导致很大程度只能通过命令行本地使用。不过用法也很灵活,可以作为 python 包调用,也可以下载主流系统预编译的可执行文件,手机上还能在 termux 上面跑。因为一直以来将 jellyfin 作为媒体管理中心,针对如何方便地 yt-dlp 到媒体库研究出了一些心得。

metube 容器应用

来自 github

alexta69/metube
最早的时候用了一段时间,可以实时显示下载进度和速度,也能查看历史记录,操作比较人性化。但为什么后来不用了呢?总结下来有着几点原因:

  • 可设置项太少,也是最大的弊端。最早的时候连下载文件夹都不能指定(新版应该加上了),另外对我比较重要的 http proxy、视频质量这些,只能手动写死配置文件。
  • 额外安装常驻后台的 docker 增加系统负担
  • 不能通过 -U 参数更新 yt-dlp 版本,只能整体更新 docker
  • 不能通过 -F 参数获得视频信息

如果你单纯图方便,这个开源小工具应该能满足你。

php webUI 简易版

来自 github

类似 metube 的 webui 工具确实很适合,最好是简单的前后端分离架构。QNAP 系统本身可以很方便的装上 yt-dlp,最简单的,下载 yt-dlp_linux 增加一个系统环境变量就能用了。考虑到安全性以及不常驻后台,已经集成到系统的 php 是首选方案。在 github 上用 youtube-dl web yt-dlp web这种关键词能搜出很多开源项目,过滤下 php 语言也有好几个活跃中的,比如 FlorianLeChat/YouTube-Downloader。我自己尝试了下 MTco/Youtube-dl-WebUI,只能说 bug 实在太多,折腾了一段时间还是放弃了。不过还是希望有大神能做出这样的工具:纯净无依赖的 php 部署,能在界面更新 yt-dlp,简单的删除/重命名功能,可指定参数,有下载进度条,可以返回视频信息…
理论上可以自己搓一个,但设计到 websocket 这种又担心遇到坑,暂时放弃。

jellyfin yt-dlp 插件


QNAP 自带的 ffmpeg 比较残废,而且不带 ffprobe,配合 yt-dlp 有时会出问题。Jellyfin 容器自带的 ffmpeg 版本比较新,而且本身具备视频管理功能,做这个事情最合适不过了。于是简单搜了下,只有一个 AECX/FinTube 勉强能满足,其它比较热门的项目都是刮削相关的。说他勉强,因为简陋到只能下载油管视频,而且除了提取 Audio 之外不能设置其它参数。于是怀着野心一顿魔改。界面上很容易做到我想要的效果,然而难在了命令行网络通讯上,也就是显示执行进度。源项目是简单粗暴地在后端等待执行完毕,再响应最初的网络请求,这会带来很多问题,比如超时、不能实时监控运行过程、关闭网页可能导致意料之外的行为… 当然,我也尝试引入 CliWrap 这种封装好的 C# 库,奈何自己的散装技术实在有限,随只能放弃。原以为 Fintube 作者已经弃坑,最近居然破天荒更新了,只不过距离我想要的效果还有很远。

Container Station (终极方案)


前面罗嗦了半天,其实都不是我想要的。最终我的方案是:借助 QNAP 网页版后台的 docker 面板,当作 web console 用。其实独立的网页控制台也有,比如 ekzhang/sshx,但总感觉安全性没有保证。下面直接上步骤:

在 jellyfin 容器里安装 yt-dlp

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
# 进入docker shell
docker exec -it -u root jellyfin-1 bash

## 以上是python版本
curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /bin/yt-dlp
chmod a+rx /bin/yt-dlp
apt update && apt install --no-install-recommends --no-install-suggests python3
## 以下是独立版本,二选一
curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux -o /bin/yt-dlp
chmod a+rx /bin/yt-dlp

# 检查是否安装成功
yt-dlp --version

# 增加常用命令别名
## yt-p:程序更新和油管相关的都需要魔法
## yt-info:只获取各种质量的版本信息,不下载
## yt-dl:下载到指定文件夹,注意路径是相对 docker 的,不是宿主机
cat >> /etc/bash.bashrc <<EOF
alias yt-p='yt-dlp --proxy http://127.0.0.1:80808'
alias yt-info='yt-dlp -F'
alias yt-info-p='yt-dlp -F --proxy http://127.0.0.1:80808'
alias yt-dl='yt-dlp -P /media/youtube -o "%(title)s.%(ext)s"'
alias yt-dl-p='yt-dlp -P /media/youtube -o "%(title)s.%(ext)s" --proxy http://127.0.0.1:80808'
EOF

到这里,只要不卸载重装,配置应该能一直生效

如何使用

如果你的 QNAP 管理页面域名是 https://qnap.domain.com,通过类似 https://qnap.domain.com/container-station/#/containers/docker/[hash string]/details 的固定链接可以直接跳转到 jellyfin 的管理面板。

管理面板

这个不是固定的超链接按钮,点击之后,首先通过 POST {"cmd": "/bin/bash", "id": "[appid]"} 请求 https://qnap.domain.com/container-station/api/v3/containers/docker/exec 建立一个 bash 进程实例,并返回 "data": {"id": "[session id]", "secret": ""}。然后构建 session url https://qnap.domain.com/container-station/#/container-exec/docker/[session id]。这里每次都会新生成一个session id,也就是说,每个实例都是独立的,并且不会自动销毁,如果刷新 session url 页面会报错 Error: Exec command [session id] is already running
当然,我们可以通过一些 js 或者 php 脚本实现该过程的自动化,但总不是太安全,因为涉及到操作 QNAP 的 cookies。所以流程就是:通过管理面板执行 /bin/bash,手机上界面太挤可以点链接在独立窗口打开;运行 yt-dlp 下载命令;执行 kill -9 $$ 结束当前进程(推荐);打开 jellyfin 后台,看看新文件有没有入库。

懒人小技巧

如果你懒得保存管理面板书签,懒得去记 yt-dlp 命令行,甚至懒得记别名,可以把上述流程用 md 的形式保存在云文档中,需要的时候直接打开类似 zzbd.org/yt 的文档短链接,照着做一遍就行,看着也不麻烦的,哈哈。如果别名不生效,