最简单的302重定向方法,进一步优化媒体库,让外网也能无须转码观看蓝光原盘。使用Openlist+Emby+Clouddrive+go-emby2openlist+autosymlink的完整解决方案。
原文体验更佳:hiripple.com/zh/blog/emb... Emby媒体库302重定向:Openlist+115网盘+go-emby2openlist
注:本博文基于Strm+Emby=无痛刮削,应对网盘风控新策略的后续内容,强烈建议先阅读前篇博文。
前言
在部署完Emby+strm方案后,外网播放高达几十GB的蓝光原盘仍然是个难题。出门在外想看电影,只能提前下载好,确实有些麻烦。
目前最佳的解决方案是使用302重定向,让客户端直接向115网盘的CDN请求资源,完全绕过家庭/本地服务器的转发开销。这样一来,电影的传输带宽仅受限于网速,而非服务器上传带宽。
当然,这种方案也存在一些权衡:
-
302重定向的播放启动速度略逊于本地转发
-
115账号存在被封风险(个人自用概率较低,但需避免多IP多线程下载)
-
部署流程相对复杂
网上虽然教程不少,但很多是复制粘贴的旧版方案,大部分停留在24年的过时方法,比如老旧的alist+nginx组合。这些方案不仅复杂繁琐,而且缺乏对ISO格式的刮削支持。
因此,本文的目标是提供最简洁的302重定向部署教程,同时保留原有的本地转发能力,实现iOS原盘刮削,并支持电影自动同步与刮削。最终达到在家享受本地转发的快速启动,在公网环境也能302流畅观影的双重体验。
市面上确实有更简单的一站式方案,比如Symmedia: www.symedia.top, 它集成了strm链接与302emby功能。不过这是非开源的付费项目(¥179),是否选择就看个人需求了。
Openlist 部署
Alist被收购后,Openlist成为了绝佳的替代方案:github.com/OpenListTea...
Openlist的作用很明确:提供302重定向能力,满足外网访问需求。这是Clouddrive无法胜任的功能。
使用Docker可以轻松部署(以Unraid为例):
yaml
services:
openlist:
image: 'openlistteam/openlist:latest'
container_name: openlist
user: '0:0'
volumes:
# 将容器数据目录映射到Unraid的appdata共享区
- '/mnt/user/appdata/openlist:/opt/openlist/data'
ports:
- '5244:5244'
environment:
- UMASK=022
- TZ=Asia/Shanghai
restart: unless-stopped
容器启动后,访问 http://localhost:5244
,按照官方文档完成登录→添加115网盘→获取API Key(后续步骤需要用到)。
go-emby2openlist 配置

官方地址:github.com/AmbitiousJu...
go-emby2openlist是一个Go语言编写的emby反向代理服务,功能强大且使用便捷。它可以反向代理emby页面,智能拦截并重定向电影资源路径(从本地路径转换为webdav 302重定向)。
引用官方说明:
网盘直链反向代理机制:
传统模式下,Emby通过磁盘挂载间接读取网盘资源,采用服务器代理模式,数据流向为:
客户端 → Emby源服务器 → 磁盘挂载服务 → OpenList → 网盘
客户端 ← Emby源服务器 ← 磁盘挂载服务(将视频数据缓存到本地,供Emby读取) ← OpenList ← 网盘
这种模式的局限性显而易见:
-
视频需经过服务器中转,观看速度受限于服务器上传带宽
-
服务器性能不足时,能流畅播放1080p已属不易,4K更是奢望
-
服务器流量和资源消耗巨大
使用网盘直链反向代理后,数据流向变为:
客户端 → Emby反代服务器 → Emby源服务器(请求Emby API接口)
客户端 ← Emby反代服务器 ← Emby源服务器(返回数据)
对于普通API接口,反代服务器将请求转发至源服务器,缓存适当结果后返回给客户端。从客户端角度看,这与直连源服务器无异。
客户端 → Emby反代服务器 ⇒ OpenList ⇒ 网盘(请求视频直链)
客户端 ← Emby反代服务器 ← OpenList ← 网盘(返回视频直链,发出重定向响应)
客户端 ⇒ 网盘(客户端获取网盘直链后直接观看,无需再消耗服务器流量)
同样使用Docker安装,Unraid配置示例:
yaml
version: '3.8'
services:
go-emby2openlist:
image: ambitiousjun/go-emby2openlist:v2.2.9
container_name: go-emby2openlist
restart: always
environment:
- TZ=Asia/Shanghai
- GIN_MODE=release
ports:
# 格式: - '宿主机端口:容器端口'
# HTTP端口(8095端口预留给Autosymlink)
- '8097:8095'
# HTTPS端口(如需启用SSL)
- '8094:8094'
volumes:
# --- 核心配置 ---
# 将宿主机配置文件映射到容器中
- ./config.yml:/app/config.yml
# --- 可选挂载 ---
# SSL证书文件目录
- /mnt/user/appdata/go-emby2openlist/ssl:/app/ssl
# 自定义注入JS/CSS文件目录
- /mnt/user/appdata/go-emby2openlist/custom-js:/app/custom-js
- /mnt/user/appdata/go-emby2openlist/custom-css:/app/custom-css
# 使用"OpenList本地目录树生成"功能时的必要挂载
# ffmpeg等库文件存放位置
- /mnt/user/appdata/go-emby2openlist/lib:/app/lib
# 生成的本地目录树存放位置
- /mnt/user/appdata/go-emby2openlist/openlist-local-tree:/app/openlist-local-tree
需要说明的是,博主使用了Cloudflare Tunnel反代+autosymlink的组合,因此没有使用项目自带的本地目录树和SSL功能。另外,该项目目前似乎不支持ISO原盘的刮削,且无法在添加电影后立即更新媒体库(需使用cron定时刷新)。综合考虑,保留原有的clouddrive+autosymlink方案是更明智的选择。
方案总结:在博主的架构中,clouddrive+autosymlink负责本地转发和媒体库刮削,而openlist+go-emby2openlist实现外网302重定向。由于go-emby2openlist本质上是反向代理服务,媒体库的刮削和管理依然由前者承担。
接下来是关键步骤:路径映射配置。Unraid环境下的config.yml示例:
yaml
# emby访问配置
emby:
# Emby服务访问地址
host: http://192.168.xxx.xxx:8096
# 以下参数保持默认或根据个人喜好调整
episodes-unplay-prior: true
resort-random-items: true
proxy-error-strategy: origin
images-quality: 100
download-strategy: direct
strm:
# strm文件内容为本地路径而非URL,因此留空
path-map:
# openlist访问配置
openlist:
# 填写OpenList服务的实际访问地址
host: http://192.168.xxx.xxx:5244
# 填写OpenList的API Token
token: openlist-xxx
# 当前使用自建strm工具,暂时禁用此功能
local-tree-gen:
enable: false
ffmpeg-enable: false
virtual-containers:
strm-containers: mkv,mp4,mov,ts,avi,webm,iso
music-containers:
auto-remove-max-count: 10000
refresh-interval: 60
scan-prefixes:
- /115/云下载
- /115/剧集
ignore-containers: jpg,jpeg,png,txt,nfo,md
# 视频预览刮削
# 非阿里云盘用户建议禁用以减少不必要的请求
video-preview:
enable: false
containers:
- mp4
- mkv
ignore-template-ids:
- LD
- SD
# 路径映射(核心配置)
path:
# emby挂载路径与openlist真实路径的前缀映射
# 程序会提取strm文件中的路径 /mnt/user/embydata/local/movie/云下载/阿凡达.mkv
# 使用下方规则进行替换,将前缀 /mnt/user/embydata/local 替换为 /
# 最终得到OpenList路径:/movie/云下载/阿凡达.mkv
emby2openlist:
- /mnt/user/embydata/local/movie:/115
- /mnt/user/embydata/local/tv:/115
# 缓存配置
cache:
enable: true
expired: 1d
# SSL配置
ssl:
# 未配置HTTPS,保持禁用状态
enable: false
single-port: false
key: testssl.cn.key
crt: testssl.cn.crt
# 日志配置
log:
disable-color: false
重要提醒:确保config.yml的路径与docker-compose.yml中的映射路径完全一致,否则容器将无法正常启动。
最后执行 docker compose up -d
,访问 http://localhost:8097
即可看到与emby完全相同的Web界面。此时下载/播放视频的地址会被302重定向至115的CDN服务器。
小技巧 :go-emby2openlist支持注入外部JS/CSS,推荐注入 emby-external-url.7o7o.cc/embyWebAddE... 实现直接跳转到本地播放器的功能。
错误排查

如果出现"没有兼容的流"错误,请按以下步骤排查:
-
首先访问emby源地址
http://localhost:8096
,如果源服务异常,说明是autosymlink与emby容器的路径配置问题,请参考前篇博文进行排查。 -
如果源服务正常,大概率是config.yaml中的路径映射配置错误。您需要检查webdav的实际地址与config.yaml中规则的匹配度。查看go-emby2openlist的容器日志可以获取实际请求路径信息,据此调整为正确的真实路径即可。
ISO刮削
这部分内容与之前的博文基本一致,在Unraid系统中调用ffprobe进行ISO刮削。现在Ripp已将JSON格式化接口开放为公共API,大家可以自由使用。
脚本示例:
bash
#!/bin/bash
# 设置脚本在遇到错误时退出
set -euo pipefail
# 定义目录路径
FFPROBE_DIR="/mnt/user/embydata/ffmpeg-master-latest-linux64-gpl/bin"
LINKS_DIR="/mnt/user/embydata/links"
TEMP_DIR="/mnt/user/embydata/temp"
MOVIES_DIR="/mnt/user/embydata/local/movie/云下载"
API_URL="http://probe.hiripple.com/format"
# 定义锁文件路径,使用/tmp目录避免权限问题
LOCK_FILE="/tmp/process_strm.lock"
# 函数:释放锁文件
cleanup() {
rm -f "$LOCK_FILE"
exit
}
# 检查是否已有实例在运行
if [ -e "$LOCK_FILE" ]; then
echo "锁文件已存在,脚本可能正在运行。退出。"
exit 1
fi
# 创建锁文件
touch "$LOCK_FILE"
# 确保在脚本退出时删除锁文件
trap cleanup EXIT
# 进入ffprobe所在目录
echo "进入目录: $FFPROBE_DIR"
cd "$FFPROBE_DIR" || { echo "无法进入目录 $FFPROBE_DIR"; exit 1; }
if [ ! -d "$TEMP_DIR" ]; then
echo "创建temp目录: $TEMP_DIR"
mkdir -p "$TEMP_DIR"
fi
# 遍历所有.strm文件
echo "扫描目录: $LINKS_DIR 以查找.strm文件"
find "$LINKS_DIR" -maxdepth 1 -type f -name "*.strm" | while read -r strm_file; do
# 提取电影名(不带.strm扩展名)
filename=$(basename "$strm_file" .strm)
echo "处理电影: $filename"
# 定义路径
mediainfo_json_link="${LINKS_DIR}/${filename}-mediainfo.json"
mediainfo_json_temp="${TEMP_DIR}/${filename}-mediainfo.json"
iso_file="${MOVIES_DIR}/${filename}.iso"
# 检查是否已存在mediainfo.json
if [ -f "$mediainfo_json_link" ]; then
echo "已存在mediainfo.json文件,跳过: $mediainfo_json_link"
continue
fi
# 检查ISO文件是否存在
if [ ! -f "$iso_file" ]; then
echo "ISO文件不存在,跳过: $iso_file"
continue
fi
# 执行ffprobe命令,生成mediainfo.json
echo "运行ffprobe生成mediainfo.json文件"
set +e # 临时禁用错误退出,以处理可能的错误
./ffprobe -v error \
-print_format json \
-show_format \
-show_streams \
-show_chapters \
-show_programs \
bluray:"$iso_file" > "$mediainfo_json_temp"
ffprobe_status=$?
set -e # 重新启用错误退出
# 检查ffprobe是否成功以及文件是否创建
if [ $ffprobe_status -ne 0 ] || [ ! -s "$mediainfo_json_temp" ]; then
echo "ffprobe执行失败或文件创建失败,跳过电影: $filename"
continue
fi
# 调用API格式化JSON
echo "调用API进行格式化"
response=$(curl -s -X POST "$API_URL" \
-H "Content-Type: application/json" \
-d @"$mediainfo_json_temp")
# 检查API调用是否成功
if [ $? -ne 0 ] || [ -z "$response" ]; then
echo "API调用失败或无响应,跳过电影: $filename"
continue
fi
# 保存API返回的格式化JSON到LINKS_DIR
echo "保存格式化后的JSON到 $mediainfo_json_link"
echo "$response" > "$mediainfo_json_link"
# 等待5秒
echo "等待5秒后处理下一个文件..."
sleep 5
echo "完成处理电影: $filename"
echo "----------------------------------------"
done
echo "所有.strm文件处理完成。"
在Emby中,如果电影缺少时长信息,将无法保存播放进度。因此,对ISO文件进行刮削显得尤为重要。
小结
最后的内网穿透可以直接使用Cloudflare Tunnel,这样通过公网访问自己的域名就能流畅播放影片了。
如果在部署过程中遇到任何问题,欢迎在下方留言交流~