Survive a ComfyUI crash, retry clips the model cuts short

Crash recovery
  ComfyUI's queue and history do not persist across a restart, so a prompt
  submitted before a crash exists nowhere afterwards. The old poll loop waited
  on that dead prompt for ever, and its error branch skipped the backoff, so it
  hammered the closed port four times a second printing "Poll error" on every
  attempt.

  run_workflow() replaces wait_for_completion(). It reports once when the
  backend goes away and once when it returns, polls every 3s in between, and on
  reconnect checks both /history and /queue: if the prompt is in neither, the
  queue did not survive and the clip is submitted again. When it cannot tell, it
  assumes the job is still alive — resubmitting a running job would waste a
  generation.

  It also starts ComfyUI itself, via the script named by [comfy] start_command,
  in a new terminal window. Guarded by a 90s cooldown and 3 attempts per run so
  a backend that dies during startup cannot spawn an endless stream of windows;
  the window pauses on exit so a failed start leaves its error on screen. Falls
  back to a background launch with a log file when there is no display. Set
  [comfy] autostart = no, or pass --no-comfy-autostart, to turn it off.

Clips cut short mid-word
  About one clip in twelve comes back truncated: the model stops before the line
  is finished. Measured on raw ComfyUI output, 6 of 80 recent clips, and 15 of
  472 in one episode. It is invisible in the text but obvious in the audio — a
  finished clip decays to about -65 dB, a cut one stops at about -16 dB.

  Truncated clips are now regenerated with a distant seed, up to
  [tts] truncation_retries extra attempts, and a run that still has bad clips
  ends by printing them as a ready-made --regen list. --check-clips reports the
  same for a job already on disk.

  Worth recording what this is NOT: the trailing-silence trimming added earlier
  was suspected, and cleared. It only cuts silence that runs to end of file, so
  a pause between words never triggers it — verified against six synthetic cases
  including a 1.2s mid-clip pause, and against real clips containing pauses. The
  truncation is present in ComfyUI's own output before this script touches it.

settings.ini
  New: [tts] truncation_retries, [comfy] autostart and start_command, all
  documented in place. The editor renders yes/no keys as a dropdown.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 14:12:33 +02:00
co-authored by Claude Opus 5
parent 200d221816
commit 7e2cee02e5
3 changed files with 298 additions and 33 deletions
+8 -1
View File
@@ -222,12 +222,15 @@ SETTING_LABELS = {
"speed": "speed",
"temperature": "speech temperature",
"max_tokens": "max tokens per clip",
"truncation_retries": "retries if cut mid-word",
"strip_leading_ms": "strip leading (ms)",
"trailing_fade_ms": "trailing fade (ms)",
"orig_volume": "sound volume",
"tts_volume": "voiceover volume",
"output_dir": "output folder",
"comfy_url": "ComfyUI URL",
"comfy_autostart": "start ComfyUI if down",
"comfy_start_command": "start script",
}
SECTION_TITLES = {"tts": "Speech", "mix": "Mix", "paths": "Paths", "comfy": "Backend"}
@@ -353,7 +356,11 @@ class SettingsDialog(tk.Toplevel):
font=(F, 10)).grid(row=row, column=0, sticky="w", padx=(6, 14))
var = tk.StringVar(value=current[key])
self.vars[key] = var
if key == "voice" and voices:
if core._DEFAULTS[key][2] is core._as_bool:
w = ttk.Combobox(body, textvariable=var, values=["yes", "no"],
width=26, state="readonly",
style="Dark.TCombobox", font=(F, 10))
elif key == "voice" and voices:
w = ttk.Combobox(body, textvariable=var, values=voices, width=26,
style="Dark.TCombobox", font=(F, 10))
else: