unarr/CHANGELOG.md
Deivid Soto 0f4ad67827 fix(transcode): make preset libx264-only + restore quality opt-in
Two issues with the 0.9.9 preset retune:

1. applyDefaults was filling Preset="veryfast" before
   ResolveEncoderProfile got to pick the latency-biased default, so the
   "superfast" change never reached users with a freshly-generated
   config.toml — only those who left the field empty saw it.

2. The configured preset was being passed through to every encoder.
   That's only valid for libx264 (ultrafast…veryslow); NVENC uses p1-p7
   and rejects anything else, QSV uses its own subset. A user with NVENC
   + preset="veryfast" would have ffmpeg reject the argv.

Now:
- TranscodeConfig.Preset documented as libx264-only with the full
  range + advice on quality vs first-start latency.
- Default in applyDefaults is empty (was "veryfast") so the engine
  fills in "superfast" on libx264.
- ResolveEncoderProfile ignores configuredPreset for vendor encoders
  (NVENC sticks to p3, QSV to veryfast, VideoToolbox has no preset
  knob). Test cases updated to lock in this behaviour.

Users who want better quality at slower first-play should set
download.transcode.preset = "veryfast" (previous default) / "faster" /
"fast" / "medium" in their config.toml.
2026-05-27 10:46:03 +02:00

21 KiB
Raw Blame History

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[0.9.9] - 2026-05-27

Added

  • per-session encoder log: every HLS session start now logs encoder=… accel=… preset=… so a "preparando sesión" complaint can be triaged from the journal alone. Cache-HIT sessions keep the existing simpler log (no ffmpeg involved).
  • probe cache: engine.ProbeFile is memoised by (path, mtime, size) for 30 minutes. A second play of the same file skips ffprobe entirely — saves 1-3 s on first-segment latency for 50+ GB MKVs. Cache key changes immediately on any file rewrite (mtime or size delta).
  • agents tab transcoder row: the web profile → agents tab now shows each agent's selected encoder (NVIDIA NVENC, Intel Quick Sync, VA-API, macOS VideoToolbox, or Software (libx264) in amber) plus the comfortable transcode-resolution cap. Surfaces the same diagnostic the daemon log carries.

Changed

  • HLS encoder presets biased for first-start latency:
    • libx264: default veryfastsuperfast (~15-20% faster encode; marginal quality loss at 5-25 Mbps target bitrates). Users wanting the previous quality can set download.transcode.preset = "veryfast" in config.toml.
    • NVENC: -preset p4 -tune hq-preset p3 -tune ll. First-segment encode drops from ~1.5 s to ~0.8 s on RTX-class GPUs.
    • QSV: -preset medium-preset veryfast. Keeps -look_ahead 0 for low-latency rate control.
    • VideoToolbox (macOS): adds -realtime 1 -q:v 50 (was unset). The realtime flag steers VideoToolbox into the low-latency code path.
  • Encoder + preset selection moved into engine.ResolveEncoderProfile so the same logic drives both argv construction and the log line.
  • download.transcode.preset is now libx264-only. The configured preset is honoured on software encode (libx264 vocabulary: ultrafast → veryslow); HW backends ignore it and use vendor-specific defaults (NVENC p3, QSV veryfast). Passing a libx264 preset to NVENC / QSV was previously rejected by ffmpeg; the documentation now reflects what was always the only correct usage.
  • Default download.transcode.preset is empty (was "veryfast"). The engine fills in "superfast" for libx264 — latency-biased. Users who want better quality at slower first-play should set it explicitly in config.toml: "veryfast" (previous default) / "faster" / "fast" / "medium". Range documented in the TranscodeConfig struct.

[0.9.8] - 2026-05-27

Fixed

  • auto-upgrade restart loop: when the server signal arrived for a version the daemon was already running (e.g. flag still set after a previous upgrade), applyAutoUpgrade would call upgrade.Execute (which no-ops), then os.Exit(0) anyway — systemd respawned, the flag was still set, the cycle repeated. Now: no-op case is detected up front, the daemon clears the server flag via /api/internal/agent/upgrade-result and stays alive.
  • upgrade flag stuck after success: the CLI never reported the upgrade outcome, so upgrade_requested stayed true in the DB forever. The daemon now calls /api/internal/agent/upgrade-result on every applyAutoUpgrade branch (success, failure, no-op) — server clears the flag, restart loops end.

Added

  • New Client.ReportUpgradeResult(agentID, success, version, error) HTTP method wrapping POST /api/internal/agent/upgrade-result.

[0.9.7] - 2026-05-26

Added

  • hls cache: persistent fMP4 segment cache keyed by (source, quality, audio_index). After a successful encode the segments
    • init.mp4 are kept under ~/.cache/unarr/hls-cache/{key}/ with a .complete marker. A second play of the same file at the same quality skips ffmpeg entirely (smoke-tested 2331× faster than re-encode). LRU
    • size-budget eviction; pinned during active play; per-key writer-lock prevents two concurrent encodes from corrupting each other. Startup reaps orphan dirs without .complete older than 10 min so a daemon crash doesn't leak disk indefinitely. New [downloads.hls_cache] block in config.toml: enabled (default true), size_gb (default 5, min 1), dir (default ~/.cache/unarr/hls-cache).
  • hls cache integrity check: on HIT, the daemon stats init.mp4 + last segment before reporting cache reuse — if a file was externally deleted, the entry is invalidated and re-encoded transparently.
  • hls cache stats: hit/miss counters surface via cache.Stats() (Hits, Misses, EntryCount, TotalBytes) and the sweeper logs a daily summary line [hls_cache] day-stats: hits=N misses=M ratio=X% entries=Y size=ZMB.
  • subtitle integrity for cached replay: Close waits up to 15 s for the subtitle extractor goroutine before sealing .complete so a HIT never serves half-written .vtt files. Timeout invalidates instead of sealing.

Changed

  • [daemon] auto_upgrade now appears in fresh config.toml files as true (it was always the implicit default; this just makes it visible in default-generated configs).

[0.9.6] - 2026-05-26

Added

  • auto-upgrade: when the web flags the agent for upgrade (POST /api/internal/agent/upgrade or the "Force update now" button), the daemon now downloads and replaces the binary in-place, then exits so the service supervisor (systemd Restart=always on Linux, the equivalent on macOS/Windows) respawns on the new version. No unarr update step required from the user. Still opt-in — only fires when the server sends the upgrade signal.

Changed

  • The OnUpgrade daemon callback no longer just logs run unarr self-update; it now triggers the actual upgrade in a background goroutine.

[0.9.5] - 2026-05-26

Added

  • funnel: optional CloudFlare Quick Tunnel subprocess. unarr funnel on spawns cloudflared as a child process and registers an anonymous https://<random>.trycloudflare.com hostname tunnelled to the daemon's HLS server. The hostname is reported back to the web on every sync so the in-browser player picks it up automatically — cross-network playback now works on torrentclaw.com without Tailscale or port forwarding. Bytes proxy through CloudFlare; TorrentClaw still doesn't relay content.
  • funnel: on by default for fresh installs (NAS/Docker get cross-network HTTPS automatically); existing configs that pre-date the feature stay off until the operator runs unarr funnel on.
  • funnel: auto-downloads cloudflared to the unarr data dir when not on PATH (Linux amd64/arm64/armhf/386). ELF magic + size sanity check on the download; O_EXCL partial-write so concurrent daemons don't clobber each other.
  • funnel: subprocess supervisor keeps the tunnel up across cloudflared crashes + CF's ~6h Quick Tunnel rotation. Exponential backoff (2 s → 5 min) on persistent failures. The web's reported URL is cleared the moment cloudflared exits so an outdated hostname doesn't keep handing out 502s.
  • funnel: unarr funnel status shows the live URL once registered. See README §[downloads.funnel] for the throughput / latency caveats of CF's free Quick Tunnels.
  • docker: the official torrentclaw/unarr image now bundles cloudflared so the funnel works the moment the container starts — no first-run download.

Fixed

  • hls/libx264: bump the H.264 level we hint to libx264 by one tier so anamorphic (>16:9) sources stop emitting unplayable streams. 720p at level 3.1 silently rejected 1728×720 cinemascope frames with frame MB size > level limit; 720p now ships at level 4.0, 1080p at 4.1. Decoder compatibility is unaffected — every device that handles 1080p already handles ≥ 4.1.

[0.9.4] - 2026-05-26

Removed

  • streaming: retire the custom WebRTC DataChannel pipeline. The daemon no longer ships pion/webrtc, the WSS signaling client, or the wire framing package — every in-browser session now uses HLS over HTTP from the daemon (Tailscale / LAN / UPnP). Browser P2P (WebTorrent) bytes never re-enabled.
  • config: [downloads.webrtc] block removed from the TOML schema; existing config files with the section parse cleanly because go-toml ignores unknown sections.
  • seed_file: mode=seed_file task handler + engine.SeedFile helper dropped — the last in-browser caller was retired with the WebRTC player.
  • wstracker-probe: standalone probe binary removed.

Changed

  • agent wire: SyncResponse.WebRTCSessions (JSON: webrtcSessions) renamed to StreamSessions (JSON: streamSessions). The Go type agent.WebRTCSession is now agent.StreamSession. Wire-incompatible with web < 2026-05-26.
  • torrent: buildMagnet no longer accepts an extraTrackers variadic — the default tracker list is the only set used.

Fixed

  • hls: clamp the ffmpeg -b:v to the bitrate cap derived from the EFFECTIVE output height instead of the requested quality. Previously asking for "2160p" on a 1080p source overshot the H.264 level we resolved from the effective height (4.0, max 20 Mbps) and made libx264 abort with VBV bitrate > level limit.

[0.9.2] - 2026-05-21

Added

  • vpn: unarr vpn command (status, enable, disable) to manage the managed WireGuard split-tunnel, with vpn status --check to verify provisioning.
  • vpn: report split-tunnel state (active, exit server) to the web on register
    • every sync, so the dashboard shows which agent holds the single WireGuard slot.
  • vpn: send the agent id when fetching the VPN config so the web can arbitrate the single WireGuard slot — the first agent claims it; the rest are told to run OpenVPN on their own host (1 agent on WireGuard + up to 9 on OpenVPN).

[0.9.1] - 2026-05-21

Added

  • mirror: update fallback URLs to use IPFS and remove GitHub Pages

Fixed

  • security: bump golang.org/x deps and add container CVE scan gate

[0.9.0] - 2026-05-21

Added

  • agent: add mirror failover, agent client refactor, status 401 detection
  • vpn: local config_file for self-hosted/personal VPN testing
  • vpn: split-tunnel torrent traffic through managed WireGuard

Documentation

  • docker: refresh Docker Hub README + sync description in CI

Fixed

  • security: CORS allowlist, URL scheme guard, state perms, ZIP slip, mirror docs
  • security: UPnP opt-in, bounded SSE reader, signed self-update
  • security: harden HLS session IDs, /health disclosure, archive password handling
  • upgrade: fetch releases from TorrentClaw app, not GitHub

Other

  • release: 0.9.0

[0.8.1] - 2026-05-08

Added

  • config: set default values for WebRTC and transcoding in minimal TOML config
  • transcode: dynamic H.264 level + HW probe + capability reporting

Changed

  • streaming: improve signal handling and remove unused components

Fixed

  • self-update: auto-restart live daemon after upgrade
  • streaming: allow HLS sessions when webrtc disabled

Other

  • gitignore: add dist-ffbinaries to ignored files
  • release: 0.8.1

[0.8.0] - 2026-05-08

Added

  • mediainfo: ResolveFFmpeg + DownloadFFmpeg mirroring ffprobe pattern
  • release: bundle ffmpeg + ffprobe in tarballs and Docker image
  • seed-file: unarr-side handler for browser-on-demand seeding (Fase 4.7.c)
  • stream: per-session quality cap from web
  • stream: real-time transcoding for non-browser-decodable codecs
  • stream: pion-based WebRTC byte streamer for browser playback
  • streaming: seek-restart, single-session, idle sweeper, probe.json
  • streaming: add HLS transport pipeline (daemon side)
  • streaming: ffmpeg transcoding pipeline (direct play / fMP4 / HW accel)
  • torrent: act as WebTorrent peer for browser ↔ unarr P2P streaming
  • wstracker-probe: -seed FILE mode for browser ↔ unarr e2e validation

Fixed

  • streaming: bounded ffmpeg auto-restart + tmpdir gc + probe/stderr safety
  • transcoder: force aac stereo 48khz + frag_duration for mse compat
  • transcoder: force main profile + setparams Rec.709 + serveRange wait
  • transcoder: correct scale filter + always force yuv420p

Other

  • release: 0.8.0
  • streaming: post-review fixes — race lock, dead branch, stderr cap
  • torrent: bump anacrolix log level Critical → Warning for visibility

[0.7.0] - 2026-04-10

Added

  • daemon: enhance service management with start, stop, restart, and status commands for Windows

Other

  • release: 0.7.0

[0.6.8] - 2026-04-10

Added

  • library: add server-driven file deletion with allow_delete config

Other

  • release: 0.6.8

[0.6.7] - 2026-04-10

Added

  • scan: always scan downloads + organize dirs, deduplicate child paths

Other

  • release: 0.6.7

[0.6.6] - 2026-04-09

Fixed

  • docker: switch ffprobe download from johnvansickle.com to BtbN/FFmpeg-Builds
  • stream: fix black screen on remote/Tailscale streaming

Other

  • release: 0.6.6

[0.6.5] - 2026-04-09

Fixed

  • upgrade: retry download on transient network errors with user feedback

Other

  • release: 0.6.5

[0.6.4] - 2026-04-09

Fixed

  • daemon: report error status when stream path is rejected

Other

  • release: 0.6.4

[0.6.3] - 2026-04-09

Fixed

  • library: use native arm64 ffprobe on Apple Silicon (osx-arm-64)

Other

  • release: 0.6.3

[0.6.2] - 2026-04-09

Added

  • library: resilient scan for large libraries and better ffprobe errors

Other

  • release: 0.6.2
  • ignore local config/ directory

[0.6.1] - 2026-04-08

Added

  • wake: long-poll wake listener for instant CLI sync

Fixed

  • resolve deadlock, data races and path traversal vulnerabilities

[0.6.0] - 2026-04-08

Added

  • sync: replace WS+DO transport with unified HTTP sync

Fixed

  • ws: add ping/pong keepalive and read deadline to detect zombie connections

Other

  • release: 0.6.0

[0.5.5] - 2026-04-07

Added

  • agent: send stream port and IPs in register request
  • stream: report duration and position in watch progress
  • stream: trackingReader with byte-based progress and rate limiting

Fixed

  • daemon: cancel watch reporter on stream switch and re-notify ready

Other

  • release: 0.5.5

[0.5.4] - 2026-04-07

Fixed

  • stream: use platform-specific socket options for Windows cross-compilation

Other

  • release: 0.5.4

[0.5.3] - 2026-04-07

Added

  • stream: persistent stream server with file swapping

Other

  • release: 0.5.3

[0.5.2] - 2026-04-07

Added

  • stream: report multi-network URLs for smart resolution

Other

  • release: 0.5.2

[0.5.1] - 2026-04-07

Added

  • daemon: add on-demand library scan via heartbeat and WebSocket

Fixed

  • agent: add retry with backoff and WebSocket connect for daemon registration
  • daemon: report failed status on stream request errors
  • daemon: use correct systemd user target and isolate test cache
  • stream: prevent duplicate events from killing active stream server

Other

  • release: 0.5.1

[0.5.0] - 2026-04-06

Added

  • organize: use server metadata for file organization and subtitle handling
  • stream: add NAT-PMP port mapping for remote downloads

Other

  • release: 0.5.0
  • release: add changelog generation and release automation

[0.4.1] - 2026-04-01

Added

  • cli: add login command and refactor shared helpers
  • stream: report watch progress to API via HTTP Range tracking

Fixed

  • ci: fix lint errors and pin CI to Go 1.25
  • lint: remove unused newStubCmd function

Other

  • cli: remove moreseed stub command
  • cli: remove redundant stub commands (monitor, open, add, compare)

[0.4.0] - 2026-03-31

Added

  • cli: upgrade command, rich status, and version cache

Fixed

  • progress: always report status transitions and poll for control signals

[0.3.7] - 2026-03-31

CI/CD

  • docker: remove dockerhub-description sync step

[0.3.6] - 2026-03-31

CI/CD

  • deps: bump docker/metadata-action from 5 to 6
  • deps: bump docker/setup-qemu-action from 3 to 4
  • deps: bump docker/login-action from 3 to 4
  • deps: bump docker/build-push-action from 6 to 7
  • deps: bump codecov/codecov-action from 5 to 6
  • docker: add Docker Hub description sync and DOCKERHUB.md

Fixed

  • ci: upgrade golangci-lint to v2.11.3 for Go 1.25 support
  • docker: upgrade alpine packages to patch CVE-2025-60876 and CVE-2026-27171
  • lint: use default:none to disable errcheck, fix all gofmt and exhaustive
  • lint: disable errcheck, tune gosec/exclusions for codebase state
  • lint: configure linters for codebase maturity, fix gofmt and ineffassign
  • lint: exclude common fire-and-forget patterns from errcheck
  • lint: resolve errcheck and bodyclose warnings for golangci-lint v2

[0.3.5] - 2026-03-30

Changed

  • migrate lint config to v2, remove daemon auto-upgrade, add trust badges

[0.3.3] - 2026-03-30

Fixed

  • ci: remove go-client checkout steps

[0.3.2] - 2026-03-30

Added

  • init: add 60s countdown, skip key, and cancel detection to browser auth

CI/CD

  • release: add Docker Hub publish and VirusTotal scan jobs

Documentation

  • add beta notice, fix install URLs to get.torrentclaw.com

Fixed

  • ci: fix virustotal job condition syntax
  • docker: simplify Dockerfile for CI builds (no local go-client)
  • release: disable homebrew tap (needs PAT, not GITHUB_TOKEN)

Other

  • re-enable homebrew tap in goreleaser

[0.3.1] - 2026-03-30

Fixed

  • build: unused variable in Windows process check
  • release: disable homebrew tap until repo is created

Other

  • rename module from torrentclaw-cli to unarr

Build

  • remove UPX compression (antivirus false positives, startup penalty)

[0.3.0] - 2026-03-29

Added

  • agent: add WebSocket transport with HTTP fallback
  • auth: browser-based CLI authentication (like Claude Code)
  • daemon: add auto-scan, force start, and stall timeout default
  • debrid: add HTTPS downloader for debrid direct URLs
  • stream: UPnP port forwarding for remote video playback
  • usenet: implement full NNTP download pipeline
  • add migrate command, media server detection, and debrid auto-config
  • replace setup with init wizard + interactive config menu
  • add clean command to remove temp files, logs, and cached data
  • add Sentry error reporting
  • improve daemon resilience, streaming, and usenet downloads
  • initial commit — unarr CLI

Changed

  • extract BuildSyncItems to library package, remove duplication

Documentation

  • improve CLI help, shell completion, and README

Fixed

  • torrent: expand tracker list, add DHT persistence and configurable timeouts
  • force-start tasks bypass HasCapacity check in dispatch loop
  • add panic recovery to auto-scan, cap DHT nodes at 200
  • harden usenet/debrid downloaders from critico review

Build