基于网盘挂载的emby服务端并实现直链播放
侧边栏壁纸
  • 累计撰写 17 篇文章
  • 累计收到 525 条评论

基于网盘挂载的emby服务端并实现直链播放

syqman
2022-06-03 / 475 评论 / 7,432 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2024年04月09日,已超过46天没有更新,若内容或图片失效,请留言反馈。
2024.4.9补充说明

随着emby版本和alist版本的更新,本文的脚本不具备一定及时性,由于这篇文章一直热度还算可以,为了使兄弟们少走弯路,有一定动手能力的,请移步作者脚本主页 emby2Alist ,聪明的朋友其实只要替换下conf.d目录下的脚本,然后按提示做修改即可,本文后续不在更新,因为笔者不玩直链好久了 😂 。

前言

  国内网盘通过rclone挂载搭建的emby服务端本身速度尚可,如果你的服务器是家里的nas,这方案算是比较合适的方案。为啥要用网盘搭建emby影视库,因为网盘提供了家里硬盘所没有的大容量,如果你的影视资源比较多的话,网盘挂载应该是你的选择。
  这里我提供了另一个思路,rclone挂载国内网盘,实现emby的直链播放,什么意思呢,即实现播放电影走的是网盘的cdn服务器,不走服务器流量,这样你播放电影不受限于家里nas的上传带宽,或者不影响vps的流量额度,此外由于是国内直链播放,速度相当的快,如果emby服务端是放在vps,vps到你家里的速度影响的只是前端的速度,即海报刷新的速度,不影响视频播放的速度。
  当然,要实现这个方案,离不开大佬的智慧结晶,我这里其实起了一个抛砖引玉的作用,贴一下群里 bpking大佬的脚本及教程,写得比较简单,适合稍微有点基础的人。我这里记录下我自己的折腾过程,本文内容可能会比较长,请做好心里准备 表情

原理

搭建 alist多种存储的目录文件列表程序 ,将需要挂载的网盘添加上去,如阿里云盘,世纪互联等,然后使用 nginx 及其 njs 模块将 emby 视频播放地址劫持到 alist 直链。

准备工作

准备一台vps,系统推荐 Debian11 ,并搭建好 emby 服务端,解决 rclone 挂载国内网盘,这里不再赘述,网上教程很多。最终访问 http://vps-ip:8096/ ,可以正常访问 emby 并正常播放视频,视为完成准备工作。

1. 安装alist并创建网盘列表

alsit 项目地址: alist项目
参照 alist文档 的安装教程,我这里采用直装版。
安装完成后,打开 http://vps-ip:5244/ ,输入密码,进入后台,选择账号-添加:

l3xtl27v.png
这边我rclone挂载的是名为 sp01 的世纪互联 sharepoint ,参考我的设置,其 中客户端ID , 客户端密钥, 刷新令牌(refresh token) 均可以在 rclone 配置中找到, sharepoint站点ID ,填你创建的site id,如果你不知道这个是什么的话,访问 获取SharePoint网站site-id
完成设置后,点击右下角的首页,进入 sp01 目录:
l3xtzhyr.png
随便点击一部电影并试试播放速度:
l3xu0xo2.png
速度不错,并且 vps 无瞬时的大流量上传的话, alist 安装完成。

2. 安装nginx

如果你的 nginx 无其他用途,仅用来反代 emby ,推荐用 前言 大佬教程里的 docker版 ,省却了很多折腾步骤,这里我决定采用安装版。要求 nginx 版本大于 1.20 ,如果你已经安装过 nginx ,可以通过以下命令查看版本:

nginx -v

版本如大于 1.20 即可,但是由于 debian 默认的 nginx 源版本往往比较低,所以我们要采用官方的安装方式: nginx官方最新版debian安装教程 。安装过程不重复了,自行参照下官网步骤。
安装njs模块

apt install nginx-module-njs

安装完成后,进入 nginx 的配置目录:

cd /etc/nginx/conf.d

创建你域名的配置,如 yourdomain.com.conf ,添加如下内容

# Load the njs script
js_path /etc/nginx/conf.d/;
js_import emby2Pan from emby.js;
#Cache images                            
proxy_cache_path /var/cache/nginx/emby levels=1:2 keys_zone=emby:100m max_size=1g inactive=30d use_temp_path=off;
proxy_cache_path /var/cache/nginx/emby/subs levels=1:2 keys_zone=embysubs:10m max_size=1g inactive=30d use_temp_path=off;
server{
    gzip on;
    listen 80;
    server_name yourdomain.com;
    # aliDrive direct stream need no-referrer
    add_header 'Referrer-Policy' 'no-referrer';
    set $emby http://127.0.0.1:8096;  #emby address
    
    # Proxy sockets traffic for jellyfin-mpv-shim and webClient
    location ~ /(socket|embywebsocket) {
        # Proxy Emby Websockets traffic
        proxy_pass $emby;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
    }

    # Redirect the stream to njs
    location ~* /videos/(\d+)/stream {             
        js_content emby2Pan.redirect2Pan;
    }
    # for webClient download ,android is SyncService api
    location ~* /Items/(\d+)/Download {
        js_content emby2Pan.redirect2Pan;
    }

     #Cache the Subtitles
    location ~* /videos/(.*)/Subtitles {
        proxy_pass $emby;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;

        proxy_cache embysubs;
        proxy_cache_revalidate on;
        proxy_cache_lock_timeout 10s;
        proxy_cache_lock on;
        proxy_cache_valid 200 30d;
        proxy_cache_key $proxy_host$uri;
        #add_header X-Cache-Status $upstream_cache_status; # This is only to check if cache is working
    }
    
    # Cache the images
    location ~ /Items/(.*)/Images {
        proxy_pass $emby;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;

        proxy_cache emby;
        proxy_cache_revalidate on;
        proxy_cache_lock_timeout 10s;  
        proxy_cache_lock on; 
        # add_header X-Cache-Status $upstream_cache_status; # This is only to check if cache is working
    }

    location / {
        # Proxy main Emby traffic
        proxy_pass $emby;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        # Disable buffering when the nginx proxy gets very resource heavy upon streaming
        proxy_buffering off;
    }
}

同目录下创建 emby.js ,添加如下内容:

//查看日志: "docker logs -f -n 10 emby-nginx 2>&1  | grep js:"
async function redirect2Pan(r) {
    //下面4个设置,通常来说保持默认即可,根据实际情况修改
    const embyHost = 'http://127.0.0.1:8096'; //这里默认emby的地址是宿主机,要注意iptables给容器放行端口
    const embyMountPath = '/mnt';  // rclone 的挂载目录, 例如将od, gd挂载到/mnt目录下:  /mnt/onedrive  /mnt/gd ,那么这里就填写 /mnt  
    const alistPwd = 'alist';      //alist password
    const alistApiPath = 'http://127.0.0.1:5244/api/public/path'; //访问宿主机上5244端口的alist api, 要注意iptables给容器放行端口

    //fetch mount emby file path
    const itemId = /[\d]+/.exec(r.uri)[0];
    const mediaSourceId = r.args.MediaSourceId;
    const api_key = r.args.api_key;
    //infuse用户需要填写下面的api_key, 感谢@amwamw968
    if ((api_key === null) || (api_key === undefined)) {
        api_key = 'b19cde886a384fc097750b412345678';//这里填自己的API KEY
        r.error(`api key for Infuse: ${api_key}`);
    }

    const itemInfoUri = `${embyHost}/emby/Items/${itemId}/PlaybackInfo?api_key=${api_key}`;
    r.error(`itemInfoUri: ${itemInfoUri}`);
    const embyRes = await fetchEmbyFilePath(itemInfoUri, mediaSourceId);
    if (embyRes.startsWith('error')) {
        r.error(embyRes);
        r.return(500, embyRes);
        return;
    }
    r.error(`mount emby file path: ${embyRes}`);

    //fetch alist direct link
    const alistFilePath = embyRes.replace(embyMountPath, '');
    const alistRes = await fetchAlistPathApi(alistApiPath, alistFilePath, alistPwd);
    if (!alistRes.startsWith('error')) {
        r.error(`redirect to: ${alistRes}`);
        r.return(302, alistRes);
        return;
    }
    if (alistRes.startsWith('error401')) {
        r.error(alistRes);
        r.return(401, alistRes);
        return;
    }
    if (alistRes.startsWith('error404')) {
        const filePath = alistFilePath.substring(alistFilePath.indexOf('/', 1));
        const foldersRes = await fetchAlistPathApi(alistApiPath, '/', alistPwd);
        if (foldersRes.startsWith('error')) {
            r.error(foldersRes);
            r.return(500, foldersRes);
            return;
        }
        const folders = foldersRes.split(',').sort();
        for (let i = 0; i < folders.length; i++) {
            r.error(`try to fetch alist path from /${folders[i]}${filePath}`);
            const driverRes = await fetchAlistPathApi(alistApiPath, `/${folders[i]}${filePath}`, alistPwd);
            if (!driverRes.startsWith('error')) {
                r.error(`redirect to: ${driverRes}`);
                r.return(302, driverRes);
                return;
            }
        }
        r.error(alistRes);
        r.return(404, alistRes);
        return;
    }
    r.error(alistRes);
    r.return(500, alistRes);
    return;
}

async function fetchAlistPathApi(alistApiPath, alistFilePath, alistPwd) {
    const alistRequestBody = {
        "path": alistFilePath,
        "password": alistPwd
    }
    try {
        const response = await ngx.fetch(alistApiPath, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json;charset=utf-8'
            },
            max_response_body_size: 65535,  
            body: JSON.stringify(alistRequestBody)
        })
        if (response.ok) {
            const result = await response.json();
            if (result === null || result === undefined) {
                return `error: alist_path_api response is null`;
            }
            if (result.message == 'success') {
                if (result.data.type == 'file') {
                    return result.data.files[0].url;
                }
                if (result.data.type == 'folder') {
                    return result.data.files.map(item => item.name).join(',');
                }
            }
            if (result.code == 401) {
                return `error401: alist_path_api ${result.message}`;
            }
            if (result.message.includes('account')) {
                return `error404: alist_path_api ${result.code} ${result.message}`;
            }
            if (result.message == 'path not found') {
                return `error404: alist_path_api ${result.message}`;
            }
            return `error: alist_path_api ${result.code} ${result.message}`;
        }
        else {
            return `error: alist_path_api ${response.status} ${response.statusText}`;
        }
    } catch (error) {
        return (`error: alist_path_api fetchAlistFiled ${error}`);
    }
}

async function fetchEmbyFilePath(itemInfoUri, mediaSourceId) {
    try {
        const res = await ngx.fetch(itemInfoUri, { max_response_body_size: 65535 });
        if (res.ok) {
            const result = await res.json();
            if (result === null || result === undefined) {
                return `error: emby_api itemInfoUri response is null`;
            }
            const mediaSource = result.MediaSources.find(m => m.Id == mediaSourceId);
            if (mediaSource === null || mediaSource === undefined) {
                return `error: emby_api mediaSourceId ${mediaSourceId} not found`;
            }
            return mediaSource.Path;
        }
        else {
            return (`error: emby_api ${res.status} ${res.statusText}`);
        }
    }
    catch (error) {
        return (`error: emby_api fetch mediaItemInfo failed,  ${error}`);
    }
}

export default { redirect2Pan };

根据注释的地方自行调整相应的配置。
修改 /etc/nginx/nginx.conf ,在首行添加如下内容:

load_module modules/ngx_http_js_module.so;

验证 nginx 配置是否问题:

nginx -c /etc/nginx/nginx.conf
nginx -t

如无报错,重启 nginx

nginx -s reload

打开上述 nginx 配置的域名,如http://yourdomain.com , 注意这里不要访问默认的 8096 端口,如果能正常访问 emby 界面, nginx 安装工作完成。

3. 验证直链播放是否成功

随机打开一部电影,验证播放、拖曳速度。
查看 nginx js 日志:

tail -f -n 10 /var/log/nginx/access.log /var/log/nginx/error.log  | grep js:

如出现以下直链地址,表示直链成功,并且此时流量不经过 vps 服务器。
l3xvie2i.png

4. 关于直链成功的一些补充说明

这里直接引用 @bpking 大哥的原话

直链播放不支持转码,转码的话只能走emby server
所以最好 在emby设置中将 播放 –> 视频 –> 互联网质量 设置为最高 ,并且将用户的转码权限关掉,确保走直链
web端各大浏览器对音频和视频编码支持情况不一,碰到不支持的情况emby会强制走转码而不会走直链 ``
3

评论 (475)

取消
  1. 头像
    翔翎
    Android · Google Chrome

    好!很棒的笔记记录!表情

    回复
  2. 头像
    青菜
    Android · Google Chrome

    学习一下,谢谢大佬

    回复
    1. 头像
      芹菜
      Windows 10 · Google Chrome
      @ 青菜

      表情学习一下~

      回复
  3. 头像
    学习小猫
    MacOS · Google Chrome

    学习一下直连。我现在都搭建完了,就是挂载不上

    回复
    1. 头像
      syqman 作者
      Windows 10 · Google Chrome
      @ 学习小猫

      挂载可以看下rclone笔记那篇的一键脚本

      回复
      1. 头像
        Android · Google Chrome
        @ syqman

        6

        回复
  4. 头像
    lazyman
    MacOS · Safari

    学习一下!!表情

    回复
  5. 头像
    Miko
    Windows 10 · Google Chrome

    感谢大佬

    回复
  6. 头像
    启明星
    Android · Google Chrome

    大佬,这个适合jellyfin么?

    回复
  7. 头像
    zuij
    Windows 10 · Google Chrome

    最近刚好需要谢谢

    回复
  8. 头像
    xyhux
    Windows 10 · Google Chrome

    来大佬这学习看看

    回复
  9. 头像
    jj
    Windows 10 · Google Chrome

    学习学习!

    回复
  10. 头像
    Cncan
    Windows 10 · Google Chrome

    研究下emby直链,感谢大神分享

    回复
  11. 头像
    shikasa
    Windows 10 · Google Chrome

    学习ing

    回复
  12. 头像
    a
    iPhone · Safari

    学习一下

    回复
  13. 头像
    do
    Windows 10 · Google Chrome

    学习一下,找下自己问题出在哪

    回复
  14. 头像
    Hazard
    Windows 10 · Google Chrome

    学习一下

    回复
  15. 头像
    lin
    Windows 10 · FireFox

    学习一下

    回复
  16. 头像
    dous
    Windows 10 · FireFox

    学习一下

    回复
  17. 头像
    白菜
    MacOS · Google Chrome

    观摩

    回复
  18. 头像
    xianxian
    iPhone · Safari

    学习下经验

    回复
  19. 头像
    1321
    Windows 10 · Google Chrome

    感谢分享

    回复
  20. 头像
    zktree
    Windows 10 · Google Chrome

    学习下表情

    回复
  21. 头像
    easn
    Windows 10 · Google Chrome

    膜拜大佬

    回复
  22. 头像
    zzzz
    Windows 10 · Google Chrome

    学习一下,谢谢大佬

    回复
  23. 头像
    1
    Windows 10 · Google Chrome

    鼠标轨迹看的难受

    回复
  24. 头像
    Seey6
    Linux · FireFox

    不错

    回复
  25. 头像
    学习三人组
    MacOS · Google Chrome

    现在被速度折磨的难受,试试您的方案

    回复
  26. 头像
    qwmush
    Windows 10 · Google Chrome

    6666666

    回复
  27. 头像
    ll22
    Windows 10 · Google Chrome

    谢谢大佬的教程

    回复
  28. 头像
    dfadf
    Windows 10 · Google Chrome

    好!很棒的笔记记录!表情

    回复
  29. 头像
    lnmf
    Windows 7 · Google Chrome

    学习一下,谢谢大佬

    回复
  30. 头像
    喜喜
    Windows 10 · Google Chrome

    学习一下,谢谢大佬

    回复
  31. 头像
    112
    Android · FireFox

    学习相关11

    回复
  32. 头像
    li
    MacOS · Safari

    谢谢作者的分享

    回复
  33. 头像
    xiba
    MacOS · Google Chrome

    不错的笔记,很详细,正好要用。

    回复
  34. 头像
    iyao
    Windows 10 · Google Chrome

    感谢大佬,终于不用耗费vps,希望开通捐赠表情

    回复
  35. 头像
    jo
    MacOS · Google Chrome

    好文章~

    回复
  36. 头像
    喵喵喵
    Android · Google Chrome

    本来想反代的,现在好像直链舒服一点

    回复
  37. 头像
    喜喜
    Windows 10 · Google Chrome

    巧了~感谢有你,解决我的 问题

    回复
  38. 头像
    阿斯弗
    Windows 10 · Google Chrome

    好!很棒的笔记记录!表情

    回复
  39. 头像
    罗布
    Windows 10 · Google Chrome

    感谢!表情

    回复
  40. 头像
    test
    Windows 10 · FireFox

    学习学习!

    回复
  41. 头像
    long
    Windows 10 · Google Chrome

    非常感谢.

    回复
  42. 头像
    abc233
    MacOS · Google Chrome

    真的可以?

    回复
  43. 头像
    皇杰斯
    Windows 10 · Google Chrome

    向大佬学习

    回复
  44. 头像
    小小飞
    MacOS · Google Chrome

    很棒的笔记

    回复
  45. 头像
    看看
    MacOS · Google Chrome

    谢谢~~~~~~~

    回复
  46. 头像
    11
    Android · Google Chrome

    感谢分享

    回复
  47. 头像
    ☆≈逍遥≈☆
    Windows 10 · Google Chrome

    回复学习一下表情

    回复
  48. 头像
    noob
    MacOS · Safari

    帮大忙了

    回复
  49. 头像
    noob
    Linux · FireFox

    学生优惠的阿里云服务器只有1M带宽,这个真的救命了

    回复
  50. 头像
    lanmao09
    Windows 10 · Google Chrome

    前来学习表情

    回复
  51. 头像
    xxx
    Windows 10 · Google Chrome

    6666

    回复
  52. 头像
    啊啊
    Windows 10 · Google Chrome

    辛苦了

    回复
  53. 头像
    mig
    Windows 10 · Google Chrome

    感谢分享!

    回复
  54. 头像
    gk4589
    MacOS · Google Chrome

    来看看怎么样

    回复
  55. 头像
    boweic
    iPhone · Safari

    学习一下

    回复
  56. 头像
    boweic
    MacOS · Google Chrome

    很棒,继续学习

    回复
  57. 头像
    nobody
    MacOS · Safari

    大佬,emby.js里的infuse api_key在哪里找,我想用infuse直链

    回复
  58. 头像
    6666666
    Windows 10 · Google Chrome

    666666666

    回复
  59. 头像
    BBK
    Windows 10 · Google Chrome

    很棒的教程 这就试试

    回复
  60. 头像
    vvx
    Windows 10 · Google Chrome

    牛逼牛逼

    回复
  61. 头像
    dean
    MacOS · Safari

    画图

    回复
  62. 头像
    boweic
    MacOS · Google Chrome

    学习学习

    回复
  63. 头像
    eureka
    Windows 10 · Google Chrome

    看一看

    回复
  64. 头像
    11
    Windows 10 · Google Chrome

    表情

    回复
  65. 头像
    sonder
    MacOS · Google Chrome

    好帅的笔记

    回复
  66. 头像
    luyi
    Windows 10 · Google Chrome

    正好需要这个

    回复
  67. 头像
    伟大哥
    Windows 10 · Google Chrome

    学习一下,正在研究哈哈哈

    回复
  68. 头像
    vector
    MacOS · Google Chrome

    好!很棒的笔记记录!表情

    回复
  69. 头像
    土豆泥
    iPhone · Safari

    学习学习表情

    回复
  70. 头像
    11111
    Windows 10 · Google Chrome

    下载链接过期

    回复
  71. 头像
    zkai
    Windows 10 · Google Chrome

    好!很棒的笔记记录

    回复
  72. 头像
    666
    Windows 10 · Google Chrome

    优秀

    回复
  73. 头像
    kufei
    iPhone · Safari

    看看怎么弄的

    回复
  74. 头像
    lucidan
    Windows 10 · Google Chrome

    学习一下

    回复
  75. 头像
    啊啊
    Windows 10 · Google Chrome

    可以

    回复
  76. 头像
    啊啊
    Windows 10 · Google Chrome

    这个方法已经失效了

    回复
  77. 头像
    阿萨
    Windows 10 · Google Chrome

    看看还能不能用

    回复
  78. 头像
    wzshjyy
    Windows 10 · Google Chrome

    666666666666666

    回复
  79. 头像
    111111
    Windows 10 · Google Chrome

    学习一下直链

    回复
  80. 头像
    xian
    Android · Google Chrome

    学习学习

    回复
  81. 头像
    hdxhcd
    Windows 10 · Google Chrome

    厉害,这就去试试

    回复
  82. 头像
    小白
    Windows 10 · FireFox

    学习一下直连.问问alist直链那里可以换成rclone serve的吗?

    回复
  83. 头像
    SakuraPY
    Windows 10 · Google Chrome

    alist v3怎么办呢,大佬?

    回复
  84. 头像
    天鱼
    Windows 10 · Google Chrome

    研究研究

    回复
  85. 头像
    试过很多次没有成功
    iPhone · Safari

    试了很多次没有成功,不知道是不是阿里网盘改策略来

    回复
  86. 头像
    好很好
    MacOS · Google Chrome

    学习

    回复
  87. 头像
    xx
    MacOS · Google Chrome

    学习一下,谢谢大佬

    回复
  88. 头像
    emilia
    Linux · Google Chrome

    来了

    回复
  89. 头像
    111
    Windows 10 · Google Chrome

    555555555555555555555

    回复
  90. 头像
    aliesz
    Windows 10 · Google Chrome

    学习到了,谢谢大佬

    回复
  91. 头像
    aliesz
    Windows 10 · Google Chrome

    大佬想问下 如果alist挂载gd或者od的话这样也能获取到alist配置的代理地址播放么

    回复
  92. 头像
    aliesz
    Windows 10 · Google Chrome

    表情

    回复
  93. 头像
    小白菜
    iPhone · Safari

    厉害了!

    回复
  94. 头像
    kaith
    Windows 10 · Google Chrome

    学习学习

    回复
  95. 头像
    ass
    Windows 10 · Google Chrome

    學一下

    回复
  96. 头像
    automan
    Windows 10 · Google Chrome

    学习一下,谢谢大佬

    回复
  97. 头像
    揽景楼
    Android · Google Chrome

    谢谢分享看看 vu

    回复
  98. 头像
    啊啊啊
    Windows 10 · Google Chrome

    谢谢分享啊

    回复
  99. 头像
    哼唧
    Windows 7 · Google Chrome

    很好的教程

    回复
  100. 头像
    Matrix
    Windows 10 · Google Chrome

    学习以下

    回复
  101. 头像
    102304768
    Android · Google Chrome

    非常受教

    回复
  102. 头像
    楠天
    Android · Google Chrome

    好!很棒的笔记记录!

    回复
  103. 头像
    楠天
    Windows 10 · Google Chrome

    好!很棒的笔记记录!表情

    回复
  104. 头像
    白菜
    Windows 10 · Google Chrome

    学习一下核心技术emby.js怎么实现的

    回复
  105. 头像
    wxhwz
    Windows 10 · Google Chrome

    学习以下

    回复
  106. 头像
    jarmo
    Windows 10 · FireFox

    学习一下,谢谢大佬

    回复
  107. 头像
    oowap
    iPhone · Safari

    非常好的技术文章

    回复
  108. 头像
    ntrman
    Windows 10 · Google Chrome

    hao,feichanghao

    回复
  109. 头像
    sda
    Windows 10 · Google Chrome

    学习一下

    回复
  110. 头像
    11223
    Windows 10 · Google Chrome

    啊啊啊啊啊啊

    回复
  111. 头像
    ericironwood
    Windows 10 · Google Chrome

    感谢大佬的指路,这对我真的帮助很大

    回复
  112. 头像
    thjjj
    Android · Google Chrome

    学习下

    回复
  113. 头像
    helloworld
    Windows 10 · Google Chrome

    看看行不行

    回复
  114. 头像
    thasd
    Android · Google Chrome

    学习一下

    回复
  115. 头像
    crusher
    MacOS · Safari

    这个好,最近正需要

    回复
  116. 头像
    丹丹
    Android · UC Browser

    学习一下

    回复
  117. 头像
    楠天
    Windows 10 · Google Chrome

    好!很棒的笔记记录!表情

    回复
  118. 头像
    thjjj
    Android · Google Chrome

    windows版本的有教程吗?

    回复
  119. 头像
    帆帆
    Windows 10 · Google Chrome

    学习一下

    回复
  120. 头像
    awd
    Windows 10 · Google Chrome

    感谢楼主!另外想问一下大佬的世纪互联是在哪买的~

    回复
  121. 头像
    楠天
    Windows 7 · Google Chrome

    好!很棒的笔记记录!

    回复
  122. 头像
    sodaer
    Windows 10 · Google Chrome

    我找了好多地方 在学习 ,只有这里有

    回复
  123. 头像
    qq人
    Windows 10 · Google Chrome

    太强了。学习学习

    回复
  124. 头像
    Juiciness5399
    MacOS · FireFox

    好!很棒的笔记记录!

    回复
  125. 头像
    rack
    Windows 10 · Google Chrome

    感谢大佬

    回复
  126. 头像
    sda
    Windows 10 · Google Chrome

    das

    回复
  127. 头像
    左←
    Android · Google Chrome

    学习了

    回复
  128. 头像
    jj
    Windows 10 · Google Chrome

    学习一下,谢谢大佬

    回复
  129. 头像
    landou
    Windows 10 · Google Chrome

    牛逼牛逼,学习试试

    回复
  130. 头像
    希希
    Windows 10 · Google Chrome

    很棒的笔记!Mark一下。硬盘不够用的时候就试一下。

    回复
  131. 头像
    br
    Windows 10 · Google Chrome

    plex是不是同理能实现?

    回复
  132. 头像
    Wilson
    MacOS · Google Chrome

    666666

    回复
  133. 头像
    YL
    Android · Google Chrome

    大佬牛逼,整起来

    回复
  134. 头像
    yl
    MacOS · Google Chrome

    学习了大佬

    回复
  135. 头像
    admin
    Windows 10 · Google Chrome

    1111

    回复
  136. 头像
    努力学习
    iPhone · Safari

    这个是值支持web播放吗?emby或者infuse支持吗

    回复
  137. 头像
    xaxa
    Windows 10 · Google Chrome

    感谢分享

    回复
  138. 头像
    sda
    Windows 10 · Google Chrome

    //查看日志: "docker logs -f -n 10 emby-nginx 2>&1 | grep js:"
    async function redirect3Pan(r) {
    //下面4个设置,通常来说保持默认即可,根据实际情况修改
    const embyHost = 'http://127.0.0.1:8096'; //这里默认emby的地址是宿主机,要注意iptables给容器放行端口
    const embyMountPath = '/'; // rclone 的挂载目录, 例如将od, gd挂载到/mnt目录下: /mnt/onedrive /mnt/gd ,那么这里就填写 /mnt
    const alistToken = ''; //alist Token
    const alistApiPath = 'http://127.0.0.1:5244/api/fs/get'; //访问宿主机上5244端口的alist api, 要注意iptables给容器放行端口

    //fetch mount emby file path
    const itemId = /[\d]+/.exec(r.uri)[0];
    const mediaSourceId = r.args.MediaSourceId;
    const api_key = r.args.api_key;
    //infuse用户需要填写下面的api_key, 感谢@amwamw968
    if ((api_key === null) || (api_key === undefined)) {
    api_key = 'b19cde886a384fc097750b412345678';//这里填自己的API KEY
    r.error(`api key for Infuse: ${api_key}`);
    }

    const itemInfoUri = `${embyHost}/emby/Items/${itemId}/PlaybackInfo?api_key=${api_key}`;
    r.error(`itemInfoUri: ${itemInfoUri}`);
    const embyRes = await fetchEmbyFilePath(itemInfoUri, mediaSourceId);
    if (embyRes.startsWith('error')) {
    r.error(embyRes);
    r.return(500, embyRes);
    return;
    }
    r.error(`mount emby file path: ${embyRes}`);
    //fetch alist direct link
    const alistFilePath = embyRes.replace(embyMountPath, '');
    const alistRes = await fetchAlistPathApi(alistApiPath, alistFilePath, alistToken);
    if (!alistRes.startsWith('error')) {
    r.error(`redirect to: ${alistRes}`);
    r.return(302, alistRes);
    return;
    }
    if (alistRes.startsWith('error401')) {
    r.error(alistRes);
    r.return(401, alistRes);
    return;
    }
    if (alistRes.startsWith('error404')) {
    const filePath = alistFilePath.substring(alistFilePath.indexOf('/', 1));
    const foldersRes = await fetchAlistPathApi(alistApiPath, '/', alistToken);
    if (foldersRes.startsWith('error')) {
    r.error(foldersRes);
    r.return(500, foldersRes);
    return;
    }
    const folders = foldersRes.split(',').sort();
    for (let i = 0; i < folders.length; i++) {
    r.error(`try to fetch alist path from /${folders[i]}${filePath}`);
    const driverRes = await fetchAlistPathApi(alistApiPath, `/${folders[i]}${filePath}`, alistToken);
    if (!driverRes.startsWith('error')) {
    r.error(`redirect to: ${driverRes}`);
    r.return(302, driverRes);
    return;
    }
    }
    r.error(alistRes);
    r.return(404, alistRes);
    return;
    }
    r.error(alistRes);
    r.return(500, alistRes);
    return;
    }

    async function fetchAlistPathApi(alistApiPath, alistFilePath, alistToken) {
    const alistRequestBody = {
    "path": alistFilePath,
    "password": ""
    }
    try {
    const response = await ngx.fetch(alistApiPath, {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json;charset=utf-8',
    'Authorization': alistToken
    },
    max_response_body_size: 65535,
    body: JSON.stringify(alistRequestBody)
    })
    if (response.ok) {
    const result = await response.json();
    if (result === null || result === undefined) {
    return `error: alist_path_api response is null`;
    }
    if (result.message == 'success') {
    if (result.data.type == 2) {
    return result.data.raw_url;
    }
    else {
    return 'error502: alist_path_api type_error!'
    }
    }
    if (result.code == 401) {
    return `error401: alist_path_api ${result.message}`;
    }
    if (result.message.includes('account')) {
    return `error404: alist_path_api ${result.code} ${result.message}`;
    }
    if (result.message == 'path not found') {
    return `error404: alist_path_api ${result.message}`;
    }
    return `error: alist_path_api ${result.code} ${result.message}`;
    }
    else {
    return `error: alist_path_api ${response.status} ${response.statusText}`;
    }
    } catch (error) {
    return (`error: alist_path_api fetchAlistFiled ${error}`);
    }
    }

    async function fetchEmbyFilePath(itemInfoUri, mediaSourceId) {
    try {
    const res = await ngx.fetch(itemInfoUri, { max_response_body_size: 65535 });
    if (res.ok) {
    const result = await res.json();
    if (result === null || result === undefined) {
    return `error: emby_api itemInfoUri response is null`;
    }
    const mediaSource = result.MediaSources.find(m => m.Id == mediaSourceId);
    if (mediaSource === null || mediaSource === undefined) {
    return `error: emby_api mediaSourceId ${mediaSourceId} not found`;
    }
    return mediaSource.Path;
    }
    else {
    return (`error: emby_api ${res.status} ${res.statusText}`);
    }
    }
    catch (error) {
    return (`error: emby_api fetch mediaItemInfo failed, ${error}`);
    }
    }
    export default { redirect3Pan};
    自己稍微修改了下,适用于alist v3版本

    回复
    1. 头像
      11
      MacOS · Safari
      @ sda

      不错~

      回复
    2. 头像
      南渡
      Windows 10 · Google Chrome
      @ sda

      alistToken哪里获取?

      回复
      1. 头像
        热心网友
        MacOS · Google Chrome
        @ 南渡

        就是密码

        回复
      2. 头像
        sda
        Windows 10 · Google Chrome
        @ 南渡

        你的alist 令牌 在管理面板->设置->其他里面

        回复
  139. 头像
    11
    Windows 10 · Google Chrome

    学习一下

    回复
  140. 头像
    jkd2022
    MacOS · Safari

    学习一下,谢谢大佬

    回复
  141. 头像
    aa
    MacOS · Google Chrome

    看看

    回复
  142. 头像
    test
    Windows 10 · Google Chrome

    学习下

    回复
  143. 头像
    T
    Windows 10 · Google Chrome

    学习一下,谢谢大佬

    回复
  144. 头像
    爱你
    Windows 10 · Google Chrome

    感谢分享

    回复
  145. 头像
    试试水
    Windows 10 · Google Chrome

    学习学习,生命在于折腾

    回复
  146. 头像
    sss
    Windows 10 · Google Chrome

    最近刚好需要谢谢

    回复
  147. 头像
    小白
    Windows 10 · Google Chrome

    谢谢大佬

    回复
  148. 头像
    南渡
    Windows 10 · Google Chrome

    插个锚点

    回复
  149. 头像
    王小波
    Windows 10 · Google Chrome

    学习一下

    回复
  150. 头像
    胡思
    Windows 10 · Google Chrome

    学习一下

    回复
  151. 头像
    哈哈哈
    Windows 10 · Google Chrome

    学习学习.感谢

    回复
  152. 头像
    南渡
    Windows 10 · Google Chrome

    你好,8095端口播放,日志报错[error] 20#20: *847 js: error500: alist_path_api 401 Guest user is disabled, login please是哪里问题呢

    回复
  153. 头像
    T
    Windows 10 · Google Chrome

    好!很棒的笔记记录!表情

    回复
  154. 头像
    你妈死了
    MacOS · Safari

    谢谢博主

    回复
  155. 头像
    Error
    Windows 10 · Google Chrome

    谢谢大佬

    回复
  156. 头像
    老王
    Windows 10 · Google Chrome

    谢谢分享,学习一下

    回复
  157. 头像
    Windows 10 · Google Chrome

    学习一下

    回复
  158. 头像
    kuci
    Windows 10 · Google Chrome

    学习一下,谢谢大佬

    回复
  159. 头像
    1
    Windows 10 · Google Chrome

    学习一下,谢谢大佬

    回复
  160. 头像
    Niki
    Windows 10 · Google Chrome

    谢谢分享

    回复
  161. 头像
    gseekleely
    Windows 10 · Google Chrome

    好!很棒的笔记记录

    回复
  162. 头像
    zhujay
    MacOS · Google Chrome

    谢谢大佬,谢谢

    回复
  163. 头像
    cx
    MacOS · Google Chrome

    学习一下

    回复
  164. 头像
    大头
    Windows 10 · Google Chrome

    感谢大佬

    回复
  165. 头像
    aibocai
    Windows 10 · Google Chrome

    我挂载完了,看到大佬的笔记,真是不错!

    回复
  166. 头像
    匿名
    MacOS · Safari

    谢谢分享

    回复
  167. 头像
    blanco
    iPhone · Safari

    学习学习

    回复
  168. 头像
    blanco
    Windows 7 · Google Chrome

    好文章 学习学习

    回复
  169. 头像
    woaibocai
    Windows 10 · Google Chrome

    mark!学习学习

    回复
  170. 头像
    良·
    Windows 10 · Google Chrome

    学习一下

    回复
  171. 头像
    xianshiping
    Windows 10 · Google Chrome

    学习

    回复
  172. 头像
    niko
    Android · Google Chrome

    感觉有点难

    回复
  173. 头像
    Jerry
    MacOS · Google Chrome

    看看看看

    回复
  174. 头像
    dooki
    Android · Google Chrome

    感谢大佬

    回复
  175. 头像
    fanta299
    MacOS · Google Chrome

    8888888

    回复
  176. 头像
    zipl1985
    Windows 10 · FireFox

    学习一下了,谢谢

    回复
  177. 头像
    [email protected]
    MacOS · Google Chrome

    没想到还有这种操作,学习一下

    回复
  178. 头像
    dk
    Windows 10 · Google Chrome

    表情

    回复
  179. 头像
    tkxz
    Android · Google Chrome

    学习一下,感谢大佬!

    回复
  180. 头像
    msttkx
    Windows 10 · Google Chrome

    学习学习

    回复
  181. 头像
    dd
    MacOS · Google Chrome

    查看隐藏内容

    回复
  182. 头像
    学习学
    Windows 10 · Google Chrome

    学习学

    回复
  183. 头像
    帅气逼人
    Windows 10 · Google Chrome

    6666表情

    回复
  184. 头像
    xxxx
    Windows 10 · Google Chrome

    感谢分享

    回复
  185. 头像
    比吧
    Windows 10 · Google Chrome

    感谢好大哥的详细介绍

    回复
  186. 头像
    阿萨德
    Windows 10 · Google Chrome

    学习一下

    回复
  187. 头像
    比吧
    Windows 10 · Google Chrome

    头像
    xxxx
    Windows 10 · Google Chrome
    感谢分享

    回复
  188. 头像
    爱好者博客
    Windows 10 · Google Chrome

    一句话,大佬牛逼 请问plex能实现直链播放吗?

    回复