perf: tighten director tag and segment helpers

This commit is contained in:
OpenClaw Agent
2026-07-09 20:03:37 +00:00
parent 58469ccb4b
commit 39af2b0150
2 changed files with 52 additions and 43 deletions

View File

@@ -53,7 +53,15 @@ function stripAudioSegmentTransient(s) {
}
function dedupeById(items = []) {
return items.filter((seg, index, self) => index === self.findIndex((s) => s.id === seg.id));
const seen = new Set();
const deduped = [];
for (const seg of items || []) {
const id = seg?.id;
if (!id || seen.has(id)) continue;
seen.add(id);
deduped.push(seg);
}
return deduped;
}
function findActiveSegmentAtFrame(segments = [], targetFrame, type) {
@@ -62,6 +70,10 @@ function findActiveSegmentAtFrame(segments = [], targetFrame, type) {
);
}
function segmentMatchesAudioSource(seg, audioFile, blobUrl) {
return !!seg && (seg.audioFile === audioFile || seg._blobUrl === blobUrl);
}
function hideWidget(w) {
if (!w) return;
@@ -2004,6 +2016,14 @@ class TimelineEditor {
return found;
}
_forEachMatchingAudioSegment(audioFile, blobUrl, visitor) {
for (const seg of this.timeline.audioSegments || []) {
if (segmentMatchesAudioSource(seg, audioFile, blobUrl)) {
visitor(seg);
}
}
}
_getSegmentsByFileKey(fileKey) {
const matches = [];
this._forEachMatchingSegment(fileKey, (seg) => {
@@ -2231,11 +2251,10 @@ class TimelineEditor {
const audioBuffer = await this._loadAudioBuffer(seg);
const matchingSegs = this.timeline.audioSegments.filter(s => s.audioFile === seg.audioFile || s._blobUrl === seg._blobUrl);
for (const s of matchingSegs) {
this._forEachMatchingAudioSegment(seg.audioFile, seg._blobUrl, (s) => {
s._audioBuffer = audioBuffer;
s._decoding = false;
}
});
} catch (err) {
console.warn("Failed to preload audio segment:", err);
seg._decoding = false;

View File

@@ -33,6 +33,11 @@ from .prompt_relay import (
from .patches import detect_model_type, apply_patches
log = logging.getLogger(__name__)
CHARACTER_TAG_GROUPS = (
("@character1", "@char1"),
("@character2", "@char2"),
("@character3", "@char3"),
)
# Setup global event loop exception handler to silence ConnectionResetError (WinError 10054/10053) on Windows
try:
@@ -283,37 +288,23 @@ def _time_range_to_latent_indices(rel_start_frames: float, rel_length_frames: fl
def _preprocess_prompts_with_characters(global_prompt, local_prompts, char1="", char2="", char3=""):
"""Invisibly swaps out @character1/@char1 tags with their high-fidelity VLM descriptions."""
gp = global_prompt or ""
char1 = char1 if char1 else ""
char2 = char2 if char2 else ""
char3 = char3 if char3 else ""
replacements = {}
for tags, value in zip(CHARACTER_TAG_GROUPS, (char1 or "", char2 or "", char3 or "")):
for tag in tags:
replacements[tag] = value
# Process Global Prompt
for tag in ["@character1", "@char1"]:
if tag in gp:
gp = gp.replace(tag, char1)
for tag in ["@character2", "@char2"]:
if tag in gp:
gp = gp.replace(tag, char2)
for tag in ["@character3", "@char3"]:
if tag in gp:
gp = gp.replace(tag, char3)
def apply_replacements(text: str) -> str:
updated = text or ""
for tag, replacement in replacements.items():
if tag in updated:
updated = updated.replace(tag, replacement)
return updated
# Process Local Timeline Prompts
locals_list = [p.strip() for p in local_prompts.split("|")] if local_prompts else []
processed_locals = []
for lp in locals_list:
for tag in ["@character1", "@char1"]:
if tag in lp:
lp = lp.replace(tag, char1)
for tag in ["@character2", "@char2"]:
if tag in lp:
lp = lp.replace(tag, char2)
for tag in ["@character3", "@char3"]:
if tag in lp:
lp = lp.replace(tag, char3)
processed_locals.append(lp)
gp = apply_replacements(global_prompt or "")
if not local_prompts:
return gp, ""
processed_locals = [apply_replacements(part.strip()) for part in local_prompts.split("|")]
return gp, " | ".join(processed_locals)
@@ -1391,8 +1382,7 @@ def _build_reference_mode_outputs(
raise ValueError("Licon MSR (Prefix) ref option requires connecting the VAE to LTX Director!")
prompt_text = (global_prompt or "") + " " + (local_prompts or "")
tag_pairs = [("@character1", "@char1"), ("@character2", "@char2"), ("@character3", "@char3")]
referenced_slots = [i for i, tags in enumerate(tag_pairs) if any(t in prompt_text for t in tags)]
referenced_slots = [i for i, tags in enumerate(CHARACTER_TAG_GROUPS) if any(t in prompt_text for t in tags)]
selected = []
for slot in referenced_slots:
if slot < len(char_slot_images):