bpking1 / embyExternalUrl

some emby/jellyfin scripts
MIT License
734 stars 129 forks source link

挂载阿里云可以正常播放,但是存在本地的文件无法播放 #53

Closed z-henry closed 11 months ago

z-henry commented 11 months ago

我的embyserver有两个媒体库,一个是阿里云盘webdav挂载到本地的文件夹,一个是正常的本地文件夹。 在外网环境,目前阿里云webdav挂载可以正常直链播放,但是本地文件夹无法播放 我尝试注释掉了,本地文件夹就可以正常播放,但是阿里云直链功能就不生效了

Redirect the stream to njs

location ~ /videos/(.)/stream {

Cache alist direct lin

   add_header    Cache-Control  max-age=3600; 
   js_content emby2Pan.redirect2Pan; 

}

z-henry commented 11 months ago

我这里通过魔改实现了,分享下改动。njs不太熟悉,还请多多指点 我是docker部署的embyserver,有两个媒体库,一个/mnt/share1映射了物理磁盘路径,一个/mnt/aliyun映射了挂载的阿里云盘,所以有如下配置

const embyMountPath = "/mnt/aliyun"; 思路是通过判断emby路径是否是embyMountPath开头,如果是则为正常直链操作,如果不是转到 location \直接交由embyserver处理

  1. 改动emby.js的函数redirect2Pan,如果不是阿里云文件,就将uri特殊格式化(videos->islocalvideos)后重定向,以便能命中location \

    //fetch local if (!embyRes.path.includes(embyMountPath)) { let args = r.variables.args; let newURI = r.uri.replace(/\/videos\//i, "/islocalvideos/") + '?' + args; r.warn(fetch local old ${r.uri}); r.warn(fetch local ${newURI}); r.internalRedirect(newURI); return; }

  2. 改动emby.conflocation \中识别到特殊的uri,再格式化回来

    location / { rewrite (.)/islocalvideos/(.) $1/videos/$2 break; # 处理 URI (islocalvideos->videos)

    Proxy main emby/jellyfin traffic

    proxy_pass $emby;

chen3861229 commented 11 months ago

1.建议将所有媒体内容交由AList分发,例如在AList中添加NAS的本地路径或者其他文件协议。 2.(可选)媒体库每次路径变动都会导致文件重新读取刷新,进一步可以添加AList的alias别名来做虚拟文件夹聚合,这个缺点是路径下全部只读。 3.(可选)交由AList管理如果分发到NAS本地视频出现花屏之类的可以在配置文件中开启changeAlistToEmby参数来解决。

z-henry commented 11 months ago

感谢回复,我会测试下这个方式

sjtuross commented 10 months ago

1.建议将所有媒体内容交由AList分发,例如在AList中添加NAS的本地路径或者其他文件协议。

2.(可选)媒体库每次路径变动都会导致文件重新读取刷新,进一步可以添加AList的alias别名来做虚拟文件夹聚合,这个缺点是路径下全部只读。

3.(可选)交由AList管理如果分发到NAS本地视频出现花屏之类的可以在配置文件中开启changeAlistToMediaServer参数来解决。

如果交由Alist分发,Emby本地媒体库的路径也要满足常量中定义的embyMountPath前缀,这会是个障碍点。

楼主的方法可以借鉴一下。索性分开定义本地和网盘挂载路径前缀列表,也不用去遍历alist里面所有挂载点了。

chen3861229 commented 10 months ago

开启config中的changeAlistToEmby参数,其实已经解决这个问题了,alist上单次没找到就会交给原始emby中转处理,不会走到下边的alist驱动遍历代码,不过当初是为解决小概率事件花屏的处理,所以默认没开启

if (!alistRes.startsWith("error")) {
    alistRes = alistRes.includes(alistIp)
      ? alistRes.replace(alistIp, alistPublicAddr)
      : alistRes;
    if (changeAlistToEmby && (alistRes.startsWith(alistIp) || alistRes.startsWith(publicDomain))) {
      // use original link
      alistRes = util.getEmbyOriginRequestUrl(r);
    }
    r.return(302, alistRes);
    return;
  }
z-henry commented 10 months ago

是的,把本地视频托管到alist,这是一个很好的办法。 但是我出于一些目的不能把本地视频交由alist托管,所以我只能继续采用我的魔改代码了

sjtuross commented 10 months ago

开启config中的changeAlistToEmby参数,其实已经解决这个问题了,alist上单次没找到就会交给原始emby中转处理,不会走到下边的alist驱动遍历代码,不过当初是为解决小概率事件花屏的处理,所以默认没开启

if (!alistRes.startsWith("error")) {
    alistRes = alistRes.includes(alistIp)
      ? alistRes.replace(alistIp, alistPublicAddr)
      : alistRes;
    if (changeAlistToEmby && (alistRes.startsWith(alistIp) || alistRes.startsWith(publicDomain))) {
      // use original link
      alistRes = util.getEmbyOriginRequestUrl(r);
    }
    r.return(302, alistRes);
    return;
  }

在这个方法之前,会先去alist查询一次,得找得到本地挂载才行,而且embyMountPath还得配合修改(网盘就不行了,这个再说)

还有,下面这个util方法是不是有问题?publicDomain按照说明是alist的public domain,而embyHost和embyPort也不是当前访问反代的实际地址

function getEmbyOriginRequestUrl(r) { const embyHost = config.publicDomain == "" ? config.embyHost : config.publicDomain + ":" + config.embyPort; return generateUrl(r, embyHost, r.uri); }

或者说反代哪里有问题,测试下来报错 image

chen3861229 commented 10 months ago

那次代码冲突了,所以合并得比较草率,之后等有时间整合下楼主的处理方式,图中你是https报错了,SSL只能在域名下生效,把embyIp这个参数中去掉s改为http://192.xxx

sjtuross commented 9 months ago

好的,另外你看看https://github.com/thsrite/emby_alipan_redirect/blob/main/nginx/conf.d/emby.js,也是基于本项目魔改的,可以支持网盘和本地资源同库

我是通过ssl域名访问nginx的,问题是现在没有单独的embyPublicDomain变量,我也没办法

chen3861229 commented 9 months ago

好的,这个改起来简单,最近抽时间改下,之前因为反馈的人不多所以没考虑这个问题。