aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xfanfictioner21
1 files changed, 21 insertions, 0 deletions
diff --git a/fanfictioner b/fanfictioner
index 7d53bce..132e46a 100755
--- a/fanfictioner
+++ b/fanfictioner
@@ -349,6 +349,15 @@ def mem_available_kb(meminfo):
return int(re.search(r"MemAvailable:\s+(\d+)", meminfo)[1])
+def progress(start, log):
+ """One self-overwriting status line: elapsed time and sd-cli's latest progress output."""
+ with open(log, "rb") as f:
+ f.seek(max(0, os.path.getsize(log) - 4096))
+ last = next((x for x in reversed(re.split(r"[\r\n]", f.read().decode(errors="replace"))) if x.strip()), "")
+ width = shutil.get_terminal_size().columns - 1
+ print(f"\r{int(time.time() - start):4d}s {last.strip()}"[:width].ljust(width), end="", flush=True)
+
+
def run_sd(args, log):
"""Run sd-cli with output in log; return an error string or None."""
with open(log, "w") as f:
@@ -358,9 +367,11 @@ def run_sd(args, log):
proc = subprocess.Popen(args, stdout=f, stderr=subprocess.STDOUT)
except OSError as e:
return f"cannot run {args[0]}: {e}"
+ start = time.time()
try:
while proc.poll() is None:
time.sleep(2)
+ progress(start, log)
if proc.poll() is None and \
mem_available_kb(Path("/proc/meminfo").read_text()) < MIN_RAM_KB:
proc.kill()
@@ -370,6 +381,8 @@ def run_sd(args, log):
proc.kill()
proc.wait()
raise
+ finally:
+ print()
if proc.returncode or "[ERROR" in Path(log).read_text(errors="replace"):
return f"sd-cli failed (exit {proc.returncode})"
return None
@@ -452,18 +465,22 @@ def review(d, profile, prompt, size, refs=(), skip=False):
k = "q"
if k in ("1", "2", "3") and not err:
log(f"{stage} pick {k}, seed {seed + int(k) - 1}, {files[int(k) - 1].name}")
+ print(f"picked {k} (seed {seed + int(k) - 1})")
return files[int(k) - 1]
if k == "r":
log(f"{stage} regenerate")
+ print("regenerating with a new seed")
break
if k == "p":
(d / "prompt.txt").write_text(prompt)
editor(d / "prompt.txt")
prompt = (d / "prompt.txt").read_text().strip() or prompt
log(f"{stage} prompt edited: {prompt}")
+ print(f"regenerating with prompt:\n{prompt}")
break
if k == "s" and skip:
log(f"{stage} skip edit")
+ print("edit skipped, scene kept as is")
return None
if k == "q":
log(f"{stage} quit")
@@ -595,6 +612,8 @@ def page_stage(p, wd, out, base):
if not scene.exists():
print(f"\n== page {p['n']}: base scene")
keep(review(d / "base", p["model"] or base, p["base_prompt"], size), scene)
+ else:
+ print(f"page {p['n']}: base scene reused from earlier pick")
for i, e in enumerate(p["edits"], 1):
nxt = d / f"edit{i}.png"
if not nxt.exists():
@@ -604,6 +623,8 @@ def page_stage(p, wd, out, base):
for n in e["characters"]]
pick = review(d / f"edit{i}", "qwen_edit", e["prompt"], size, refs, skip=True)
keep(pick or scene, nxt)
+ else:
+ print(f"page {p['n']}: edit {i} ({', '.join(e['characters'])}) reused from earlier pick")
scene = nxt
keep(scene, out)
log(f"page {p['n']} -> {out}")