Add separate pair camera configs

This commit is contained in:
2026-06-24 20:01:12 +02:00
parent 2ba0aeb3e9
commit 04ff829a9b
3 changed files with 26 additions and 4 deletions
+8 -1
View File
@@ -265,7 +265,8 @@ add `SxCP Qwen Camera Translator` after it:
The translator accepts the Qwen labels such as `front-right quarter view`, The translator accepts the Qwen labels such as `front-right quarter view`,
`eye-level shot`, and `medium shot`, then emits the same `camera_config` format `eye-level shot`, and `medium shot`, then emits the same `camera_config` format
as the native camera nodes. as the native camera nodes. `suppress_phone_visibility` is enabled by default so
generic Qwen camera views do not add `phone hidden` or other phone wording.
`SxCP Caption Naturalizer` rewrites tag-like captions or labeled prompts into `SxCP Caption Naturalizer` rewrites tag-like captions or labeled prompts into
more natural language. Connect the prompt builder's `metadata_json` output to more natural language. Connect the prompt builder's `metadata_json` output to
@@ -374,6 +375,9 @@ hardcore defaults to `from_camera_config`, which emits no camera sentence unless
a camera config is connected or you select an explicit hardcore camera mode. a camera config is connected or you select an explicit hardcore camera mode.
For stronger camera control, connect `SxCP Camera Control` or For stronger camera control, connect `SxCP Camera Control` or
`SxCP Camera Orbit Control` to the pair node's optional `camera_config` input. `SxCP Camera Orbit Control` to the pair node's optional `camera_config` input.
For different softcore and hardcore camera views, connect separate camera
configs to `softcore_camera_config` and `hardcore_camera_config`; those override
the shared `camera_config` for their side.
Options: Options:
@@ -414,6 +418,9 @@ Options:
separate base camera mode for the hardcore output. `from_camera_config` is separate base camera mode for the hardcore output. `from_camera_config` is
neutral with no connected camera config, and uses `SxCP Camera Control` or neutral with no connected camera config, and uses `SxCP Camera Control` or
`SxCP Camera Orbit Control` when one is connected. `SxCP Camera Orbit Control` when one is connected.
- Pair camera inputs: use shared `camera_config` for one camera on both sides,
or use `softcore_camera_config` and `hardcore_camera_config` for two separate
Qwen/Orbit camera controls.
- `camera_detail`: `from_camera_config`, `off`, `compact`, or `full` for the - `camera_detail`: `from_camera_config`, `off`, `compact`, or `full` for the
pair prompt camera text. Use `from_camera_config` with `SxCP Qwen Camera pair prompt camera text. Use `from_camera_config` with `SxCP Qwen Camera
Translator` so the translator's own detail setting is preserved. Translator` so the translator's own detail setting is preserved.
+9
View File
@@ -460,6 +460,7 @@ class SxCPQwenCameraTranslator:
"priority": (camera_priority_choices(), {"default": "locked"}), "priority": (camera_priority_choices(), {"default": "locked"}),
"camera_detail": (camera_detail_choices(), {"default": "compact"}), "camera_detail": (camera_detail_choices(), {"default": "compact"}),
"include_degrees": ("BOOLEAN", {"default": False}), "include_degrees": ("BOOLEAN", {"default": False}),
"suppress_phone_visibility": ("BOOLEAN", {"default": True}),
}, },
"optional": { "optional": {
"camera_info": (ANY_TYPE,), "camera_info": (ANY_TYPE,),
@@ -483,6 +484,7 @@ class SxCPQwenCameraTranslator:
priority, priority,
camera_detail, camera_detail,
include_degrees, include_degrees,
suppress_phone_visibility,
camera_info=None, camera_info=None,
): ):
config = build_qwen_camera_config_json( config = build_qwen_camera_config_json(
@@ -497,6 +499,7 @@ class SxCPQwenCameraTranslator:
priority=priority, priority=priority,
camera_detail=camera_detail, camera_detail=camera_detail,
include_degrees=include_degrees, include_degrees=include_degrees,
suppress_phone_visibility=suppress_phone_visibility,
) )
parsed = json.loads(config) parsed = json.loads(config)
camera_prompt = parsed.get("custom_camera_prompt", "") camera_prompt = parsed.get("custom_camera_prompt", "")
@@ -1286,6 +1289,8 @@ class SxCPInstaOFPromptPair:
"options_json": ("STRING", {"default": "", "multiline": True}), "options_json": ("STRING", {"default": "", "multiline": True}),
"filter_config": ("STRING", {"default": "", "multiline": True}), "filter_config": ("STRING", {"default": "", "multiline": True}),
"camera_config": ("STRING", {"default": "", "multiline": True}), "camera_config": ("STRING", {"default": "", "multiline": True}),
"softcore_camera_config": ("STRING", {"default": "", "multiline": True}),
"hardcore_camera_config": ("STRING", {"default": "", "multiline": True}),
"character_profile": ("STRING", {"default": "", "multiline": True}), "character_profile": ("STRING", {"default": "", "multiline": True}),
"character_cast": ("STRING", {"default": "", "multiline": True}), "character_cast": ("STRING", {"default": "", "multiline": True}),
"extra_positive": ("STRING", {"default": "", "multiline": True}), "extra_positive": ("STRING", {"default": "", "multiline": True}),
@@ -1320,6 +1325,8 @@ class SxCPInstaOFPromptPair:
options_json="", options_json="",
filter_config="", filter_config="",
camera_config="", camera_config="",
softcore_camera_config="",
hardcore_camera_config="",
character_profile="", character_profile="",
character_cast="", character_cast="",
extra_positive="", extra_positive="",
@@ -1341,6 +1348,8 @@ class SxCPInstaOFPromptPair:
options_json=options_json or "", options_json=options_json or "",
filter_config=filter_config or "", filter_config=filter_config or "",
camera_config=camera_config or "", camera_config=camera_config or "",
softcore_camera_config=softcore_camera_config or "",
hardcore_camera_config=hardcore_camera_config or "",
character_profile=character_profile or "", character_profile=character_profile or "",
character_cast=character_cast or "", character_cast=character_cast or "",
extra_positive=extra_positive or "", extra_positive=extra_positive or "",
+9 -3
View File
@@ -1760,6 +1760,7 @@ def build_qwen_camera_config_json(
priority: str = "locked", priority: str = "locked",
camera_detail: str = "compact", camera_detail: str = "compact",
include_degrees: bool = False, include_degrees: bool = False,
suppress_phone_visibility: bool = True,
) -> str: ) -> str:
info_values = _qwen_camera_info_values(camera_info) info_values = _qwen_camera_info_values(camera_info)
if prefer_camera_info and info_values is not None: if prefer_camera_info and info_values is not None:
@@ -1779,7 +1780,7 @@ def build_qwen_camera_config_json(
subject_focus=subject_focus, subject_focus=subject_focus,
lens=lens, lens=lens,
orientation=orientation, orientation=orientation,
phone_visibility=phone_visibility, phone_visibility="auto" if not _is_false(suppress_phone_visibility) else phone_visibility,
priority=priority, priority=priority,
camera_detail=camera_detail, camera_detail=camera_detail,
include_degrees=include_degrees, include_degrees=include_degrees,
@@ -4669,6 +4670,8 @@ def build_insta_of_pair(
options_json: str | dict[str, Any] | None = None, options_json: str | dict[str, Any] | None = None,
filter_config: str | dict[str, Any] | None = None, filter_config: str | dict[str, Any] | None = None,
camera_config: str | dict[str, Any] | None = None, camera_config: str | dict[str, Any] | None = None,
softcore_camera_config: str | dict[str, Any] | None = None,
hardcore_camera_config: str | dict[str, Any] | None = None,
character_profile: str | dict[str, Any] | None = "", character_profile: str | dict[str, Any] | None = "",
character_cast: str | dict[str, Any] | list[Any] | None = "", character_cast: str | dict[str, Any] | list[Any] | None = "",
extra_positive: str = "", extra_positive: str = "",
@@ -4844,10 +4847,13 @@ def build_insta_of_pair(
soft_level = INSTA_OF_SOFT_LEVELS[options["softcore_level"]] soft_level = INSTA_OF_SOFT_LEVELS[options["softcore_level"]]
hard_level = INSTA_OF_HARDCORE_LEVELS[options["hardcore_level"]] hard_level = INSTA_OF_HARDCORE_LEVELS[options["hardcore_level"]]
hard_camera_mode = options["hardcore_camera_mode"] hard_camera_mode = options["hardcore_camera_mode"]
soft_camera_source = softcore_camera_config or camera_config
hard_camera_source = hardcore_camera_config or camera_config
if hard_camera_mode == "same_as_softcore": if hard_camera_mode == "same_as_softcore":
hard_camera_mode = options["softcore_camera_mode"] hard_camera_mode = options["softcore_camera_mode"]
soft_camera_config = _camera_config_with_mode(camera_config, options["softcore_camera_mode"]) hard_camera_source = soft_camera_source
hard_camera_config = _camera_config_with_mode(camera_config, hard_camera_mode) soft_camera_config = _camera_config_with_mode(soft_camera_source, options["softcore_camera_mode"])
hard_camera_config = _camera_config_with_mode(hard_camera_source, hard_camera_mode)
soft_camera_config = _insta_camera_config_with_detail(soft_camera_config, options["camera_detail"]) soft_camera_config = _insta_camera_config_with_detail(soft_camera_config, options["camera_detail"])
hard_camera_config = _insta_camera_config_with_detail(hard_camera_config, options["camera_detail"]) hard_camera_config = _insta_camera_config_with_detail(hard_camera_config, options["camera_detail"])
soft_camera_directive, soft_camera_config = _camera_directive(soft_camera_config) soft_camera_directive, soft_camera_config = _camera_directive(soft_camera_config)