Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion CHANGELOG.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.1.4] - 2026-09-04

### Added

- Plex Web can now work with
[ShimWeave](https://github.com/InfinityPacer/ShimWeave) for more STRM sources
that need browser-side remuxing or audio compatibility handling. Media still
travels directly from the CDN to the browser without consuming NAS media
bandwidth.

### Improved

- Initial playback, long seeks, and clean shutdown were verified with MKV,
HEVC, and AAC. Local media, ordinary clients, and requests without ShimWeave
keep their existing Plex behavior.
- Temporary direct URLs can be refreshed during playback, so long sessions and
seeks do not depend on an expired CDN URL.

### Known limitations

- Actual format support depends on ShimWeave, the browser, the operating system,
and hardware decoding. This release does not transcode on the Gateway or NAS
and does not promise every MKV, 4K, HDR, Dolby Vision, or audio combination.
- In the acceptance environment, one 4K HEVC Main 10 with EAC3 source is still
explicitly reported as unsupported by ShimWeave 0.0.1. Similar sources must
be verified against the actual browser and hardware.

## [0.1.3] - 2026-08-30

### Added
Expand Down Expand Up @@ -85,7 +112,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
gateway redirects playback.
- Logs and metrics exclude Plex tokens and complete signed media URLs.

[Unreleased]: https://github.com/InfinityPacer/plex-gateway/compare/v0.1.3...HEAD
[Unreleased]: https://github.com/InfinityPacer/plex-gateway/compare/v0.1.4...HEAD
[0.1.4]: https://github.com/InfinityPacer/plex-gateway/compare/v0.1.3...v0.1.4
[0.1.3]: https://github.com/InfinityPacer/plex-gateway/compare/v0.1.2...v0.1.3
[0.1.2]: https://github.com/InfinityPacer/plex-gateway/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/InfinityPacer/plex-gateway/compare/v0.1.0...v0.1.1
Expand Down
24 changes: 23 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@

## [未发布]

## [0.1.4] - 2026-09-04

### 新增

- Plex Web 可与 [ShimWeave](https://github.com/InfinityPacer/ShimWeave) 配合播放更多需要
浏览器端转封装或音频兼容处理的 STRM,媒体仍由 CDN 直接发送到浏览器,不占用 NAS
媒体带宽。

### 改进

- 已验证 MKV、HEVC、AAC 的起播、长进度拖动和关闭播放。本地媒体、普通客户端及未启用
ShimWeave 的请求继续保持原有 Plex 行为。
- 播放期间可按需刷新临时直链,避免长时间播放或拖动进度依赖已经过期的 CDN 地址。

### 已知限制

- 实际格式支持取决于 ShimWeave、浏览器、操作系统和硬件解码能力。本版本不在 Gateway
或 NAS 上转码,也不承诺支持所有 MKV、4K、HDR、Dolby Vision 或音频组合。
- 当前验收环境中的一组 4K HEVC Main 10 + EAC3 片源仍由 ShimWeave 0.0.1 明确报告为
不支持格式;其他同类片源仍需按实际浏览器和硬件验证。

## [0.1.3] - 2026-08-30

### 新增
Expand Down Expand Up @@ -71,7 +92,8 @@
- Gateway 返回云端播放重定向前,由 Plex 使用当前客户端凭据授权对应 Part。
- 日志和指标不包含 Plex Token 或完整的签名媒体 URL。

[未发布]: https://github.com/InfinityPacer/plex-gateway/compare/v0.1.3...HEAD
[未发布]: https://github.com/InfinityPacer/plex-gateway/compare/v0.1.4...HEAD
[0.1.4]: https://github.com/InfinityPacer/plex-gateway/compare/v0.1.3...v0.1.4
[0.1.3]: https://github.com/InfinityPacer/plex-gateway/compare/v0.1.2...v0.1.3
[0.1.2]: https://github.com/InfinityPacer/plex-gateway/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/InfinityPacer/plex-gateway/compare/v0.1.0...v0.1.1
Expand Down
36 changes: 30 additions & 6 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
STRM-backed cloud media. Plex remains the metadata, authentication, library,
and watch-state authority. The gateway observes Plex metadata, resolves an
eligible STRM through MediaVault, and returns one HTTP 302 response so the
client downloads media directly from the cloud CDN.
client downloads media directly from the cloud CDN. A browser extension that
negotiates `control-v1` can instead use bodyless control exchanges while media
still travels directly from the CDN to the browser.

Local Plex media is never rewritten. Cache misses, mapping failures, invalid
STRM files, MediaVault failures, and every unsupported endpoint fall back to
Expand All @@ -32,8 +34,9 @@ short-lived grant is created only after Plex explicitly marks the same Part as
Direct Play. If the client then requests universal `start`,
`start.mpd`, or `start.m3u8`, the gateway requires that grant from the same
playback session and exact Media/Part, authorizes the Part again, and returns
the same CDN redirect without starting Plex Transcoder or synthesizing Plex
metadata.
control information to ShimWeave or the CDN redirect to an ordinary client.
Neither path starts Plex Transcoder, synthesizes Plex metadata, or sends media
bytes through the gateway.

The gateway applies the same MediaInfo projection rules to every client. A
disabled-by-default experimental playback veto checks the Plex for Apple TV,
Expand All @@ -53,9 +56,13 @@ elements that have the shape of STRM Parts. When the
browser natively supports the container and codecs, the element can follow the
302 and read the CDN directly even when the final origin has no CORS header;
media bytes still bypass the gateway. Sources that require DASH, remuxing, or
transcoding remain unsupported. The gateway does not synthesize manifests or
proxy video streams. Setting `PLEX_WEB_DIRECT_PLAY_ENABLED=false` restores a
fully transparent Plex Web shell.
audio transcoding remain unsupported by the built-in helper.
[ShimWeave](https://github.com/InfinityPacer/ShimWeave) can negotiate
`control-v1` for these sources and perform browser-side remuxing or necessary
audio compatibility handling. The gateway still does not synthesize manifests
or proxy video streams. Setting `PLEX_WEB_DIRECT_PLAY_ENABLED=false` restores a
fully transparent Plex Web shell without disabling the separate extension
protocol.

## Compatibility status

Expand All @@ -66,10 +73,27 @@ fully transparent Plex Web shell.
| Plex iOS ExperimentalPlayer | Direct Play verified | STRM uses the universal decision/start redirect path. Descriptive Gateway Streams can provide 4K, HEVC, HDR/DV, and related technical fields; audio state or playback badges may remain incomplete until Plex has materialized native Stream rows. |
| Plex for Apple TV | Direct Play verified | HDR STRM uses the universal decision/start redirect path. Apple TV 4K supports Dolby Vision Profile 5 Direct Play, while Plex version, container, and source combinations may still affect compatibility; the gateway does not reject it by default. |
| Plex Web cloud Direct Play | Direct Play verified | MP4/H.264/AAC was verified for initial playback, pause, resume, and seek with CDN-direct delivery. Other containers and codecs depend on native browser support; sources that require DASH, remuxing, or transcoding remain unsupported. |
| Plex Web with ShimWeave | Basic integration verified | Initial playback and long seeks were verified with MKV, HEVC, and AAC. The extension reads media from the CDN and handles it in the browser. One tested 4K HEVC Main 10 with EAC3 source remains explicitly unsupported; additional 4K, HDR/DV, and audio combinations depend on ShimWeave, the browser, operating system, and hardware. |

This is an independent community project. It is not affiliated with, endorsed
by, or sponsored by Plex, MediaVault, Infuse, or their respective owners.

## Using ShimWeave

`plex-gateway 0.1.4` and later include the ShimWeave `control-v1` protocol with
no additional environment variable. After installing
[ShimWeave 0.0.1 or later](https://github.com/InfinityPacer/ShimWeave/releases),
the extension takes over only when Plex Web cannot play the source natively,
Plex has authorized the exact STRM Part for Direct Play, and both sides complete
protocol negotiation. Existing Plex behavior remains unchanged without the
extension, after a failed negotiation, for local media, and for browser-native
sources.

The gateway returns only control information and the current temporary media
address. The browser requests Range data directly from the CDN, so media bytes
never traverse the gateway or NAS. See the ShimWeave README for installation,
supported formats, and current limitations.

## Container image

Release images use
Expand Down
34 changes: 25 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
> **状态:** 实验性。透明代理和 STRM 重定向链路已经实现,但客户端兼容性仍然有限,必须针对每个 Plex 客户端和播放模式分别验证。

`plex-gateway` 是一个面向 STRM 云端媒体 Direct Play 的故障回退型 Plex
协议适配器。Plex 仍然是元数据、身份认证、媒体库和观看状态的权威来源。Gateway
观察 Plex 元数据,通过 MediaVault 解析符合条件的 STRM,并返回一次 HTTP 302,
让客户端直接从云端 CDN 下载媒体。
协议适配器。Plex 仍然是元数据、身份认证、媒体库和观看状态的权威来源。普通客户端播放时,
Gateway 观察 Plex 元数据,通过 MediaVault 解析符合条件的 STRM,并返回 HTTP 302,让客户端
直接从云端 CDN 下载媒体。支持 `control-v1` 的浏览器扩展可改用无媒体 body 的控制交换;媒体
仍由浏览器直接从 CDN 读取。

本地 Plex 媒体不会被重写。缓存未命中、路径映射失败、STRM 文件无效、MediaVault
失败以及所有不支持的 endpoint 都会无条件回退到原始 Plex 请求。
Expand All @@ -24,8 +25,9 @@ Part。Part 缓存未命中时,请求会原样发送给 Plex;Gateway 不会
响应的前提下,请求 Plex 将该播放选择为 Direct Play。只有当该完整响应明确将同一个
Part 标记为 Direct Play 后,Gateway 才会创建短期授权。如果客户端随后请求通用的
`start`、`start.mpd` 或 `start.m3u8`,Gateway 会要求该播放会话及精确 Media/Part
对应的授权,再次为 Part 请求授权,并返回同一个 CDN 重定向,而不会启动 Plex
Transcoder 或合成 Plex 元数据。
对应的授权,再次为 Part 请求授权。普通客户端收到 CDN 重定向;声明 `control-v1` 的请求收到
固定控制端点和短期 bearer,浏览器随后为每个 Range 换取临时 CDN URL。两条路径都不会启动
Plex Transcoder、合成 Plex 元数据或让媒体字节经过 Gateway。

Gateway 对所有客户端使用同一套 MediaInfo 投影规则。默认关闭的实验性播放 veto 只在
Plex 已返回同一 STRM Part 的 Direct Play decision、且本次 MediaInfo 增强已经取得新鲜
Expand All @@ -34,12 +36,14 @@ Plex 已返回同一 STRM Part 的 Direct Play decision、且本次 MediaInfo
额外探测。Apple TV 硬件支持 Profile 5,实际兼容性还受 Plex 版本、容器和片源影响,
因此 veto 默认关闭。

能够在这些路径上接受原始媒体重定向的原生客户端可以直接使用此链路。Plex Web
兼容层默认开启:Gateway 只在 Plex Web shell 中加载一个版本化脚本,并只对同源、
能够在这些路径上接受原始媒体重定向的原生客户端可以直接使用此链路。未安装 ShimWeave 时,
默认启用的 Plex Web 兼容层只在 Plex Web shell 中加载一个版本化脚本,并只对同源、
呈 STRM Part 形态的 `/library/parts/.../file` 或 `.strm` 媒体元素移除 `crossorigin`。浏览器原生支持该容器和编码时,可以按
普通媒体元素跟随 302 直接读取 CDN,即使最终源站没有 CORS header;媒体字节仍不经过
Gateway。需要 DASH、转封装或转码的片源仍不支持,Gateway 不合成 manifest,也不代理
视频流。关闭 `PLEX_WEB_DIRECT_PLAY_ENABLED` 后,Plex Web 页面恢复完全透明代理。
Gateway。需要 DASH、转封装或音频转码的片源仍无法由该内置薄层处理。[ShimWeave](https://github.com/InfinityPacer/ShimWeave)
可通过 `control-v1` 接管这类播放,并在浏览器内完成转封装或必要的音频兼容处理;Gateway 仍不合成
manifest、不代理视频流。关闭 `PLEX_WEB_DIRECT_PLAY_ENABLED` 后,内置薄层恢复完全透明代理,
不影响扩展的独立协商协议。

## 兼容性状态

Expand All @@ -50,10 +54,22 @@ Gateway。需要 DASH、转封装或转码的片源仍不支持,Gateway 不合
| Plex iOS ExperimentalPlayer | 已验证 Direct Play | STRM 使用通用 decision/start 重定向链路。Gateway 描述性 Stream 可补充 4K、HEVC、HDR/DV 等技术字段;Plex 尚未物化原生 Stream 行时,音轨状态或播放页徽标仍可能不完整。 |
| Plex for Apple TV | 已验证 Direct Play | HDR STRM 使用通用 decision/start 重定向链路。Apple TV 4K 支持 DV Profile 5 Direct Play,但 Plex 版本、容器和片源组合仍可能影响兼容性;Gateway 默认不拒绝。 |
| Plex Web 云端 Direct Play | 已验证 Direct Play | MP4/H.264/AAC 样本已验证首播、暂停、继续和 seek,并保持 CDN 直达;其他容器与编码取决于浏览器原生能力,需要 DASH、转封装或转码的片源不支持。 |
| Plex Web + ShimWeave | 已验证基础联动 | MKV、HEVC、AAC 已验证起播和长进度拖动。媒体由扩展从 CDN 读取并在浏览器内处理;当前一组 4K HEVC Main 10 + EAC3 样本仍明确不支持,更多 4K、HDR/DV 和音频组合取决于 ShimWeave、浏览器、系统及硬件能力。 |

本项目是独立的社区项目,与 Plex、MediaVault、Infuse 或其各自所有者没有关联,
也未获得其认可或赞助。

## 与 ShimWeave 配合

`plex-gateway 0.1.4` 起内置 ShimWeave `control-v1` 协议,无需增加环境变量。安装
[ShimWeave 0.0.1 或更高版本](https://github.com/InfinityPacer/ShimWeave/releases) 后,
扩展只会在 Plex Web 无法原生播放、Plex 已为准确 STRM Part 建立 Direct Play 授权且双方完成
协议协商时接管播放。未安装扩展、协商失败、本地媒体或浏览器原生可播内容继续使用原有 Plex
路径。

Gateway 只返回控制信息和当前有效的临时媒体地址。媒体 Range 数据始终由浏览器直接请求 CDN,
不会经过 Gateway 或 NAS。ShimWeave 的安装方法、支持格式和已知限制以其项目 README 为准。

## 容器镜像

发布后的镜像将使用:
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.3
0.1.4
35 changes: 28 additions & 7 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ gateway; the isolated analysis worker may read a bounded amount for probing.
to the final CDN URL. The start path does not repeat the metadata lookup or
STRM read. Local media and every uncertain selection remain ordinary Plex
traffic.
- A `start.mpd` request that declares ShimWeave `control-v1` is terminated with
a bodyless control descriptor only after the same Grant and Plex Part
authorization succeed. The descriptor separates stable content identity, a
fixed same-origin control path, and a high-entropy bearer carried only in a
request header. Each controlled Range request may
overlay only its single `Range` header onto the immutable client context,
resolves one ephemeral MediaVault URL, and receives that URL in a bodyless
response header. The browser then creates a separate credential-free CDN
request. The gateway never follows the URL or handles media bytes.
- Timeline, scrobble, sessions, playlists, subtitles, images, transcode
segments, and every unrecognized endpoint remain ordinary Plex traffic.
- When Plex Web compatibility is enabled, only successful `GET /web/` and
Expand Down Expand Up @@ -107,7 +116,8 @@ control-file and metadata readers.
| Technical MediaInfo | A validated producer record, or Gateway SQLite for fallback-probed media; Plex fields and response enrichment are projections. Plex DB production writes are not enabled in this release. | Source or STRM fingerprint change, schema change, or freshness policy. |
| Part cache | Derived by metadata observation or an authenticated playback selection, keyed by `Part.id`. | Configured TTL or process restart. |
| Direct Play grant | Published only after a complete Plex decision explicitly accepts the exact Part; a new related decision revokes the previous grant first. | Five-minute TTL, bounded eviction, or explicit revocation. |
| MediaVault direct URL | Produced for the active authorized request and copied only to `Location`. | Never persisted or reused by the gateway. |
| ShimWeave control ticket | In-memory bearer issued only after a live Direct Play grant and repeated Plex Part authorization. The attempt key is stored as a digest and retained client headers are bounded. | Thirty-minute idle TTL, 24-hour absolute TTL, bounded eviction, or process restart. |
| MediaVault direct URL | Produced for the active authorized request and copied to `Location`, or to the bodyless `control-v1` response header. | Never persisted or reused by the gateway. |

## Multi-volume path mapping

Expand Down Expand Up @@ -151,14 +161,17 @@ an HTTP(S) `Location` becomes one `302 Found` response from the gateway. The
full redirect URL, query values, Plex tokens, cookies, and API keys are never
logged.

The complete client request header set is cloned onto every MediaVault
The complete client request header set is cloned onto the initial MediaVault
`/redirect` request, including bounded internal redirect hops. Query-carried
`X-Plex-*` context is promoted to headers when the client did not already send
the corresponding header. Direct-link resolution is always an internal `GET`
control request, so a client `HEAD` can still receive the same gateway 302 even
when MediaVault does not implement `HEAD`. Because Plex credentials and cookies
are included, the configured MediaVault origin is a trusted upstream and must
not point to an untrusted service.
the corresponding header. A ShimWeave control ticket retains that authorized
snapshot within a 64 KiB limit; later calls may replace only one non-empty
`Range` header and cannot replace Plex Token, Cookie, Authorization, or other
identity context. Direct-link resolution is always an internal `GET` control
request, so a client `HEAD` can still receive the same result when MediaVault
does not implement `HEAD`. Because Plex credentials and cookies are included,
the configured MediaVault origin is a trusted upstream and must not point to an
untrusted service.

## Failure policy

Expand Down Expand Up @@ -284,6 +297,14 @@ The redirect plane requires a client that can consume the final raw media URL.
Native players are not subject to browser cross-origin fetch enforcement and
may accept redirects from either Part or eligible universal start routes.

ShimWeave integration is negotiated per request and remains outside the normal
redirect path. The gateway owns Plex authorization and temporary URL exchange;
the extension owns browser capability checks, media reads, remuxing, and audio
compatibility handling. Requests without a valid `control-v1` negotiation,
including local media and browser-native playback, retain Plex's original
behavior. Gateway protocol support therefore does not imply that every media
format is playable in a particular browser or device.

Plex Web sets `crossorigin=anonymous` on its HTML media element. When a cloud
Part redirects from the Gateway origin to a CDN without CORS headers, the
browser rejects an otherwise natively playable file before Plex Web falls back
Expand Down
Loading