I got tired of paying for streaming apps, yet still having to fight them. YouTube downloads on my phone were unreliable, Netflix would randomly lock me out while traveling, and most smart-TV apps are even worse.

I built my own pipeline: local [[intake|subscription list]], download, organize, re-encode, and watch. It works on my phone and on my TV.

I still pay for Youtube Premium, Amazon Prime, and Netflix; I consider this pipeline a more useful version of a DVR. At the end of the day the quality is actually worse (since I’m optimizing for storage, especially for downloading to my phone), but the interface is exactly what I want.

Media downloader + player setup (Fedora KDE, rootless containers)

This runs on Fedora KDE (immutable) with rootless Podman containers managed by systemd user services (with linger). I wanted something that behaves like a small service: predictable startup, explicit networks, explicit paths, and as few host changes as possible.

In day-to-day use it:

What’s running

Host choices:

Services:

Basic Flow

Networking

I ended up with two networking setups.

Internal services:

qBittorrent:

Storage layout and the permissions mess

I keep all persistent state in two places:

Things I screwed up at first:

The Sonarr/Radarr import problem and the real fix

The most annoying problem was the media would get lost between subscription and Jellyfin. The issue came down to paths.

qBittorrent (host network) and Sonarr/Radarr (bridge network) were looking at different filesystem paths for the same downloads

Fix:

Indexers and FlareSolverr

FlareSolverr:

This avoids copy/pasting indexer settings into three different UIs.

YouTube subscriptions (ytdl-sub)

When automation breaks, I can still trigger the downloader manually inside the container.

This needs to be updated if YouTube changes their interface, and is the least stable part of my system.

I also use this for music off YouTube, although I still just use YouTube Music. The Premium version isn’t enshitified yet.

Tdarr post-processing

Tdarr runs after import to compress the files. I get 90% compression on most BitTorrent downloads, but it is still roughly HD.

What it’s trying to do

This flow targets oversized, high-bitrate files and recompresses them to a controlled HEVC profile. The goal is disk savings with predictable output, and no pointless churn.

How it behaves

  1. Skip anything already processed
  2. Skip anything that won’t benefit
  3. Encode with one consistent profile
  4. If it errors, try a fallback path
  5. Record the outcome so it won’t loop

Details:

Boot and reliability

Early failures were mostly self-inflicted:

Once cleaned up, everything comes up reliably. (Except qbittorent… sometimes the VPN fails to connect and it just gets stuck download metadata. Sometimes other pods too…)