Skip to content

v2.7.10

Latest

Choose a tag to compare

@github-actions github-actions released this 25 Jun 20:13
· 6 commits to main since this release

[2.7.10] - 2026-06-25

Changed

  • Bumped nelux 0.12.70.12.9. 0.12.9 rebuilds the Windows wheels against FFmpeg master headers/libs and delay-loads the actual FFmpeg DLL names found at build time, so the nelux import/decode path no longer breaks when TAS downloads a newer shared FFmpeg build (e.g. avcodec-63) than the avcodec-62 ABI the 0.12.7 wheel was built against; the runtime DLL diagnostic helper mirrors the same fallback and no longer reports a missing avcodec-63.dll when the compatible avcodec-62.dll set is present.

Fixed

  • --decode_method nvdec silently hung or crashed on sources NVDEC cannot handle (e.g. After Effects prerender AVIs with codec=rawvideo, pix_fmt=bgr24). nelux's NVDEC path only decodes H.264/HEVC/VP9/AV1 with YUV pix_fmts (NV12/P010/P016/YUV444); a raw/RGB source has no cuvid decoder, so nelux.VideoReader(decode_accelerator="nvdec") deadlocked/failed opaquely at construction and the CPU fallback in BuildBuffer.__call__ never fired (constructor hang, not raise). main.py now ffprobes the input codec + pix_fmt and, when NVDEC is requested but the source is incompatible, downgrades to CPU decode with a clear logging.warning. Also normalized args.decode_method to lowercase at the source so the AE-bridge JSON's uppercase "NVDEC" matches the cache-invalidation guard in src/io/ffmpegSettings.py (decodeMethod == "nvdec".lower()); argparse choices=["cpu","nvdec"] enforced lowercase only on the CLI path, not on --json.
  • Pipeline (main.py process()) and motion-blur (src/motionBlur.py _processFrames) deadlocked the ThreadPoolExecutor when processFrame raised mid-run (CUDA OOM, TRT engine mismatch, corrupt frame, etc.). The finally only closed the write buffer, leaving the read-thread blocked on put() to a full decodeBuffer — so ThreadPoolExecutor.__exit__ waited forever and only a KeyboardInterrupt (os._exit(130)) could escape. Both loops now drain readBuffer.decodeBuffer in a finally block so the decoder's blocking put() returns and the reader thread reaches its sentinel-enqueue; motion-blur's loop body is also wrapped in try/finally (the success-only writeBuffer.close() at the end was insufficient).
  • --interpolate_method rife*-tensorrt with --half corrupted every later tensor in the process. RifeTensorRT.handleModel called torch.set_default_dtype(torch.float16) and never restored it, so any subsequent torch.zeros/torch.tensor/torch.full (dedup SSIM init, restore model load, depth normalizer, writeBuffer frame conversion, …) silently became fp16. The line was redundant — every tensor creation in the file already passes an explicit dtype= — and is now removed.
  • Removed the dead --demo code path (main.py elif self.demo: + the self.demo attribute). The branch imported src.neluxDemo, whose source was deleted (only a stale cp313 .pyc remained, un-loadable on cp314); argparse had no --demo flag either, so the branch was unreachable and would have raised ModuleNotFoundError if ever hit.
  • After a per-frame exception the success-only stats block in VideoProcessor.start() still reported a misleading Total Execution Time / FPS and Output Size: 0.0 MB because process() swallowed the exception in its own try/except and returned normally. process() now records the error on self.processingError and start() emits a single Processing FAILED after <s>: <error> line instead, so failed runs no longer look like they succeeded with a nonsense FPS.
  • The FFmpeg-subprocess writer (src/io/ffmpegSettings.py WriteBuffer.__call__) waited only 3s for ffmpeg to drain + finalize in its finally block and logged a noisy Cleanup error: Command [...] timed out after 3 seconds warning whenever the encoder was still flushing — especially common when the worker had died early and the pipe was starved. Bumped to 30s, switched the timeout branch to kill() + a DEBUG log, and kept the genuine-error branch at WARNING.
  • Concurrent TAS workers (e.g. AE bridge rendering multiple precomps) all opened the same TAS-Log.log with filemode="w" and interleaved at the line level, making each run's init block + Processed/Encoded N frames appear twice in the merged view. The log file is now per-run as TAS-Log-<pid>.log (path in the new cs.LOG_PATH), so concurrent runs no longer truncate + pollute each other.