bpking1 / embyExternalUrl

some emby/jellyfin scripts
MIT License
698 stars 126 forks source link

plex直链失败 #59

Closed dzhl closed 3 months ago

dzhl commented 9 months ago

使用了最新的plex方案,不过docker方面只用了其中的nignx服务,alist和plex都是单独安装的,plex是通过官方docker安装的。现在网页上通过8095端口可以访问到plex服务器,但实际测试下来,视频文件没有走直链,仍是plex服务器中转的。在网页端登录plex后台后,按照说明把公开访问的端口也设为8095,这时网页端通过8095端口仍是能找到plex服务器,但plex客户端就访问不到plex服务器,这是什么原因呢?

dzhl1201 commented 5 months ago

vpn局域网模拟测试了下,无解,plex这点强制性太高,在服务启动时候时候就会把局域网和公网ip还有自定义服务器访问 URL上传到plex.tv,同时也上传了geoip服务器的地理位置信息。。。 全局刷新页面可以看到 https://clients.plex.tv/api/v2/resources 这个接口调用,局域网的优先级是最高的,只要联通,详情页就不会请求当前访问的域名或ip了,本来我的环境是docker plex host网络,宿主机局域网段是192.168.xxx, 改为了bridge网络,甚至映射了32400到22400, 结果还是发现plex自己请求172.xxx的docker桥接网段且用了22400,因为群晖的docker有些残废,无法测试container网络模式。 解决方案 1.想办法将plex服务和其他局域网设备严格网络隔离,局域网找不到就会走自定义url了,隔离方式可以试试docker的container指定nginx的容器名称,或者添加防火墙规则,限制只有nginx可以访问plex。 2.最简单的还是建议非局域网使用吧。

我在开启open clash的fake ip模式后,web端就无法播放,开发工具里显示访问172.xxx失败,就是获取strm里的内容出错,如果换成其他代理工具或者使用openclash的redir ip模式,web端可以正常访问。不知道这个情况对解决局域网访问是否有帮助。

另外是否可以阻止上传局域网ip呢?或者是否在上图中局域网网络内的填写什么内容可以解决这个问题呢?或者组织局域网访问端口

chen3861229 commented 5 months ago

plex部分接口优先使用局域网,本意是好的,提升网络反应和增加服务容错,它本身貌似没有提供相关参数关闭这个行为,本来我以为的关闭本地网络发现和关闭中转可以禁用此行为,但是局域网下并没有生效,只能自行寻找偏方强行禁用了。 以下是猜测,任选一个应该可以解决,但是没有实际测试过

服务端方向 1.较难,想办法将plex服务和其他局域网设备严格网络隔离,局域网找不到就会走自定义url了,隔离方式可以试试docker的container指定nginx的容器名称,或者添加防火墙规则,限制只有nginx可以访问plex。 2.很难,基本无法阻止,尝试阻止plex上传局域网ip或者改写报文内容将 https://clients.plex.tv/api/v2/resources 以达到将自己域名connections.local = true,这是客户端的查询接口,需要自己扒服务端plex与plex.tv上报的接口。

客户端方向 1.较简单,使用路由器的访客wifi内网隔离功能,或者连接旁路由的wifi,以达到隔离plex局域网访问 2.较简单,使用代理软件的不同路由模式尝试,或者更改客户机的防火墙规则禁止掉plex的局域网访问 3.较简单,plex安卓官方客户端高级设置里可以自定义连接ip和端口,可以留空ip只填nginx的短裤,注意ios没有这个选项 4.很简单,使用公网访问自己plex,避免局域网的使用情况,确保nginx的处理生效 5.最简单,ios平台使用第三方客户端,原本plex对于strm的支持就是只能远程直链的重定向下载,响应的是301,而部分第三方客户端播放可能使用的下载接口,支持情况不统一 可以断定plex就是把这个活丢出去了,自身客户端并不想支持播放,因为还有bug,体验不是很好,如果媒体库全部为远程strm直链,且客户端全部为第三方,其实用不着部署nginx了

测试已通过 1.局域网环境下的Web浏览器添加拓展解决,并更新最新代码 e6cb4294e72b3140870f42da1bb966bb image

sjtuross commented 5 months ago

@chen3861229 我这边测试了一下,plex是docker部署,bridge网络,关键是以下2个高亮的设置,目的就是不让plex知道我的局域网地址,它就不会通告plex.direct。这样设置就不会请求我局域网地址https://192-168-1-X.{uuid}.plex.direct:32400,尽管我docker上32400的端口转发并没有关掉。以下测试在局域网192.168.1.X进行,没做任何网络限制

  1. 日志看到重定向了,浏览器在疯狂从云盘下载数据,但不知为何不播放
  2. iOS客户端不能放strm和DV的片子,其他正常
  3. 第三方客户端(Vidhub)都正常

image

sjtuross commented 5 months ago

前面浏览器不能播放的原因知道了,是因为被判定要转码(未必是视频,估计是音频,因为directStream是1),以下来自浏览器console里面的信息。如果判定不需要转码的片子,浏览器可以正常播放,区别就在于directPlay是0还是1

这是不能播放的情况

[Transcoder] Video (start) options: {
  "hasMDE": 1,
  "path": "/library/metadata/10783",
  "mediaIndex": 0,
  "partIndex": 0,
  "protocol": "dash",
  "fastSeek": 1,
  "directPlay": 0,
  "directStream": 1,
  "subtitleSize": 100,
  "audioBoost": 100,
  "location": "wan",
  "addDebugOverlay": 0,
  "autoAdjustQuality": 0,
  "directStreamAudio": 0,
  "mediaBufferSize": 102400,
  "X-Plex-Session-Identifier": "pmq38tlk4schui4kfgux602b",
  "session": "2kxlvat32lgt0zkszzlc8a7c",
  "subtitles": "auto",
  "X-Plex-Client-Profile-Extra": "append-transcode-target-codec(type=videoProfile&context=streaming&audioCodec=aac&protocol=dash)",
  "X-Plex-Incomplete-Segments": 1
}

这是可以播放的情况

[Transcoder] Video (decision) options: {
  "hasMDE": 1,
  "path": "/library/metadata/11350",
  "mediaIndex": 0,
  "partIndex": 0,
  "protocol": "dash",
  "fastSeek": 1,
  "directPlay": 1,
  "directStream": 1,
  "subtitleSize": 100,
  "audioBoost": 100,
  "location": "wan",
  "addDebugOverlay": 0,
  "autoAdjustQuality": 0,
  "directStreamAudio": 1,
  "mediaBufferSize": 102400,
  "X-Plex-Session-Identifier": "pmq38tlk4schui4kfgux602b",
  "session": "uc16noq9zsjj7eet8jmcrkqg",
  "subtitles": "burn",
  "X-Plex-Client-Profile-Extra": "append-transcode-target-codec(type=videoProfile&context=streaming&audioCodec=aac&protocol=dash)",
  "X-Plex-Incomplete-Segments": 1
}
chen3861229 commented 5 months ago

1.多谢提供测试情况,这个首选网络接口刚才也想到了,奈何我是host模式,所以没过多测试,还有一个解决方法是【...过度想象了,局域网环境直接用ip:nginx端口就行了,不会经过xxx.plex.direct:32400,这是plex对于域名https的局域网兼容】

2.directPlay这个参数在nginx反代中有做修改,仅当转发给plex服务端覆盖为了1,不过你提供的日志看来是客户端还是优先自己判断了一遍,这个我测试一下

sjtuross commented 5 months ago

ios平台使用第三方客户端,原本plex对于strm的支持就是只能远程直链的重定向下载,响应的是301,而第三方客户端播放全部直接使用的下载接口,可以断定plex就是把这个活丢出去了,自身客户端并不想支持播放,因为还有bug,体验不是很好,如果媒体库全部为远程strm直链,且客户端全部为第三方,其实用不着部署nginx了

关于这一点,我刚刚在没有反代的Plex上加了strm库,然后用vidhub测试,得到错误信息“播放失败,文件格式不支持或者文件已损坏”,貌似还是需要nginx

chen3861229 commented 5 months ago

好吧,我这边测试情况还是比较少,应该还是不同客户端支持情况不同,我去更新下文档说明

chen3861229 commented 5 months ago

浏览器那个看了下控制台日志,能支持播放的格式太少了,这点emby也是一样的(稍微多一点),虽然反代并改写了结果判断,但是播放端不支持的媒体格式的话就没办法了,还是优先用对应平台客户端吧

location ~* /video/:/transcode/universal/decision {
        set $args "$args&directPlay=1&directStream=1";
}

以下是edge浏览器的媒体格式支持情况,看到只支持【mp4,ogg,mpegts,flv,mkv】的视频格式,音频的支持范围也就几个

[MDE] Augmented profile: {
  "directPlay": {
    "mp4": {
      "mimeType": "video/mp4; codecs=\"avc1.42E01E\"",
      "video": {
        "codecs": {
          "h264": {
            "maxWidth": 4096,
            "maxHeight": 2160
          },
          "hevc": {
            "maxWidth": 4096,
            "maxHeight": 2160,
            "maxBitDepth": 10,
            "codecID": [
              "hev1"
            ]
          }
        },
        "maxWidth": 1920,
        "maxHeight": 1280,
        "maxFrameRate": 60
      },
      "audio": {
        "codecs": {
          "aac": {}
        }
      }
    },
    "ogg": {
      "mimeType": "video/ogg",
      "video": {
        "maxWidth": 1920,
        "maxHeight": 1280,
        "maxFrameRate": 60
      }
    },
    "mpegts": {
      "protocol": "hls",
      "video": {
        "maxWidth": 1920,
        "maxHeight": 1280,
        "maxFrameRate": 60
      }
    },
    "flv": {
      "video": {
        "maxWidth": 1920,
        "maxHeight": 1280,
        "maxFrameRate": 60
      }
    },
    "mkv": {
      "mimeType": "video/webm",
      "video": {
        "codecs": {
          "vp8": {
            "maxWidth": 4096,
            "maxHeight": 2160
          },
          "vp9": {
            "maxWidth": 4096,
            "maxHeight": 2160
          }
        },
        "maxWidth": 1920,
        "maxHeight": 1280,
        "maxFrameRate": 60
      },
      "audio": {
        "codecs": {
          "opus": {},
          "vorbis": {}
        }
      }
    }
  },
  "directStream": {
    "video": {
      "maxWidth": 1920,
      "maxHeight": 1280,
      "maxFrameRate": 60,
      "maxBitDepth": 8,
      "codecs": {
        "h264": {
          "maxWidth": 4096,
          "maxHeight": 2160
        },
        "hevc": {
          "maxWidth": 4096,
          "maxHeight": 2160,
          "maxBitDepth": 10
        }
      }
    },
    "audio": {
      "codecs": {
        "aac": {}
      },
      "maxBitrate": 192,
      "maxChannels": 2
    }
  }
}
sjtuross commented 5 months ago

是的,浏览器差不多到此为止了,日常都是用客户端的,我用浏览器仅仅是为了调试

sjtuross commented 5 months ago

关于这一点,我刚刚在没有反代的Plex上加了strm库,然后用vidhub测试,得到错误信息“播放失败,文件格式不支持或者文件已损坏”,貌似还是需要nginx

@chen3861229 是我strm里面地址的问题,刚刚修正了,vidhub可以不需要反代就能播放strm,大佬你是正确的

x1ao4 commented 5 months ago

vidhub可以不需要反代就能播放strm

666