feat(funnel): cloudflare quick tunnel embedded subprocess (0.9.5)
Gives the daemon a public HTTPS hostname (`https://<random>.trycloudflare.com`)
so the in-browser player on torrentclaw.com plays cross-network without
Tailscale or port forwarding — the mixed-content block that was breaking
HTTPS-page → HTTP-daemon fetches is gone. Bytes proxy through CloudFlare,
never through TorrentClaw infra (preserves the aggregator legal posture).
New surface:
• `internal/funnel/` package: subprocess wrapper + auto-download for
cloudflared. Linux amd64/arm64/armhf/386 fetched from GitHub releases
on first run, validated by ELF magic + size sanity, O_EXCL partial
write so concurrent daemons don't clobber each other.
• `unarr funnel on/off/status` cobra command (sibling of `unarr vpn`).
• Daemon supervisor goroutine keeps cloudflared up across crashes + CF's
~6h Quick Tunnel rotation. Exponential backoff (2 s → 5 min). On exit
the reported URL is cleared so the web stops handing out a dead host.
• Wire: agent registers/syncs a FunnelURL field; web prefers it over
Tailscale/LAN for in-browser playback (HlsStreamPlayer + Stremio
addon).
Default ON for fresh installs (NAS/Docker get it without terminal-in);
existing configs that pre-date the feature stay off until the operator
opts in with `unarr funnel on`.
Docker image now bundles cloudflared (built per TARGETARCH via buildx).
Also fixed: libx264 'frame MB size > level limit' on anamorphic >16:9
sources. The level we hint to libx264 was derived from height alone,
which busted on 720p cinemascope (1728×720 = 4860 MBs > level 3.1's
3600). Bumped each tier: 720p → 4.0, 1080p → 4.1.
Version: 0.9.4 → 0.9.5.
This commit is contained in:
parent
ca7de23a56
commit
88316e7017
15 changed files with 778 additions and 13 deletions
|
|
@ -129,12 +129,13 @@ func (h HWAccel) FFmpegVideoCodec(target string) string {
|
|||
}
|
||||
}
|
||||
|
||||
// H264LevelForHeight returns the lowest H.264 profile level capable of encoding
|
||||
// a stream at the given output pixel height (assumes ~16:9, ≤30 fps). The
|
||||
// previous code used a fixed "4.0" which silently rejects anything above 1080p
|
||||
// — libx264 logs "frame MB size > level limit" and emits a corrupt stream.
|
||||
// Returning a tighter level on smaller outputs keeps player compatibility on
|
||||
// older devices where the encoder can't auto-pick.
|
||||
// H264LevelForHeight returns the lowest H.264 profile level capable of
|
||||
// encoding a stream at the given output pixel height. Each tier carries
|
||||
// enough macroblock headroom to handle ANAMORPHIC content (up to ~2.4:1
|
||||
// cinemascope) at 30 fps — a fixed 16:9 assumption used to silently bust
|
||||
// the level on a 720p movie shot in 2.4:1 (1728×720 = 4860 MBs > 3.1's
|
||||
// 3600 limit; libx264 logs "frame MB size > level limit" and emits a
|
||||
// corrupt stream).
|
||||
func H264LevelForHeight(height int) string {
|
||||
switch {
|
||||
case height <= 0:
|
||||
|
|
@ -142,11 +143,14 @@ func H264LevelForHeight(height int) string {
|
|||
// re-introduce the silent-failure mode that motivated this helper.
|
||||
return "5.1"
|
||||
case height <= 480:
|
||||
return "3.0"
|
||||
case height <= 720:
|
||||
return "3.1"
|
||||
case height <= 1080:
|
||||
case height <= 720:
|
||||
// 4.0 instead of 3.1: covers 720p anamorphic (e.g. 1728×720) +
|
||||
// MB rate up to 245k/s (3.1 caps at 108k/s — broken at 24 fps).
|
||||
return "4.0"
|
||||
case height <= 1080:
|
||||
// 4.1 instead of 4.0: covers 1080p anamorphic + 30 fps (~245k MBs/s).
|
||||
return "4.1"
|
||||
case height <= 1440:
|
||||
return "5.0"
|
||||
case height <= 2160:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue