Codec-aware transcode routing, two-stage queue, request candidate picker, admin reorg

- Requests approval now shows a Radarr/Sonarr candidate picker instead of grabbing the first search result (fixes wrong-title/wrong-year matches)
- approve_request reuses an existing Radarr/Sonarr entry instead of erroring when content is already in the library
- New codec-check queue (step 1) probes source codecs and skips transcoding entirely for already browser-native files; only non-native content reaches the transcode queue (step 2)
- Fixes ffmpeg hard-failing on non-H.264 sources via the h264_mp4toannexb bitstream filter (root cause of the fix-audio-all failures)
- Added Codec Check Worker / Transcode Worker to the services health panel with restart
- Reorganized the admin page into Pipeline/Utilities dropdowns; added the missing Sonarr Import link
- Bumped VERSION 1.0.0 -> 1.1.0
This commit is contained in:
root
2026-07-30 20:41:11 -05:00
parent 671074764e
commit b28a49e8fa
13 changed files with 784 additions and 50 deletions
+12 -1
View File
@@ -54,7 +54,10 @@ def search_movie(base_url: str, api_key: str, term: str) -> List[Dict]:
def add_movie(base_url: str, api_key: str, tmdb_id: int, title: str, year: Optional[int]) -> Dict:
"""Adds a movie by tmdb_id with monitoring + an immediate search enabled, using the first
configured quality profile and root folder — same defaults Radarr's own UI would pre-fill."""
configured quality profile and root folder — same defaults Radarr's own UI would pre-fill.
If the movie is already in Radarr's library, Radarr rejects the add with a 400
MovieExistsValidator — in that case, reuse the existing movie and just kick off a search
instead of surfacing the add as a failure."""
base_url = base_url.rstrip("/")
h = _h(api_key)
profiles = requests.get(f"{base_url}/api/v3/qualityprofile", headers=h, timeout=15).json()
@@ -67,6 +70,14 @@ def add_movie(base_url: str, api_key: str, tmdb_id: int, title: str, year: Optio
"monitored": True, "addOptions": {"searchForMovie": True},
}
r = requests.post(f"{base_url}/api/v3/movie", json=payload, headers=h, timeout=20)
if r.status_code == 400 and any(e.get("errorCode") == "MovieExistsValidator" for e in (r.json() or [])):
existing = requests.get(f"{base_url}/api/v3/movie", params={"tmdbId": tmdb_id}, headers=h, timeout=15).json()
if not existing:
raise RuntimeError("Radarr reported movie already exists but it could not be found")
movie = existing[0]
requests.put(f"{base_url}/api/v3/movie/{movie['id']}", json={**movie, "monitored": True}, headers=h, timeout=15)
requests.post(f"{base_url}/api/v3/command", json={"name": "MoviesSearch", "movieIds": [movie["id"]]}, headers=h, timeout=15)
return {"radarr_id": movie["id"], "title": movie.get("title"), "year": movie.get("year")}
r.raise_for_status()
added = r.json()
return {"radarr_id": added["id"], "title": added.get("title"), "year": added.get("year")}