The project was called Transcode until 2026-11-13; entries before that date use the old name. Two version lines: the controller (web app on the box) and the agent (node package). Every deploy of the controller bumps app/config.py VERSION and gets an entry here; every node package build bumps AGENT_VERSION in agent/transcode_agent.py and gets an entry. deploy/deploy.sh and agent/build_package.ps1 refuse to run without a matching entry.
Controller VM — 2026-11-13
- The controller runs on its own machine (VM
mediafarm, 10.0.0.42) instead of the shared aaPanel box, with its own database. The switch took 10 seconds while nothing was running; the nodes reconnected by themselves. The address is unchanged: the public name still arrives at the aaPanel box, which passes everything on. - Deploys can be undone. Every deploy is a folder of its own: it is checked (compiles, imports) before the switch, a backup is taken first, and a release that does not answer goes back to the previous one by itself;
deploy.sh rollbackdoes the same by hand. Python packages are installed at the exact versions production ran. - The service is started again by systemd whenever it ends, also when the database is slow at boot (Supervisor gave up after three tries). Backups: every night and before every deploy, 30 days kept, and they now include the settings file and the uploaded graphics.
Controller 0.22.5 — 2026-11-13
- The system is called MediaFarm. It records, streams, plays out and converts, so "Transcode" named only one of its jobs. The new name is on the page titles, the header, the footer and the first-run page. Nothing else changed: the address stays
transcode.waar.work, and on the nodes the folderC:\TranscodeAgent, the serviceTranscodeAgentand the firewall rule "Transcode Agent" keep their names, so no node needs an update. The node's own panel and its README take the new name with the next node package.
Controller 0.22.4 — 2026-11-11
- AV1 files can be a source. The farm's FFmpeg has no software AV1 decoder, so a job whose source was AV1 failed on every node ("Decode error rate 1 exceeds maximum"). Such a job now decodes on the graphics card (
-hwaccel cuda) and goes only to nodes whose card can (RTX 30-series or newer: ENG01, ENG07, EG08, EG10; not PCR-Ingest02's Quadro P4000). While no such node is free the job waits and says so. Jobs that go through the frame server (QTGMC, RTX upscale) and audio-only jobs are unchanged. - A source that cannot be decoded no longer pauses nodes. The owner's "social temp" task fed thirteen AV1 files to the queue; each node failed three in a row and the safety rule paused ENG01, EG10, EG08 and ENG07 for 10 minutes. A decode failure is now counted against the job, not the node.
Controller 0.22.3 — 2026-11-11
- Profiles: a fourth Loudness choice, "YouTube (−14 LUFS)" (peaks under −1 dB). The social profiles normalise to −16 LUFS ("Web"); YouTube plays at −14 and does not turn quiet uploads up, so the owner's AV1 test read "content −16.9 dB, target −14" in Stats for nerds and plays about 3 dB under other videos. No profile was changed: pick the new choice in the profiles that go to YouTube.
Controller 0.22.2 — 2026-11-10
- Streams to a far server no longer lose frames. The first YouTube stream (ENG01, 10 Mbit/s) reached YouTube at a flat 5.5 Mbit/s and lost half its frames ("YouTube is not receiving enough video"), while the uplink carried 89 Mbit/s and the encoder ran at 9× real time. Cause: FFmpeg on Windows waits for "writable" before every send, and Windows says so only while less than the socket's send buffer (64 KB by default) is unacknowledged, so one connection carries 64 KB per round trip: 5.5–7 Mbit/s to a server 75–95 ms away. RTMP / RTMPS and MPEG-TS over TCP outputs now ask for a 2 MB send buffer (measured with the farm's FFmpeg over 75 ms: 7 → 74 Mbit/s). A running always-on output takes it at its next start. RTSP and HLS push open their connection in a way that does not take the option yet.
- A live output that connects but loses frames says so on its tile, in words, with the rate that gets through; it used to show as sending, with only a growing drop count in the run list.
Controller 0.22.1 — 2026-11-10
- A live output that cannot connect says why in words on its tile ("the node cannot reach the destination: the connection timed out. Check that this node has a route to it…") instead of FFmpeg's "Error number -138". Found with the first YouTube stream from PCR-Ingest02: that node's network has no route to the internet.
- A task whose node runs a package too old for it says "update the node" on its tile and in the Tasks list; it used to wait without a word.
Controller 0.22.0 — 2026-11-10
- Device out profiles. A profile whose encoder is "Device out — no encoder" hands the picture raw to a device after the profile's whole processing chain, the same one file jobs get: crop, de-interlace, frame size and rate, denoise / sharpen, graphics, burned text, 8 or 10 bit. Four are added once: Device out: as source, 1080i50, 1080p50, 1080p25. Such a profile cannot write a file or a stream, and an encoding profile cannot feed a device; saving says so.
- Device as a target (live tasks): an SDI output of a Blackmagic card or a monitor of the task's node, picked from what the node lists. An SDI card takes its video mode from what the profile makes (1920×1080 at 25 frames interlaced = 1080i50). A monitor shows the picture full screen and plays the sound on that PC's default device; it is always fed progressive, and someone must be logged on at that PC. So a node can be a de-interlacer or a scaler between an SDI input and an SDI output, with the buffer in between.
- NDI as a target: the processed picture as an NDI source with its own name (the unprocessed feed stays the NDI switch under More). NDI as an In: any NDI source the task's node sees; Find sources lists them.
- These need node package 0.17.0; an older node says so instead of failing.
- The SDI output has not been run on a card yet: no node with a free card was at hand. Everything else was run end to end on ENG01.
- An always-on Out that ends because its task is disarmed is no longer listed as failed.
Agent 0.17.0 — 2026-11-10
- NDI In: the hub takes an NDI source through the NDI library's frame synchroniser — one picture per frame period on this node's clock, fields joined into full frames for an interlaced sender, exactly one frame of sound; the first 1.5 s after connecting are not buffered (the synchroniser's sound is uneven while it settles).
- Device outputs: a run can feed FFmpeg's DeckLink output, a player (ffplay, now in the package) started in the logged-on user's session and fed over loopback, or the NDI library (processed picture and sound handed back over loopback, sent two frames behind on the node's own clock). A live run takes the profile's graphics as inputs.
- The node reports its output devices (DeckLink outputs, the monitors of the logged-on user) with its capture devices, and answers which NDI sources it sees.
Controller 0.21.0 — 2026-11-10
- Tasks are an In and its Outs. One Tasks list and one editor for everything the farm does by itself. The In is a watched folder, a list of files, a stream address or a capture device; every Out is a profile plus a target: a folder or a saved stream destination. The task picks its engine from the In: a watched folder and files in Convert mode make jobs for any node, as before; a stream, a capture device and files in Play mode are live, run on one node, and are armed, started and watched on the Ingest page. The watch task and the ingest sources that existed are these tasks now, with the same settings; nothing was re-created, and a capture that was armed stayed armed. A task cannot move between converting and live: make a new one.
- Files as an In. A list of files in a chosen order, picked from any location. Convert: Run now makes one job per file and Out. Play once / Play in a loop: the node plays the list in real time, every file fitted into the chosen frame size and rate, a file without sound playing silent; Start plays it from its first frame; a play-once task disarms itself at the end; armed and not started, it repeats as a preview.
- Stream as an In. Any address the node's FFmpeg opens: RTMP, RTSP, HLS and other HTTP streams, MPEG-TS over UDP or RTP. The node opens it when the task is armed and again by itself when the feed drops.
- Stream destinations (Locations page): a platform preset (YouTube, Facebook, Twitch, X, Instagram, TikTok, LinkedIn, Kick, Telegram, Vimeo, Restream) with its stream key, or any RTMP / RTMPS server, MPEG-TS over UDP, RTP or TCP, an RTSP server, HLS pushed over HTTP, Icecast. Saved once, picked as the target of any Out. A key is never shown again after saving and is in no log, page or report. Saving refuses a profile the destination cannot take ("YouTube Live takes H.264 / HEVC / AV1 video; this profile encodes ProRes").
- Outs run on Start or always. An Out of a live task runs from Start to Stop like a recording, or by itself whenever the task is armed; the controller starts those again when they end. A stream that drops is reconnected by the node; the tile shows the destination's name, and why it last dropped in its tooltip.
- Remux. A profile whose video encoder is Copy sends or stores the compressed picture and sound as they are, from a stream or files (never from a capture device). For a unicast UDP / RTP address, which only one reader can open, the capture repeats the feed on a loopback port for the remux.
- New default profiles, added once: Remux, Stream 1080p and Stream 720p (constant bitrate, key frame every 2 s, AAC).
- "Ingest wins" still means recordings into files: a node that only streams keeps taking encode jobs.
- A sound-only profile may be an Out of a live task (an MP3 of the programme sound, radio to Icecast).
- Live tasks that use any of this need node package 0.16.0; an older node says so instead of failing.
Agent 0.16.0 — 2026-11-10
- The capture hub takes a play list as its input (files decoded, fitted, joined and paced to real time; one looped file repeats without a gap, a longer list starts its next pass at once) and reports "ended" after a list played once.
- A run can send to a stream instead of writing a file: started again 3 s after it ends by itself, counting the reconnects and keeping the last reason; the address with its key is replaced in everything logged or reported.
- Sound-only runs (no picture piped to the encoder) and remux runs (one FFmpeg that copies the compressed streams from the address or the files, no hub).
- Only recordings into files pause this node's encode jobs.
Controller 0.20.8 — 2026-11-09
- Node card: a FIREWALL warning when the agent could not add its own Windows Firewall rule (agent 0.15.6); the node's
firewallreport rides with its metrics like the clock report does.
Agent 0.15.6 — 2026-11-09
- The agent opens Windows Firewall for itself. It runs as a service, so Windows never shows the "allow this app" prompt for its python.exe, and without a rule the NDI library inside it can neither answer discovery queries (UDP 5353) nor accept a receiver's connection (TCP 5960 and up): PCR-Ingest02's two NDI outputs were sending to nobody, while ENG07's worked on a PC where those ports were open. At start the agent now adds the inbound rule "Transcode Agent" for its own python.exe (all profiles; re-made when it names another python.exe or is disabled) and reports the result with every sync; setup.ps1 adds the same rule on install and removes it on uninstall. Discovery still stops at the subnet: a receiver on another VLAN needs the node's address under NDI Access Manager → Remote Sources (PCR-Ingest02 is 10.100.2.102), or an NDI Discovery Server.
Controller 0.20.7 — 2026-11-08
- Levels are checked before NVENC does. A profile that names an H.264 / HEVC level, or that writes interlaced H.264 (field coding stops at level 4.1), is held to that level's limits for its profile: max rate, frame size and frame rate are checked when the profile is saved and again when a job or capability test is built, with a plain message ("level 4.2 High allows a max rate of 75 Mbit/s; this profile asks for 200 Mbit/s — lower the max rate or pick a higher level") instead of the encoder's "InitializeEncoder failed: Invalid Level". The VBV buffer the controller derives (twice the max rate) is capped at what the level allows, so an interlaced Main profile with a 40 Mbit/s max rate now gets a 75 Mbit buffer and passes (HQ Archive v8 failed on every node with 80). Saving a profile with the level on Auto warns when the max rate pushes the file past level 5.1, which many phones and TVs refuse (Social's 200 Mbit/s max rate was tagging files level 6.1). Limits measured on the RTX 5080 — NAL HRD factors Main 1.2, High 1.5, HEVC Main tier 1.1 — table and rules in
app/levels.py.
Controller 0.20.6 — 2026-11-06
- Circuit breaker counts node faults only. When a job fails again on another node with the same error, that is the job's problem; it no longer counts toward pausing the node. (The Invalid Level film paused ENG07, ENG01 and EG10 in a row, leaving nothing to run the archive profiles.)
Controller 0.20.5 — 2026-11-06
- Fix: "Invalid Level" from NVENC on interlaced outputs wider than 1920. H.264 cannot be coded interlaced above the 1080i raster (level 4.1, 1920x1088), and MPEG-2 stops at 1920x1152. A profile that keeps the source size and asks for interlaced output failed on a 1998x1080 DCI film (HQ/LQ Archive, jobs 645/646). Such an output is now fitted into 1920x1080 with bars, keeping the picture's aspect.
Controller 0.20.4 — 2026-11-05
- Queued jobs follow a corrected profile. A job waiting in the queue stays pinned to the profile version it was made with; once the profile is saved again that old version is never re-tested, so the job could wait forever with "no online node has passed the capability test". Saving a profile now moves its queued, not-yet-assigned jobs to the new version. (Eight WEB AV1 jobs sat like that for an hour today after the B-frames fix.)
Controller 0.20.3 — 2026-11-05
- B-frames held to what the encoder accepts. NVENC refuses more than 7 B-frames ("For non-Hierarchical-GOP, number of B-frames must be <= 7"); a profile saved with 25 failed its capability test on every node and eight WEB AV1 jobs sat in the queue for an hour with nowhere to run. The FFmpeg arguments now cap B-frames at 7 for NVENC and 16 for x264/x265, the profile editor saves within those limits and says so on the field.
Controller 0.20.2 — 2026-11-05
- Source dialog: the DeckLink input kind no longer says it needs an FFmpeg built with DeckLink support — the SDK engine opens the card itself. On a node whose FFmpeg has no DeckLink input (agent 0.15.5 reports that) the FFmpeg engine is greyed out and the SDK engine preselected.
Agent 0.15.5 — 2026-11-05
- Device detection reports FFmpeg's own DeckLink input separately (
decklink_ffmpeg), so the dialog can tell "the card is there" from "FFmpeg can open it". - When the on-demand tile stream encoder stops, its last queued fragments are dropped, so the next watcher starts cleanly with the new encoder's init segment instead of three stale fragments.
Controller 0.20.1 — 2026-11-05
- Source dialog on DeckLink SDK data. With a node that has the SDK helper, the Add/Edit source dialog shows each card with its live signal state, offers the input formats that card really has (Auto-detect only on cards that sense the input; a card without detection gets its detected mode preselected), its real input connections and audio channel counts, a status line (model, detection, signal and mode, busy, API version), and offers the SDK engine only where the helper exists. Nodes without a probe keep the fixed lists. Saving accepts any mode code the SDK listed; Optical SDI and S-Video inputs are new choices.
Controller 0.20.0 — 2026-11-05
- DeckLink SDK capture engine (with agent 0.15.0). A source can run on the SDK engine instead of a capture FFmpeg: the card writes every frame straight into the node's ring buffer by DMA — no capture process, no pipe, no copies — and each frame carries its hardware timestamp, arrival time and embedded timecode. Chosen per source ("capture engine" in the source settings, DeckLink only; FFmpeg stays the default). The Node page gets a DeckLink section: what the SDK sees (cards, connections, modes, signal, temperature) with Probe now and a 5-second Test capture per input.
- Ingest tile: an SDK badge with the frame's embedded timecode for sources on the SDK engine.
Agent 0.15.4 — 2026-11-05
- Fix: black tile pictures after arming (0.15.0–0.15.3). The capture FFmpeg was still encoding the old always-on tile stream next to the new on-demand encoder; both fed the same relay, the browser received two interleaved streams (25 and 12.5 fps) and showed black. The capture process no longer encodes a stream; only StreamEnc does, while someone watches.
Agent 0.15.3 — 2026-11-05
- dlcapture 0.1.3: an integrity check on the ring — every frame is hashed when it arrives and checked again when it leaves the ring;
overwrittenin the stat/done events counts frames the driver wrote into while they were still held (must stay 0). The third test on PCR-Ingest02 delivered 127 frames in 5 s at 25.000 fps with timecode and no drops, while the driver kept asking for more buffers than the ring has and recycled on its own; this check proves it recycles only released frames.
Agent 0.15.2 — 2026-11-05
- dlcapture 0.1.2: the driver asks for frame buffers of the full SDI raster (1125 lines for 1080, 5,760,000 bytes for 1080i50 v210), not the active picture, and hands back a pointer inside it — slots are now sized for the raster and each frame's metadata carries the picture's offset in its slot. The second test on PCR-Ingest02 still refused the first request and got no frames; this is the fix.
Agent 0.15.1 — 2026-11-05
- dlcapture 0.1.1, after the first run on PCR-Ingest02's DeckLink SDI 4K: a timed test no longer ends when its stdin is closed (the test runner has none), ring slots are 64 KB larger than the frame (the driver's first buffer request was refused), 16 spare slots for the driver's queue instead of 8, and the stat/done events report the largest buffer the driver asked for. The Node page test uses a 48-slot ring.
Agent 0.15.0 — 2026-11-05
- DeckLink SDK capture engine (dlcapture.exe in the package): the card DMAs into a shared-memory ring the helper owns; the hub follows its frame counter and pushes views into that memory — no copies while armed. Per-frame hardware timestamps, arrival times, timecode and no-signal flags; an input format change restarts the helper within a second. The FFmpeg capture stays for sources not switched over, for DirectShow and for the test source.
- Live tile stream on demand. The stream is encoded by its own process only while someone watches, at half the frame rate, and stops 8 s after the last watcher left — until now the capture FFmpeg encoded it all day. Saves about 4 of the 11 CPU-seconds an armed 1080i source cost per 10 s, on both engines.
- The ring may carry packed 10-bit v210 (SDK engine); recorders and previews read it through FFmpeg's v210 demuxer, the NDI output unpacks it in numpy.
- New requests decklink_probe and decklink_test for the Node page; hello reports the SDK probe under capture.sdk.
Controller 0.19.1 — 2026-11-05
- Duplicate for locations and graphics, like profiles. A location's Duplicate opens the Add form filled in from it under a free name ("X (copy)"), and saving also copies the per-node path overrides. A graphic's Duplicate makes the copy at once — same file, placement and timing, nothing uploaded again — and opens it for renaming.
Controller 0.19.0 — 2026-11-04
- New login role "ingest operator". Can arm, disarm, start and stop recordings on the Ingest page, alone or together, and see the public pages; cannot change sources, nodes, profiles, tasks or jobs, and does not see those pages in the menu. Operators and engineers keep everything they had. Set the role on the Users page.
Controller 0.18.8 — 2026-11-04
- Group stops (Stop all / Stop selected) end the files 1.5 s after the click, on one instant: a node can only cut frames it has not fed yet, and an encoder at live had already fed 200 ms past the click when the command landed (PCR-Ingest02 314 frames against ENG07's exact 309). With the lead every node receives the command before the instant and all files end on the same frame.
Controller 0.18.7 — 2026-11-04
- Synchronised stop exact to the frame: a recording's stop instant is translated with the same clock offset its start was, so the frame count is identical on every node of a group however the offset estimate moves in between (it moved 40 ms, one frame, in a test). The offset estimate itself now takes the least-delayed of the last 15 samples instead of the median, and stamps a sync on arrival before reading its body.
Controller 0.18.6 — 2026-11-04
- Synchronised stop. Stop all / Stop selected send one stop instant to every node (a single Stop sends the click), in the node's clock like the start. With agent 0.14.4 a recording started on a common instant ends after exactly the frames between the two instants, so every file of a group has the same frame count; the 12:46 run had the same first frame on all four files but two frames more on ENG07, because each node stopped when the command landed.
Agent 0.14.5 — 2026-11-04
- Synchronised stop fixed: 0.14.4 counted the frames to the stop instant but the feeding step still dropped every frame once the stop command had arrived, so files still ended where the command landed (320 and 270 frames for an expected 310). Frames up to the instant are now fed and the files of a group come out with the same count.
Agent 0.14.4 — 2026-11-04
- Synchronised stop. A stop may carry an instant: the recording feeds exactly round((stop − start) × fps) frames from its start instant (or from its first frame for a plain start) and then closes; 10 s past the instant without those frames it closes anyway.
Controller 0.18.5 — 2026-11-04
- Dashboard node card: one CLOCK line on every online node — its drift against the controller in milliseconds (positive = ahead) and the NTP server its time service follows with the node's own offset against it; orange from one second or when the time sync failed.
Controller 0.18.4 — 2026-11-04
- Node clocks follow the station's NTP server. New setting *NTP server* (Settings): every hello and sync carries it to the agents; a node whose clock the controller sees off by a second or more is told to resync at once (at most every ten minutes). The dashboard's node card shows what the node's time service follows and its measured offset (agent 0.14.3).
Agent 0.14.3 — 2026-11-04
- Keeps the node's clock on the controller's NTP server. On Windows the agent points the Windows Time service at it (NTP client mode, 15-minute polls, any offset over 1 s stepped at once instead of slewed for hours), makes sure the service runs, resyncs, and measures the offset against that server — on start, every 30 minutes, and when the controller asks. The result travels with every sync.
Controller 0.18.3 — 2026-11-04
- Node clocks measured; common starts corrected for them. Every sync from an agent 0.14.2 node carries the node's clock; the controller keeps how many seconds each node is ahead, sends a common start instant to each node in its own clock and converts the reported first-frame time back. A node that is off by a second or more is flagged on the Ingest tile ("clock +36 s") and on the dashboard's node card. Background: ENG07's clock ran 36 s ahead, so its files from a common start held 36 s more picture than PCR-Ingest02's while reporting a perfect start — the node's time sync still needs fixing, since its file names and logs are off by the same amount.
Agent 0.14.2 — 2026-11-04
- Every sync carries the node's clock, so the controller can measure and correct for a node whose time is off.
Controller 0.18.2 — 2026-11-04
- Common starts refuse a source that is not ready. Start selected / Start all check that every source's capture is armed with signal and holds at least 2 s of frames; otherwise nothing starts and the page names the source (for example "capture restarting" after its settings were saved) and asks before starting anyway. A first frame more than half a second after the common instant is marked in orange in the Recordings table with the delay, and the tooltip carries the node's own account of the start (agent 0.14.1). The source editor says that saving a changed buffer restarts the capture. Background: an ENG07 source saved ten seconds before a Start-selected began 28 s after the common instant while the two PCR-Ingest02 files were within 18 ms.
Agent 0.14.1 — 2026-11-04
- Synchronised starts hold across capture restarts. Every buffered frame now carries its own wall time (frames from before a restart keep theirs; the start instant is found by binary search), a recording reports how its start was resolved and how late its first frame was, and a hub replaced for a settings change waits until the old capture has closed before the new one opens the device, instead of both fighting for the card.
Controller 0.18.1 — 2026-11-04
- Ingest toolbar: the "all" tick box is gone; Start all / Stop all already cover it.
Controller 0.18.0 — 2026-11-04
- Start together, and Start/Stop all or selected. Every Ingest tile has a tick box; the toolbar has Start all, Stop all, Start selected and Stop selected. Sources started by one button share ONE start instant (the click minus the smallest pre-roll among them): each node begins with the frame nearest that instant in its own buffer, so the files line up frame for frame, across nodes too as far as their clocks agree (agent 0.14.0; older agents start live as before). The first-frame time of every recording is stored and shown in the Started cell's tooltip with its offset from the common instant.
Agent 0.14.0 — 2026-11-04
- Synchronised starts. The hub keeps a wall-clock estimate for every buffered frame (earliest arrival over the last 12 s, so the pipe's bursts do not shift it). A recording spec with
start_atbegins with the frame nearest that instant — from the buffer when it is in the past, waiting when it is a moment ahead — and reports the wall time of its first frame.
Controller 0.17.3 — 2026-11-04
- Profile editor: the audio Bitrate row is shown only for codecs that have one (AAC, MP3, AC-3, E-AC-3, Opus…); PCM and FLAC hide it instead of asking for a number that was ignored.
Controller 0.17.2 — 2026-11-04
- Profile editor: the de-interlacer and the QTGMC preset (and their help) are shown only when de-interlacing is on, and the preset only while QTGMC is the chosen de-interlacer. With "Never" there was nothing to choose, yet both selects stayed.
Controller 0.17.1 — 2026-11-04
- Ingest tile: while a source records, its button is a solid red stop button with a white square; the red record dot shows only when idle. The old stop icon (a square inside a circle) read as another record dot.
Controller 0.17.0 — 2026-11-04
- Ingest page shows bitrates and the node's network link. Every recording now carries a live write rate (the slope of the node's byte reports over the last ten seconds) shown in the Recordings table next to the file's average, and the source tile shows the rate of its recordings plus how much of the node's link is in use, in warning colour from 85%. Background: eight parallel ProRes recordings on ENG07 wrote 8 × 122 Mb/s, the whole 1 Gb/s link, and every one fell 15 s behind live — visible now before the drops start.
Controller 0.16.2 — 2026-11-03
- ProRes fast mode is now a quantiser list with live bitrates. 0.16.0/0.16.1 named the levels after sizes measured on a clip from an already-compressed recording; on the real camera feed every quantiser is about twice as big (camera noise costs bits): a quantiser-1 recording of WAAR PGM wrote 604 Mb/s. Re-encoding 10 s of that recording (HQ 1080i25, 8 threads): q1 584 Mb/s PSNR 65.6 dB · q2 432 / 59.8 · q3 350 / 56.4 · q4 296 / 54.0 · q5 257 / 52.3 · q6 227 / 50.9 · q8 183 / 48.8 · slow search 194 / 47.5 at 7–10× the CPU. The editor offers q1–q6, q8 and the search, with these numbers in the help; new profiles default to q4. Profiles saved with the 0.16.0/0.16.1 names keep encoding exactly as before and show as q1 / q2 / q3 in the editor.
Controller 0.16.1 — 2026-11-03
- ProRes fast mode: quality levels. "fast · best quality" (quantiser 1), "fast · finer" (one step finer than Apple's size) and "fast · Apple size" (0.16.0's fixed mode). A finer fixed quantiser costs no CPU to speak of (HQ q1 14.9 CPU-s vs q3 13.7 per 10 s of 1080i50) and only makes the file bigger: HQ q1 261 Mb/s at PSNR 68.1 dB, q2 207 Mb/s at 62.9 dB, q3 176 Mb/s at 59.6 dB. Owner's rule: quality and speed first, size last.
Controller 0.16.0 — 2026-11-03
- ProRes encoder mode (profile editor). FFmpeg's prores_ks default is a bitrate search — every slice is estimated at every quantiser before it is coded — and it cost ~9 CPU threads for ONE 1080i25 HQ stream: on PCR-Ingest02 (i7-3770, where Metus Ingest records two ProRes channels) one recording took 87 % of the CPU. The new mode "fast — one quantiser per flavour" codes each slice once (
-q:v): measured on 10 s of 1080i50 programme with 8 encoder threads, HQ went from 91 CPU-s (181 Mb/s, PSNR 54.6 dB) to 14 CPU-s at a better picture (176 Mb/s, PSNR 59.6 dB); the file size then follows the content instead of being held constant. New ProRes profiles default to the fast mode; existing profiles keep the search until they are switched in the editor (a new profile version, as any edit). Jobs and ingest recordings both follow the profile.
Controller 0.15.2 — 2026-11-02
- Ingest on a node whose card cannot open NVENC. The live preview encoder (part of the capture FFmpeg) was NVENC on any NVIDIA card; on a card whose NVENC probe opened no session the capture died with the preview and restarted in a loop (PCR-Ingest02, Quadro P4000 on driver 553.50 — this FFmpeg build needs 570 or newer: "[h264_nvenc] The minimum required Nvidia driver for nvenc is (unknown) or newer"). Such a node now gets the x264 preview; recordings there use the profile's own encoder as before.
Controller 0.15.1 — 2026-11-02
- Ingest tile: the NDI pill's tooltip shows the output's send jitter (from agent 0.13.1).
Agent 0.13.2 — 2026-11-02
- NDI audio clicks fixed. The NDI library sizes its audio channel stride from the frame maximum; 0.13.x set that two samples above what was sent, so channel 2 was shifted by two samples and ended every frame with two uninitialised values — audible as clicks. Every audio write is now exactly one video frame of samples (1920 at 25 fps), kept exact by a small FIFO for fractional frame rates.
Agent 0.13.1 — 2026-11-02
- NDI output paced. 0.13.0 handed each frame to the NDI library the moment the capture delivered it; the capture pipe delivers in small bursts, and receivers showed the bursts as a stutter in picture and sound. The output now stays two frames behind live and sends one frame per frame period on its own clock (the capture still sets the long-term rate); it reports the send jitter and how often it had to rebuild its cushion.
Controller 0.15.0 — 2026-11-02
- NDI output for ingest sources. A source can be sent as NDI while it is armed (source dialog: NDI output on/off, name, 8-bit UYVY or 10-bit P216); receivers see
NODE (name). The Ingest tile shows the NDI state and the connections it serves. It is one more consumer of the node's capture buffer, carried in the hub spec outside its key: switching it on, off or renaming it never reopens the card or touches a running recording, and it is the one setting that may change while the source records. Needs agent 0.13.0 on the node; the dialog says when a node cannot send NDI yet.
Agent 0.13.0 — 2026-11-02
- NDI output (
NdiOut): the newest buffer unit goes to the NDI 6 library (cyndilib, bundled in the package with its runtime DLL and numpy) as UYVY straight from an 8-bit buffer, or P216 / UYVY converted from a 10-bit buffer, with float audio; interlaced sources go out as full frames. It starts when the source is armed, follows the live edge (skips rather than lags), reports its receivers every second, keeps running through a capture restart (black + silence, like a recording) and never pauses transcode jobs.capture.ndiin hello says whether the node has the library.
Controller 0.14.0 — 2026-11-02
- Cloud page: what the NAS uploads to Google Drive. TrueNAS runs the cloud-sync task (SOCIAL → Google Drive /Share/Social, every hour); the controller now reads it over the TrueNAS API and shows it: the run in progress with percent, speed, time left and every file in flight, the last result, the next run, an upload log of every file sent (searchable, with the Transcode job that made it), the run history with each run's full rclone log, and on a job's page a "Cloud" line — uploaded at …, uploading now, or waiting for the next sync. Operators get the NAS's own Sync now / Stop buttons. Runs and files are kept in the controller's database (the NAS forgets its jobs at a restart). Settings (engineer): TrueNAS address, API key and the NAS's name in location paths.
Controller 0.13.0 — 2026-10-26
- RTX AI upscaling (frame server). Profiles → Processing → Upscaling: Standard (lanczos, as before) or NVIDIA RTX Video Super Resolution on the node's RTX GPU — "detail" (NVIDIA level 19: sharper edges, hair and lettering, grain and texture kept; the choice for 1080i programmes to 2160p masters), "clean-up" (level 4: also removes blockiness and noise; web, phone and old SD material) or a custom level with a strength 0.5–1.0. It applies only when the output is larger than the source and the frames are progressive; then the frame server crops, de-interlaces (QTGMC when chosen, otherwise nnedi3) and upscales, and FFmpeg encodes finished frames (10-bit when either side is 10-bit). Measured on ENG01 (benchmarks/ENG01_rtx_vsr_2026-10-25.md): every RTX mode beats lanczos at 1080 → 2160p; the GPU step costs 5 ms per 4K frame on an RTX 5080, 17 ms on a 3080 Ti, so a de-interlaced job stays QTGMC-bound. The capability test for such profiles de-interlaces and upscales a 720×576i test clip through the GPU; nodes without an RTX 20-series-or-newer card, driver 550.58+ or the rtx folder (agent 0.12) fail it and never get the jobs. The node page shows "RTX Video SR" with the feature DLL version and each GPU's readiness. Live ingest never upscales.
Agent 0.12.0 — 2026-10-26
- RTX Video Super Resolution in the package (
ffmpeg\vapoursynth\rtx\): the WAAR VapourSynth filterrtxvsr.dll(plain C, agent\rtxvsr\, built with the MSYS2 gcc — no CUDA Toolkit, no Visual Studio) and NVIDIA's feature DLLnvngx_vsr.dll1.8.3 (NVIDIA-signed; distributable inside an application under the NVIDIA RTX SDKs licence — see the README there for the notification and attribution clauses). The NGX core and CUDA come with the display driver. At start the agent asks the plugin per GPU whether the feature runs (rtx.Info) and reportsrtx_vsrin hello (fingerprint, TEST_VERSION 4: every node re-tests). The job's.vpynow does crop → de-interlace (QTGMC / nnedi3 / none) → RTX upscale; a CPU-encoded job uses the node's first RTX-capable card. agent.toml:rtx_vsr(folder; default<vapoursynth>\rtx).
Controller 0.12.0 — 2026-10-25
- QTGMC de-interlacer (frame server). A fifth de-interlacer per profile: QTGMC, the motion-compensated de-interlacer broadcasters use for archive work, run by a VapourSynth frame server that ships inside the node package (agent 0.11.0 — nothing is installed on the node). The agent writes a small script per job; FFmpeg reads it as its video input and the original file for the audio, so progress, previews and the output check work as before. "Automatic" keeps the per-frame decision (a luma port of FFmpeg's idet logic inside the script), so the progressive 25p pictures in a 1080i signal pass through untouched. Preset per profile: Faster / Medium / Slower — on ENG01 (2 × Xeon Gold 5118, whole CPU) 1080i50 → 25p runs at about 15 / 12 / 8 fps through FFmpeg, and Automatic on mixed programme material about twice that. A node whose package has no frame server fails the capability test for such profiles and never gets the jobs; the test clip for them is a real 1080i25 TFF weave, so VapourSynth itself is exercised. A live ingest recording cannot run a frame server: a QTGMC profile falls back to bwdif there. The node page shows the frame server (VapourSynth / QTGMC versions) under FFmpeg.
Agent 0.11.0 — 2026-10-25
- VapourSynth frame server in the package (
ffmpeg\vapoursynth\: embedded Python 3.12, VapourSynth R81, the vsjetpack QTGMC with mvutensils, znedi3, akarin, vszip, zsmooth, resize2 and BestSource — about 120 MB in the zip). The agent reports it in hello, points FFmpeg's vapoursynth demuxer at it through the environment (FFMPEG_VSSCRIPT_DLL, PATH) and writeswork\frameserver\<job>.vpyfor QTGMC jobs; the script is removed when the job ends. agent.toml:vapoursynth(folder; defaultffmpeg\vapoursynth),vapoursynth_threads(0 = all),vapoursynth_cache_mb(8192). Capability tests run again on every node (TEST_VERSION 3). - FFmpeg build revision 3 (the same static n7.1.1 + DeckLink build):
--enable-vapoursynthplus two WAAR patches of the demuxer — the DLL path from FFMPEG_VSSCRIPT_DLL (portable VapourSynth, no registry entry) and frame prefetching (-prefetch, default = VapourSynth's thread count), without which the demuxer asked for one frame at a time and QTGMC ran at a quarter of its speed (2.9 → 12 fps on ENG01).
Controller 0.11.0 — 2026-10-25
- Adaptive de-interlacing. The programme feed carries progressive 25p pictures inside the 1080i50 signal between real interlaced camera shots (measured on PCR1 recordings: three of five excerpts fully progressive, one fully interlaced, one mixed). De-interlacing every frame softened the progressive ones. With "Automatic" each frame is now detected on its own (idet) and only frames that really hold two fields are de-interlaced; "Always" keeps the old behaviour. The de-interlacer is a profile choice: bwdif (default), estdif, nnedi fast, nnedi best; nnedi needs agent 0.10.8 (its weights ship in the node package). Ingest recordings use the same chain when a profile asks for progressive output.
Controller 0.10.3 — 2026-10-25
- Profiles, Scan: a new choice "Keep fields, flag progressive (cheaper)". The fields stay as they come, nothing is de-interlaced, the file is flagged progressive and the encoder runs in progressive mode — about 25 % less CPU for ProRes than proper interlaced coding, which is what the native DeckLink recording does with "Keep source". It is what the DirectShow recordings did before, so it lets a node record the same number of ProRes streams as then.
Controller 0.10.2 — 2026-10-25
- Source editor: the DeckLink input-format help says that Auto-detect needs a card that senses the input format and that older cards (DeckLink Studio 2) need a fixed format, which is why ENG07's native source did not open.
Controller 0.10.1 — 2026-10-25
- Node page: under the FFmpeg version, the path and size of the FFmpeg file the node actually runs (agent 0.10.3).
Controller 0.10.0 — 2026-10-25
- Ingest wins on a node. While a source records, the scheduler places no new transcode jobs on that node, and the node suspends the encodes already running there; they resume when the recording ends. An encode suspended for more than 10 minutes is given up and queued again without counting an attempt, so it runs on another node, or on the same one once the recording is over. Paused jobs show "paused for ingest" on the dashboard. Needs agent 0.10.0 for the pause.
Controller 0.9.2 — 2026-10-25
- Ingest tiles: the buffer / lag text beside the buttons no longer picks up the dashboard's stat-card box style.
Controller 0.9.1 — 2026-10-25
- Ingest tiles: buffer, lag and drops sit beside the buttons, so they stay visible when a source has several outputs (the outputs line is the one that gets cut off).
Controller 0.9.0 — 2026-10-25
- Several outputs per ingest source, like the encoders of a watch-folder task: each output is a profile with its own folder, sub-folder and file name, with an on/off switch. Start records every enabled output at once from the same buffer (a ProRes master and an H.264 proxy side by side), Stop ends them all; the tile shows "REC ×2", one lag number per output, and the recordings list names the profile of every file. The buffer is kept in 10-bit as soon as one output needs it. Existing sources keep their single output.
- The Ingest page is visible without a login, like the dashboard: pictures, meters and state; arming, recording and settings still need an operator or engineer login.
- Recordings follow the profile's picture size, fit and scan: a 540p proxy profile records 960x540 progressive (deinterlaced when the signal is interlaced); a master profile with size 0 keeps the input as it is.
Controller 0.8.4 — 2026-10-25
- Ingest tiles: the consumer chips are gone; after the buffer the line shows "lag 0-0" — the previewer's backlog first, then one number per attached encoder (frames behind live), more numbers as encoders are added. The tooltip names each number; the large view shows the same.
Controller 0.8.3 — 2026-10-25
- Ingest tiles: a chip for every consumer of the buffer — the previewer (streaming / ready / starting) and each attached encoder with its profile and whether it keeps up — so a source with several encoders shows each one.
Controller 0.8.2 — 2026-10-25
- Encoder lag as a performance indicator: while a source records, its tile and the large view say how many frames the encoder is behind the live picture ("keeping up" when zero); the recordings list keeps the peak lag of every recording, orange above one second. Needs agent 0.9.1 for the numbers.
Controller 0.8.1 — 2026-10-25
- Ingest tiles and the large view: the audio meters are vertical bars beside the picture (one per channel, filled from the bottom, a line at -18 dBFS), like a multiviewer, instead of a row under the text.
Controller 0.8.0 — 2026-10-25
- Ingest as a monitor wall. The sources are tiles, four per row on a wide screen, each with a live H.264 stream of the signal (quarter size, 1 Mbit/s, a few frames behind live, encoded on the node's GPU where it has one), the state and format over the picture, audio peak meters per channel underneath, and arm / record / settings buttons. Click the picture for the large view with the same stream and meters. The stream only flows while someone has the page open; the 1-picture-a-second thumbnails stay as the fallback. Needs agent 0.9.0.
Controller 0.7.0 — 2026-10-25
- Ingest with a capture hub. A source can be armed: its node holds the card open the whole time and keeps the last N seconds of picture and sound in memory (*Buffer* on the source: 1–60 s, default 5). You see the live picture before recording, Start attaches the encoder to that buffer with no gap and, with *pre-roll*, begins that many seconds in the past; the encoder never touches the card, so it can be restarted without losing the signal. Signal loss, the detected format, buffer fill, driver drops and encoder drops are shown live in the row and in the preview window; while the capture process restarts, a running recording gets black frames and silence so the file stays continuous, and the gap is counted. *Keep armed whenever the node is online* arms a source by itself; Arm / Disarm buttons otherwise, and Start arms if needed. Needs agent 0.8.0.
Controller 0.6.5 — 2026-10-24
- Live preview window: the status line under the picture (progress, node, speed; for a recording length and size) was squeezed into a 16-pixel column since 0.5.14 — the help-icon style had the same class name.
Controller 0.6.4 — 2026-10-24
- Ingest: a live picture per running recording (one frame a second, deinterlaced for interlaced signals) in the source row and the recordings list; click it for the large view with length, size and dropped frames, like a job's preview. Needs agent 0.7.3.
Controller 0.6.3 — 2026-10-24
- Ingest source editor: the DirectShow kind (the card through Blackmagic's Windows driver) is first and the default; a new source on a node whose FFmpeg has no native DeckLink but sees a Blackmagic device switches to DirectShow by itself, preselects the card for video and audio and its 1080 at 25 fps 10-bit (v210) format; the native DeckLink hint has a one-click switch to the driver route.
Controller 0.6.2 — 2026-10-24
- Ingest, DirectShow sources: a Capture format dropdown (size, frame rate, pixel format) read from the chosen device on the node, plus a signal setting (progressive / interlaced top or bottom field first, guessed from the format) so a Blackmagic card through the WDM driver records 1080i50 as 1080i50 instead of the device's default format. "What FFmpeg listed on the node" shows the raw device list for checking. Needs agent 0.7.2.
- A DirectShow device with both video and audio pins (Blackmagic WDM Capture) was only shown as an audio device.
Controller 0.6.1 — 2026-10-24
- Ingest source editor: Device and Audio device are dropdowns of what the node's FFmpeg sees, detected live on the node when the dialog opens, when another node is picked, or with the "Detect devices" button (agent 0.7.1; older agents show what they reported at start). A saved device that is not detected right now stays selectable and is marked.
Controller 0.6.0 — 2026-10-24
- Ingest (live capture), first version: a new page where a *source* is a live input on one node — a Blackmagic DeckLink card (needs an FFmpeg built with DeckLink support on that node), any DirectShow capture device (the Blackmagic WDM driver works with the standard FFmpeg), or a test pattern — with the profile that encodes the recording live and the folder it goes to. Start / Stop buttons; the node writes
.partand finalises the file on Stop; length, size and dropped frames are shown live; a safety limit stops a recording by itself after N hours. Needs agent 0.7.0 on the capture node. Schedules and more sources come later.
Controller 0.5.14 — 2026-10-23
- Explanations no longer sit on the pages: every intro text and field help is a small "i" icon next to the heading or the field label, and the text opens in a balloon on hover or click.
Controller 0.5.13 — 2026-10-23
- Profiles list: the Version and Updated columns are gone (the profile page still shows its versions).
Controller 0.5.12 — 2026-10-23
- Node setting "Jobs at once": a limit for the whole node on top of the per-resource slots (1 = one encode at a time whatever the GPUs and CPU could take). Relay hand-offs do not count. The dashboard shows "1 of 2 jobs running" on a limited node.
Controller 0.5.11 — 2026-10-22
- Jobs list: the Speed column shows the whole encode's speed for finished jobs (source duration ÷ encode time) and the live speed only while a job runs. Before, a finished job kept whatever its last live report held, so jobs whose last report came during the copy to the NAS showed nothing.
Controller 0.5.10 — 2026-10-22
- Moving graphics (image sequences, animated files) are pre-rendered once by the node into the overlay's own pixel format with size and opacity baked in (agent 0.6.3), so nothing is converted per frame during the encode. Measured on ENG01: a full-frame PNG sequence cost 45% of the job's speed, now 22%; a small logo sequence 36%, now 15% — about what a still costs. The first job with a new graphic pays the render once.
Controller 0.5.9 — 2026-10-22
- Without a login only the Dashboard and Jobs are shown; Tasks, Profiles and Nodes (lists and pages) need a login like the other pages.
Controller 0.5.8 — 2026-10-22
- Locations: a "Used by" column (and section on the location page) shows every task that watches the location, writes its outputs there or moves files into it, as links to the tasks; unused locations say so.
- Fix: the Locations page failed to render while a node had not yet reported free space (0.5.7).
Controller 0.5.7 — 2026-10-22
- When things go wrong (owner request): - Stall watchdog: a job whose progress does not move for 4 minutes (setting) — frozen FFmpeg, hung share — is killed and retried elsewhere; a hand-off that stops moving is given to another courier. - Storage outages: an I/O failure (share gone, I/O error, disk full) no longer burns an attempt. The job waits 90 s, the node re-checks its locations at once, and while no node reaches the location the job simply waits and resumes by itself. - Leftovers: half-written .part files of jobs and hand-offs that were cut short (crash, power off, node away) are deleted on the target and the relay by the first node that reaches them; nodes clear their cache on start. - Free-space gate: a job is held with a clear reason when its target (or the relay) has not got room for its output, instead of failing near the end. - A relay copy someone deleted is fetched again; a source that is itself unreadable fails for good instead of being retried on every node; a node that lost contact and finished its job late keeps its file and the duplicate is stopped. - Circuit breaker: a node that fails 3 jobs within 15 minutes takes no new jobs for 10 minutes (shown as "paused"). - Saving a task that watches the same folder as another task warns about the double encode. - Locations page shows the free space of every location as the nodes see it (agent 0.6.2).
Controller 0.5.6 — 2026-10-22
- Profiles: Entropy coding is two choices, CABAC (default) and CAVLC — the third "encoder default" entry was the same thing as CABAC.
Controller 0.5.5 — 2026-10-22
- Profiles: a Quality tuning row for H.264 / HEVC / AV1 — tune (film, animation, grain…), adaptive quantisation with strength, psy-rd, lookahead, reference frames, NVENC multipass and B-frames as references, and key frames at scene cuts — each offered and applied only where the encoder has it; empty = the encoder's default, so existing profiles do not change. A button fills in the recommended quality settings for the chosen encoder.
Controller 0.5.4 — 2026-10-22
- Profile editor exact to the encoder: profile and level (new), pixel format, rate control, DNx profile, the container and the audio codec are choice lists that offer only what the chosen encoder or container accepts (H.264 High 4:2:2 / level 4.1, HEVC Main 10, ProRes 4444 → 4:4:4 formats, MXF → PCM, …). Nothing is typed any more, and the server keeps only valid values, so a profile can never carry a setting its encoder does not understand.
Controller 0.5.3 — 2026-10-22
- Profiles: H.264/HEVC details as in editing software — entropy coding (CABAC / CAVLC), deblocking filter, open / closed GOP (closed = every key frame is an IDR frame) — and colour signalling (primaries, transfer, matrix) written into the stream for every encoder. Existing profiles keep their behaviour (CABAC, deblocking on, closed GOP, colour unspecified).
- Profiles: the output aspect is always explicit — 16:9, 4:3, 1:1 or 9:16 (default 16:9); "square pixels / keep" is gone, so the aspect handling (bars / crop / stretch) always applies to a source of another shape. A profile saved before this keeps "as source" until it is saved again (the editor then shows 16:9).
Controller 0.5.2 — 2026-10-22
- Profiles with job history can be deleted: finished jobs keep the profile's name in their history and show "profile deleted" instead of a link, and cannot be retried. Only a task that still uses the profile, or jobs still waiting or running with it, block the deletion.
Controller 0.5.1 — 2026-10-22
- Locations: the pages show when a node created a location folder that was missing (agent 0.6.1).
Controller 0.5.0 — 2026-10-21
- Relay locations and couriers (needs agent 0.6.0 on the nodes that courier). A location can be marked relay: a hand-off share every node may reach while the real locations stay restricted. When the best free encoder cannot reach a job's source or target, a courier (any node that reaches both the relay and the real location) copies the source into the relay first, the encoder reads and writes there, and a courier moves the output to the real target afterwards. The scheduler counts the hand-off time, so a relayed node only wins when it is still faster. Fetched sources are shared by all encoders of a file and cleaned up when nobody needs them; an undelivered output waits a day in the relay and Retry delivers it without re-encoding. New job states
fetching/delivering(shown in Encoding now with the courier and the copy rate); the node page shows each node's role (encoder only / courier / both / direct). - Profile editor: bitrate, max bitrate and GOP / B-frames hide for ProRes and DNxHR (their quality comes from the flavour / profile), and the H.264/HEVC profile field shows only for H.264 and HEVC encoders.
Controller 0.4.12 — 2026-10-21
- The public read-only pages (dashboard, jobs, node status) are public from the internet too, as the owner decided; HTTPS stays enforced there and the agent API stays LAN-only. Engineer/operator pages need a login as before.
Controller 0.4.11 — 2026-10-21
- Reachable from outside the LAN (owner request): from a non-LAN address every page, the dashboard included, needs a login and HTTPS; the agent API answers LAN addresses only (in the app and in nginx). Inside the LAN nothing changes. nginx rule for the site: deploy/transcode_rewrite.conf.
Controller 0.4.10 — 2026-10-21
- Fix: a job that failed the instant it started (for example its source file was gone) could get stuck as "running" forever — the node's sync report about the failed attempt arrived after the job had already been re-assigned to the same node, so the controller marked the new attempt running although the node never received it. Such late reports are now ignored, and a running job its node has not reported for 30 s is recovered: cancelled if a cancel was pending, otherwise retried like any failed attempt.
Controller 0.4.9 — 2026-10-21
- Live previews no longer slow the encode: they come from a second, separate 1 fps filter graph fed by the decoder instead of a split of the finished picture (measured on ENG01: about 20% of the job's speed before, about 5% now). The preview still shows crop, de-interlace, geometry, sharpen, graphics, text and fades; the temporal denoise and the timecode burn-in are not in it. Jobs started before the deploy keep their old command. No node update needed.
Controller 0.4.8 — 2026-10-21
- Profiles: Denoise and Sharpen are each a method plus an amount (two selects). Sharpen gained CAS (contrast-adaptive, no halos) next to the unsharp mask. Older profiles keep their meaning.
Controller 0.4.7 — 2026-10-21
- Profiles: the Denoise setting offers two methods — temporal (atadenoise: fast, keeps detail) and spatial + temporal (hqdn3d: slow, smooths), each in light / medium / strong. Existing profiles keep hqdn3d.
Controller 0.4.6 — 2026-10-21
- Node page: "May run on" chips show the test result too — a resource that failed the profile's test is crossed out in red and cannot be switched on; a resource not tested yet is dashed.
Controller 0.4.5 — 2026-10-21
- Node page: a profile can be forbidden per resource ("May run on" chips: gpu0, gpu1, cpu …); the scheduler and the speed matrix respect it. Default: every resource may run every profile.
Controller 0.4.4 — 2026-10-21
- Tasks: "Watch folders" became Tasks with a kind per task (watch folder now; copy and upload placeholders). Old
/watchlinks redirect to/tasks. - Tasks: "Encode again" per seen file and "Forget all files" per task, so files are re-encoded on the next scan.
- Profiles: one encoder per profile (select); quality/speed preset as a dropdown per encoder; Scan locked to progressive for AV1 / HEVC; the output file-name pattern moved to the task's encoder rows only.
- Scheduler: per-node network limit (default on, 80% of the busiest link), reactive (20 s average) and predictive (source bitrate × speed in, estimated output bitrate × speed out); wait reasons explain it.
- Dashboard: node cards show agent version, update available / waiting / updating / failed, and a NET row with in/out rates, link speed and a "holding jobs" marker.
- Nodes: FFmpeg process priority per node (idle … realtime); slot maximums from cores / threads / measured NVENC session limit (shared pool check); remote agent update from the node page; node package download; local panel link.
- Changelog page at
/changelog, linked from the version in the footer. - Scheduler: a second job on an already busy GPU or CPU is estimated at a share of its speed, so files spread over nodes instead of piling onto the fastest one.
Controller 0.4.3 — 2026-10-21
- Node page: capability results refresh live (queued → testing now → result) without reloading; per-profile buttons post in the background.
- Graphics: no frame-rate field (an image sequence is one image per output frame); offset and width in percent or pixels (independent radio pairs); width in percent is % of the graphic's own size; reference picture under the preview; preview output size 2160p / 1080p / 720p / 540p with a readout.
- Dashboard: a file's encoders stay together in "Encoding now" (finished and queued siblings shown muted); queue only lists files with nothing running yet.
Controller 0.4.2 — 2026-10-21
- Frames: no add/edit form inline on any list; Add buttons and row clicks open the item page in a dialog (
Sec-Fetch-Dest: iframe); saves close the dialog and refresh the list. - "New job" hidden (route kept, nothing links to it). Queue and Encoding now group jobs by source file.
Controller 0.4.1 — 2026-10-20
- Watch task editor: Watch settings on top, then an Encoders list; each encoder has its own location, sub-folder, keep-structure, if-exists rule and file-name pattern with variables.
Controller 0.4.0 — 2026-10-20
- Graphics library (stills, animated, image sequences; placement relative to the frame; node-side cache).
- Processing per video profile: de-interlace, aspect fit, crop, denoise, sharpen, fades, timecode burn-in, text overlay. Whole video chain as one filter_complex; previews branch after overlays.
Controller 0.3.0 — 2026-10-20
- Redesign: Fira Sans / Fira Code, green accent, SVG icons, stat cards; dashboard order cards → Encoding now → Queue → Nodes → Recent; job names on node cards.
Controller 0.2.0 — 2026-10-20
- Live previews: one small picture per second per running job, click for a larger view. Interlacing without the lowpass filter.
Controller 0.1.0 — 2026-10-20
- First release: profiles, locations, watch folders, jobs, nodes with per-GPU capability tests and learned speeds, scheduler, public dashboard, roles.
Agent 0.10.8 — 2026-10-25
- The package ships the nnedi neural de-interlacer weights next to FFmpeg and the agent fills the
{nnedi}placeholder in job and recording commands with their path.
Agent 0.10.7 — 2026-10-25
- When a capture does not start, the source shows FFmpeg's own last lines (why the card did not open, no signal, unsupported format) instead of a generic message.
Agent 0.10.6 — 2026-10-25
- DeckLink cards are listed again: FFmpeg prints each card as "id [name] (types)" and the trailing part made the parser skip the line, so ENG07's DeckLink Studio 2 was not offered in the editor.
Agent 0.10.5 — 2026-10-25
- The capture detection keeps FFmpeg's own lines from the DeckLink listing (the card names, or why the DeckLink driver could not be reached), shown under "What FFmpeg listed on the node" in the source editor.
Agent 0.10.4 — 2026-10-25
- Same package re-issued so that a node which kept the old FFmpeg through the last updates (ENG07: a leftover capture process held the file) replaces it now that 0.10.3 has ended the leftover.
Agent 0.10.3 — 2026-10-25
- An FFmpeg process left behind by a previous agent instance (a capture it could not stop when it restarted for an update) kept
ffmpeg.exeopen, so the update could not replace it (ENG07 stayed on the old build twice). The agent now ends such leftovers at start-up and before it restarts for an update, and the launcher does the same before copying. The node also reports the path, size and time of the FFmpeg file it runs.
Agent 0.10.2 — 2026-10-25
- A self-update first stops the capture hubs of armed sources: their FFmpeg process kept
ffmpeg.exeopen on the node, so the launcher could not replace it and the node kept the old FFmpeg (seen on ENG07). The controller arms the sources again as soon as the new agent is up.
Agent 0.10.1 — 2026-10-25
- The node package ships the farm's own FFmpeg 7.1.1 build with native Blackmagic DeckLink input (plus x264, x265, NVENC, MP3, Opus, VP8/9, freetype text) instead of gyan.dev's essentials build. A node with a DeckLink card and Blackmagic Desktop Video installed can be used through the native DeckLink kind on the Ingest page; the FFmpeg version string changes, so every node re-runs its capability tests once.
Agent 0.10.0 — 2026-10-25
- Ingest first: the capture process runs at high priority and recording encoders above normal, so transcode jobs on the same node give way; running encodes are suspended while a recording runs and resumed afterwards, and one suspended longer than
ingest_pause_max(600 s) is given up for the controller to place elsewhere. The drop and fill counters of a source start from zero at every recording start.
Agent 0.9.2 — 2026-10-25
- The hub reports the previewer's backlog (fragments waiting to be sent to the controller) as
stream_lag, 0 when nobody watches.
Agent 0.9.1 — 2026-10-25
- Recordings report the encoder's backlog (frames behind the newest frame in the buffer) and its peak; the pre-roll catch-up at the start is not counted.
Agent 0.9.0 — 2026-10-25
- Armed sources make a live preview stream: a third output of the capture FFmpeg (H.264 480 px wide, 1 Mbit/s, key frame every second, no B-frames; NVENC when the node has an NVIDIA card, x264 ultrafast otherwise) as fragmented MP4, relayed to the controller in one upload connection while someone watches. Audio peak meters per channel are computed from the buffer and sent with the stream ten times a second.
Agent 0.8.0 — 2026-10-25
- Capture hub per armed source: one FFmpeg holds the device open and streams raw video and audio into a ring buffer in memory; recordings are encoders attached to the ring (raw video on a pipe, audio on a loopback socket), with pre-roll from the buffer; previews come from the hub; audio stays locked to the picture by stream position; black and silence fill a capture restart; the capture process is restarted by itself when it dies. A buffer that would not fit in RAM refuses to arm with a clear message.
Agent 0.7.3 — 2026-10-24
- Recordings write the same 1 fps preview JPEGs as jobs (small always, large while someone watches) and the agent sends them to the controller's Ingest page.
Agent 0.7.2 — 2026-10-24
- Capture detection lists a DirectShow device under video *and* audio when it has both kinds of pins (the Blackmagic WDM Capture device was sorted as audio only), keeps FFmpeg's raw device list for the editor, and answers "list this device's formats" (size / frame rate / pixel format) for the capture format dropdown.
Agent 0.7.1 — 2026-10-24
- Answers the controller's "detect capture devices" request (DeckLink cards, DirectShow video and audio devices) so a card or driver installed after the agent started shows up in the Ingest editor without a restart.
Agent 0.7.0 — 2026-10-24
- Live capture: the node runs recordings for the controller's Ingest page (DeckLink native, DirectShow or a test pattern), reports length / size / dropped frames every sync, stops gracefully (FFmpeg writes the file's index) when told to, and finalises
.partinto the target file. At start-up the agent reports which capture inputs its FFmpeg supports and the devices it sees.
Agent 0.6.3 — 2026-10-22
- Pre-render cache for moving graphics: a sequence or animated graphic is rendered once into a lossless FFV1 file in the overlay's pixel format (scale and opacity included) and reused by every later job with the same graphic, format and size.
Agent 0.6.2 — 2026-10-22
- A finished file whose copy to the target fails is kept in the cache and the copy is retried every 30 s for up to 30 minutes (phase "waiting for target") — a short NAS outage no longer costs the encode.
- The location check reports free space; a failed job triggers the check at once.
- Leftover .part files in the cache are removed at start; the result of a job names the location it wrote to.
Agent 0.6.1 — 2026-10-22
- A location folder that is missing is created by the node (and created again within a minute if someone deletes it), as long as its parent folder exists. A path whose parent is missing too is reported as no access and never built, so a wrong path on the wrong machine does not turn into an empty folder.
Agent 0.6.0 — 2026-10-21
- Courier work: the node runs relay hand-offs the controller gives it (copy a source into the relay share, move a finished output from the relay to its target) with progress, rate and cancel, reported like jobs. Transfers write
.partfiles and rename at the end; the local panel lists them.
Agent 0.5.1 — 2026-10-21
- Staging keeps reading the source from its location (owner decision): only the output goes through the local cache and is then copied to the target. The space check is output estimate × 1.2 + 1 GB.
Agent 0.5.0 — 2026-10-21
- Local staging (default on, per node): the source is copied into the node's cache (
<agent folder>\cacheor the folder set on the node page), encoded there, verified, and the finished file is copied to the target and renamed — the NAS only ever sees complete files. Before each job the free space is checked against the source size plus 1.2 × the estimated output plus 1 GB; without room the job writes directly to the target and says so in its timeline. - New phases "copying in" / "copying out" on the dashboard and the node panel; the job's timeline gets a note with the cache used or the reason for writing directly.
Agent 0.4.3 — 2026-10-21
- Real link speed on Windows from the 64-bit adapter table (10 GbE showed as unknown before).
Agent 0.4.2 — 2026-10-21
- Network throughput in the metrics: in/out per interface with link speed.
Agent 0.4.1 — 2026-10-21
- Remote update: downloads the controller's package when idle, stages it, exits; the launcher applies it. The service runs
launcher.ps1, which restarts the agent itself (nssm does not restart reliably here).
Agent 0.4.0 — 2026-10-21
- Node package: one folder with bundled Python, FFmpeg, nssm and the agent;
setup.cmdinstalls the service. - Local panel at http://localhost:8781: running jobs with pictures, hardware, locations, log, restart, re-measure.
- Final rename retried (Windows file locks); profile name in job payloads.
Agent 0.3.2 — 2026-10-21
- Measures the NVENC session limit at start (and whether the GPUs share one pool).
Agent 0.3.1 — 2026-10-21
- FFmpeg process priority from the controller, applied to running encodes too.
Agent 0.3.0 — 2026-10-20
- Graphics cache by content hash,
{font}placeholder, processing filters, previews of the composed picture.
Agent 0.2.0 — 2026-10-20
- Live preview pictures sent every second (large one only while watched).
Agent 0.1.0 — 2026-10-20
- First release: hello/sync loop, capability tests, jobs with progress, locations access check, Windows service.
MediaFarm 0.22.5