Speed up transcoding without overloading the VM, add bulk retry

- nice level 19 -> 10 (was the absolute lowest CPU priority) and cap
  ffmpeg to 6 threads on this 8-core host, leaving headroom for Mongo,
  the *arr stack, and the API itself instead of an unbounded encode.
- Add POST /transcode/queue/retry-failed to re-queue every failed/
  cancelled job at once; label the per-job Retry button with text
  (was icon-only) and clarify in the page copy that failed/cancelled
  jobs never delete the movie — retry just re-queues the same file.
This commit is contained in:
Myron Blair
2026-07-26 21:21:22 -05:00
parent c174ac60b1
commit 4e72f568f3
3 changed files with 33 additions and 6 deletions
+15 -4
View File
@@ -44,6 +44,14 @@ export default function TranscodeQueue() {
catch (err) { toast.error(err.response?.data?.detail || "Could not retry"); }
};
const retryAllFailed = async () => {
try {
const { data } = await api.post("/transcode/queue/retry-failed");
toast.success(`Re-queued ${data.retried} job(s)`);
load();
} catch (err) { toast.error(err.response?.data?.detail || "Could not retry"); }
};
const togglePause = async () => {
try {
const { data } = await api.post("/transcode/queue/pause", { paused: !stats.paused });
@@ -64,9 +72,9 @@ export default function TranscodeQueue() {
<span className="text-xs uppercase tracking-[0.3em] text-[#D9381E]">Background</span>
<h1 className="font-display text-5xl md:text-6xl font-black tracking-tighter text-white mt-3">Transcode Queue</h1>
<p className="text-[#8A8A8A] mt-4 max-w-2xl">
One job runs at a time at low CPU priority. Auto-transcode is currently:{" "}
One job runs at a time, moderate CPU priority, capped threads so it can't starve the rest of the stack. Auto-transcode is currently:{" "}
<span className="text-white">{stats.auto_transcode === "off" ? "off" : `auto · ${stats.auto_transcode}`}</span>
{" — "}<a href="/admin/settings" className="text-[#D9381E] hover:text-[#ED4B32]">change in Settings</a>
{" — "}<a href="/admin/settings" className="text-[#D9381E] hover:text-[#ED4B32]">change in Settings</a>. Failed and cancelled jobs never delete the movie retry re-queues the same file.
</p>
<div className="mt-8 grid grid-cols-2 sm:grid-cols-5 gap-3">
@@ -86,6 +94,9 @@ export default function TranscodeQueue() {
{stats.paused ? <PlayIcon size={14} strokeWidth={1.5} /> : <Pause size={14} strokeWidth={1.5} />}
{stats.paused ? "Resume" : "Pause"}
</button>
<button onClick={retryAllFailed} disabled={!stats.failed && !stats.cancelled} className="flex items-center gap-2 border border-[#222] hover:border-[#D9381E] hover:text-[#D9381E] text-[#8A8A8A] px-4 py-2 text-xs uppercase tracking-[0.2em] transition-colors disabled:opacity-50" data-testid="queue-retry-all">
<RotateCcw size={14} strokeWidth={1.5} /> Retry All Failed
</button>
<button onClick={clearFinished} className="flex items-center gap-2 border border-[#222] hover:border-[#fca5a5] hover:text-[#fca5a5] text-[#8A8A8A] px-4 py-2 text-xs uppercase tracking-[0.2em] transition-colors" data-testid="queue-clear">
<Trash2 size={14} strokeWidth={1.5} /> Clear Finished
</button>
@@ -124,8 +135,8 @@ export default function TranscodeQueue() {
</button>
)}
{(j.status === "failed" || j.status === "cancelled") && (
<button onClick={() => retry(j.id)} className="text-[#8A8A8A] hover:text-[#D9381E]" data-testid={`retry-${j.id}`} aria-label="Retry">
<RotateCcw size={14} strokeWidth={1.5} />
<button onClick={() => retry(j.id)} className="flex items-center gap-1 text-[10px] uppercase tracking-[0.2em] text-[#8A8A8A] hover:text-[#D9381E]" data-testid={`retry-${j.id}`}>
<RotateCcw size={13} strokeWidth={1.5} /> Retry
</button>
)}
</div>