@oh-story/dsh 0.1.9 → 0.1.11
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 +14 -14
- package/lib/client.js +209 -73
- package/lib/client.js.map +3 -3
- package/lib/drama/manifest.json +248 -168
- package/lib/drama/skills/short-drama/SKILL.md +16 -4
- package/lib/drama/skills/short-drama/assets/project-template/short-drama.json +3 -0
- package/lib/drama/skills/short-drama/references/creator-documents.md +3 -0
- package/lib/drama/skills/short-drama/references/knowhow-index.md +15 -0
- package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +14 -0
- package/lib/drama/skills/short-drama/scripts/project_tool.py +131 -0
- package/lib/drama/skills/short-drama-assets/SKILL.md +2 -1
- package/lib/drama/skills/short-drama-assets/references/asset-review-checklist.md +2 -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/era-anchors.md +37 -0
- package/lib/drama/skills/short-drama-assets/references/stage-contract.md +2 -0
- package/lib/drama/skills/short-drama-assets/references/voice-direction.md +28 -0
- package/lib/drama/skills/short-drama-develop/SKILL.md +10 -4
- package/lib/drama/skills/short-drama-develop/assets/adaptation-map.example.jsonl +1 -1
- package/lib/drama/skills/short-drama-develop/assets/creative-brief.md +8 -0
- package/lib/drama/skills/short-drama-develop/references/adaptation-craft.md +80 -13
- package/lib/drama/skills/short-drama-develop/references/episode-design.md +95 -12
- package/lib/drama/skills/short-drama-develop/references/genre-and-hook-playbook.md +9 -5
- package/lib/drama/skills/short-drama-develop/references/genre-cards//345/244/215/344/273/207/346/211/223/350/204/270.md +1 -1
- package/lib/drama/skills/short-drama-develop/references/genre-cards//347/263/273/347/273/237/346/265/201.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//351/200/206/350/242/255.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards//351/207/215/347/224/237/347/251/277/350/266/212.md +51 -0
- package/lib/drama/skills/short-drama-develop/references/genre-cards.md +10 -7
- package/lib/drama/skills/short-drama-develop/references/premise-devices.md +15 -9
- package/lib/drama/skills/short-drama-develop/references/serial-character-and-memory.md +3 -2
- package/lib/drama/skills/short-drama-develop/references/stage-contract.md +14 -7
- package/lib/drama/skills/short-drama-develop/references/story-craft.md +7 -3
- package/lib/drama/skills/short-drama-edit/SKILL.md +65 -44
- package/lib/drama/skills/short-drama-edit/assets/remotion/README.md +49 -13
- package/lib/drama/skills/short-drama-edit/assets/remotion/package.json +4 -2
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/Overlay.tsx +31 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/Root.tsx +5 -5
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/Subtitles.tsx +68 -69
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/font.ts +39 -29
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/rules.mjs +188 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/schema.ts +26 -13
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/Card.tsx +72 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/CornerChip.tsx +39 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/ScreenText.tsx +36 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/SystemPanel.tsx +44 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/TaskPanel.tsx +100 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/chrome.tsx +197 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/screen/tokens.ts +62 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/tsconfig.json +1 -0
- package/lib/drama/skills/short-drama-edit/assets//345/211/252/350/276/221/345/215/225.md +6 -4
- package/lib/drama/skills/short-drama-edit/references/cut-craft.md +26 -67
- package/lib/drama/skills/short-drama-edit/references/delivery-verify.md +31 -56
- package/lib/drama/skills/short-drama-edit/references/generated-footage.md +42 -78
- package/lib/drama/skills/short-drama-edit/references/sound-and-subtitles.md +44 -92
- package/lib/drama/skills/short-drama-edit/references/stage-contract.md +14 -16
- package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +1272 -125
- package/lib/drama/skills/short-drama-edit/scripts/selftest.py +113 -9
- 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-novel-analyze/SKILL.md +3 -3
- package/lib/drama/skills/short-drama-novel-analyze/assets/episode-candidate.example.jsonl +2 -2
- package/lib/drama/skills/short-drama-novel-analyze/references/adaptation-triage.md +8 -4
- package/lib/drama/skills/short-drama-novel-analyze/references/adaptation-value.md +10 -3
- package/lib/drama/skills/short-drama-novel-analyze/references/aggregation-and-entities.md +25 -1
- package/lib/drama/skills/short-drama-novel-analyze/references/stage-contract.md +1 -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 +4 -5
- package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +6 -19
- package/lib/drama/skills/short-drama-review/references/review-method.md +6 -1
- package/lib/drama/skills/short-drama-review/references/rubric-assets-prompts.md +11 -0
- package/lib/drama/skills/short-drama-review/references/rubric-story-script.md +77 -3
- package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +24 -35
- package/lib/drama/skills/short-drama-review/references/stage-contract.md +3 -0
- package/lib/drama/skills/short-drama-storyboard/SKILL.md +23 -11
- package/lib/drama/skills/short-drama-storyboard/references/blocking-playbooks.md +1 -1
- package/lib/drama/skills/short-drama-storyboard/references/lighting-craft.md +39 -0
- package/lib/drama/skills/short-drama-storyboard/references/production-shot-grammar.md +2 -2
- package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +139 -34
- package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +5 -3
- package/lib/drama/skills/short-drama-video-prompts/SKILL.md +15 -12
- package/lib/drama/skills/short-drama-video-prompts/references/camera-audio-continuity.md +29 -0
- package/lib/drama/skills/short-drama-video-prompts/references/delivery-profile.md +4 -5
- package/lib/drama/skills/short-drama-video-prompts/references/generability.md +4 -2
- package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +52 -39
- package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +24 -21
- package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +9 -23
- package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +14 -26
- package/lib/drama/skills/short-drama-video-prompts/references/review-and-fixtures.md +1 -1
- 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 +3 -2
- package/lib/drama/skills/short-drama-video-prompts/references/target-model-profile.md +8 -1
- package/lib/drama/skills/short-drama-video-prompts/references/wan-3.0.md +103 -0
- package/lib/drama/skills/short-drama-video-prompts/scripts/motion_timing_check.py +8 -7
- package/lib/drama/skills/short-drama-write/SKILL.md +10 -7
- package/lib/drama/skills/short-drama-write/references/dialogue-craft.md +1 -1
- package/lib/drama/skills/short-drama-write/references/script-craft.md +56 -3
- package/lib/drama/skills/short-drama-write/references/stage-contract.md +4 -0
- package/lib/drama/skills/short-drama-write/scripts/duration_estimate.py +48 -2
- package/lib/index.js +346 -98
- 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 +607 -327
- package/lib/oh-story/roles/chapter-extractor.md +177 -237
- package/lib/oh-story/roles/character-designer.md +1 -2
- package/lib/oh-story/roles/consistency-checker.md +15 -13
- package/lib/oh-story/roles/narrative-writer.md +36 -38
- package/lib/oh-story/roles/story-architect.md +9 -61
- package/lib/oh-story/roles/story-explorer.md +20 -125
- package/lib/oh-story/roles/story-researcher.md +0 -1
- package/lib/oh-story/skills/story/SKILL.md +15 -9
- package/lib/oh-story/skills/story/VERSION +1 -1
- package/lib/oh-story/skills/story/references/author-memory-maintenance.md +75 -0
- package/lib/oh-story/skills/story/references/author-memory.md +46 -94
- 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 +59 -73
- package/lib/oh-story/skills/story-deslop/references/agent-calls.md +5 -0
- package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +12 -11
- package/lib/oh-story/skills/story-deslop/references/author-memory-maintenance.md +75 -0
- package/lib/oh-story/skills/story-deslop/references/author-memory.md +46 -94
- package/lib/oh-story/skills/story-deslop/references/banned-words.md +2 -2
- package/lib/oh-story/skills/story-deslop/references/deslop-gates.md +22 -5
- package/lib/oh-story/skills/story-deslop/references/style-resolution.md +4 -4
- package/lib/oh-story/skills/story-deslop/scripts/author_memory_commit.py +934 -170
- package/lib/oh-story/skills/story-deslop/scripts/check-ai-patterns.js +155 -8
- package/lib/oh-story/skills/story-import/SKILL.md +64 -584
- package/lib/oh-story/skills/story-import/references/character-state-reverse.md +1 -1
- package/lib/oh-story/skills/story-import/references/deep-analysis.md +47 -0
- package/lib/oh-story/skills/story-import/references/format-and-structure.md +1 -1
- package/lib/oh-story/skills/story-import/references/import-report.md +64 -0
- package/lib/oh-story/skills/story-import/references/import-special-cases.md +34 -0
- package/lib/oh-story/skills/story-import/references/import-tracking.md +95 -0
- package/lib/oh-story/skills/story-import/references/length-routing.md +1 -1
- package/lib/oh-story/skills/story-import/references/outline-reverse-rules.md +79 -0
- package/lib/oh-story/skills/story-import/references/outline-reverse.md +24 -0
- 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 +98 -92
- package/lib/oh-story/skills/story-import/references/structure-mapping-short.md +24 -12
- package/lib/oh-story/skills/story-import/references/tracking-initialization.md +1 -1
- package/lib/oh-story/skills/story-import/references/tracking-transaction.md +15 -11
- package/lib/oh-story/skills/story-import/scripts/build_outline_brief.py +332 -0
- package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +132 -27
- package/lib/oh-story/skills/story-import/scripts/tracking_commit.py +478 -15
- package/lib/oh-story/skills/story-import/scripts/wordcount_core.py +182 -23
- package/lib/oh-story/skills/story-long-analyze/SKILL.md +81 -270
- package/lib/oh-story/skills/story-long-analyze/references/author-facing.md +252 -0
- package/lib/oh-story/skills/story-long-analyze/references/deconstruction-notes.md +3 -3
- package/lib/oh-story/skills/story-long-analyze/references/final-checks.md +19 -0
- package/lib/oh-story/skills/story-long-analyze/references/index-rebuild.md +11 -0
- package/lib/oh-story/skills/story-long-analyze/references/inspiration-library.md +105 -0
- package/lib/oh-story/skills/story-long-analyze/references/pipeline-ops.md +138 -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/stage1-golden-chapters.md +128 -0
- package/lib/oh-story/skills/story-long-analyze/references/stage2-extraction.md +229 -0
- package/lib/oh-story/skills/story-long-analyze/references/stage3-plot-rhythm.md +480 -0
- package/lib/oh-story/skills/story-long-analyze/references/stage4-characters-settings.md +195 -0
- package/lib/oh-story/skills/story-long-analyze/references/stage5-report.md +33 -0
- package/lib/oh-story/skills/story-long-analyze/references/style-profile-generator.md +55 -128
- package/lib/oh-story/skills/story-long-analyze/references/style-profile-protocol.md +6 -6
- package/lib/oh-story/skills/story-long-analyze/references/synthesis-inputs.md +39 -0
- 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 +1145 -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 +45 -194
- package/lib/oh-story/skills/story-long-scan/references/platform-ciweimao.md +19 -0
- package/lib/oh-story/skills/story-long-scan/references/platform-fanqie.md +45 -0
- package/lib/oh-story/skills/story-long-scan/references/platform-jjwxc.md +28 -0
- package/lib/oh-story/skills/story-long-scan/references/platform-qidian.md +35 -0
- package/lib/oh-story/skills/story-long-scan/references/platform-qimao.md +27 -0
- package/lib/oh-story/skills/story-long-scan/references/topic-decision.md +6 -2
- package/lib/oh-story/skills/story-long-write/SKILL.md +49 -81
- package/lib/oh-story/skills/story-long-write/references/agent-calls.md +47 -0
- package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +12 -11
- package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +24 -202
- package/lib/oh-story/skills/story-long-write/references/author-memory-maintenance.md +75 -0
- package/lib/oh-story/skills/story-long-write/references/author-memory.md +46 -94
- package/lib/oh-story/skills/story-long-write/references/banned-words.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/benchmark-recall.md +7 -11
- package/lib/oh-story/skills/story-long-write/references/character-relations.md +49 -1
- package/lib/oh-story/skills/story-long-write/references/cross-book-recall.md +26 -0
- package/lib/oh-story/skills/story-long-write/references/deslop-gates.md +171 -0
- package/lib/oh-story/skills/story-long-write/references/dialogue-mastery.md +4 -0
- package/lib/oh-story/skills/story-long-write/references/emotion-on-page.md +116 -0
- package/lib/oh-story/skills/story-long-write/references/emotional-arc-design.md +1 -114
- package/lib/oh-story/skills/story-long-write/references/emotional-methods.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/genre-prose-cards.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/long-chapter-quality.md +7 -15
- package/lib/oh-story/skills/story-long-write/references/long-format.md +0 -8
- package/lib/oh-story/skills/story-long-write/references/long-genre-catalog.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/long-genre-mechanics.md +3 -3
- package/lib/oh-story/skills/story-long-write/references/opening-design.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/outline-conflict.md +4 -4
- package/lib/oh-story/skills/story-long-write/references/outline-methods.md +7 -7
- package/lib/oh-story/skills/story-long-write/references/outline-rhythm.md +3 -3
- package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +14 -69
- package/lib/oh-story/skills/story-long-write/references/plot-frameworks.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/plot-special-topics.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/project-files.md +19 -13
- package/lib/oh-story/skills/story-long-write/references/reader-contract-and-progression.md +13 -5
- package/lib/oh-story/skills/story-long-write/references/reference-index.md +5 -6
- package/lib/oh-story/skills/story-long-write/references/stop-and-fix.md +9 -0
- package/lib/oh-story/skills/story-long-write/references/style-combat-face.md +1 -58
- package/lib/oh-story/skills/story-long-write/references/style-genre-modules.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/style-resolution.md +4 -4
- package/lib/oh-story/skills/story-long-write/references/tracking-initialization.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +15 -11
- package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +81 -121
- package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +41 -139
- package/lib/oh-story/skills/story-long-write/references/workflow-outline.md +157 -0
- package/lib/oh-story/skills/story-long-write/references/workflow-revision.md +57 -67
- package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +112 -253
- package/lib/oh-story/skills/story-long-write/references/workflow-volume.md +142 -0
- package/lib/oh-story/skills/story-long-write/references/writer-prompt-fallback.md +6 -4
- package/lib/oh-story/skills/story-long-write/references/writing-craft.md +19 -65
- 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_architect_brief.py +260 -0
- package/lib/oh-story/skills/story-long-write/scripts/build_writer_prompt.py +226 -25
- package/lib/oh-story/skills/story-long-write/scripts/check-ai-patterns.js +155 -8
- package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +132 -27
- package/lib/oh-story/skills/story-long-write/scripts/check-outline-copy.js +7 -2
- package/lib/oh-story/skills/story-long-write/scripts/outline_view.py +7 -4
- package/lib/oh-story/skills/story-long-write/scripts/storyctl.py +304 -46
- package/lib/oh-story/skills/story-long-write/scripts/tracking_commit.py +478 -15
- package/lib/oh-story/skills/story-long-write/scripts/wordcount_core.py +182 -23
- package/lib/oh-story/skills/story-review/SKILL.md +31 -302
- package/lib/oh-story/skills/story-review/references/agent-prompts.md +184 -0
- package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +12 -11
- package/lib/oh-story/skills/story-review/references/author-memory-maintenance.md +75 -0
- package/lib/oh-story/skills/story-review/references/author-memory.md +46 -94
- package/lib/oh-story/skills/story-review/references/banned-words.md +2 -2
- package/lib/oh-story/skills/story-review/references/batch-review.md +19 -0
- package/lib/oh-story/skills/story-review/references/character-relations.md +49 -1
- package/lib/oh-story/skills/story-review/references/dialogue-mastery.md +4 -0
- package/lib/oh-story/skills/story-review/references/review-quality.md +6 -11
- package/lib/oh-story/skills/story-review/references/review-tracking.md +10 -0
- package/lib/oh-story/skills/story-review/references/solo.md +52 -0
- package/lib/oh-story/skills/story-review/references/style-resolution.md +4 -4
- package/lib/oh-story/skills/story-review/references/tracking-initialization.md +1 -1
- package/lib/oh-story/skills/story-review/references/tracking-transaction.md +15 -11
- package/lib/oh-story/skills/story-review/scripts/author_memory_commit.py +934 -170
- package/lib/oh-story/skills/story-review/scripts/check-ai-patterns.js +155 -8
- package/lib/oh-story/skills/story-review/scripts/tracking_commit.py +478 -15
- package/lib/oh-story/skills/story-review/scripts/wordcount_core.py +182 -23
- package/lib/oh-story/skills/story-setup/SKILL.md +71 -452
- package/lib/oh-story/skills/story-setup/references/agent-references/agent-quality.md +4 -4
- package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +12 -11
- package/lib/oh-story/skills/story-setup/references/agent-references/banned-words.md +2 -2
- package/lib/oh-story/skills/story-setup/references/agent-references/benchmark-style-load.md +107 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/character-relations.md +49 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/deslop-gates.md +22 -5
- 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/emotion-on-page.md +116 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/emotional-arc-design.md +1 -114
- package/lib/oh-story/skills/story-setup/references/agent-references/format-and-structure.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/genre-prose-cards.md +1 -1
- 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-genre-catalog.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/long-genre-mechanics.md +3 -3
- package/lib/oh-story/skills/story-setup/references/agent-references/long-quality.md +7 -5
- package/lib/oh-story/skills/story-setup/references/agent-references/opening-design.md +2 -2
- package/lib/oh-story/skills/story-setup/references/agent-references/outline-conflict.md +4 -4
- package/lib/oh-story/skills/story-setup/references/agent-references/outline-methods.md +7 -7
- package/lib/oh-story/skills/story-setup/references/agent-references/outline-rhythm.md +3 -3
- package/lib/oh-story/skills/story-setup/references/agent-references/short-emotional-methods.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/short-genre-formulas.md +0 -15
- package/lib/oh-story/skills/story-setup/references/agent-references/short-reversal.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/style-combat-face.md +1 -58
- package/lib/oh-story/skills/story-setup/references/agent-references/style-genre-modules.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/style-resolution.md +4 -4
- package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +19 -65
- package/lib/oh-story/skills/story-setup/references/diagnostics.md +4 -4
- package/lib/oh-story/skills/story-short-analyze/SKILL.md +56 -110
- package/lib/oh-story/skills/story-short-analyze/references/analysis-character-relations.md +1 -1
- package/lib/oh-story/skills/story-short-analyze/references/analysis-method.md +42 -0
- package/lib/oh-story/skills/story-short-analyze/references/optional-modules.md +97 -0
- package/lib/oh-story/skills/story-short-analyze/references/output-contract.md +9 -47
- package/lib/oh-story/skills/story-short-analyze/references/quality-checklist.md +80 -0
- package/lib/oh-story/skills/story-short-analyze/references/source-story-quality.md +4 -4
- package/lib/oh-story/skills/story-short-analyze/references/stage2-3-structure-emotion.md +308 -0
- package/lib/oh-story/skills/story-short-analyze/references/stage4-6-reversal-summary.md +611 -0
- package/lib/oh-story/skills/story-short-scan/SKILL.md +35 -65
- package/lib/oh-story/skills/story-short-scan/references/manual-rank-input.md +36 -0
- package/lib/oh-story/skills/story-short-scan/references/platform-dianzhong.md +24 -0
- package/lib/oh-story/skills/story-short-scan/references/platform-heiyan.md +21 -0
- package/lib/oh-story/skills/story-short-scan/references/topic-match.md +38 -0
- package/lib/oh-story/skills/story-short-write/SKILL.md +23 -175
- package/lib/oh-story/skills/story-short-write/references/agent-calls.md +13 -0
- package/lib/oh-story/skills/story-short-write/references/author-memory-maintenance.md +75 -0
- package/lib/oh-story/skills/story-short-write/references/author-memory.md +46 -94
- package/lib/oh-story/skills/story-short-write/references/banned-words.md +2 -2
- package/lib/oh-story/skills/story-short-write/references/benchmark-recall.md +1 -21
- package/lib/oh-story/skills/story-short-write/references/dialogue-mastery.md +4 -0
- package/lib/oh-story/skills/story-short-write/references/emotional-methods.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/genre-writing-formulas.md +0 -15
- package/lib/oh-story/skills/story-short-write/references/output-contract.md +9 -47
- package/lib/oh-story/skills/story-short-write/references/reference-index.md +17 -47
- package/lib/oh-story/skills/story-short-write/references/scene-craft.md +40 -0
- package/lib/oh-story/skills/story-short-write/references/short-craft.md +7 -43
- package/lib/oh-story/skills/story-short-write/references/short-format.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/short-prose-quality.md +2 -1
- package/lib/oh-story/skills/story-short-write/references/short-reversal.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/style-resolution.md +4 -4
- package/lib/oh-story/skills/story-short-write/references/submission-craft.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/villain-and-reveal.md +5 -10
- package/lib/oh-story/skills/story-short-write/references/workflow-design.md +21 -13
- package/lib/oh-story/skills/story-short-write/references/workflow-draft.md +116 -0
- package/lib/oh-story/skills/story-short-write/references/workflow-revision.md +99 -0
- package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +7 -119
- package/lib/oh-story/skills/story-short-write/scripts/author_memory_commit.py +934 -170
- package/lib/oh-story/skills/story-short-write/scripts/check-ai-patterns.js +155 -8
- package/lib/oh-story/skills/story-short-write/scripts/check-outline-copy.js +7 -2
- 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/client/video-studio.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 +53 -1
- 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/lib/types/video-project.d.ts.map +1 -1
- package/lib/types/workspace-route.d.ts.map +1 -1
- package/lib/video-recap/CHANGELOG.md +60 -1
- package/lib/video-recap/README.en.md +348 -137
- package/lib/video-recap/README.md +340 -136
- package/lib/video-recap/manifest.json +406 -251
- package/lib/video-recap/skills/video-assemble/SKILL.md +30 -15
- package/lib/video-recap/skills/video-assemble/references/audio-modes.md +63 -0
- package/lib/video-recap/skills/video-assemble/references/explicit-audio-mix.md +75 -0
- package/lib/video-recap/skills/video-assemble/references/foreground-compose.md +118 -0
- package/lib/video-recap/skills/video-assemble/references/narration-adoption.md +103 -0
- package/lib/video-recap/skills/video-assemble/references/packaging.md +45 -0
- package/lib/video-recap/skills/video-assemble/references/pair-media.md +74 -0
- package/lib/video-recap/skills/video-assemble/references/source-score.md +147 -0
- package/lib/video-recap/skills/video-assemble/references/subtitle-track.md +202 -0
- package/lib/video-recap/skills/video-assemble/scripts/adoption/__init__.py +1 -0
- package/lib/video-recap/skills/video-assemble/scripts/adoption/audio_mix_binding.py +279 -0
- package/lib/video-recap/skills/video-assemble/scripts/adoption/frozen_audio.py +187 -0
- package/lib/video-recap/skills/video-assemble/scripts/adoption/narration_binding.py +323 -0
- package/lib/video-recap/skills/video-assemble/scripts/adoption/strict_inputs.py +109 -0
- package/lib/video-recap/skills/video-assemble/scripts/adoption/strict_publish.py +130 -0
- package/lib/video-recap/skills/video-assemble/scripts/artifacts.py +10 -46
- package/lib/video-recap/skills/video-assemble/scripts/assemble.py +378 -119
- package/lib/video-recap/skills/video-assemble/scripts/assemble_constants.py +29 -12
- package/lib/video-recap/skills/video-assemble/scripts/assembly_contract.py +95 -44
- package/lib/video-recap/skills/video-assemble/scripts/assembly_settings.py +75 -32
- package/lib/video-recap/skills/video-assemble/scripts/audio_mix.py +11 -11
- package/lib/video-recap/skills/video-assemble/scripts/compose_foreground.py +293 -0
- package/lib/video-recap/skills/video-assemble/scripts/export_jianying.py +71 -78
- package/lib/video-recap/skills/video-assemble/scripts/jianying/__init__.py +1 -0
- package/lib/video-recap/skills/video-assemble/scripts/{jianying_builders.py → jianying/builders.py} +39 -67
- package/lib/video-recap/skills/video-assemble/scripts/{jianying_model.py → jianying/model.py} +3 -11
- package/lib/video-recap/skills/video-assemble/scripts/{jianying_optional.py → jianying/optional.py} +1 -1
- package/lib/video-recap/skills/video-assemble/scripts/jianying/schema.py +53 -0
- package/lib/video-recap/skills/video-assemble/scripts/{jianying_templates.py → jianying/templates.py} +1 -1
- package/lib/video-recap/skills/video-assemble/scripts/{jianying_timeline_contract.py → jianying/timeline_contract.py} +34 -13
- package/lib/video-recap/skills/video-assemble/scripts/{jianying_writer.py → jianying/writer.py} +7 -17
- package/lib/video-recap/skills/video-assemble/scripts/lib.py +37 -4
- package/lib/video-recap/skills/video-assemble/scripts/media.py +12 -21
- package/lib/video-recap/skills/video-assemble/scripts/narration_audio.py +64 -34
- package/lib/video-recap/skills/video-assemble/scripts/packaging.py +122 -0
- package/lib/video-recap/skills/video-assemble/scripts/pair_media.py +216 -0
- package/lib/video-recap/skills/video-assemble/scripts/render_preflight.py +1 -3
- package/lib/video-recap/skills/video-assemble/scripts/source_score.py +469 -0
- package/lib/video-recap/skills/video-assemble/scripts/source_subtitles.py +25 -9
- package/lib/video-recap/skills/video-assemble/scripts/subtitles/__init__.py +1 -0
- package/lib/video-recap/skills/video-assemble/scripts/{subtitle_core.py → subtitles/core.py} +13 -6
- package/lib/video-recap/skills/video-assemble/scripts/{subtitle_render.py → subtitles/render.py} +5 -4
- package/lib/video-recap/skills/video-assemble/scripts/subtitles/track.py +324 -0
- package/lib/video-recap/skills/video-assemble/scripts/subtitles/track_binding.py +200 -0
- package/lib/video-recap/skills/video-assemble/scripts/timeline.py +30 -46
- package/lib/video-recap/skills/video-assemble/scripts/timeline_emit.py +91 -7
- package/lib/video-recap/skills/video-assemble/scripts/visual_render.py +22 -8
- package/lib/video-recap/skills/video-cut/SKILL.md +34 -16
- package/lib/video-recap/skills/video-cut/references/shot-review.md +50 -0
- package/lib/video-recap/skills/video-cut/scripts/cut.py +2 -28
- package/lib/video-recap/skills/video-cut/scripts/cut_cli.py +58 -62
- package/lib/video-recap/skills/video-cut/scripts/cut_contract.py +21 -106
- package/lib/video-recap/skills/video-cut/scripts/cut_render.py +14 -9
- package/lib/video-recap/skills/video-cut/scripts/lib.py +39 -0
- package/lib/video-recap/skills/video-cut/scripts/narration_mapping.py +2 -155
- package/lib/video-recap/skills/video-cut/scripts/narrative_selection.py +244 -0
- package/lib/video-recap/skills/video-cut/scripts/shot_review.py +357 -0
- package/lib/video-recap/skills/video-recap/SKILL.md +86 -42
- package/lib/video-recap/skills/video-recap/references/audio-routing.md +126 -0
- package/lib/video-recap/skills/video-recap/references/config-playbook.md +12 -8
- package/lib/video-recap/skills/video-recap/references/data-schema.md +44 -33
- package/lib/video-recap/skills/video-recap/references/resource-library.md +151 -0
- package/lib/video-recap/skills/video-recap/references/shift-left-qc-schema.md +1 -1
- package/lib/video-recap/skills/video-recap/scripts/doctor.py +123 -30
- package/lib/video-recap/skills/video-recap/scripts/final_qc.py +22 -75
- package/lib/video-recap/skills/video-recap/scripts/lib.py +3 -3
- package/lib/video-recap/skills/video-recap/scripts/library.py +509 -0
- package/lib/video-recap/skills/video-recap/scripts/materials.py +63 -91
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc.py +8 -70
- package/lib/video-recap/skills/video-recap/scripts/project_binding.py +286 -0
- package/lib/video-recap/skills/video-recap/scripts/qc/__init__.py +1 -0
- package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_client.py → qc/mimo_client.py} +1 -1
- package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_evidence.py → qc/mimo_evidence.py} +33 -66
- package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_observations.py → qc/mimo_observations.py} +3 -11
- package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_payload.py → qc/mimo_payload.py} +4 -7
- package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_report.py → qc/mimo_report.py} +17 -28
- package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_runner.py → qc/mimo_runner.py} +2 -2
- package/lib/video-recap/skills/video-recap/scripts/qc_contract.py +0 -19
- package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +119 -50
- package/lib/video-recap/skills/video-recap/scripts/recap_inspect.py +32 -114
- package/lib/video-recap/skills/video-recap/scripts/recap_review.py +9 -23
- package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +387 -334
- package/lib/video-recap/skills/video-recap/scripts/recap_runtime.py +23 -23
- package/lib/video-recap/skills/video-recap/scripts/recap_source.py +278 -0
- package/lib/video-recap/skills/video-recap/scripts/recap_stage_qc.py +25 -12
- package/lib/video-recap/skills/video-recap/scripts/recap_timeline.py +59 -52
- package/lib/video-recap/skills/video-recap/scripts/resource_lock.py +162 -0
- package/lib/video-recap/skills/video-script/SKILL.md +16 -13
- package/lib/video-recap/skills/video-script/references/creative-editing-playbook.md +9 -5
- package/lib/video-recap/skills/video-script/references/promotional-copy.md +68 -0
- package/lib/video-recap/skills/video-script/references/research-guide.md +1 -1
- package/lib/video-recap/skills/video-script/scripts/evidence_bundle.py +24 -76
- package/lib/video-recap/skills/video-script/scripts/lib.py +10 -87
- package/lib/video-recap/skills/video-script/scripts/narration_lint.py +63 -39
- package/lib/video-recap/skills/video-script/scripts/review.py +0 -2
- package/lib/video-recap/skills/video-script/scripts/review_grounding.py +35 -59
- package/lib/video-recap/skills/video-script/scripts/review_response.py +66 -128
- package/lib/video-recap/skills/video-script/scripts/review_runner.py +12 -20
- package/lib/video-recap/skills/video-script/scripts/speech_ownership.py +4 -4
- package/lib/video-recap/skills/video-script/scripts/validate.py +53 -42
- package/lib/video-recap/skills/video-understanding/SKILL.md +6 -4
- package/lib/video-recap/skills/video-understanding/references/data-schema.md +50 -156
- package/lib/video-recap/skills/video-understanding/references/research-guide.md +4 -4
- package/lib/video-recap/skills/video-understanding/scripts/asr.py +85 -65
- package/lib/video-recap/skills/video-understanding/scripts/asr_timing_evidence.py +270 -0
- package/lib/video-recap/skills/video-understanding/scripts/brief.py +2 -5
- package/lib/video-recap/skills/video-understanding/scripts/briefing/__init__.py +1 -0
- package/lib/video-recap/skills/{video-script/scripts/agent_brief.py → video-understanding/scripts/briefing/builder.py} +38 -35
- package/lib/video-recap/skills/video-understanding/scripts/{brief_context.py → briefing/context.py} +4 -35
- package/lib/video-recap/skills/{video-script/scripts/brief_inputs.py → video-understanding/scripts/briefing/inputs.py} +9 -31
- package/lib/video-recap/skills/{video-script/scripts/brief_timeline.py → video-understanding/scripts/briefing/timeline.py} +5 -6
- package/lib/video-recap/skills/video-understanding/scripts/consolidate.py +65 -116
- package/lib/video-recap/skills/video-understanding/scripts/detect.py +31 -40
- package/lib/video-recap/skills/video-understanding/scripts/lib.py +30 -86
- package/lib/video-recap/skills/video-understanding/scripts/narration_lint.py +63 -39
- package/lib/video-recap/skills/video-understanding/scripts/speech_ownership.py +4 -4
- package/lib/video-recap/skills/video-understanding/scripts/storyboard.py +17 -79
- package/lib/video-recap/skills/video-understanding/scripts/understanding_brief.py +14 -40
- package/lib/video-recap/skills/video-understanding/scripts/understanding_cache.py +64 -46
- package/lib/video-recap/skills/video-understanding/scripts/understanding_runner.py +31 -11
- package/lib/video-recap/skills/video-understanding/scripts/understanding_storyboard.py +19 -14
- package/lib/video-recap/skills/video-understanding/scripts/vlm.py +80 -108
- package/lib/video-recap/skills/video-voiceover/SKILL.md +29 -19
- package/lib/video-recap/skills/video-voiceover/references/index-tts.md +31 -0
- package/lib/video-recap/skills/video-voiceover/scripts/approved_text_policy.py +123 -0
- package/lib/video-recap/skills/video-voiceover/scripts/dub.py +51 -59
- package/lib/video-recap/skills/video-voiceover/scripts/lib.py +8 -44
- package/lib/video-recap/skills/video-voiceover/scripts/providers/__init__.py +1 -0
- package/lib/video-recap/skills/video-voiceover/scripts/providers/index_tts.py +184 -0
- package/lib/video-recap/skills/video-voiceover/scripts/voiceover.py +212 -134
- 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-analyze/references/material-decomposition.md +0 -530
- package/lib/oh-story/skills/story-long-analyze/references/output-templates.md +0 -559
- package/lib/oh-story/skills/story-long-scan/references/scan-output-format.md +0 -207
- package/lib/oh-story/skills/story-long-write/references/state-tracking.md +0 -108
- package/lib/oh-story/skills/story-short-analyze/references/material-decomposition.md +0 -678
- package/lib/oh-story/skills/story-short-analyze/references/output-templates.md +0 -561
- package/lib/video-recap/skills/video-assemble/scripts/jianying_schema.py +0 -98
- package/lib/video-recap/skills/video-recap/references/creative-editing-playbook.md +0 -225
- package/lib/video-recap/skills/video-recap/references/research-guide.md +0 -74
- package/lib/video-recap/skills/video-recap/references/timeline-and-jianying.md +0 -250
- package/lib/video-recap/skills/video-script/scripts/brief_context.py +0 -348
- package/lib/video-recap/skills/video-script/scripts/narration.py +0 -12
- package/lib/video-recap/skills/video-understanding/scripts/agent_brief.py +0 -399
- package/lib/video-recap/skills/video-understanding/scripts/brief_inputs.py +0 -290
- package/lib/video-recap/skills/video-understanding/scripts/brief_timeline.py +0 -327
- /package/lib/video-recap/skills/video-assemble/scripts/{jianying_tracks.py → jianying/tracks.py} +0 -0
- /package/lib/video-recap/skills/video-recap/scripts/{mimo_qc_contract.py → qc/mimo_contract.py} +0 -0
- /package/lib/video-recap/skills/video-voiceover/scripts/{fish_audio.py → providers/fish_audio.py} +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""Own recap timeline artifacts, continuation state, and cut QC surfaces."""
|
|
2
2
|
|
|
3
|
-
import hashlib
|
|
4
3
|
import json
|
|
5
4
|
import os
|
|
6
5
|
import shlex
|
|
@@ -15,6 +14,7 @@ from recap_runtime import (
|
|
|
15
14
|
_multi_run_manifest_payload,
|
|
16
15
|
_run_manifest_payload,
|
|
17
16
|
)
|
|
17
|
+
from recap_source import audio_binding, uses_narration
|
|
18
18
|
|
|
19
19
|
ASSEMBLY_MANIFEST = "assembly_manifest.json"
|
|
20
20
|
|
|
@@ -23,6 +23,7 @@ PHASE_LEDGER = "recap_phase.json"
|
|
|
23
23
|
CUT_TIMELINE_CRAFT_BULLETS = [
|
|
24
24
|
"- 片段顺序必须服务同一条故事主线,而不是无序高光;可使用 0–1 个 cold open,随后回到 setup → turn → escalation → payoff。",
|
|
25
25
|
"- 每个片段必须对应 `recap_story_plan.json` 中的一个 change-based beat;删除后不损失因果、人物或情绪的片段通常不保留。",
|
|
26
|
+
"- 已从源证据确认的必保问答、反应或兑现段,写入同一 `clip_plan.json.required_evidence`(nodes登记id/source绝对路径/start/end原片秒/track/content,before登记必要先后);只锁具体区间,不锁整个beat。剪点吸附后工具会核验,reason或花字不能代替缺失的源段。",
|
|
26
27
|
"- `reason` 统一写成 `beat_id | function | change | POV | preferred moment | 入点 | 出点`,不能只写 hook、重要剧情或事件摘要。",
|
|
27
28
|
"- 优先保留因果、揭示、决定、关系移动、情绪转向与不可替代的表演/反应;跳过片尾、广告、重复静态画面和水印废片段。",
|
|
28
29
|
"- 片段追求最短但完整:建立镜头可以短,关键表演/反应允许多停一点;在完整台词、完整动作或自然声音边界结束,避免原声从半句中切入或切出。",
|
|
@@ -104,24 +105,15 @@ def _print_grounding_qc_pointer(work_dir):
|
|
|
104
105
|
def _print_narration_review_pointer(work_dir, *, review_ran=True):
|
|
105
106
|
"""Surface the advisory narration review produced by this run, if any.
|
|
106
107
|
|
|
107
|
-
Review is optional/fail-open
|
|
108
|
-
|
|
108
|
+
Review is optional/fail-open: review_ran=False (disabled or failed) prints nothing so a
|
|
109
|
+
stale narration_review.md from an older run is never surfaced. When it ran, video-script's
|
|
110
|
+
review_runner has written both narration_review.json and .md.
|
|
109
111
|
"""
|
|
110
112
|
_print_grounding_qc_pointer(work_dir)
|
|
111
113
|
if not review_ran:
|
|
112
114
|
return
|
|
113
115
|
review_md = Path(work_dir) / "narration_review.md"
|
|
114
|
-
|
|
115
|
-
return
|
|
116
|
-
review_json = Path(work_dir) / "narration_review.json"
|
|
117
|
-
if not review_json.exists():
|
|
118
|
-
print(f"[video-recap] 📋 解说评审(建议性,不拦截)→ {review_md}")
|
|
119
|
-
return
|
|
120
|
-
try:
|
|
121
|
-
data = load_json(review_json)
|
|
122
|
-
except (OSError, ValueError):
|
|
123
|
-
print(f"[video-recap] 📋 解说评审(建议性,不拦截)→ {review_md}")
|
|
124
|
-
return
|
|
116
|
+
data = load_json(Path(work_dir) / "narration_review.json")
|
|
125
117
|
n_err = sum(1 for f in data["findings"] if f["severity"] == "error")
|
|
126
118
|
print(
|
|
127
119
|
f"[video-recap] 📋 解说评审(建议性,不拦截): {data['verdict']} · "
|
|
@@ -152,11 +144,17 @@ def _manifest_mismatches(work_dir, video, args):
|
|
|
152
144
|
# as a mismatch rather than a crash.
|
|
153
145
|
mismatches = [
|
|
154
146
|
f"{key}: expected {expected[key]!r}, got {actual.get(key)!r}"
|
|
155
|
-
for key in ("source_video", "
|
|
147
|
+
for key in ("source_video", "source_video_identity")
|
|
156
148
|
if actual.get(key) != expected[key]
|
|
157
149
|
]
|
|
158
150
|
if _settings_for_compare(actual["settings"]) != _settings_for_compare(expected["settings"]):
|
|
159
151
|
mismatches.append("settings: 当前 CLI/env 参数与 Phase A manifest 不匹配")
|
|
152
|
+
actual_audio = actual.get("audio")
|
|
153
|
+
expected_audio = audio_binding(args)
|
|
154
|
+
if actual_audio != expected_audio:
|
|
155
|
+
mismatches.append(
|
|
156
|
+
f"audio: expected {expected_audio!r}, got {actual_audio!r}"
|
|
157
|
+
)
|
|
160
158
|
return mismatches
|
|
161
159
|
|
|
162
160
|
|
|
@@ -168,15 +166,23 @@ def _multi_manifest_mismatches(work_dir, videos, args, source_records):
|
|
|
168
166
|
if actual.get("mode") != "multi_source":
|
|
169
167
|
return [f"mode: expected 'multi_source', got {actual.get('mode')!r}"]
|
|
170
168
|
mismatches = []
|
|
171
|
-
identity = ("source_id", "source_path", "
|
|
172
|
-
|
|
169
|
+
identity = ("source_id", "source_path", "source_video_identity")
|
|
170
|
+
# A 0.5.0 manifest carries `source_video_fingerprint` instead of `source_video_identity`;
|
|
171
|
+
# .get() reports it as a mismatch rather than a crash.
|
|
172
|
+
if [{k: s.get(k) for k in identity} for s in actual["sources"]] != [
|
|
173
173
|
{k: s[k] for k in identity} for s in expected["sources"]
|
|
174
174
|
]:
|
|
175
175
|
mismatches.append(
|
|
176
|
-
"sources: 当前输入视频列表/顺序/source_id/
|
|
176
|
+
"sources: 当前输入视频列表/顺序/source_id/identity 与 Phase A manifest 不匹配"
|
|
177
177
|
)
|
|
178
178
|
if _settings_for_compare(actual["settings"]) != _settings_for_compare(expected["settings"]):
|
|
179
179
|
mismatches.append("settings: 当前 CLI/env 参数与 Phase A manifest 不匹配")
|
|
180
|
+
actual_audio = actual.get("audio")
|
|
181
|
+
expected_audio = audio_binding(args)
|
|
182
|
+
if actual_audio != expected_audio:
|
|
183
|
+
mismatches.append(
|
|
184
|
+
f"audio: expected {expected_audio!r}, got {actual_audio!r}"
|
|
185
|
+
)
|
|
180
186
|
return mismatches
|
|
181
187
|
|
|
182
188
|
|
|
@@ -184,10 +190,6 @@ def _read_assembly_output(work_dir):
|
|
|
184
190
|
return Path(load_json(Path(work_dir) / ASSEMBLY_MANIFEST)["final_output"])
|
|
185
191
|
|
|
186
192
|
|
|
187
|
-
def _file_md5(path):
|
|
188
|
-
return hashlib.md5(Path(path).read_bytes()).hexdigest()
|
|
189
|
-
|
|
190
|
-
|
|
191
193
|
def _read_phase_ledger(work_dir):
|
|
192
194
|
"""Phase ledger (cut mode): which artifacts exist and the clip_plan/narration they match.
|
|
193
195
|
|
|
@@ -209,14 +211,17 @@ def _write_phase_ledger(work_dir, **fields):
|
|
|
209
211
|
return ledger
|
|
210
212
|
|
|
211
213
|
|
|
212
|
-
def _cut_narration_is_stale(ledger,
|
|
214
|
+
def _cut_narration_is_stale(ledger, current_clip_plan_identity):
|
|
213
215
|
"""Two-pass cut: the narration is authored against the rendered cut shown at the A2 pause,
|
|
214
|
-
i.e. against the clip_plan recorded in the ledger
|
|
215
|
-
while that narration is still present, it
|
|
216
|
-
|
|
216
|
+
i.e. against the clip_plan recorded in the ledger (its ``{size, mtime_ns}`` identity). If
|
|
217
|
+
clip_plan.json was rewritten since (a re-cut) while that narration is still present, it
|
|
218
|
+
describes the OLD cut — stale."""
|
|
219
|
+
return ledger is not None and ledger["clip_plan_identity"] != current_clip_plan_identity
|
|
217
220
|
|
|
218
221
|
|
|
219
222
|
def _continuation_command(video, work_dir, args):
|
|
223
|
+
# Values a project binding filled in are re-derived from --project on resume.
|
|
224
|
+
bound = getattr(args, "_bound_from_project", frozenset())
|
|
220
225
|
parts = [
|
|
221
226
|
sys.executable,
|
|
222
227
|
str(_entry("video-recap", "recap.py")),
|
|
@@ -232,12 +237,14 @@ def _continuation_command(video, work_dir, args):
|
|
|
232
237
|
parts += ["--style", args.style]
|
|
233
238
|
if args.edit_mode != "full":
|
|
234
239
|
parts += ["--edit-mode", args.edit_mode]
|
|
240
|
+
if args.audio_mode != "narration":
|
|
241
|
+
parts += ["--audio-mode", args.audio_mode]
|
|
242
|
+
if args.audio_stream_index != 0:
|
|
243
|
+
parts += ["--audio-stream-index", str(args.audio_stream_index)]
|
|
235
244
|
if args.target_duration:
|
|
236
245
|
parts += ["--target-duration", args.target_duration]
|
|
237
246
|
if args.allow_duration_drift:
|
|
238
247
|
parts.append("--allow-duration-drift")
|
|
239
|
-
if args.allow_sparse_cut:
|
|
240
|
-
parts.append("--allow-sparse-cut")
|
|
241
248
|
if args.skip_asr:
|
|
242
249
|
parts.append("--skip-asr")
|
|
243
250
|
if args.mimo_video_overview:
|
|
@@ -250,14 +257,17 @@ def _continuation_command(video, work_dir, args):
|
|
|
250
257
|
parts.append("--no-consolidate")
|
|
251
258
|
if args.consolidate_asr:
|
|
252
259
|
parts.append("--consolidate-asr")
|
|
253
|
-
if args
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
260
|
+
if uses_narration(args):
|
|
261
|
+
if args.mimo_tts_voice and "mimo_tts_voice" not in bound:
|
|
262
|
+
parts += ["--mimo-tts-voice", args.mimo_tts_voice]
|
|
263
|
+
if args.tts_provider != "auto" and "tts_provider" not in bound:
|
|
264
|
+
parts += ["--tts-provider", args.tts_provider]
|
|
265
|
+
if args.voice_ref and "voice_ref" not in bound:
|
|
266
|
+
parts += ["--voice-ref", args.voice_ref]
|
|
267
|
+
if args.allow_partial_tts:
|
|
268
|
+
parts.append("--allow-partial-tts")
|
|
269
|
+
if args.preserve_approved_text:
|
|
270
|
+
parts.append("--preserve-approved-text")
|
|
261
271
|
if args.burn_subtitles is not None:
|
|
262
272
|
parts.append("--burn-subtitles" if args.burn_subtitles else "--no-burn-subtitles")
|
|
263
273
|
if args.subtitle_y_top is not None:
|
|
@@ -272,16 +282,23 @@ def _continuation_command(video, work_dir, args):
|
|
|
272
282
|
parts.append("--jianying-bundle-media")
|
|
273
283
|
if args.jianying_no_bundle_media:
|
|
274
284
|
parts.append("--jianying-no-bundle-media")
|
|
275
|
-
if args
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
285
|
+
if uses_narration(args):
|
|
286
|
+
if args.review_narration is not None:
|
|
287
|
+
parts.append(
|
|
288
|
+
"--review-narration" if args.review_narration else "--no-review-narration"
|
|
289
|
+
)
|
|
290
|
+
if args.require_narration_review:
|
|
291
|
+
parts.append("--require-narration-review")
|
|
292
|
+
if args.material_library_dir and "material_library_dir" not in bound:
|
|
280
293
|
parts += ["--material-library-dir", args.material_library_dir]
|
|
294
|
+
if getattr(args, "project", None):
|
|
295
|
+
parts += ["--project", args.project]
|
|
281
296
|
if args.use_materials:
|
|
282
297
|
parts.append("--use-materials")
|
|
283
298
|
if args.save_materials:
|
|
284
299
|
parts.append("--save-materials")
|
|
300
|
+
if args.require_final_qc:
|
|
301
|
+
parts.append("--require-final-qc")
|
|
285
302
|
return " ".join(shlex.quote(part) for part in parts)
|
|
286
303
|
|
|
287
304
|
|
|
@@ -398,7 +415,6 @@ def _write_multi_source_clip_brief(work_dir, source_records, args):
|
|
|
398
415
|
f"### {s['source_id']} — {s['source_name']}",
|
|
399
416
|
f"- path: `{s['source_path']}`",
|
|
400
417
|
f"- work_dir: `{swd}`",
|
|
401
|
-
f"- fingerprint: `{s['source_video_fingerprint']}`",
|
|
402
418
|
f"- material_id: `{s['material_id']}`",
|
|
403
419
|
]
|
|
404
420
|
excerpt = _brief_excerpt(swd / "agent_narration_brief.md")
|
|
@@ -449,11 +465,7 @@ def _write_multi_source_output_speech_evidence(work_dir, source_records, plan):
|
|
|
449
465
|
when = float(anchor["time"])
|
|
450
466
|
if not (source_start - 0.05 <= when <= source_end + 0.05):
|
|
451
467
|
continue
|
|
452
|
-
|
|
453
|
-
pause = float(anchor["pause_start"])
|
|
454
|
-
except (TypeError, ValueError):
|
|
455
|
-
pause = when
|
|
456
|
-
pause = max(source_start, min(pause, when))
|
|
468
|
+
pause = max(source_start, min(float(anchor["pause_start"]), when))
|
|
457
469
|
item = dict(anchor)
|
|
458
470
|
item.update(
|
|
459
471
|
source_id=source_id,
|
|
@@ -491,11 +503,6 @@ def _write_multi_source_output_speech_evidence(work_dir, source_records, plan):
|
|
|
491
503
|
"artifact": "speech_boundary_anchors_output.json",
|
|
492
504
|
"timeline": "cut_output",
|
|
493
505
|
"source_artifact": "multi_source_manifest.json",
|
|
494
|
-
"clip_plan_fingerprint": hashlib.md5(
|
|
495
|
-
json.dumps(
|
|
496
|
-
plan, ensure_ascii=False, sort_keys=True, separators=(",", ":"), default=str
|
|
497
|
-
).encode("utf-8")
|
|
498
|
-
).hexdigest(),
|
|
499
506
|
"sentence_anchors": sorted(mapped_anchors, key=lambda row: row["time"]),
|
|
500
507
|
"speech_spans": sorted(mapped_speech, key=lambda row: (row["start"], row["end"])),
|
|
501
508
|
"quiet_windows": sorted(mapped_quiet, key=lambda row: (row["start"], row["end"])),
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""Record every resource and template a finished run used: ``work_dir/resource_lock.json``.
|
|
2
|
+
|
|
3
|
+
Facts come from artifacts the stages already wrote (run manifest, ``tts_meta.json``,
|
|
4
|
+
``assembly_manifest.json``) plus the optional project binding. When a library is
|
|
5
|
+
configured, each file-backed entry is matched to a registered resource by resolved path
|
|
6
|
+
so its licence and consent status travel with the run. Nothing here changes a render.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
from datetime import datetime, timezone
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
import library as library_lib
|
|
15
|
+
from materials import file_identity
|
|
16
|
+
|
|
17
|
+
LOCK_NAME = "resource_lock.json"
|
|
18
|
+
LOCK_SCHEMA = "video-recap.resource-lock.v1"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _read(path: Path):
|
|
22
|
+
try:
|
|
23
|
+
return json.loads(path.read_text(encoding="utf-8"))
|
|
24
|
+
except (OSError, ValueError):
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _file_entry(role: str, path, detail=None) -> dict:
|
|
29
|
+
entry = {"role": role, "path": None, "size": None, "mtime_ns": None,
|
|
30
|
+
"detail": detail or {}, "library": None}
|
|
31
|
+
if path:
|
|
32
|
+
resolved = Path(path).expanduser().resolve()
|
|
33
|
+
entry["path"] = str(resolved)
|
|
34
|
+
if resolved.is_file():
|
|
35
|
+
entry.update(file_identity(resolved))
|
|
36
|
+
return entry
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _source_entries(work_dir: Path) -> list[dict]:
|
|
40
|
+
manifest = _read(work_dir / "recap_run_manifest.json") or {}
|
|
41
|
+
if manifest.get("mode") == "multi_source":
|
|
42
|
+
return [_file_entry("source_video", s.get("source_path"), {"source_id": s.get("source_id")})
|
|
43
|
+
for s in manifest.get("sources", [])]
|
|
44
|
+
if manifest.get("source_video"):
|
|
45
|
+
return [_file_entry("source_video", manifest["source_video"])]
|
|
46
|
+
return []
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _voice_entry(work_dir: Path) -> dict | None:
|
|
50
|
+
meta = _read(work_dir / "tts_meta.json")
|
|
51
|
+
if not isinstance(meta, dict):
|
|
52
|
+
return None
|
|
53
|
+
voice = meta.get("voice") or {"provider": meta.get("engine")}
|
|
54
|
+
reference = voice.get("reference") or {}
|
|
55
|
+
entry = _file_entry("voice", reference.get("path"), {
|
|
56
|
+
"provider": voice.get("provider"), "model": voice.get("model"),
|
|
57
|
+
"voice_id": voice.get("voice_id"),
|
|
58
|
+
})
|
|
59
|
+
return entry
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _assembly_entries(work_dir: Path) -> list[dict]:
|
|
63
|
+
manifest = _read(work_dir / "assembly_manifest.json") or {}
|
|
64
|
+
settings = manifest.get("assembly_settings") or {}
|
|
65
|
+
entries = []
|
|
66
|
+
bgm = (settings.get("audio_mix") or {}).get("bgm_path")
|
|
67
|
+
if bgm:
|
|
68
|
+
entries.append(_file_entry("bgm", bgm))
|
|
69
|
+
packaging = (settings.get("video_filters") or {}).get("packaging_layers") or {}
|
|
70
|
+
for layer in packaging.get("layers", []):
|
|
71
|
+
entries.append(_file_entry("packaging_layer", layer.get("path"), {"name": layer.get("name")}))
|
|
72
|
+
style = settings.get("subtitle_style")
|
|
73
|
+
if isinstance(style, dict):
|
|
74
|
+
entries.append(_file_entry("subtitle_font", style.get("font_file"),
|
|
75
|
+
{"family": style.get("font_name")}))
|
|
76
|
+
return entries
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _match_library(entries: list[dict], index: dict) -> None:
|
|
80
|
+
by_path = {}
|
|
81
|
+
for resource in index["resources"]:
|
|
82
|
+
for f in resource["files"]:
|
|
83
|
+
by_path[str(Path(f["path"]).resolve())] = resource
|
|
84
|
+
voices = [r for r in index["resources"] if r["kind"] == "voice"]
|
|
85
|
+
records = {r["id"]: json.loads(Path(r["record"]).read_text(encoding="utf-8"))
|
|
86
|
+
for r in index["resources"]}
|
|
87
|
+
for entry in entries:
|
|
88
|
+
resource = by_path.get(entry["path"]) if entry["path"] else None
|
|
89
|
+
if (resource is None and entry["role"] == "voice" and not entry["path"]
|
|
90
|
+
and isinstance(entry["detail"].get("voice_id"), str) and entry["detail"]["voice_id"]):
|
|
91
|
+
detail = entry["detail"]
|
|
92
|
+
resource = next((v for v in voices
|
|
93
|
+
if (records[v["id"]].get("voice") or {}).get("provider") == detail.get("provider")
|
|
94
|
+
and (records[v["id"]].get("voice") or {}).get("voice_id") == detail.get("voice_id")), None)
|
|
95
|
+
if resource is None:
|
|
96
|
+
continue
|
|
97
|
+
record = records[resource["id"]]
|
|
98
|
+
entry["library"] = {"id": resource["id"], "kind": resource["kind"],
|
|
99
|
+
"license": resource["license"],
|
|
100
|
+
"consent": (record.get("consent") or {}).get("status")}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _attention(entries: list[dict], library_configured: bool) -> list[dict]:
|
|
104
|
+
items = []
|
|
105
|
+
for entry in entries:
|
|
106
|
+
role, lib = entry["role"], entry["library"]
|
|
107
|
+
if role == "source_video":
|
|
108
|
+
continue
|
|
109
|
+
if lib is None:
|
|
110
|
+
if library_configured and (entry["path"] or role == "voice"):
|
|
111
|
+
items.append({"code": "unregistered", "role": role,
|
|
112
|
+
"message": "资源库中没有登记这项资源,授权状态未知"})
|
|
113
|
+
continue
|
|
114
|
+
if lib["license"] in {"unknown", "restricted"}:
|
|
115
|
+
items.append({"code": f"license_{lib['license']}", "role": role,
|
|
116
|
+
"message": f"{lib['id']} 的授权状态为 {lib['license']},交付前需要人工确认"})
|
|
117
|
+
if role == "voice" and entry["path"] and lib.get("consent") != "granted":
|
|
118
|
+
items.append({"code": f"consent_{lib.get('consent') or 'unknown'}", "role": role,
|
|
119
|
+
"message": f"{lib['id']} 的参考音频声音授权未确认"})
|
|
120
|
+
return items
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def build_resource_lock(work_dir, *, library_dir=None, project=None) -> dict:
|
|
124
|
+
"""Assemble the lock payload from a finished work_dir; ``project`` is a resolved binding."""
|
|
125
|
+
work_dir = Path(work_dir)
|
|
126
|
+
entries = _source_entries(work_dir)
|
|
127
|
+
voice = _voice_entry(work_dir)
|
|
128
|
+
if voice:
|
|
129
|
+
entries.append(voice)
|
|
130
|
+
entries += _assembly_entries(work_dir)
|
|
131
|
+
entries += list((project or {}).get("resources", []))
|
|
132
|
+
library_root = None
|
|
133
|
+
if library_dir and Path(library_dir).is_dir():
|
|
134
|
+
library_root = str(Path(library_dir).resolve())
|
|
135
|
+
index, _ = library_lib.scan_library(library_root)
|
|
136
|
+
_match_library(entries, index)
|
|
137
|
+
return {
|
|
138
|
+
"schema": LOCK_SCHEMA,
|
|
139
|
+
"generated_at": datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z"),
|
|
140
|
+
"work_dir": str(work_dir.resolve()),
|
|
141
|
+
"library": library_root,
|
|
142
|
+
"project": ({"path": project["path"], "name": project.get("name", "")} if project else None),
|
|
143
|
+
"templates": list((project or {}).get("templates", [])),
|
|
144
|
+
"resources": entries,
|
|
145
|
+
"attention": _attention(entries, library_root is not None),
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def write_resource_lock(work_dir, *, library_dir=None, project=None) -> dict:
|
|
150
|
+
lock = build_resource_lock(work_dir, library_dir=library_dir, project=project)
|
|
151
|
+
path = Path(work_dir) / LOCK_NAME
|
|
152
|
+
path.write_text(json.dumps(lock, ensure_ascii=False, indent=2), encoding="utf-8")
|
|
153
|
+
return lock
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def summary_line(lock: dict) -> str:
|
|
157
|
+
registered = sum(1 for e in lock["resources"] if e["library"])
|
|
158
|
+
text = (f"[video-recap] 资源记录: {LOCK_NAME}({len(lock['resources'])} 项,"
|
|
159
|
+
f"资源库已登记 {registered} 项)")
|
|
160
|
+
if lock["attention"]:
|
|
161
|
+
text += "\n" + "\n".join(f"[video-recap] ⚠ {a['role']}: {a['message']}" for a in lock["attention"])
|
|
162
|
+
return text
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: video-script
|
|
3
3
|
description: >
|
|
4
|
-
|
|
5
|
-
agent_narration_brief.md 与
|
|
6
|
-
|
|
7
|
-
可选 style_card.json、cut 模式需要的 clip_plan.json,以及通过校验的 narration.json
|
|
4
|
+
对已完成分析的视频进行导演与剪辑策划,再写带时间戳的中文解说并校验;也处理已有短片的
|
|
5
|
+
宣发标题、花字修订和外部文案回填。普通策划输入 work_dir 的 agent_narration_brief.md 与
|
|
6
|
+
vlm_analysis.json;文案返修输入当前成片的工程与内容证据。策划输出 recap_story_plan.json、visual_audio_board.json、
|
|
7
|
+
可选 style_card.json、cut 模式需要的 clip_plan.json,以及通过校验的 narration.json;仅宣发文案任务交付提案或回填既有包装计划。
|
|
8
|
+
触发词:解说词、写解说、视频旁白、宣发标题、花字修订、文案回填、
|
|
8
9
|
narration script、写稿、解说文案、剪辑思路、导演思路。
|
|
9
10
|
---
|
|
10
11
|
|
|
11
12
|
## 1. 定位
|
|
12
13
|
|
|
14
|
+
只改宣发标题、封面、花字或回填外部文案时,直接读 `references/promotional-copy.md`,
|
|
15
|
+
按当前短片的观看理由和兑现位置处理指定文字层,不重做下述策划/旁白链。
|
|
16
|
+
普通解说写作不因此增加平台调研或包装任务。
|
|
17
|
+
|
|
13
18
|
本技能负责:创作方向、画面/声音计划、旁白写作与校验。Agent 不是 JSON 填写器,而要依次扮演:
|
|
14
19
|
|
|
15
20
|
1. 导演
|
|
@@ -18,9 +23,9 @@ description: >
|
|
|
18
23
|
4. 声音/旁白编辑
|
|
19
24
|
5. 第一次观看的观众
|
|
20
25
|
|
|
21
|
-
Agent 先记录简洁决定,再写时间线产物。`validate.py` 负责对理解索引做机械校验;full
|
|
26
|
+
Agent 先记录简洁决定,再写时间线产物。`validate.py` 负责对理解索引做机械校验;full 模式默认还会执行预算整理并计算旁白的原声重叠。已有批准稿应加 `--preserve-approved-text`,保留段落顺序、数量、时间、文本、停顿和扩展元数据,仅允许依据现有声音证据更新 `overlaps_speech`。
|
|
22
27
|
|
|
23
|
-
下面的 `scripts/...`
|
|
28
|
+
下面的 `scripts/...` 均相对于本技能目录。若执行器从仓库根目录启动,请给脚本路径加上本技能的绝对目录。
|
|
24
29
|
|
|
25
30
|
### 1.1 创作控制模式
|
|
26
31
|
|
|
@@ -125,7 +130,7 @@ cut 模式先根据 `recap_story_plan.json` 与 `visual_audio_board.json` 写原
|
|
|
125
130
|
beat_id | function | change | POV | preferred moment | 入点 | 出点
|
|
126
131
|
```
|
|
127
132
|
|
|
128
|
-
片段顺序必须构成一条完整故事线,而不是无序高光。可使用 0–1 个 cold open,随后回到因果清楚的 setup → turn → escalation → payoff
|
|
133
|
+
片段顺序必须构成一条完整故事线,而不是无序高光。可使用 0–1 个 cold open,随后回到因果清楚的 setup → turn → escalation → payoff。片段长度服从具体时刻,不使用统一秒数模板;片尾必须保留完整台词或动作。密集 scene-change 候选的来源判断与处理规则由剪辑阶段定义,写计划时遵循同一规则,不制造人工闪切。
|
|
129
134
|
|
|
130
135
|
## 4. 撰写旁白
|
|
131
136
|
|
|
@@ -232,17 +237,15 @@ python3 scripts/review.py --work-dir <work_dir>
|
|
|
232
237
|
|
|
233
238
|
```bash
|
|
234
239
|
python3 scripts/validate.py --work-dir <work_dir> --mode full
|
|
240
|
+
python3 scripts/validate.py --work-dir <work_dir> --mode full --preserve-approved-text
|
|
235
241
|
# cut 输出时间线由编排器使用 --mode cut_output
|
|
236
242
|
```
|
|
237
243
|
|
|
238
|
-
命令写出 `narration_lint.json`。full
|
|
244
|
+
命令写出 `narration_lint.json`。full 模式默认执行字符预算整理、去重合并并依据安静窗口计算 `overlaps_speech`,但不会把时间段移动到安静窗口;`--preserve-approved-text` 则保留批准稿的原始时间、文本、停顿、顺序与扩展元数据,只允许更新实测 `overlaps_speech`。修复所有 error 后重复运行,直到校验干净,再继续 TTS 与合成。
|
|
239
245
|
|
|
240
246
|
片名或题材明确但缺少剧情上下文时,先按本技能的 `references/research-guide.md` 写 `background_research.json`。若理解素材偏薄,brief 中的数量只能当上限:宁可少写、写实,也不要为凑数复述画面。
|
|
241
247
|
|
|
242
248
|
## 7. 能力边界
|
|
243
249
|
|
|
244
|
-
- 不运行 ASR / VLM
|
|
245
|
-
-
|
|
246
|
-
- 不根据平台分析做优化;先建立内容意图与剪辑一致性。
|
|
247
|
-
- `review.py` 不改写 `narration.json`;是否采用严格门禁由调用方决定。
|
|
248
|
-
- `validate.py` 不改写文本含义,只检查或对齐时间与安静窗口。
|
|
250
|
+
- 不运行 ASR / VLM,不合成 TTS,不渲染视频;只消费视频理解索引。
|
|
251
|
+
- 平台研究仅用于明确的宣发任务;不替代当前片内事实,也不默认改变解说和剪辑。
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
- **DIRECTED**:用户已经指定结构、镜头、台词或表达,目标是准确落实而不是展示替代创意。
|
|
9
9
|
- **REVISION**:基于已有版本看片修改。最新反馈覆盖旧决定;本轮未点名内容默认冻结。
|
|
10
10
|
|
|
11
|
-
REVISION 先列本轮修改项与冻结项。表达、节奏、字幕意见写回 `style_card.json`,镜头与声音意见写回 `visual_audio_board.json`;只有故事主线改变才更新 `recap_story_plan.json
|
|
11
|
+
REVISION 先列本轮修改项与冻结项。表达、节奏、字幕意见写回 `style_card.json`,镜头与声音意见写回 `visual_audio_board.json`;只有故事主线改变才更新 `recap_story_plan.json`。删除内容时也删除过期的计划描述。只提能定位到 beat、镜头边界或句子的具体局部修法,未点名层继续冻结;完成后分别验证“该变的确实变了”和“不该变的没有漂移”。
|
|
12
12
|
|
|
13
13
|
## 决策优先级
|
|
14
14
|
|
|
@@ -53,7 +53,9 @@ beat 不是固定秒数、场景名或一句旁白;beat 是一次可感知的
|
|
|
53
53
|
- 情绪如何转向;
|
|
54
54
|
- 风险或代价如何升级。
|
|
55
55
|
|
|
56
|
-
如果移除一个 beat
|
|
56
|
+
如果移除一个 beat 后,因果、人物或情绪都没有损失,它通常不值得占用成片时间。精简不能只保“发生了什么”:还要保住人物动机、接受条件,以及人物为何犹豫或行动;缺前提时回到源证据,用更短的原声或解说补齐,不恢复无关长铺垫。钩子必须提出这条故事真正会兑现的问题,不能制造正文不回答的夸张承诺。
|
|
57
|
+
|
|
58
|
+
准备移交剪辑时,把这类不可删除的具体源时刻写入同一 `clip_plan.json.required_evidence`:`nodes` 每项记录唯一 `id`、实际文件绝对路径 `source`、原片秒 `start/end`、`track`(audio/video)和 `content`;多源可补 `source_id`。`before` 用 `[前提id, 回应id]` 登记本片必需的顺序。只锁必要区间,不锁整个 beat;不依赖 `reason` 里的“保留前提”一句话。剪辑执行器会在吸附剪点后核对这些要求,缺段时先修选择,再配音包装。
|
|
57
59
|
|
|
58
60
|
### 3. 画面剪辑:选择时刻,而不只选择事件
|
|
59
61
|
|
|
@@ -65,16 +67,18 @@ beat 不是固定秒数、场景名或一句旁白;beat 是一次可感知的
|
|
|
65
67
|
- **不可替代瞬间**:停顿、迟疑、失误、眼神、动作声音中,哪一个让人物变得真实?
|
|
66
68
|
- **节奏**:这一拍需要冲过去,还是需要多停半秒让含义落地?
|
|
67
69
|
- **边界**:优先完整动作、完整台词和自然声音边界;不要机械地把每个片段切成同一长度。
|
|
70
|
+
- **兑现**:以某个可见结果为看点时,只写证据已呈现的结果,不推断更强的结果(例:证据只到受击,就不能写成倒地或胜负)。
|
|
68
71
|
|
|
69
72
|
进入 `clip_plan.json` 的不是“发生过的所有重要事件”,而是最能让观众经历这条主线的具体时刻。
|
|
70
73
|
|
|
71
|
-
|
|
74
|
+
目标不是绝对最短,而是**最短但完整**:晚进不能丢掉理解动作所需的前提,早出不能吃掉表演的回报。建立空间和事实的镜头通常可以短;关键对视、亲吻、受伤反应、决定落地或沉默可以多停一点,让观众先感受到再离开。有情感回应或知情变化的反应镜不是冗余,不能仅因它是反打或停留较短就机械删除。
|
|
72
75
|
|
|
73
76
|
场景之间的 IN / OUT 也要有任务:
|
|
74
77
|
|
|
75
78
|
- 新人物、地点或情绪场景,先给画面一个可感知的建立时刻,再让旁白进入;旁白不必与画面同帧起跑。
|
|
76
79
|
- OUT 优先落在动作完成、反应落地、台词句末、沉默结束或干净硬切前。
|
|
77
80
|
- 不要在原片叠化、闪白或其他转场的中间再切一次。转场至少由画面变化、动作延续、声音接力或叙事跨越中的一项驱动。
|
|
81
|
+
- 跨场镜头只能作明确的并置或主题呼应,不得拼成同场出手、接触、反应的虚假因果;花字只能补有证据的必要前提,不能替补源证据或提前宣布结果。
|
|
78
82
|
|
|
79
83
|
scene-change score、逐帧亮度和接点 contact sheet 只用于诊断:检查每个接点前后约 0.5–1 秒,定位硬切、白闪或曝光叠化候选。修复优先收进稳定镜头、保留原片完整转场的一侧、扩展源素材,或用相邻有效镜头补足时长;不能为了视觉干净切断台词。最终必须真实播放接点,不能把检测分数当成观看结论。
|
|
80
84
|
|
|
@@ -90,7 +94,7 @@ ffmpeg -i input.mp4 -vf "select='gt(scene,0.35)',showinfo" -an -f null -
|
|
|
90
94
|
- **本次剪辑制造的切点**:优先移动 IN / OUT、恢复同一源镜头的连续运动、合并相邻片段,或换成有叙事任务的连接镜头;能消除就不保留。溶解、闪白和包装不能用来遮掩坏接点。
|
|
91
95
|
- **有意的原片蒙太奇**:只有当每个短镜头都提供新信息、动作或节奏回报,且正常播放仍清楚可读时才保留;否则按无关或过短镜头处理。
|
|
92
96
|
|
|
93
|
-
|
|
97
|
+
密集度不是单一固定秒数门槛。反打是否保留取决于它有没有新增信息,例如关系、情感回应、知情变化或空间/动作结果,而不是是否达到统一时长;先找同一短窗内的连续候选,再以正常速度播放判断观众感受到的是有效节奏还是闪烁。
|
|
94
98
|
|
|
95
99
|
### 4. 声音与旁白:先分工,再写字
|
|
96
100
|
|
|
@@ -128,7 +132,7 @@ ffmpeg -i input.mp4 -vf "select='gt(scene,0.35)',showinfo" -an -f null -
|
|
|
128
132
|
再逐 beat 追问:
|
|
129
133
|
|
|
130
134
|
- 删除它,什么会坏?什么都不坏就删。
|
|
131
|
-
-
|
|
135
|
+
- 删除或换掉反应镜头后,是否丢失情感回应、知情变化或新的动作结果?
|
|
132
136
|
- 旁白改成原声或沉默,含义是否更好?
|
|
133
137
|
- 提前揭示或延后揭示,哪一个更符合 POV?
|
|
134
138
|
- 能否晚进、早出,而不损失理解?
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# 宣发标题、花字与文案返修
|
|
2
|
+
|
|
3
|
+
用户要求宣发选题、标题/封面/发布稿、花字优化,或把外部模型的文案回填时使用。
|
|
4
|
+
只写解说或精修剪点时不增加这一步。
|
|
5
|
+
|
|
6
|
+
## 先确定这条片卖什么
|
|
7
|
+
|
|
8
|
+
从当前短片而不是整部剧提炼一个具体观看理由:人物做了什么选择、付出什么代价,
|
|
9
|
+
观众将看懂什么或感受到什么。先标出片内兑现的画面/原声位置,再写承诺。
|
|
10
|
+
同一批可以分别卖关系、选择、笑点、动作或推理,不把每条都套成反转或复仇。
|
|
11
|
+
|
|
12
|
+
用户需要案例研究时,按发行状态选来源:
|
|
13
|
+
|
|
14
|
+
- **已播剧**:看本剧社媒的真实讨论、传播切片与观众关注点,再判断当前短片能否承接。
|
|
15
|
+
- **未发布剧**:用剧本特色和片内证据形成受众假设,参考近期成功宣发案例;不假设本剧已有热度。
|
|
16
|
+
|
|
17
|
+
记录参考物料的发布者、链接、发布日期、采集日期、具体做法及可借部分。
|
|
18
|
+
单条播放、整剧热度、话题聚合量分开写;有数字也不等于证明某句标题带来了成绩。
|
|
19
|
+
旧研究需要更新时再查证;未查到的效果不补数字,离线方案明确只依据已有材料。
|
|
20
|
+
|
|
21
|
+
## 给其他模型的任务包
|
|
22
|
+
|
|
23
|
+
按共同剧情与观看理由分组,让每组有足够上下文,但每条分别交付。直接用短 Markdown
|
|
24
|
+
任务包即可,不另造视频时间线。每条提供:
|
|
25
|
+
|
|
26
|
+
1. **当前版本**:具体工程、对应成片和待渲染修改;有版本号时沿用已有值。
|
|
27
|
+
2. **片内内容**:正文结束点、故事起因与回报、当前选镜、原声/解说字幕、时间属于哪版成片。
|
|
28
|
+
3. **现有文案**:两行标题、花字及其位置/时间、时空提示;封面和发布稿存在时一并给出。
|
|
29
|
+
4. **本轮范围**:允许修改的文字层,以及保留的剪点、字幕、旁白、声音、样式和片尾。
|
|
30
|
+
5. **证据缺口**:角色所说与已发生事实的差别、未出现的结果、模糊专名和未核时码。
|
|
31
|
+
|
|
32
|
+
附一段可直接使用的要求:
|
|
33
|
+
|
|
34
|
+
> 先解释这条短片为什么值得点开、看完得到什么,再给主推文案;需要备选时按不同观看理由区分,
|
|
35
|
+
> 不只替换近义词。两行常驻标题、封面字和发布标题各司其职。花字、时空提示分别列修改;
|
|
36
|
+
> 每处给原文、建议、成片位置和片内依据。没有必要就不加花字。只看到工程/字幕时,
|
|
37
|
+
> 时间窗是提案,不能声称已看片。若问题只能靠改镜头或声音解决,单列出来,不用加字掩盖。
|
|
38
|
+
|
|
39
|
+
## 写字时的分工
|
|
40
|
+
|
|
41
|
+
| 层 | 工作 | 常见修法 |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| 常驻标题 | 让陌生观众理解人物处境与本片回报 | 用动作和代价降低人名/术语门槛;不提前宣布未呈现的胜负 |
|
|
44
|
+
| 封面字 | 在封面画面上聚焦一个看点 | 不再塞一遍两行标题;文字需与所选封面帧一致 |
|
|
45
|
+
| 发布标题 | 补关系、背景或观看邀请 | 不把解说全文搬过来,不冒充角色原话 |
|
|
46
|
+
| 花字 | 补必要理解、观察方向或克制的情绪批注 | 不重复对白、不遮关键动作;拥挤时优先撤花字 |
|
|
47
|
+
| 时空提示 | 说明当前/往事、地点或画外判断来源 | 跟随画面切换,不跟跨场旁白提前切换 |
|
|
48
|
+
| 对白/旁白字幕 | 忠实承载当前可听见的话 | 不属于宣发改字范围,不拿新花字覆盖或替代 |
|
|
49
|
+
|
|
50
|
+
“却”“不是……而是……”不是禁词;当素材没有需要纠正的预期时,直接写行动和后果。
|
|
51
|
+
人物许诺不等于事情已成,单向凝望不等于双方相爱,受伤不等于死亡。
|
|
52
|
+
批量检查重复的是观看理由和句式,不把共享镜头但回报不同的片子合并成同题。
|
|
53
|
+
|
|
54
|
+
## 回填到当前工程
|
|
55
|
+
|
|
56
|
+
- 先核任务包对应的工程是否仍是本轮采用基础;已有新剪点、换序、换声或待渲染字幕时,
|
|
57
|
+
把建议重新对到新版本,不把旧全文覆盖回去,也不凭文件修改时间决定采用。
|
|
58
|
+
- 复制当前工程为新候选,只改本轮采用项;未明确改动的文字、ID、时码、位置和可见性保留。
|
|
59
|
+
**没提到不等于删除**。`notes=[]` 在提案中可表示不新增;回填完整工程时则是清空整轨,
|
|
60
|
+
必须先把“保留/新增/替换/删除”逐项说明白。
|
|
61
|
+
- 新增或明确调整花字/时空标的时间时,先对照当前成片的真实画面/台词和帧钟确定出入点;
|
|
62
|
+
CFR核实际帧,VFR用真实PTS找到对应帧号。建议窗只到小数三位时,不当作已核准的帧级锚点。
|
|
63
|
+
- 使用已有包装工程的字段,不再造一套对白轨:标题、花字、时空提示各写回它们原本所在的层,
|
|
64
|
+
时间最终写整数半开区间的帧号,不是浮点秒数;工程里指向素材、字幕和样式的引用原样保留。
|
|
65
|
+
封面与发布稿仍放文案交付,不塞进画面渲染计划。
|
|
66
|
+
- 回填后比较修改前后:逐项核已采用的文字变化、未改层一致、时窗未超正文。已有制作工具先做
|
|
67
|
+
计划校验;用户只要改轨时到此停止。渲染后再核新字实际出现、遮挡和阅读负担,不能把
|
|
68
|
+
工程已改叫成片已更新。
|