feat: split frame strength into high/low noise strength per frame
Each frame path now has two strength fields instead of one: 'start frame high strength', 'start frame low strength' (and same for middle/end). Migration splits old single 'X frame strength' into both new keys using the same value. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+11
-4
@@ -96,9 +96,12 @@ def _get_data(name: str, file_name: str, seq: int = Query(default=1)) -> dict[st
|
|||||||
result = dict(match)
|
result = dict(match)
|
||||||
# Inject strength defaults if not yet saved to JSON
|
# Inject strength defaults if not yet saved to JSON
|
||||||
for key, default in (
|
for key, default in (
|
||||||
("start frame strength", 1.0),
|
("start frame high strength", 1.0),
|
||||||
("middle frame strength", 1.0),
|
("start frame low strength", 1.0),
|
||||||
("end frame strength", 1.0),
|
("middle frame high strength", 1.0),
|
||||||
|
("middle frame low strength", 1.0),
|
||||||
|
("end frame high strength", 1.0),
|
||||||
|
("end frame low strength", 1.0),
|
||||||
):
|
):
|
||||||
result.setdefault(key, default)
|
result.setdefault(key, default)
|
||||||
# Computed stem names from frame paths
|
# Computed stem names from frame paths
|
||||||
@@ -133,7 +136,11 @@ def _get_keys(name: str, file_name: str, seq: int = Query(default=1)) -> dict[st
|
|||||||
else:
|
else:
|
||||||
types.append("STRING")
|
types.append("STRING")
|
||||||
# Injected defaults — always present even if not yet saved to JSON
|
# Injected defaults — always present even if not yet saved to JSON
|
||||||
for key in ("start frame strength", "middle frame strength", "end frame strength"):
|
for key in (
|
||||||
|
"start frame high strength", "start frame low strength",
|
||||||
|
"middle frame high strength", "middle frame low strength",
|
||||||
|
"end frame high strength", "end frame low strength",
|
||||||
|
):
|
||||||
if key not in match:
|
if key not in match:
|
||||||
keys.append(key)
|
keys.append(key)
|
||||||
types.append("FLOAT")
|
types.append("FLOAT")
|
||||||
|
|||||||
+12
-10
@@ -317,9 +317,9 @@ def render_batch_processor(state: AppState):
|
|||||||
'seed', 'camera', KEY_SEQUENCE_NUMBER,
|
'seed', 'camera', KEY_SEQUENCE_NUMBER,
|
||||||
'frame_to_skip', 'logic index', 'transition', 'vace_length',
|
'frame_to_skip', 'logic index', 'transition', 'vace_length',
|
||||||
'input_a_frames', 'input_b_frames', 'reference switch', 'vace schedule',
|
'input_a_frames', 'input_b_frames', 'reference switch', 'vace schedule',
|
||||||
'start frame path', 'start frame strength',
|
'start frame path', 'start frame high strength', 'start frame low strength',
|
||||||
'middle frame path', 'middle frame strength',
|
'middle frame path', 'middle frame high strength', 'middle frame low strength',
|
||||||
'end frame path', 'end frame strength',
|
'end frame path', 'end frame high strength', 'end frame low strength',
|
||||||
'video file path',
|
'video file path',
|
||||||
}
|
}
|
||||||
standard_keys.update(lora_keys)
|
standard_keys.update(lora_keys)
|
||||||
@@ -560,10 +560,10 @@ def _render_sequence_card(i, seq, batch_list, data, file_path, state,
|
|||||||
|
|
||||||
# --- Frame paths (start / middle / end) ---
|
# --- Frame paths (start / middle / end) ---
|
||||||
logic_val = int(seq.get('logic index', 0))
|
logic_val = int(seq.get('logic index', 0))
|
||||||
for bit, img_label, img_key, str_key in [
|
for bit, img_label, img_key, hi_key, lo_key in [
|
||||||
(0, 'Start Frame', 'start frame path', 'start frame strength'),
|
(0, 'Start Frame', 'start frame path', 'start frame high strength', 'start frame low strength'),
|
||||||
(1, 'Middle Frame', 'middle frame path', 'middle frame strength'),
|
(1, 'Middle Frame', 'middle frame path', 'middle frame high strength', 'middle frame low strength'),
|
||||||
(2, 'End Frame', 'end frame path', 'end frame strength'),
|
(2, 'End Frame', 'end frame path', 'end frame high strength', 'end frame low strength'),
|
||||||
]:
|
]:
|
||||||
ui.label(img_label).classes('text-caption text-weight-bold q-mt-sm')
|
ui.label(img_label).classes('text-caption text-weight-bold q-mt-sm')
|
||||||
with ui.row().classes('w-full items-center no-wrap q-mt-xs'):
|
with ui.row().classes('w-full items-center no-wrap q-mt-xs'):
|
||||||
@@ -581,11 +581,13 @@ def _render_sequence_card(i, seq, batch_list, data, file_path, state,
|
|||||||
f'style="width:36px;height:36px;object-fit:cover;'
|
f'style="width:36px;height:36px;object-fit:cover;'
|
||||||
f'border-radius:4px;cursor:pointer;flex-shrink:0">'
|
f'border-radius:4px;cursor:pointer;flex-shrink:0">'
|
||||||
).on('click', img_dlg.open)
|
).on('click', img_dlg.open)
|
||||||
str_inp = dict_number('Strength', seq, str_key, default=1.0,
|
|
||||||
step=0.05, format='%.2f').style(
|
|
||||||
'width:80px').props('outlined dense')
|
|
||||||
sw = ui.switch(value=bool((logic_val >> bit) & 1))
|
sw = ui.switch(value=bool((logic_val >> bit) & 1))
|
||||||
frame_switches.append(sw)
|
frame_switches.append(sw)
|
||||||
|
with ui.row().classes('w-full no-wrap q-mt-xs q-gutter-xs'):
|
||||||
|
dict_number('High', seq, hi_key, default=1.0,
|
||||||
|
step=0.05, format='%.2f').classes('col').props('outlined dense')
|
||||||
|
dict_number('Low', seq, lo_key, default=1.0,
|
||||||
|
step=0.05, format='%.2f').classes('col').props('outlined dense')
|
||||||
|
|
||||||
with splitter.after:
|
with splitter.after:
|
||||||
# Mode
|
# Mode
|
||||||
|
|||||||
@@ -44,11 +44,14 @@ DEFAULTS = {
|
|||||||
"reference switch": 1,
|
"reference switch": 1,
|
||||||
"video file path": "",
|
"video file path": "",
|
||||||
"start frame path": "",
|
"start frame path": "",
|
||||||
"start frame strength": 1.0,
|
"start frame high strength": 1.0,
|
||||||
|
"start frame low strength": 1.0,
|
||||||
"middle frame path": "",
|
"middle frame path": "",
|
||||||
"middle frame strength": 1.0,
|
"middle frame high strength": 1.0,
|
||||||
|
"middle frame low strength": 1.0,
|
||||||
"end frame path": "",
|
"end frame path": "",
|
||||||
"end frame strength": 1.0,
|
"end frame high strength": 1.0,
|
||||||
|
"end frame low strength": 1.0,
|
||||||
|
|
||||||
# --- LoRAs (name as STRING, strength as FLOAT) ---
|
# --- LoRAs (name as STRING, strength as FLOAT) ---
|
||||||
"lora 1 high": "",
|
"lora 1 high": "",
|
||||||
@@ -173,6 +176,13 @@ def _migrate_key_renames(data: dict) -> None:
|
|||||||
item['end frame path'] = item.pop('flf image path')
|
item['end frame path'] = item.pop('flf image path')
|
||||||
if 'reference image path' in item and 'start frame path' not in item:
|
if 'reference image path' in item and 'start frame path' not in item:
|
||||||
item['start frame path'] = item.pop('reference image path')
|
item['start frame path'] = item.pop('reference image path')
|
||||||
|
# Split old single strength into high+low
|
||||||
|
for prefix in ('start frame', 'middle frame', 'end frame'):
|
||||||
|
old_key = f'{prefix} strength'
|
||||||
|
if old_key in item:
|
||||||
|
val = item.pop(old_key)
|
||||||
|
item.setdefault(f'{prefix} high strength', val)
|
||||||
|
item.setdefault(f'{prefix} low strength', val)
|
||||||
|
|
||||||
|
|
||||||
def _migrate_lora_keys(data: dict) -> None:
|
def _migrate_lora_keys(data: dict) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user