@oh-story/dsh 0.1.9 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -12
- package/lib/client.js +204 -72
- package/lib/client.js.map +3 -3
- package/lib/drama/manifest.json +84 -74
- package/lib/drama/skills/short-drama/SKILL.md +2 -2
- package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +14 -0
- package/lib/drama/skills/short-drama-assets/references/character-and-look.md +10 -0
- package/lib/drama/skills/short-drama-assets/references/continuity-lock.md +6 -9
- package/lib/drama/skills/short-drama-assets/references/voice-direction.md +28 -0
- package/lib/drama/skills/short-drama-edit/SKILL.md +27 -29
- package/lib/drama/skills/short-drama-edit/assets//345/211/252/350/276/221/345/215/225.md +2 -2
- package/lib/drama/skills/short-drama-edit/references/cut-craft.md +24 -67
- package/lib/drama/skills/short-drama-edit/references/delivery-verify.md +27 -56
- package/lib/drama/skills/short-drama-edit/references/generated-footage.md +37 -79
- package/lib/drama/skills/short-drama-edit/references/sound-and-subtitles.md +39 -92
- package/lib/drama/skills/short-drama-edit/references/stage-contract.md +12 -16
- package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +126 -11
- package/lib/drama/skills/short-drama-edit/scripts/selftest.py +64 -0
- package/lib/drama/skills/short-drama-image-prompts/SKILL.md +2 -0
- package/lib/drama/skills/short-drama-image-prompts/references/common-recipe.md +11 -0
- package/lib/drama/skills/short-drama-produce/SKILL.md +5 -1
- package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +14 -20
- package/lib/drama/skills/short-drama-produce/references/providers/minimax-h3-video.md +8 -26
- package/lib/drama/skills/short-drama-produce/references/providers/minimax-speech.md +41 -0
- package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +142 -1
- package/lib/drama/skills/short-drama-review/SKILL.md +2 -3
- package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +6 -19
- package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +9 -35
- package/lib/drama/skills/short-drama-storyboard/SKILL.md +10 -6
- package/lib/drama/skills/short-drama-storyboard/references/lighting-craft.md +39 -0
- package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +58 -21
- package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +1 -1
- package/lib/drama/skills/short-drama-video-prompts/SKILL.md +10 -9
- package/lib/drama/skills/short-drama-video-prompts/references/camera-audio-continuity.md +17 -0
- package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +12 -38
- package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +4 -7
- package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +8 -22
- package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +6 -19
- package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.0.md +2 -3
- package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +34 -9
- package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +2 -2
- package/lib/drama/skills/short-drama-write/SKILL.md +2 -4
- package/lib/index.js +289 -91
- package/lib/index.js.map +4 -4
- package/lib/novel-to-game/README.md +299 -59
- package/lib/novel-to-game/README_ZH.md +299 -56
- package/lib/novel-to-game/VERSION +1 -1
- package/lib/novel-to-game/examples/jin-ping-mei/build/BUILD_BRIEF.md +3 -1
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/RUN.md +11 -3
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/new-guofeng.css +397 -8
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/css/style.css +0 -31
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/data.js +71 -73
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/engine.js +78 -89
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/main.js +37 -14
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/js/text.js +5 -5
- package/lib/novel-to-game/examples/jin-ping-mei/build/app/package.json +2 -1
- package/lib/novel-to-game/examples/jin-ping-mei/qa/README.md +11 -16
- package/lib/novel-to-game/examples/jin-ping-mei/qa/verification.json +11 -11
- package/lib/novel-to-game/examples/jin-ping-mei/qa/verify_playable_model.mjs +23 -0
- package/lib/novel-to-game/manifest.json +77 -87
- package/lib/novel-to-game/skills/game-art-direction/SKILL.md +7 -12
- package/lib/novel-to-game/skills/game-art-direction/references/art-direction-method.md +27 -106
- package/lib/novel-to-game/skills/game-build/SKILL.md +13 -14
- package/lib/novel-to-game/skills/game-build/references/blender-asset-workflow.md +24 -0
- package/lib/novel-to-game/skills/game-build/references/build-brief-contract.md +45 -82
- package/lib/novel-to-game/skills/game-build/references/generative-media-pipeline.md +14 -45
- package/lib/novel-to-game/skills/game-build/references/playable-model-contract.md +30 -65
- package/lib/novel-to-game/skills/game-build/references/tts-production-contract.md +13 -27
- package/lib/novel-to-game/skills/game-concept/SKILL.md +13 -15
- package/lib/novel-to-game/skills/game-concept/references/concept-method.md +28 -75
- package/lib/novel-to-game/skills/game-qa/SKILL.md +6 -7
- package/lib/novel-to-game/skills/game-qa/references/test-design-method.md +9 -5
- package/lib/novel-to-game/skills/game-world-design/SKILL.md +12 -16
- package/lib/novel-to-game/skills/game-world-design/references/narrative-design-method.md +23 -72
- package/lib/novel-to-game/skills/game-world-design/references/numeric-design-method.md +14 -48
- package/lib/novel-to-game/skills/game-world-design/references/world-design-method.md +36 -103
- package/lib/novel-to-game/skills/novel-game-analyze/SKILL.md +4 -10
- package/lib/novel-to-game/skills/novel-game-analyze/references/gameability-protocol.md +4 -4
- package/lib/novel-to-game/skills/novel-to-game/SKILL.md +9 -21
- package/lib/novel-to-game/skills/novel-to-game/references/intake-method.md +5 -4
- package/lib/novel-to-game/skills/novel-to-game/references/pipeline-contract.md +5 -8
- package/lib/oh-story/manifest.json +230 -185
- package/lib/oh-story/roles/chapter-extractor.md +177 -237
- package/lib/oh-story/roles/consistency-checker.md +4 -4
- package/lib/oh-story/roles/narrative-writer.md +24 -25
- package/lib/oh-story/roles/story-architect.md +5 -5
- package/lib/oh-story/roles/story-explorer.md +11 -11
- package/lib/oh-story/skills/story/SKILL.md +13 -7
- package/lib/oh-story/skills/story/VERSION +1 -1
- package/lib/oh-story/skills/story/references/author-memory.md +54 -24
- package/lib/oh-story/skills/story/scripts/author_memory_commit.py +934 -170
- package/lib/oh-story/skills/story-cover/SKILL.md +10 -1
- package/lib/oh-story/skills/story-deslop/SKILL.md +40 -53
- package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +11 -10
- package/lib/oh-story/skills/story-deslop/references/author-memory.md +54 -24
- package/lib/oh-story/skills/story-deslop/references/deslop-gates.md +1 -1
- package/lib/oh-story/skills/story-deslop/scripts/author_memory_commit.py +934 -170
- package/lib/oh-story/skills/story-import/SKILL.md +77 -81
- package/lib/oh-story/skills/story-import/references/character-state-reverse.md +1 -1
- package/lib/oh-story/skills/story-import/references/state-tracking.md +4 -69
- package/lib/oh-story/skills/story-import/references/structure-mapping-long.md +10 -8
- package/lib/oh-story/skills/story-import/references/tracking-transaction.md +8 -6
- package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +34 -16
- package/lib/oh-story/skills/story-import/scripts/tracking_commit.py +210 -2
- package/lib/oh-story/skills/story-import/scripts/wordcount_core.py +3 -0
- package/lib/oh-story/skills/story-long-analyze/SKILL.md +91 -258
- package/lib/oh-story/skills/story-long-analyze/references/author-facing.md +245 -0
- package/lib/oh-story/skills/story-long-analyze/references/deconstruction-notes.md +2 -2
- package/lib/oh-story/skills/story-long-analyze/references/inspiration-library.md +105 -0
- package/lib/oh-story/skills/story-long-analyze/references/material-decomposition.md +113 -105
- package/lib/oh-story/skills/story-long-analyze/references/output-templates.md +169 -125
- package/lib/oh-story/skills/story-long-analyze/references/pipeline-ops.md +172 -64
- package/lib/oh-story/skills/story-long-analyze/references/semantic-acceptance-fixtures.md +84 -0
- package/lib/oh-story/skills/story-long-analyze/references/style-profile-generator.md +42 -132
- package/lib/oh-story/skills/story-long-analyze/references/style-profile-protocol.md +5 -5
- package/lib/oh-story/skills/story-long-analyze/scripts/build_chapter_index.py +466 -0
- package/lib/oh-story/skills/story-long-analyze/scripts/inspect_existing_assets.py +702 -0
- package/lib/oh-story/skills/story-long-analyze/scripts/inspiration_index.py +864 -0
- package/lib/oh-story/skills/story-long-analyze/scripts/manage_analysis_run.py +1106 -0
- package/lib/oh-story/skills/story-long-analyze/scripts/render_relation_chart.py +425 -0
- package/lib/oh-story/skills/story-long-scan/SKILL.md +4 -1
- package/lib/oh-story/skills/story-long-write/SKILL.md +38 -29
- package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +11 -10
- package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +25 -20
- package/lib/oh-story/skills/story-long-write/references/author-memory.md +54 -24
- package/lib/oh-story/skills/story-long-write/references/benchmark-recall.md +3 -3
- package/lib/oh-story/skills/story-long-write/references/cross-book-recall.md +26 -0
- package/lib/oh-story/skills/story-long-write/references/dialogue-mastery.md +4 -0
- package/lib/oh-story/skills/story-long-write/references/emotional-methods.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/long-chapter-quality.md +4 -13
- package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/project-files.md +9 -7
- package/lib/oh-story/skills/story-long-write/references/reader-contract-and-progression.md +12 -4
- package/lib/oh-story/skills/story-long-write/references/reference-index.md +1 -2
- package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +8 -6
- package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +86 -115
- package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +55 -120
- package/lib/oh-story/skills/story-long-write/references/workflow-revision.md +15 -11
- package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +66 -68
- package/lib/oh-story/skills/story-long-write/references/writer-prompt-fallback.md +3 -3
- package/lib/oh-story/skills/story-long-write/references/writing-craft.md +4 -12
- package/lib/oh-story/skills/story-long-write/scripts/author_memory_commit.py +934 -170
- package/lib/oh-story/skills/story-long-write/scripts/build_writer_prompt.py +139 -18
- package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +34 -16
- package/lib/oh-story/skills/story-long-write/scripts/outline_view.py +5 -3
- package/lib/oh-story/skills/story-long-write/scripts/storyctl.py +58 -0
- package/lib/oh-story/skills/story-long-write/scripts/tracking_commit.py +210 -2
- package/lib/oh-story/skills/story-long-write/scripts/wordcount_core.py +3 -0
- package/lib/oh-story/skills/story-review/SKILL.md +68 -85
- package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +11 -10
- package/lib/oh-story/skills/story-review/references/author-memory.md +54 -24
- package/lib/oh-story/skills/story-review/references/dialogue-mastery.md +4 -0
- package/lib/oh-story/skills/story-review/references/review-quality.md +4 -10
- package/lib/oh-story/skills/story-review/references/tracking-transaction.md +8 -6
- package/lib/oh-story/skills/story-review/scripts/author_memory_commit.py +934 -170
- package/lib/oh-story/skills/story-review/scripts/tracking_commit.py +210 -2
- package/lib/oh-story/skills/story-review/scripts/wordcount_core.py +3 -0
- package/lib/oh-story/skills/story-setup/SKILL.md +50 -42
- package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +11 -10
- package/lib/oh-story/skills/story-setup/references/agent-references/deslop-gates.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/dialogue-mastery.md +4 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/long-emotional-methods.md +2 -2
- package/lib/oh-story/skills/story-setup/references/agent-references/long-quality.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +4 -12
- package/lib/oh-story/skills/story-setup/references/diagnostics.md +1 -1
- package/lib/oh-story/skills/story-short-analyze/SKILL.md +22 -3
- package/lib/oh-story/skills/story-short-analyze/references/material-decomposition.md +5 -1
- package/lib/oh-story/skills/story-short-scan/SKILL.md +5 -1
- package/lib/oh-story/skills/story-short-write/SKILL.md +6 -147
- package/lib/oh-story/skills/story-short-write/references/author-memory.md +54 -24
- package/lib/oh-story/skills/story-short-write/references/dialogue-mastery.md +4 -0
- package/lib/oh-story/skills/story-short-write/references/reference-index.md +2 -0
- package/lib/oh-story/skills/story-short-write/references/workflow-design.md +3 -2
- package/lib/oh-story/skills/story-short-write/references/workflow-draft.md +126 -0
- package/lib/oh-story/skills/story-short-write/references/workflow-revision.md +32 -0
- package/lib/oh-story/skills/story-short-write/scripts/author_memory_commit.py +934 -170
- package/lib/types/client/drama-production-view.d.ts.map +1 -1
- package/lib/types/client/file-activity.d.ts +19 -1
- package/lib/types/client/file-activity.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/production-prompts.d.ts +7 -0
- package/lib/types/client/production-prompts.d.ts.map +1 -1
- package/lib/types/client/production-runtime.d.ts +16 -0
- package/lib/types/client/production-runtime.d.ts.map +1 -1
- package/lib/types/drama-adapters.d.ts +5 -3
- package/lib/types/drama-adapters.d.ts.map +1 -1
- package/lib/types/native-hooks.d.ts +52 -0
- package/lib/types/native-hooks.d.ts.map +1 -1
- package/lib/types/role-identity.d.ts +17 -0
- package/lib/types/role-identity.d.ts.map +1 -0
- package/lib/types/role-tool.d.ts.map +1 -1
- package/lib/types/skill-provider.d.ts.map +1 -1
- package/package.json +45 -45
- package/lib/novel-to-game/skills/game-world-design/references/dialogue-design-method.md +0 -58
- package/lib/novel-to-game/skills/game-world-design/references/game-writing-craft.md +0 -53
- package/lib/novel-to-game/skills/novel-to-game/references/intake-benchmark-reference.md +0 -38
- package/lib/oh-story/skills/story-long-write/references/state-tracking.md +0 -108
|
@@ -41,13 +41,21 @@ MAX_ERROR_BODY_BYTES = 64 * 1024
|
|
|
41
41
|
TERMINAL_FAILURES = {"failed", "cancelled", "canceled", "timeout", "expired"}
|
|
42
42
|
SEEDANCE_RATIOS = {"adaptive", "1:1", "3:4", "4:3", "9:16", "16:9", "21:9"}
|
|
43
43
|
SEEDANCE_REFERENCE_ROLES = {
|
|
44
|
+
"first_frame": "image_url",
|
|
45
|
+
"last_frame": "image_url",
|
|
44
46
|
"reference_image": "image_url",
|
|
45
47
|
"reference_video": "video_url",
|
|
46
48
|
"reference_audio": "audio_url",
|
|
47
49
|
}
|
|
50
|
+
# One opening frame and one closing frame, because each names a single position
|
|
51
|
+
# in the take. Note what is deliberately absent: the sibling adapter forbids
|
|
52
|
+
# mixing frame conditioning with reference conditioning, and that rule belongs
|
|
53
|
+
# to that provider's reference, not to this one. Do not carry it across.
|
|
54
|
+
SEEDANCE_SINGULAR_ROLES = {"first_frame", "last_frame"}
|
|
48
55
|
MINIMAX_VIDEO_RATIOS = {"adaptive", "1:1", "3:4", "4:3", "9:16", "16:9", "21:9"}
|
|
49
56
|
MINIMAX_VIDEO_RESOLUTIONS = {"480P", "768P", "2K"}
|
|
50
57
|
MINIMAX_VIDEO_PROMPT_LIMIT = 7000
|
|
58
|
+
MINIMAX_SPEECH_TEXT_LIMIT = 5000
|
|
51
59
|
MINIMAX_VIDEO_ROLES = {
|
|
52
60
|
"first_frame": "image_url",
|
|
53
61
|
"last_frame": "image_url",
|
|
@@ -369,10 +377,18 @@ def compile_seedance_payload(
|
|
|
369
377
|
counters = {"image_url": 0, "video_url": 0, "audio_url": 0}
|
|
370
378
|
labels = {"image_url": "图片", "video_url": "视频", "audio_url": "音频"}
|
|
371
379
|
reference_tokens: list[str] = []
|
|
380
|
+
singular_seen: set[str] = set()
|
|
372
381
|
for role in reference_roles:
|
|
373
382
|
field = SEEDANCE_REFERENCE_ROLES.get(role)
|
|
374
383
|
if field is None:
|
|
375
384
|
raise ValueError(f"unsupported Seedance reference role: {role}")
|
|
385
|
+
if role in SEEDANCE_SINGULAR_ROLES:
|
|
386
|
+
if role in singular_seen:
|
|
387
|
+
raise ValueError(f"Seedance accepts one {role} reference")
|
|
388
|
+
singular_seen.add(role)
|
|
389
|
+
# A frame role still occupies a picture slot, so it keeps counting: the
|
|
390
|
+
# tokens are positional, and skipping one would point every later
|
|
391
|
+
# `@图片N` in the prose at the wrong picture.
|
|
376
392
|
counters[field] += 1
|
|
377
393
|
reference_tokens.append(f"@{labels[field]}{counters[field]}")
|
|
378
394
|
if task_type in {"edit", "extend"} and "reference_video" not in reference_roles:
|
|
@@ -738,6 +754,82 @@ def compile_gpt_image_2_payload(job: Mapping[str, Any]) -> dict[str, Any]:
|
|
|
738
754
|
}
|
|
739
755
|
|
|
740
756
|
|
|
757
|
+
MINIMAX_SPEECH_EMOTIONS = {
|
|
758
|
+
"happy", "sad", "angry", "fearful", "disgusted", "surprised", "neutral",
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
def compile_minimax_speech_payload(job: Mapping[str, Any]) -> dict[str, Any]:
|
|
763
|
+
"""Compile a tts job into the official MiniMax speech JSON body.
|
|
764
|
+
|
|
765
|
+
The voice catalogue is deliberately not enumerated here. Which preset voices
|
|
766
|
+
an account can reach depends on the model and the account, no published list
|
|
767
|
+
is authoritative for both, and a list frozen into this file would either
|
|
768
|
+
refuse a voice that works or vouch for one that does not. The document owns
|
|
769
|
+
the value and a reviewer reads it; the adapter only checks its shape.
|
|
770
|
+
"""
|
|
771
|
+
|
|
772
|
+
text, parameters = _require_job(job, "tts")
|
|
773
|
+
parameters = _take(
|
|
774
|
+
parameters,
|
|
775
|
+
{"model", "voice_id", "speed", "vol", "pitch", "emotion",
|
|
776
|
+
"sample_rate", "bitrate", "format"},
|
|
777
|
+
)
|
|
778
|
+
model = parameters.pop("model", "")
|
|
779
|
+
if not isinstance(model, str) or not model.strip():
|
|
780
|
+
raise ValueError("MiniMax speech model must be explicitly configured")
|
|
781
|
+
voice_id = parameters.pop("voice_id", "")
|
|
782
|
+
if not isinstance(voice_id, str) or not voice_id.strip() or voice_id != voice_id.strip():
|
|
783
|
+
raise ValueError("MiniMax speech requires a confirmed voice_id")
|
|
784
|
+
if len(text) > MINIMAX_SPEECH_TEXT_LIMIT:
|
|
785
|
+
raise ValueError("MiniMax speech text exceeds the provider limit")
|
|
786
|
+
|
|
787
|
+
target_format = Path(job["outputs"][0]).suffix.casefold().lstrip(".")
|
|
788
|
+
requested_format = parameters.pop("format", target_format)
|
|
789
|
+
if requested_format != target_format or requested_format not in {"mp3", "wav"}:
|
|
790
|
+
raise ValueError("MiniMax output format must match a supported target extension")
|
|
791
|
+
sample_rate = parameters.pop("sample_rate", 32000)
|
|
792
|
+
bitrate = parameters.pop("bitrate", 128000)
|
|
793
|
+
if sample_rate not in {16000, 24000, 32000, 44100}:
|
|
794
|
+
raise ValueError("unsupported MiniMax sample rate")
|
|
795
|
+
if bitrate not in {32000, 64000, 128000, 256000}:
|
|
796
|
+
raise ValueError("unsupported MiniMax bitrate")
|
|
797
|
+
|
|
798
|
+
voice_setting: dict[str, Any] = {"voice_id": voice_id}
|
|
799
|
+
emotion = parameters.pop("emotion", None)
|
|
800
|
+
if emotion is not None:
|
|
801
|
+
if emotion not in MINIMAX_SPEECH_EMOTIONS:
|
|
802
|
+
raise ValueError("unsupported MiniMax speech emotion")
|
|
803
|
+
voice_setting["emotion"] = emotion
|
|
804
|
+
for name, low, high in (("speed", 0.5, 2.0), ("vol", 0.1, 10.0)):
|
|
805
|
+
value = parameters.pop(name, None)
|
|
806
|
+
if value is None:
|
|
807
|
+
continue
|
|
808
|
+
if isinstance(value, bool) or not isinstance(value, (int, float)):
|
|
809
|
+
raise ValueError(f"MiniMax speech {name} must be a number")
|
|
810
|
+
if not low <= float(value) <= high:
|
|
811
|
+
raise ValueError(f"MiniMax speech {name} is outside the supported range")
|
|
812
|
+
voice_setting[name] = float(value)
|
|
813
|
+
pitch = parameters.pop("pitch", None)
|
|
814
|
+
if pitch is not None:
|
|
815
|
+
if isinstance(pitch, bool) or not isinstance(pitch, int) or not -12 <= pitch <= 12:
|
|
816
|
+
raise ValueError("MiniMax speech pitch is outside the supported range")
|
|
817
|
+
voice_setting["pitch"] = pitch
|
|
818
|
+
|
|
819
|
+
return {
|
|
820
|
+
"model": model.strip(),
|
|
821
|
+
"text": text,
|
|
822
|
+
"stream": False,
|
|
823
|
+
"output_format": "hex",
|
|
824
|
+
"voice_setting": voice_setting,
|
|
825
|
+
"audio_setting": {
|
|
826
|
+
"sample_rate": sample_rate,
|
|
827
|
+
"bitrate": bitrate,
|
|
828
|
+
"format": requested_format,
|
|
829
|
+
},
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
|
|
741
833
|
def compile_minimax_music_payload(job: Mapping[str, Any]) -> dict[str, Any]:
|
|
742
834
|
"""Compile an audio job into the official MiniMax Music 3.0 JSON body."""
|
|
743
835
|
prompt, parameters = _require_job(job, "music")
|
|
@@ -1372,6 +1464,44 @@ def _run_minimax(job: Mapping[str, Any]) -> tuple[Path, str | None]:
|
|
|
1372
1464
|
)
|
|
1373
1465
|
|
|
1374
1466
|
|
|
1467
|
+
def _run_minimax_speech(job: Mapping[str, Any]) -> tuple[Path, str | None]:
|
|
1468
|
+
token = _credential("MINIMAX_API_KEY")
|
|
1469
|
+
body = compile_minimax_speech_payload(job)
|
|
1470
|
+
base = _base_url("MINIMAX_BASE_URL", MINIMAX_BASE_URL)
|
|
1471
|
+
result, _ = _request_json(
|
|
1472
|
+
f"{base}/t2a_v2",
|
|
1473
|
+
provider="minimax-speech",
|
|
1474
|
+
body=body,
|
|
1475
|
+
token=token,
|
|
1476
|
+
)
|
|
1477
|
+
base_resp = result.get("base_resp")
|
|
1478
|
+
if not isinstance(base_resp, Mapping) or base_resp.get("status_code") != 0:
|
|
1479
|
+
raise AdapterFailure(
|
|
1480
|
+
"MiniMax speech synthesis failed",
|
|
1481
|
+
code=_provider_code(result) or "generation_failed",
|
|
1482
|
+
request_id=_safe_token(result.get("trace_id")),
|
|
1483
|
+
)
|
|
1484
|
+
data = result.get("data")
|
|
1485
|
+
audio = data.get("audio") if isinstance(data, Mapping) else None
|
|
1486
|
+
if not isinstance(audio, str) or not audio:
|
|
1487
|
+
raise AdapterFailure(
|
|
1488
|
+
"MiniMax did not return audio data",
|
|
1489
|
+
code="missing_audio",
|
|
1490
|
+
request_id=_safe_token(result.get("trace_id")),
|
|
1491
|
+
)
|
|
1492
|
+
try:
|
|
1493
|
+
content = bytes.fromhex(audio)
|
|
1494
|
+
except ValueError as exc:
|
|
1495
|
+
raise AdapterFailure("MiniMax returned invalid audio data") from exc
|
|
1496
|
+
if not content:
|
|
1497
|
+
raise AdapterFailure("MiniMax returned empty audio data")
|
|
1498
|
+
trace_id = result.get("trace_id")
|
|
1499
|
+
return (
|
|
1500
|
+
_temporary_output(job, job["outputs"][0], content),
|
|
1501
|
+
trace_id if isinstance(trace_id, str) else None,
|
|
1502
|
+
)
|
|
1503
|
+
|
|
1504
|
+
|
|
1375
1505
|
def _run_minimax_video(job: Mapping[str, Any]) -> tuple[Path, str]:
|
|
1376
1506
|
token = _credential("MINIMAX_API_KEY")
|
|
1377
1507
|
base = _base_url("MINIMAX_VIDEO_BASE_URL", MINIMAX_VIDEO_BASE_URL)
|
|
@@ -1484,8 +1614,15 @@ def _selftest() -> None:
|
|
|
1484
1614
|
"modality": "music", "prompt": "cinematic", "references": [],
|
|
1485
1615
|
"outputs": ["制作成果/a.mp3"], "parameters": {"lyrics": "[Verse]\nHello"},
|
|
1486
1616
|
}
|
|
1617
|
+
speech = {
|
|
1618
|
+
"modality": "tts", "prompt": "你们做了多久?", "references": [],
|
|
1619
|
+
"outputs": ["制作成果/a.mp3"],
|
|
1620
|
+
"parameters": {"model": "configured-speech-model", "voice_id": "a-preset"},
|
|
1621
|
+
}
|
|
1487
1622
|
if compile_gpt_image_2_payload(image)["model"] != OPENAI_MODEL:
|
|
1488
1623
|
raise RuntimeError("GPT Image 2 self-test failed")
|
|
1624
|
+
if compile_minimax_speech_payload(speech)["voice_setting"]["voice_id"] != "a-preset":
|
|
1625
|
+
raise RuntimeError("MiniMax speech self-test failed")
|
|
1489
1626
|
seedance = compile_seedance_payload(
|
|
1490
1627
|
video,
|
|
1491
1628
|
model="configured-model",
|
|
@@ -1553,7 +1690,10 @@ def main() -> int:
|
|
|
1553
1690
|
parser.add_argument(
|
|
1554
1691
|
"provider",
|
|
1555
1692
|
nargs="?",
|
|
1556
|
-
choices=(
|
|
1693
|
+
choices=(
|
|
1694
|
+
"seedance", "gpt-image-2", "minimax-music", "minimax-h3",
|
|
1695
|
+
"minimax-speech",
|
|
1696
|
+
),
|
|
1557
1697
|
)
|
|
1558
1698
|
parser.add_argument("--selftest", action="store_true")
|
|
1559
1699
|
args = parser.parse_args()
|
|
@@ -1571,6 +1711,7 @@ def main() -> int:
|
|
|
1571
1711
|
"gpt-image-2": _run_openai,
|
|
1572
1712
|
"minimax-music": _run_minimax,
|
|
1573
1713
|
"minimax-h3": _run_minimax_video,
|
|
1714
|
+
"minimax-speech": _run_minimax_speech,
|
|
1574
1715
|
}
|
|
1575
1716
|
path, provider_job_id = runners[args.provider](job)
|
|
1576
1717
|
response: dict[str, Any] = {
|
|
@@ -71,9 +71,8 @@ license: MIT
|
|
|
71
71
|
- 剧本对白、动作、声音、画面文字是否都有画面/声音承载;
|
|
72
72
|
- 人物、地点、道具状态和镜头起止是否连续;
|
|
73
73
|
- 提示词是否从准确起点到准确终点;
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
[视觉运动审查表](references/rubric-visual-motion.md));
|
|
74
|
+
- 目标模型画音同轨时,声音内容、时序和发声边界是否与来源一致;无对白镜是否交代底声或静默
|
|
75
|
+
(`VID-22`、`VID-23`,见 [视觉运动审查表](references/rubric-visual-motion.md));
|
|
77
76
|
- 私有输入、凭据、绝对路径或内部流程文字是否泄漏。
|
|
78
77
|
|
|
79
78
|
缺少必要输入时只停止依赖它的判断,其他问题可以继续汇总。
|
|
@@ -71,25 +71,12 @@
|
|
|
71
71
|
- 角色名/资产引用进入台词内文;
|
|
72
72
|
- 音效、环境底噪与对白方向没有来源或相互遮蔽。
|
|
73
73
|
|
|
74
|
-
目标模型画音同轨时(`VID-23
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
**空形式本身就是合规写法**:`non_diegetic_music: N/A` 是「本镜没有非画内配乐」的正面陈述,
|
|
81
|
-
不是待填占位符。只有整行不存在时才报,永远不要要求 owner 删掉已经写好的空形式;
|
|
82
|
-
- 用排除句代替声轨描述:正文出现 `No dialogue`、`无对白` 而没有正面写出这条声轨由什么组成、
|
|
83
|
-
覆盖多长——问题在于正文没交代本镜该有什么声音,不在于"否定会招来它";
|
|
84
|
-
- 完整性声明枚举了本镜没有的层:无对白镜写出
|
|
85
|
-
`The audio timeline is complete after the listed ambience, effects and timed dialogue.`
|
|
86
|
-
是一句与本镜事实不符的话;
|
|
87
|
-
- 无对白镜从没说清声轨**是什么**:既没有覆盖全时长的底声构成,也没给在场人物一个可见的
|
|
88
|
-
不说话状态(嘴唇闭合)。
|
|
89
|
-
|
|
90
|
-
中间两条同时出现时按一个 finding 报,证据引这两句话本身:它们互相矛盾,本身就是声音契约
|
|
91
|
-
没写清。修订要求写成正面声轨,不能是"再加一句不要对白"。本套件实测未观察到这组写法导致
|
|
92
|
-
模型补出台词,报 finding 时不要这样断言。
|
|
74
|
+
目标模型画音同轨时(`VID-23`),检查声音内容、时序、发声边界是否符合来源,
|
|
75
|
+
总结是否错误地引入不存在的声音层。无对白镜也应交代需要的底声或静默。
|
|
76
|
+
H3 无非画内配乐时,`non_diegetic_music: N/A` 是有效的空形式。
|
|
77
|
+
|
|
78
|
+
按实际遗漏、矛盾与影响报告问题,不因出现 `No dialogue` 或第二个否定句判错,
|
|
79
|
+
不把 H3 的小样本表现套到所有同轨模型上。相关证据指向同一个问题时合并报告。
|
|
93
80
|
|
|
94
81
|
### 5. 负面补丁淹没动作
|
|
95
82
|
|
|
@@ -86,41 +86,15 @@
|
|
|
86
86
|
- Does each media reference state its exact purpose, what may be copied, and what
|
|
87
87
|
must not be copied, rather than treating all visible pixels as authority?
|
|
88
88
|
|
|
89
|
-
For a copyable body,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
rendered — did not reproduce in this suite's probes, so cite the body's own clarity,
|
|
99
|
-
not that mechanism, when you raise this.)
|
|
100
|
-
- When the target model generates audio in the same pass (`VID-23`), is the sound written
|
|
101
|
-
as a closed positive event set — what the track consists of, and across what span —
|
|
102
|
-
rather than a list of what must not be heard? Check three failures by name:
|
|
103
|
-
- an exclusion clause (`No dialogue`, `无对白`, `no music`) standing in for a positive
|
|
104
|
-
soundscape, so the body never says what this shot sounds like;
|
|
105
|
-
- a completeness declaration that enumerates a layer this shot does not have. "The audio
|
|
106
|
-
timeline is complete after the listed ambience, effects and timed dialogue" on a shot
|
|
107
|
-
with no lines states something untrue of this shot. Read the declaration against the
|
|
108
|
-
shot's actual layers, not against a template;
|
|
109
|
-
- a shot that leaves the non-diegetic music layer unstated. This is the one sound defect
|
|
110
|
-
with measured consequences: bodies that omitted the layer came back with an invented
|
|
111
|
-
score. **The dialect's empty form satisfies this** — for H3 that is the literal line
|
|
112
|
-
`non_diegetic_music: N/A`, which is a correct statement of "no non-diegetic music",
|
|
113
|
-
not a placeholder. Raise this only when the layer is missing from the body altogether;
|
|
114
|
-
never ask an owner to delete a present empty form;
|
|
115
|
-
- a shot with no lines whose body never says what the track *is* for the full duration,
|
|
116
|
-
and never gives the on-screen performers a visible non-speaking state.
|
|
117
|
-
Report a contradictory pair — an exclusion clause plus a declaration that enumerates the
|
|
118
|
-
excluded layer — as one finding against the body's sound contract, and quote both
|
|
119
|
-
sentences. Raise it as an internally inconsistent sound contract, which it is; do not
|
|
120
|
-
assert that it makes the model invent lines, which this suite has probed and not seen.
|
|
121
|
-
|
|
122
|
-
These two apply to a body the review itself is about to ask an owner to rewrite. A revision
|
|
123
|
-
request that removes a defect by adding `no ...` has moved the defect, not fixed it.
|
|
89
|
+
For a copyable body (`VID-22`, `VID-23`), check that actions and sound match the
|
|
90
|
+
source and that the timeline accounts for the intended ambience or silence.
|
|
91
|
+
A summary must not introduce a layer absent from the shot. H3's
|
|
92
|
+
`non_diegetic_music: N/A` is a valid empty music layer.
|
|
93
|
+
|
|
94
|
+
Report a concrete contradiction, omission or ambiguity. A negative clause is
|
|
95
|
+
not a defect by itself; do not impose a clause count or assume that negation
|
|
96
|
+
causes the model to generate the excluded content. Keep model-specific
|
|
97
|
+
observations scoped to their tested model and execution path.
|
|
124
98
|
|
|
125
99
|
For a pickup or alternate, ask these separately:
|
|
126
100
|
|
|
@@ -7,7 +7,8 @@ license: MIT
|
|
|
7
7
|
# 短剧分镜与冻结关键帧
|
|
8
8
|
|
|
9
9
|
把剧本和视觉事实转成有镜头职责、空间连续性和可冻结起点的 `剧集/<EP>/分镜.md`。
|
|
10
|
-
每镜使用二级标题 `## SHOT-...`,同镜下用 `### 冻结关键帧提示词`
|
|
10
|
+
每镜使用二级标题 `## SHOT-...`,同镜下用 `### 冻结关键帧提示词` 写起始帧正文;
|
|
11
|
+
需要时另加 `### 收尾关键帧提示词` 写终点正文。
|
|
11
12
|
|
|
12
13
|
## Quick Start
|
|
13
14
|
|
|
@@ -53,6 +54,9 @@ license: MIT
|
|
|
53
54
|
末尾反应;把估时依据简写在本镜「声音」里。具体做法见 [对白估时](references/shot-craft.md#对白估时)。
|
|
54
55
|
4. 锁定人物朝向、位置、视线、持物、出入口、屏幕方向和必要状态;上游已有会限制动作空间的持续关系时,把关系投影进本镜起点与终点。
|
|
55
56
|
5. 冻结关键帧只投影镜头起点;删除终点才出现的文字、动作、姿态或道具状态。
|
|
57
|
+
镜头的职责落在收尾那一下时,另写 `### 收尾关键帧提示词` 投影**终点**——同一格画面的
|
|
58
|
+
另一端,规则完全对称:删除起点才有、终点已经不在的东西。它是可选的,写法与取舍见
|
|
59
|
+
[首尾成对](references/shot-craft.md#首尾成对)。
|
|
56
60
|
6. 关键帧成稿后,先从成稿正文读出这一格里需要保持身份、造型或地理的人物、地点和道具,
|
|
57
61
|
再用同一份清单一次填满三条依据:
|
|
58
62
|
|
|
@@ -71,11 +75,10 @@ license: MIT
|
|
|
71
75
|
|
|
72
76
|
- 每镜有唯一职责、明确来源、可见起止状态和合理时长。「来源」以《剧本.md》里真实存在的场景 ID 开头,
|
|
73
77
|
ID 之后可以跟必要短引文,跨场次的镜头用 `、` 连写多条;`creator_markdown_check.py` 会核对每个 ID 都解析得到。
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
确实看不见就在「视觉依据」末尾写 `;画外:<类别>「<名称>」`,机械核对认这个写法。
|
|
78
|
+
- 「来源」短引文应对应本镜承担的动作或声音。正文提到画外人物时,可在视觉依据写
|
|
79
|
+
`;画外:<类别>「<名称>」`;这只声明其不在画面,不能代替必要动作的落实。
|
|
80
|
+
需要看见的动作应另有镜头承载,或说明为何省略。
|
|
81
|
+
|
|
79
82
|
- 剧本里的每个场景都要有镜头承载。确实决定不拍某一场时,在《分镜.md》正文开头写一行
|
|
80
83
|
`- 未拍场次:<场景 ID>(理由:……)`,多项用 `;` 连接。SHT-01 一直允许带理由的省略,
|
|
81
84
|
但省略和漏拍在成稿文档里长得一模一样,所以理由要写下来,而不是留在对话里。
|
|
@@ -145,6 +148,7 @@ license: MIT
|
|
|
145
148
|
- 关键场次比较导演方案:[场次视觉计划](references/scene-visual-plan.md)
|
|
146
149
|
- 检查原文是否都有画面承载:[Coverage Audition](references/coverage-audition.md)
|
|
147
150
|
- 多人、群体和复杂空间调度:[调度手册](references/blocking-playbooks.md)
|
|
151
|
+
- 谁被照亮、怎么写才执行得出:[光的设计](references/lighting-craft.md)
|
|
148
152
|
- 冻结瞬间、注意中心和可读性:[关键帧手艺](references/keyframe-craft.md)
|
|
149
153
|
- 漫剧/二维漫画形态的共享画风词汇:[漫剧关键帧词表](references/comic-keyframe-lexicon.md)
|
|
150
154
|
- 剧本事实到关键帧的完整示例:[剧本到关键帧](references/screenplay-to-keyframe-example.md)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# 光的设计
|
|
2
|
+
|
|
3
|
+
## 分工
|
|
4
|
+
|
|
5
|
+
- 《视觉设定.md》的地点条目记录光源、窗户位置和已经确定的光线状态。
|
|
6
|
+
- 分镜选择本镜的注意中心,说明哪些脸、动作或证据必须可读。
|
|
7
|
+
- 提示词把这些选择写成可观察的画面结果。
|
|
8
|
+
|
|
9
|
+
开灯、停电和时段变化会改变场景事实,应来自剧本或已接受的视觉设定。
|
|
10
|
+
|
|
11
|
+
## 按镜头职责设计
|
|
12
|
+
|
|
13
|
+
先确定观众需要看清什么,再选择亮暗关系、光比与背景分离程度。
|
|
14
|
+
需要读表情时保留相关面部细节;需要隐藏身份时可以用剪影或遮暗。
|
|
15
|
+
关注点可以靠亮度、色彩、轮廓或局部对比突出,不要求它总是全画面最亮的部分。
|
|
16
|
+
|
|
17
|
+
竖屏按实际构图检查人物与背景是否分得开。近景中的脸部光线、多人纵深中的背景光,
|
|
18
|
+
各自承担不同信息;不要仅按画幅省略环境或默认加轮廓光。
|
|
19
|
+
|
|
20
|
+
## 把光位与画面效果一起写清
|
|
21
|
+
|
|
22
|
+
光位术语后补充它在画面上的结果,并明确左右指画面还是人物自身。例如:
|
|
23
|
+
|
|
24
|
+
> 主光来自画面左侧;画面左侧脸颊较亮,另一侧留柔和阴影,眼睛仍可辨认。
|
|
25
|
+
|
|
26
|
+
仅写「电影感、氛围感强」不足以决定画面。一次图片模型对照中,描述受光结果比只写
|
|
27
|
+
光位更稳定;这可以作为起步写法,不能据此保证其他模型或视频同样执行。
|
|
28
|
+
暗部深度、边缘亮光和背景亮度按本镜需要写,不把例子中的效果全部照搬。
|
|
29
|
+
|
|
30
|
+
## 参考板与跨镜连续性
|
|
31
|
+
|
|
32
|
+
参考板的均匀照明用于看清形制,不自动成为每个镜头的打光方案。
|
|
33
|
+
绑定角色板时说明保留身份与造型;本镜的光仍依据场景事实。
|
|
34
|
+
|
|
35
|
+
同一连续场景维持光源关系与既定色调;视角、取景范围和人物位置变化可以带来正常的
|
|
36
|
+
画面亮度差异。不要要求所有镜头的平均 RGB 相同。
|
|
37
|
+
|
|
38
|
+
生成后对比相邻镜头中可比较的脸、衣物或场景表面。曝光和白平衡的小幅偏差交给剪辑
|
|
39
|
+
校正;光源方向或剧情光态错误回上游修订。测量用于定位差异,是否有问题仍结合画面判断。
|
|
@@ -14,8 +14,12 @@
|
|
|
14
14
|
3. [场面调度与地理](#场面调度与地理)
|
|
15
15
|
4. [景别与摄影机动机](#景别与摄影机动机)
|
|
16
16
|
5. [时长与切镜](#时长与切镜)
|
|
17
|
-
6. [
|
|
18
|
-
7. [
|
|
17
|
+
6. [视觉方向选择](#视觉方向选择-sht-07)
|
|
18
|
+
7. [相连边界](#相连边界-con-01)
|
|
19
|
+
8. [首尾成对](#首尾成对)
|
|
20
|
+
9. [一镜到底还是切开](#一镜到底还是切开)
|
|
21
|
+
10. [常见问题](#常见问题)
|
|
22
|
+
11. [审查问题](#审查问题)
|
|
19
23
|
|
|
20
24
|
## 先落实原文,再追求画面
|
|
21
25
|
|
|
@@ -65,26 +69,13 @@
|
|
|
65
69
|
镜头可以负责建立空间、让观众站到某个人物一边、展示证据、暂缓信息、转移权力、
|
|
66
70
|
表现反应,或让后果无法回避。“中景展示人物说话”不算足够的镜头目的。
|
|
67
71
|
|
|
68
|
-
###
|
|
72
|
+
### 承受者的反应
|
|
69
73
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
爽点不成立。**分镜阶段就要决定谁承受这一下、哪一镜给他**,不要留给剪辑去补,
|
|
76
|
-
因为剪辑只能在已经生成的素材里选,选不出一个没拍过的反应。
|
|
77
|
-
|
|
78
|
-
具体到写法:
|
|
79
|
-
|
|
80
|
-
- 台词落点是针对某个在场的人时,检查分镜里有没有一镜的画面主体是**那个人**;
|
|
81
|
-
- 没有就补一镜,通常很短(一到两秒足够:停手、抬眼、想开口又闭嘴);
|
|
82
|
-
- 承受者不在场时,那一下的后果要落到别的可见东西上(屏幕、门、被推开的文件),
|
|
83
|
-
否则这次打击在画面上没有发生过;
|
|
84
|
-
- 群像镜头**不算**承受者反应:一张在四个人里的脸承担不了「他输了」这件事。
|
|
85
|
-
|
|
86
|
-
**这条只在剧情确实存在承受者时生效。** 不为每句台词配反应镜头,也不把它变成正反打配额——
|
|
87
|
-
安静的场次、独角戏、纯信息交代不适用。
|
|
74
|
+
**`SHT-27 · reviewed_invariant`**:打击、否定或翻盘需要观众理解其后果时,
|
|
75
|
+
分镜应安排可读的承受者反应或其他后果载体。
|
|
76
|
+
可以用独立反应镜、双人镜内的调度、清楚的群像反应、声音或物件状态承载。
|
|
77
|
+
现有画面已经清楚就不必补镜;需要保留反应或承受者不在场时,注明叙事安排。
|
|
78
|
+
审查按后果能否被理解判断,不按人数、景别或反应镜数量判断。
|
|
88
79
|
|
|
89
80
|
### 观众可见性 (`SHT-12`)
|
|
90
81
|
|
|
@@ -145,6 +136,22 @@
|
|
|
145
136
|
要观众读到什么反而没人回答。判断标准始终是必须被读到的信息存在于哪个尺度——证据在
|
|
146
137
|
指节上就给大特写,后果在两人距离上就不该切近。
|
|
147
138
|
|
|
139
|
+
### 竖屏把可用的景别收窄了
|
|
140
|
+
|
|
141
|
+
上面那张表是横平竖直的电影景别谱系。**竖屏不是把它裁窄,是让其中两档变得难用**。
|
|
142
|
+
|
|
143
|
+
机制很简单:远景和全景靠的是**横向铺开的信息**——谁站在谁旁边、队伍有多长、这个人
|
|
144
|
+
离出口有多远。9:16 的横向只有 16:9 的三分之一强,同样的信息铺进去要么挤成一条,
|
|
145
|
+
要么小到读不出。所以竖屏短剧的实际用法以中景、近景、特写为主,远景与全景出现得少。
|
|
146
|
+
|
|
147
|
+
但这**不是禁令,是换一种排法**:竖屏的空间要靠**纵深**而不是横向来交代——前景、中景、
|
|
148
|
+
后景分层,用门框、桌沿、台阶、人的前后遮挡把关系立起来(见
|
|
149
|
+
[竖屏多人调度](blocking-playbooks.md#1-竖屏多人调度))。做到了这一点,竖屏一样能给全景;
|
|
150
|
+
做不到就不要用这一档去承担交代空间的职责,改用一个更近的镜头单独给一次。
|
|
151
|
+
|
|
152
|
+
**竖屏的横向视野窄,观众的视线本来就被逼到画面中央**,这既是小景别好用的原因,
|
|
153
|
+
也是大景别失效的原因——同一件事的两面。
|
|
154
|
+
|
|
148
155
|
只有注意或关系发生变化时才改变景别和角度。场面声音变大,不等于镜头必须从全景一路
|
|
149
156
|
推到大特写。反过来,一旦决定切镜,新镜就要在景别、角度或人物关系里至少改变一项;
|
|
150
157
|
相邻两镜完全同景别、同角度、同关系时,这次切镜没有职责,应当改变收放或并回一镜。
|
|
@@ -227,3 +234,33 @@
|
|
|
227
234
|
- 是否绑定了准确的造型、观察视角、道具状态、双手状态和文字政策?
|
|
228
235
|
- 结束边界是否为下一镜提供清楚的开始状态?
|
|
229
236
|
- 删除或合并本镜,会不会丢失故事意义?
|
|
237
|
+
|
|
238
|
+
## 首尾成对
|
|
239
|
+
|
|
240
|
+
终点的可见状态对本镜重要,且目标模型支持尾帧时,可以补写
|
|
241
|
+
`### 收尾关键帧提示词`。它只描述终点,不混入起点或中间动作。
|
|
242
|
+
若起终状态相同,或变化发生在画外,通常无需另做尾帧。
|
|
243
|
+
|
|
244
|
+
Seedance 2.5 的一个镜头对照中,绑定尾帧改善了末帧落位;这不是所有模型和动作的保证。
|
|
245
|
+
生成后仍检查中间动作、节奏和终点,不能只比较最后一帧。
|
|
246
|
+
|
|
247
|
+
当前生产工具从 `分镜.md` 的 `SHOT-...` 只提取「冻结关键帧提示词」,即首帧。
|
|
248
|
+
要在套件内生产尾帧,交图片提示词阶段建立单独的 `IMG-...` 条目,注明来自本 SHOT 的
|
|
249
|
+
终点、保留已确认的视觉依据,再以该条目作为 image job 的来源。不得用首帧选择器提交尾帧正文。
|
|
250
|
+
实际图片生成后按目标方言绑定 `用途:结束帧`。
|
|
251
|
+
|
|
252
|
+
## 一镜到底还是切开
|
|
253
|
+
|
|
254
|
+
先看这场戏需要什么,再考虑生成与修订成本。
|
|
255
|
+
|
|
256
|
+
- 连续等待、沉默、空间调度或完整表演,可考虑一镜到底。
|
|
257
|
+
- 需要选择不同表演、突出反应或精确安排切点,可考虑分开生成再剪。
|
|
258
|
+
- 长段生成一处失败可能需要重出更多素材;分开生成则需要额外处理跨镜一致性。
|
|
259
|
+
|
|
260
|
+
一次 Seedance 2.5 对白场次实测出现过长镜头发声时间过早的问题。
|
|
261
|
+
有严格落点时应检查目标模型的时序能力并试听,不能保证分成镜头就能锁定每句发声时间。
|
|
262
|
+
长镜头也可以在剪辑中截取,是否保留完整时长由叙事决定。
|
|
263
|
+
|
|
264
|
+
多镜容器是在一次生成里安排多个切口;一镜到底则不切镜。
|
|
265
|
+
容器可减少提交次数,但不自动保证跨镜一致性,也仍可在生成后剪辑。
|
|
266
|
+
各镜合并时重新整理参考素材与编号,并核对结果中的实际切点。
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
| SHT-24 | reviewed_invariant | A visual basis describes this frame, not the episode's cast list. Each declared 控制 scope stays within what this frame can carry, and a binding is not carried forward merely because the subject remains in the scene. |
|
|
39
39
|
| SHT-25 | structural_invariant | Every real reference image a shot binds declares one 用途 from the closed set 身份/造型状态/地理/构图/尺度/效果/起始帧/结束帧/风格, so the shot can say which start frame and which identity/geography/prop pictures a downstream job sends. At most one 起始帧 and one 结束帧 per shot, and 结束帧 requires 起始帧. |
|
|
40
40
|
| SHT-26 | structural_invariant | A shot's 来源 is its claim on the screenplay: whatever it quotes, this shot is the one that films it. Every 视觉设定 entry the quote calls by name is therefore either in this shot's 视觉依据 or declared 画外 there. Quoting an action performed by someone the frame never shows takes that action off every list — no other shot claims it and nothing reports it missing, so it simply never gets filmed, and the gap only surfaces when a person watches the finished film. The check matches entry names rather than 画面代称, because a 来源 quote comes from 剧本.md; an entry that opted out with `画面代称:无` stays out of this check too. |
|
|
41
|
-
| SHT-27 | reviewed_invariant | When a beat
|
|
41
|
+
| SHT-27 | reviewed_invariant | When understanding a beat requires seeing its effect on a character, provide a readable reaction or consequence. A separate shot, staging within a shared shot, sound, or an object may carry it. Judge legibility against the intended reveal; do not require a shot count or exclude group shots by default. |
|
|
42
42
|
|
|
43
43
|
### `CON`
|
|
44
44
|
|
|
@@ -81,17 +81,18 @@ license: MIT
|
|
|
81
81
|
8. 写“静态锚点 → 起点 → 唯一动作(触发、接触、落点)→ 次级反应 → 运镜 → 声音 → 终点”,
|
|
82
82
|
必要时用秒数分段;下一镜从这个终点继续,不另造镜外转换。
|
|
83
83
|
9. 只在真实参考帧已经说明静态外观时删除重复描述;《视觉设定.md》连续性锁的锁面不在可删之列。
|
|
84
|
-
10.
|
|
84
|
+
10. 把限制动作空间的已确认关系写成贯穿本镜的正向可见状态,只安排关系允许的动作通道;只有分镜明确改变关系时才写变化过程。优先用可见状态说明边界,必要时保留明确的排除条件。
|
|
85
85
|
11. 逐镜读取文字义务。除非剧本或创作者明确要求,正文用本镜已解析的视频提示词语言直接写明任何时刻都不生成非画内字幕、caption 和对白文字叠加,不能只写抽象的“文字层为空”;这条默认与旗帜、标牌、屏幕等画内文字独立。画内 `exact_readable` 逐字写明字符、语言、承载面和位置,不能用全局 `no-text` 覆盖。
|
|
86
86
|
12. 声音同轨时,把允许的发声按来源、说话人、口语语言和顺序写成完整时间线;每句从原文首字到末字,
|
|
87
87
|
且逐字对白在单镜可复制正文中只出现一次。视觉动作段只按时间和说话人引用该声音事件,不再抄一遍
|
|
88
88
|
台词。事件外回到已声明的环境声或静默。Brief、剧本或声音方向已经明确禁止外语前导、语气词、
|
|
89
89
|
额外人声或重复时,把这些**已确认的发声边界**在完整时间线末尾合并写一次;不靠“只包含”让执行端
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
猜,也不自行扩充新的禁用类别。时间线总结只列本镜实际有的声音层。
|
|
91
|
+
无对白镜写清底声或静默及其覆盖区间;嘴部动作按剧本表演,不默认强制闭嘴。
|
|
92
|
+
非画内配乐按目标方言声明,有需要时明确写空。
|
|
93
|
+
13. 成稿时检查动作、声音和限制条件是否清楚且相容。正面状态有助于表达目标,必要的否定条件
|
|
94
|
+
可以保留;不按否定句数量判错。确认不跨下一镜、不要求互斥动作、不让人物或道具瞬移变形。
|
|
95
|
+
|
|
95
96
|
14. 用户要整集就完成整集,镜头组只是内部批次。
|
|
96
97
|
15. 同一连续时空中相邻正式生成段、且目标档案支持续接时,默认选择“从上一段生成结果续接”;
|
|
97
98
|
一镜一生成只决定每次装一个镜头,不等于各镜独立文生。只有创作者明确要求独立重生成,或上游
|
|
@@ -112,12 +113,12 @@ license: MIT
|
|
|
112
113
|
- 运镜与人物动作不争夺注意力;复杂运镜必须有叙事理由。
|
|
113
114
|
- 声音只写该镜需要的对白、画外音、环境或转场职责,不擅自补歌词。
|
|
114
115
|
- 非画内字幕、caption 和对白文字叠加默认不生成;正文直接声明全镜任何时刻都不生成这些内容,不用抽象工作流术语代替执行指令。只有剧本或创作者明确要求才开启。画内精确文字是独立允许集合,不因关闭字幕而消失,也不让未批准文字混入。
|
|
115
|
-
- 同轨对白/VO/OS
|
|
116
|
-
-
|
|
116
|
+
- 同轨对白/VO/OS 同时写逐字文本、口语语言和发声边界;不添加来源没有的声源或重复限制。
|
|
117
|
+
- 无对白镜同样说明底声或静默;时间线总结与实际声音层一致。H3 无非画内配乐时写 `non_diegetic_music: N/A`。
|
|
117
118
|
- 正文里被引号或 `<d>` 包起来的中文必须逐字来自《剧本.md》,画内标牌文字可来自《视觉设定.md》;
|
|
118
119
|
分镜自己写下的画内文字与声音同样算数。`creator_markdown_check.py` 会核对四字以上的引文(VID-25)。
|
|
119
120
|
台词不在剧本里就回到写作技能改剧本,不在提示词里改。
|
|
120
|
-
-
|
|
121
|
+
- 上游持续关系用贯穿状态和允许动作通道表达,避免重复限制或冲突动作。
|
|
121
122
|
- 本镜命中的连续性锁,锁面原样出现在可复制正文里;颜色、材质、形制这类跨镜不变事实不靠模型记忆。
|
|
122
123
|
- 正文可直接复制,不含占位符、流程说明、文件路径或 QA 结论。
|
|
123
124
|
|
|
@@ -80,6 +80,23 @@ Camera behavior 要回答“观众注意为什么在此刻改变”。常见动
|
|
|
80
80
|
|
|
81
81
|
这里不是同时 lock 和 move。若 transition 改变 shot 已接受的 camera design,仍需 storyboard 同意。
|
|
82
82
|
|
|
83
|
+
### 摄影机与主体的相对运动
|
|
84
|
+
|
|
85
|
+
主体快跑与摄影机缓推可以同时成立,关键是写清两者的相对关系与画面结果。
|
|
86
|
+
需要跟随时说明跟随方向和构图;需要人物离开画面时,保留缓推或固定机位也可以。
|
|
87
|
+
不能为了消除速度差异而改写上游已确定的运镜。
|
|
88
|
+
|
|
89
|
+
### 运动说明
|
|
90
|
+
|
|
91
|
+
按本镜需要说明运动方式、方向、速度或触发时机、终点以及要保持的空间关系。
|
|
92
|
+
与上一节的起点和落点一起核对,不要求每次恰好四项。
|
|
93
|
+
|
|
94
|
+
### 运镜术语属于方言
|
|
95
|
+
|
|
96
|
+
推轨、变焦、摇、甩、升降这些词在不同目标模型里的解析并不一致——有的模型的官方指南
|
|
97
|
+
推荐 `push in` 而完全不收录 `dolly in`。**不要把一个模型上验证过的运镜词表照搬到另一个
|
|
98
|
+
模型的正文里**;术语与写法以目标模型的方言文档为准,方言里没有记载的词按未验证对待。
|
|
99
|
+
|
|
83
100
|
### 非冲突但可能过载
|
|
84
101
|
|
|
85
102
|
pan 同时微调焦点、handheld 带自然呼吸、dolly 配合轻微 tilt 未必矛盾;是否太复杂由 reviewer 结合 purpose 判断,不能靠 camera 动词计数硬挡。
|