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`,
`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
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.
For stronger camera control, connect `SxCP Camera Control` or
`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:
@@ -414,6 +418,9 @@ Options:
separate base camera mode for the hardcore output. `from_camera_config` is
neutral with no connected camera config, and uses `SxCP Camera Control` or
`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
pair prompt camera text. Use `from_camera_config` with `SxCP Qwen Camera
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"}),
"camera_detail": (camera_detail_choices(), {"default": "compact"}),
"include_degrees": ("BOOLEAN", {"default": False}),
"suppress_phone_visibility": ("BOOLEAN", {"default": True}),
},
"optional": {
"camera_info": (ANY_TYPE,),
@@ -483,6 +484,7 @@ class SxCPQwenCameraTranslator:
priority,
camera_detail,
include_degrees,
suppress_phone_visibility,
camera_info=None,
):
config = build_qwen_camera_config_json(
@@ -497,6 +499,7 @@ class SxCPQwenCameraTranslator:
priority=priority,
camera_detail=camera_detail,
include_degrees=include_degrees,
suppress_phone_visibility=suppress_phone_visibility,
)
parsed = json.loads(config)
camera_prompt = parsed.get("custom_camera_prompt", "")
@@ -1286,6 +1289,8 @@ class SxCPInstaOFPromptPair:
"options_json": ("STRING", {"default": "", "multiline": True}),
"filter_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_cast": ("STRING", {"default": "", "multiline": True}),
"extra_positive": ("STRING", {"default": "", "multiline": True}),
@@ -1320,6 +1325,8 @@ class SxCPInstaOFPromptPair:
options_json="",
filter_config="",
camera_config="",
softcore_camera_config="",
hardcore_camera_config="",
character_profile="",
character_cast="",
extra_positive="",
@@ -1341,6 +1348,8 @@ class SxCPInstaOFPromptPair:
options_json=options_json or "",
filter_config=filter_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_cast=character_cast or "",
extra_positive=extra_positive or "",
+9 -3
View File
@@ -1760,6 +1760,7 @@ def build_qwen_camera_config_json(
priority: str = "locked",
camera_detail: str = "compact",
include_degrees: bool = False,
suppress_phone_visibility: bool = True,
) -> str:
info_values = _qwen_camera_info_values(camera_info)
if prefer_camera_info and info_values is not None:
@@ -1779,7 +1780,7 @@ def build_qwen_camera_config_json(
subject_focus=subject_focus,
lens=lens,
orientation=orientation,
phone_visibility=phone_visibility,
phone_visibility="auto" if not _is_false(suppress_phone_visibility) else phone_visibility,
priority=priority,
camera_detail=camera_detail,
include_degrees=include_degrees,
@@ -4669,6 +4670,8 @@ def build_insta_of_pair(
options_json: str | dict[str, Any] | None = None,
filter_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_cast: str | dict[str, Any] | list[Any] | None = "",
extra_positive: str = "",
@@ -4844,10 +4847,13 @@ def build_insta_of_pair(
soft_level = INSTA_OF_SOFT_LEVELS[options["softcore_level"]]
hard_level = INSTA_OF_HARDCORE_LEVELS[options["hardcore_level"]]
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":
hard_camera_mode = options["softcore_camera_mode"]
soft_camera_config = _camera_config_with_mode(camera_config, options["softcore_camera_mode"])
hard_camera_config = _camera_config_with_mode(camera_config, hard_camera_mode)
hard_camera_source = soft_camera_source
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"])
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)