@oh-story/dsh 0.1.8 → 0.1.9
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 +11 -11
- package/lib/client.js +35 -14
- package/lib/client.js.map +2 -2
- package/lib/drama/manifest.json +165 -69
- package/lib/drama/skills/short-drama/SKILL.md +5 -1
- package/lib/drama/skills/short-drama/scripts/creator_markdown_check.py +126 -9
- package/lib/drama/skills/short-drama/scripts/project_tool.py +11 -0
- package/lib/drama/skills/short-drama-assets/references/character-and-look.md +18 -0
- package/lib/drama/skills/short-drama-assets/references/continuity-lock.md +10 -1
- package/lib/drama/skills/short-drama-edit/SKILL.md +148 -0
- package/lib/drama/skills/short-drama-edit/agents/openai.yaml +4 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/README.md +60 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/package.json +15 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/remotion.config.ts +6 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/Root.tsx +26 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/Subtitles.tsx +88 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/font.ts +46 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/index.ts +4 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/src/schema.ts +32 -0
- package/lib/drama/skills/short-drama-edit/assets/remotion/tsconfig.json +13 -0
- package/lib/drama/skills/short-drama-edit/assets//345/211/252/350/276/221/345/215/225.md +43 -0
- package/lib/drama/skills/short-drama-edit/references/cut-craft.md +81 -0
- package/lib/drama/skills/short-drama-edit/references/delivery-verify.md +58 -0
- package/lib/drama/skills/short-drama-edit/references/generated-footage.md +96 -0
- package/lib/drama/skills/short-drama-edit/references/sound-and-subtitles.md +113 -0
- package/lib/drama/skills/short-drama-edit/references/stage-contract.md +55 -0
- package/lib/drama/skills/short-drama-edit/scripts/edit_tool.py +1041 -0
- package/lib/drama/skills/short-drama-edit/scripts/selftest.py +456 -0
- package/lib/drama/skills/short-drama-image-prompts/assets/image-prompts.md +5 -0
- package/lib/drama/skills/short-drama-image-prompts/assets/lookdev-prompts.md +3 -0
- package/lib/drama/skills/short-drama-novel-analyze/references/aggregation-and-entities.md +2 -2
- package/lib/drama/skills/short-drama-novel-analyze/references/chapter-extraction.md +4 -1
- package/lib/drama/skills/short-drama-produce/SKILL.md +24 -3
- package/lib/drama/skills/short-drama-produce/references/adapter-contract.md +28 -0
- package/lib/drama/skills/short-drama-produce/references/providers/minimax-h3-video.md +24 -5
- package/lib/drama/skills/short-drama-produce/references/providers/seedance.md +7 -0
- package/lib/drama/skills/short-drama-produce/scripts/fixture_adapter.py +18 -1
- package/lib/drama/skills/short-drama-produce/scripts/production_tool.py +181 -2
- package/lib/drama/skills/short-drama-produce/scripts/provider_adapters.py +57 -2
- package/lib/drama/skills/short-drama-review/SKILL.md +3 -0
- package/lib/drama/skills/short-drama-review/references/production-quality-gates.md +20 -0
- package/lib/drama/skills/short-drama-review/references/rubric-visual-motion.md +36 -0
- package/lib/drama/skills/short-drama-storyboard/SKILL.md +7 -0
- package/lib/drama/skills/short-drama-storyboard/assets/keyframe-prompts.md +4 -0
- package/lib/drama/skills/short-drama-storyboard/references/shot-craft.md +39 -0
- package/lib/drama/skills/short-drama-storyboard/references/stage-contract.md +2 -0
- package/lib/drama/skills/short-drama-video-prompts/SKILL.md +7 -1
- package/lib/drama/skills/short-drama-video-prompts/references/minimax-h3.md +101 -6
- package/lib/drama/skills/short-drama-video-prompts/references/motion-recipe.md +7 -1
- package/lib/drama/skills/short-drama-video-prompts/references/performance-action-timing.md +35 -0
- package/lib/drama/skills/short-drama-video-prompts/references/production-prompt-grammar.md +3 -1
- package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.0.md +13 -3
- package/lib/drama/skills/short-drama-video-prompts/references/seedance-2.5.md +35 -4
- package/lib/drama/skills/short-drama-video-prompts/references/stage-contract.md +1 -1
- package/lib/drama/skills/short-drama-write/SKILL.md +13 -2
- package/lib/drama/skills/short-drama-write/references/screenplay-format.md +6 -0
- package/lib/drama/skills/short-drama-write/references/stage-contract.md +1 -0
- package/lib/index.js +4 -2
- package/lib/index.js.map +2 -2
- package/lib/novel-to-game/VERSION +1 -1
- package/lib/novel-to-game/manifest.json +28 -28
- package/lib/novel-to-game/skills/game-art-direction/SKILL.md +6 -27
- package/lib/novel-to-game/skills/game-build/SKILL.md +12 -29
- package/lib/novel-to-game/skills/game-concept/SKILL.md +10 -26
- package/lib/novel-to-game/skills/game-qa/SKILL.md +5 -15
- package/lib/novel-to-game/skills/game-qa/references/test-design-method.md +1 -1
- package/lib/novel-to-game/skills/game-world-design/SKILL.md +19 -28
- package/lib/novel-to-game/skills/game-world-design/references/dialogue-design-method.md +1 -2
- package/lib/novel-to-game/skills/novel-game-analyze/SKILL.md +6 -9
- package/lib/novel-to-game/skills/novel-to-game/SKILL.md +6 -11
- package/lib/novel-to-game/skills/novel-to-game/references/intake-benchmark-reference.md +0 -4
- package/lib/novel-to-game/skills/novel-to-game/references/intake-method.md +1 -3
- package/lib/novel-to-game/skills/novel-to-game/references/pipeline-contract.md +3 -5
- package/lib/oh-story/manifest.json +292 -172
- package/lib/oh-story/roles/character-designer.md +1 -1
- package/lib/oh-story/roles/narrative-writer.md +56 -242
- package/lib/oh-story/roles/story-architect.md +1 -1
- package/lib/oh-story/skills/story/SKILL.md +1 -1
- package/lib/oh-story/skills/story/VERSION +1 -1
- package/lib/oh-story/skills/story/references/author-memory.md +10 -8
- package/lib/oh-story/skills/story-deslop/SKILL.md +20 -182
- package/lib/oh-story/skills/story-deslop/references/anti-ai-writing.md +19 -47
- package/lib/oh-story/skills/story-deslop/references/author-memory.md +10 -8
- package/lib/oh-story/skills/story-deslop/references/banned-words.md +3 -1
- package/lib/oh-story/skills/story-deslop/references/deslop-gates.md +154 -0
- package/lib/oh-story/skills/story-deslop/references/style-resolution.md +27 -0
- package/lib/oh-story/skills/story-deslop/scripts/check-ai-patterns.js +6 -1
- package/lib/oh-story/skills/story-deslop/scripts/check-degeneration.js +39 -20
- package/lib/oh-story/skills/story-deslop/scripts/normalize-punctuation.js +10 -5
- package/lib/oh-story/skills/story-deslop/scripts/style-whitelist.js +39 -0
- package/lib/oh-story/skills/story-import/SKILL.md +2 -2
- package/lib/oh-story/skills/story-import/references/format-and-structure.md +2 -2
- package/lib/oh-story/skills/story-import/references/tracking-initialization.md +31 -0
- package/lib/oh-story/skills/story-import/references/tracking-transaction.md +2 -29
- package/lib/oh-story/skills/story-import/scripts/check-outline-contract.js +176 -12
- package/lib/oh-story/skills/story-long-analyze/SKILL.md +1 -1
- package/lib/oh-story/skills/story-long-write/SKILL.md +20 -193
- package/lib/oh-story/skills/story-long-write/references/anti-ai-writing.md +19 -47
- package/lib/oh-story/skills/story-long-write/references/artifact-protocols.md +62 -7
- package/lib/oh-story/skills/story-long-write/references/author-memory.md +10 -8
- package/lib/oh-story/skills/story-long-write/references/banned-words.md +3 -1
- package/lib/oh-story/skills/story-long-write/references/benchmark-recall.md +20 -0
- package/lib/oh-story/skills/story-long-write/references/dialogue-mastery.md +6 -4
- package/lib/oh-story/skills/story-long-write/references/long-chapter-quality.md +2 -2
- package/lib/oh-story/skills/story-long-write/references/long-format.md +2 -0
- package/lib/oh-story/skills/story-long-write/references/outline-structure-theory.md +2 -0
- package/lib/oh-story/skills/story-long-write/references/project-files.md +108 -0
- package/lib/oh-story/skills/story-long-write/references/reference-index.md +87 -0
- package/lib/oh-story/skills/story-long-write/references/style-combat-face.md +1 -1
- package/lib/oh-story/skills/story-long-write/references/style-craft.md +9 -29
- 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 +27 -0
- package/lib/oh-story/skills/story-long-write/references/tracking-initialization.md +31 -0
- package/lib/oh-story/skills/story-long-write/references/tracking-transaction.md +2 -29
- package/lib/oh-story/skills/story-long-write/references/workflow-chapter.md +51 -52
- package/lib/oh-story/skills/story-long-write/references/workflow-daily.md +8 -7
- package/lib/oh-story/skills/story-long-write/references/workflow-setup.md +36 -15
- package/lib/oh-story/skills/story-long-write/references/writer-prompt-fallback.md +22 -0
- package/lib/oh-story/skills/story-long-write/references/writing-craft.md +69 -2
- package/lib/oh-story/skills/story-long-write/scripts/build_writer_prompt.py +410 -0
- package/lib/oh-story/skills/story-long-write/scripts/check-ai-patterns.js +6 -1
- package/lib/oh-story/skills/story-long-write/scripts/check-degeneration.js +39 -20
- package/lib/oh-story/skills/story-long-write/scripts/check-outline-contract.js +176 -12
- package/lib/oh-story/skills/story-long-write/scripts/check-outline-copy.js +90 -23
- package/lib/oh-story/skills/story-long-write/scripts/normalize-punctuation.js +10 -5
- package/lib/oh-story/skills/story-long-write/scripts/outline_view.py +283 -0
- package/lib/oh-story/skills/story-long-write/scripts/style-whitelist.js +39 -0
- package/lib/oh-story/skills/story-review/SKILL.md +13 -3
- package/lib/oh-story/skills/story-review/references/anti-ai-writing.md +19 -47
- package/lib/oh-story/skills/story-review/references/author-memory.md +10 -8
- package/lib/oh-story/skills/story-review/references/banned-words.md +3 -1
- package/lib/oh-story/skills/story-review/references/dialogue-mastery.md +6 -4
- package/lib/oh-story/skills/story-review/references/review-quality.md +2 -2
- package/lib/oh-story/skills/story-review/references/style-resolution.md +27 -0
- package/lib/oh-story/skills/story-review/references/tracking-initialization.md +31 -0
- package/lib/oh-story/skills/story-review/references/tracking-transaction.md +2 -29
- package/lib/oh-story/skills/story-review/scripts/check-ai-patterns.js +6 -1
- package/lib/oh-story/skills/story-review/scripts/check-degeneration.js +39 -20
- package/lib/oh-story/skills/story-review/scripts/normalize-punctuation.js +10 -5
- package/lib/oh-story/skills/story-review/scripts/style-whitelist.js +39 -0
- package/lib/oh-story/skills/story-setup/SKILL.md +17 -10
- package/lib/oh-story/skills/story-setup/references/agent-references/anti-ai-writing.md +19 -47
- package/lib/oh-story/skills/story-setup/references/agent-references/banned-words.md +3 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/deslop-gates.md +154 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/dialogue-mastery.md +6 -4
- package/lib/oh-story/skills/story-setup/references/agent-references/format-and-structure.md +2 -2
- package/lib/oh-story/skills/story-setup/references/agent-references/short-genre-formulas.md +1 -1
- package/lib/oh-story/skills/story-setup/references/agent-references/style-combat-face.md +1 -1
- 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 +27 -0
- package/lib/oh-story/skills/story-setup/references/agent-references/writing-craft.md +69 -2
- package/lib/oh-story/skills/story-setup/references/diagnostics.md +38 -0
- package/lib/oh-story/skills/story-short-analyze/references/analysis-writing-techniques.md +1 -1
- package/lib/oh-story/skills/story-short-analyze/references/source-story-quality.md +2 -2
- package/lib/oh-story/skills/story-short-write/SKILL.md +18 -186
- package/lib/oh-story/skills/story-short-write/references/author-memory.md +10 -8
- package/lib/oh-story/skills/story-short-write/references/banned-words.md +3 -1
- package/lib/oh-story/skills/story-short-write/references/benchmark-recall.md +60 -0
- package/lib/oh-story/skills/story-short-write/references/dialogue-mastery.md +6 -4
- package/lib/oh-story/skills/story-short-write/references/genre-styles//344/270/226/346/203/205/346/211/223/350/204/270.md +2 -2
- package/lib/oh-story/skills/story-short-write/references/genre-styles//345/217/214/347/224/267/344/270/273.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/genre-styles//345/244/215/344/273/207/346/211/223/350/204/270.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/genre-styles//345/256/205/346/226/227/345/256/253/346/226/227.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/200/273/350/243/201/350/261/252/351/227/250.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/202/254/347/226/221.md +5 -5
- package/lib/oh-story/skills/story-short-write/references/genre-styles//346/260/221/344/277/227/346/200/252/350/260/210.md +4 -4
- package/lib/oh-story/skills/story-short-write/references/genre-styles//347/224/234/345/256/240.md +5 -5
- package/lib/oh-story/skills/story-short-write/references/genre-styles//350/277/275/345/246/273/347/201/253/350/221/254/345/234/272.md +3 -3
- package/lib/oh-story/skills/story-short-write/references/genre-writing-formulas.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/genre-writing-techniques.md +1 -1
- package/lib/oh-story/skills/story-short-write/references/reference-index.md +53 -0
- package/lib/oh-story/skills/story-short-write/references/short-craft.md +12 -14
- package/lib/oh-story/skills/story-short-write/references/short-deslop.md +10 -10
- package/lib/oh-story/skills/story-short-write/references/short-format.md +3 -1
- package/lib/oh-story/skills/story-short-write/references/short-prose-quality.md +2 -2
- package/lib/oh-story/skills/story-short-write/references/style-resolution.md +27 -0
- package/lib/oh-story/skills/story-short-write/references/workflow-design.md +77 -0
- package/lib/oh-story/skills/story-short-write/references/writing-workflow.md +5 -5
- package/lib/oh-story/skills/story-short-write/scripts/check-ai-patterns.js +6 -1
- package/lib/oh-story/skills/story-short-write/scripts/check-degeneration.js +39 -20
- package/lib/oh-story/skills/story-short-write/scripts/check-delivery-contract.js +34 -5
- package/lib/oh-story/skills/story-short-write/scripts/check-outline-copy.js +90 -23
- package/lib/oh-story/skills/story-short-write/scripts/normalize-punctuation.js +10 -5
- package/lib/oh-story/skills/story-short-write/scripts/style-whitelist.js +39 -0
- package/lib/types/client/drama-production-view.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/production-prompts.d.ts.map +1 -1
- package/lib/types/client/production-runtime.d.ts +17 -0
- package/lib/types/client/production-runtime.d.ts.map +1 -1
- package/lib/types/skill-provider.d.ts.map +1 -1
- package/lib/video-recap/CHANGELOG.md +31 -1
- package/lib/video-recap/manifest.json +162 -162
- package/lib/video-recap/skills/video-assemble/scripts/artifacts.py +4 -9
- package/lib/video-recap/skills/video-assemble/scripts/assemble.py +47 -60
- package/lib/video-recap/skills/video-assemble/scripts/assembly_contract.py +77 -115
- package/lib/video-recap/skills/video-assemble/scripts/assembly_settings.py +41 -40
- package/lib/video-recap/skills/video-assemble/scripts/audio_automation.py +22 -32
- package/lib/video-recap/skills/video-assemble/scripts/audio_mix.py +102 -192
- package/lib/video-recap/skills/video-assemble/scripts/jianying_builders.py +14 -35
- package/lib/video-recap/skills/video-assemble/scripts/jianying_model.py +14 -12
- package/lib/video-recap/skills/video-assemble/scripts/jianying_optional.py +8 -9
- package/lib/video-recap/skills/video-assemble/scripts/jianying_schema.py +3 -14
- package/lib/video-recap/skills/video-assemble/scripts/jianying_timeline_contract.py +23 -12
- package/lib/video-recap/skills/video-assemble/scripts/jianying_tracks.py +1 -4
- package/lib/video-recap/skills/video-assemble/scripts/jianying_writer.py +24 -25
- package/lib/video-recap/skills/video-assemble/scripts/lib.py +31 -85
- package/lib/video-recap/skills/video-assemble/scripts/media.py +100 -144
- package/lib/video-recap/skills/video-assemble/scripts/narration_audio.py +101 -195
- package/lib/video-recap/skills/video-assemble/scripts/render_preflight.py +10 -21
- package/lib/video-recap/skills/video-assemble/scripts/source_subtitles.py +90 -169
- package/lib/video-recap/skills/video-assemble/scripts/subtitle_core.py +69 -122
- package/lib/video-recap/skills/video-assemble/scripts/subtitle_render.py +10 -17
- package/lib/video-recap/skills/video-assemble/scripts/timeline.py +33 -48
- package/lib/video-recap/skills/video-assemble/scripts/timeline_emit.py +14 -20
- package/lib/video-recap/skills/video-assemble/scripts/visual_render.py +135 -213
- package/lib/video-recap/skills/video-cut/scripts/cut_cli.py +49 -57
- package/lib/video-recap/skills/video-cut/scripts/cut_contract.py +38 -74
- package/lib/video-recap/skills/video-cut/scripts/cut_render.py +46 -95
- package/lib/video-recap/skills/video-cut/scripts/lib.py +23 -25
- package/lib/video-recap/skills/video-cut/scripts/media_geometry.py +70 -173
- package/lib/video-recap/skills/video-cut/scripts/narration_mapping.py +28 -53
- package/lib/video-recap/skills/video-cut/scripts/sentence_boundaries.py +162 -322
- package/lib/video-recap/skills/video-recap/references/timeline-and-jianying.md +6 -7
- package/lib/video-recap/skills/video-recap/scripts/doctor.py +104 -124
- package/lib/video-recap/skills/video-recap/scripts/final_qc.py +255 -412
- package/lib/video-recap/skills/video-recap/scripts/lib.py +30 -52
- package/lib/video-recap/skills/video-recap/scripts/materials.py +97 -120
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_client.py +7 -12
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_evidence.py +46 -97
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_observations.py +18 -36
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_payload.py +29 -47
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_report.py +43 -76
- package/lib/video-recap/skills/video-recap/scripts/mimo_qc_runner.py +2 -1
- package/lib/video-recap/skills/video-recap/scripts/qc_contract.py +2 -1
- package/lib/video-recap/skills/video-recap/scripts/recap_cli.py +2 -2
- package/lib/video-recap/skills/video-recap/scripts/recap_inspect.py +129 -145
- package/lib/video-recap/skills/video-recap/scripts/recap_review.py +27 -20
- package/lib/video-recap/skills/video-recap/scripts/recap_runner.py +20 -31
- package/lib/video-recap/skills/video-recap/scripts/recap_runtime.py +31 -106
- package/lib/video-recap/skills/video-recap/scripts/recap_stage_qc.py +43 -113
- package/lib/video-recap/skills/video-recap/scripts/recap_timeline.py +196 -377
- package/lib/video-recap/skills/video-script/scripts/agent_brief.py +1 -1
- package/lib/video-recap/skills/video-script/scripts/agent_text.py +63 -172
- package/lib/video-recap/skills/video-script/scripts/brief_context.py +80 -135
- package/lib/video-recap/skills/video-script/scripts/brief_inputs.py +125 -167
- package/lib/video-recap/skills/video-script/scripts/brief_timeline.py +93 -208
- package/lib/video-recap/skills/video-script/scripts/deslop_qc.py +20 -46
- package/lib/video-recap/skills/video-script/scripts/lib.py +30 -26
- package/lib/video-recap/skills/video-script/scripts/narration_lint.py +145 -140
- package/lib/video-recap/skills/video-script/scripts/review_response.py +12 -42
- package/lib/video-recap/skills/video-script/scripts/review_runner.py +0 -6
- package/lib/video-recap/skills/video-script/scripts/speech_ownership.py +39 -100
- package/lib/video-recap/skills/video-script/scripts/timeline_fusion.py +33 -124
- package/lib/video-recap/skills/video-understanding/scripts/agent_brief.py +1 -1
- package/lib/video-recap/skills/video-understanding/scripts/agent_text.py +63 -172
- package/lib/video-recap/skills/video-understanding/scripts/asr.py +1 -2
- package/lib/video-recap/skills/video-understanding/scripts/brief_context.py +80 -135
- package/lib/video-recap/skills/video-understanding/scripts/brief_inputs.py +125 -167
- package/lib/video-recap/skills/video-understanding/scripts/brief_timeline.py +93 -208
- package/lib/video-recap/skills/video-understanding/scripts/consolidate.py +1 -1
- package/lib/video-recap/skills/video-understanding/scripts/deslop_qc.py +20 -46
- package/lib/video-recap/skills/video-understanding/scripts/lib.py +31 -26
- package/lib/video-recap/skills/video-understanding/scripts/narration_lint.py +145 -140
- package/lib/video-recap/skills/video-understanding/scripts/speech_ownership.py +39 -100
- package/lib/video-recap/skills/video-understanding/scripts/timeline_fusion.py +33 -124
- package/lib/video-recap/skills/video-understanding/scripts/vlm.py +1 -4
- package/lib/video-recap/skills/video-voiceover/scripts/dub.py +7 -13
- package/lib/video-recap/skills/video-voiceover/scripts/fish_audio.py +12 -30
- package/lib/video-recap/skills/video-voiceover/scripts/lib.py +98 -131
- package/lib/video-recap/skills/video-voiceover/scripts/tts_audio.py +17 -28
- package/lib/video-recap/skills/video-voiceover/scripts/voiceover.py +151 -240
- package/package.json +41 -41
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { continueRender, delayRender } from "remotion";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Remotion captures a frame as soon as React has painted, so a font still being
|
|
5
|
+
* fetched is simply absent from it. Nothing downstream reports that: the film
|
|
6
|
+
* measures correct and reads wrong.
|
|
7
|
+
*/
|
|
8
|
+
export const waitForFonts = (): void => {
|
|
9
|
+
const handle = delayRender("等待字体就绪");
|
|
10
|
+
document.fonts.ready.then(
|
|
11
|
+
() => continueRender(handle),
|
|
12
|
+
() => continueRender(handle),
|
|
13
|
+
);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* `document.fonts.ready` promises that loading finished, not that the requested
|
|
18
|
+
* family exists — a missing face raises nothing, the browser substitutes, and
|
|
19
|
+
* the film ships in the wrong typeface. Measuring is the only reliable test:
|
|
20
|
+
* identical widths against a family that cannot exist mean nothing resolved.
|
|
21
|
+
*/
|
|
22
|
+
let familyChecked = "";
|
|
23
|
+
|
|
24
|
+
export const assertFamilyResolves = (fontFamily: string, sample: string): void => {
|
|
25
|
+
// Runs on every frame, so measure once per family.
|
|
26
|
+
if (!sample || familyChecked === fontFamily) return;
|
|
27
|
+
const canvas = document.createElement("canvas");
|
|
28
|
+
const context = canvas.getContext("2d");
|
|
29
|
+
if (!context) return;
|
|
30
|
+
|
|
31
|
+
const measure = (family: string): number => {
|
|
32
|
+
context.font = `700 64px ${family}`;
|
|
33
|
+
return context.measureText(sample).width;
|
|
34
|
+
};
|
|
35
|
+
// A name no font can carry, so it always lands on the browser's last resort.
|
|
36
|
+
const fallbackOnly = measure('"__no_such_family__"');
|
|
37
|
+
const requested = measure(`${fontFamily}, "__no_such_family__"`);
|
|
38
|
+
if (requested === fallbackOnly) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`字幕字体 ${fontFamily} 在渲染环境里一个都没装上,` +
|
|
41
|
+
"画面会落到浏览器的兜底字体。装一款其中的字体," +
|
|
42
|
+
"或给 render 传一个本机确实有的字体族。",
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
familyChecked = fontFamily;
|
|
46
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type Cue = {
|
|
2
|
+
/** Output-time seconds, measured from the rendered segments. */
|
|
3
|
+
start: number;
|
|
4
|
+
end: number;
|
|
5
|
+
/** The line as written in 剧本.md. Never a transcription. */
|
|
6
|
+
text: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type SubtitleProps = {
|
|
10
|
+
cues: Cue[];
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
fps: number;
|
|
14
|
+
durationInSeconds: number;
|
|
15
|
+
/** Type size as a fraction of frame height, so one number survives any delivery. */
|
|
16
|
+
fontScale: number;
|
|
17
|
+
/** Distance from the bottom edge, also a fraction of frame height. */
|
|
18
|
+
bottomScale: number;
|
|
19
|
+
fontFamily: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const defaultProps: SubtitleProps = {
|
|
23
|
+
cues: [],
|
|
24
|
+
width: 1080,
|
|
25
|
+
height: 1920,
|
|
26
|
+
fps: 24,
|
|
27
|
+
durationInSeconds: 1,
|
|
28
|
+
fontScale: 0.034,
|
|
29
|
+
bottomScale: 0.055,
|
|
30
|
+
fontFamily:
|
|
31
|
+
'"PingFang SC", "Noto Sans CJK SC", "Source Han Sans SC", "Microsoft YaHei", sans-serif',
|
|
32
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# EP001 剪辑单
|
|
2
|
+
|
|
3
|
+
- 成片目标时长:25.00 秒
|
|
4
|
+
- 画幅与帧率:9:16 · 1080×1920 · 24fps
|
|
5
|
+
- 交付响度:-16 LUFS
|
|
6
|
+
- 字幕:硬字幕,台词逐字取自《剧本.md》,底部安全区内,避开画内屏幕文字
|
|
7
|
+
- 未采用镜头:MOTION-EP001-009(理由:质量不可用——全段人物身份漂移,可用带不足 0.5 秒);MOTION-EP001-018(理由:文件缺失——尚未生产)
|
|
8
|
+
|
|
9
|
+
## CUT-EP001-001 · 手指停在按钮上
|
|
10
|
+
|
|
11
|
+
- 来源:MOTION-EP001-010 · 制作成果/videos/SHOT-EP001-010.mp4
|
|
12
|
+
- 入点:0.60
|
|
13
|
+
- 出点:3.60
|
|
14
|
+
- 时长:3.00
|
|
15
|
+
- 取舍:入点=手指已经悬在按钮上方、开始下压;出点=按钮按下、界面开始响应,再往后 0.4 秒手指位置回弹
|
|
16
|
+
- 声音:保留原声(室内底噪与一次点击声)
|
|
17
|
+
- 字幕:无
|
|
18
|
+
|
|
19
|
+
## CUT-EP001-002 · 弹窗展开
|
|
20
|
+
|
|
21
|
+
- 来源:MOTION-EP001-011 · 制作成果/videos/SHOT-EP001-011.mp4
|
|
22
|
+
- 入点:0.90
|
|
23
|
+
- 出点:3.40
|
|
24
|
+
- 时长:2.50
|
|
25
|
+
- 取舍:入点=弹窗动画已经展开过半,起势的静止两帧删掉;出点=弹窗完全展开且文字可读的最后一帧,之后画面开始整体提亮
|
|
26
|
+
- 声音:保留原声,与上一段做 0.15 秒交叉淡入(两段底噪水平差 4 dB)
|
|
27
|
+
- 字幕:无
|
|
28
|
+
|
|
29
|
+
## CUT-EP001-003 · 他念出那句话
|
|
30
|
+
|
|
31
|
+
- 来源:MOTION-EP001-017 · 制作成果/videos/SHOT-EP001-017.mp4
|
|
32
|
+
- 入点:2.00
|
|
33
|
+
- 出点:7.00
|
|
34
|
+
- 时长:5.00
|
|
35
|
+
- 取舍:入点=按发声区间前推 0.3 秒余量,开头 1.5 秒的凝视与上一段蓄势重复,整段去掉;出点=句尾收音之后 0.4 秒,人物姿态尚未回弹
|
|
36
|
+
- 声音:保留原声;音乐在 4.20 秒进入,台词发声区间内压低 9 dB,句尾停顿处恢复
|
|
37
|
+
- 字幕:这条路我自己走
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
说明:本文件是格式样例,`制作成果/videos/...` 是示意路径。真实项目里每个「来源」的路径都必须
|
|
42
|
+
指向当前可读的文件,`check` 会逐条核对。「未采用镜头」的两条理由分别示范了必须区分的两类——
|
|
43
|
+
文件缺失回生产,质量不可用回上游改提示词。
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# 入出点与镜序
|
|
2
|
+
|
|
3
|
+
可用带划完之后,剪辑要回答两个问题:**这一段从哪一帧进、到哪一帧出**,以及**这些段落按
|
|
4
|
+
什么顺序连起来**。两个问题都在带内解决;带外的帧不参与讨论。
|
|
5
|
+
|
|
6
|
+
## 入点
|
|
7
|
+
|
|
8
|
+
入点取**动作已经在进行中**的那一帧,不取动作准备开始的那一帧。
|
|
9
|
+
|
|
10
|
+
观众补得上开头,补不上结尾。一个人伸手去拿东西,从「手已经在移动」进,观众自动知道他要拿;
|
|
11
|
+
从「手还放在桌上」进,前面那半秒只是在等。生成素材的起势帧几乎总是这半秒。
|
|
12
|
+
|
|
13
|
+
具体判断:从候选入点往后放,如果前 0.3 秒删掉之后这一段的信息没有减少,就删掉。反复这样问,
|
|
14
|
+
直到再删就丢信息为止。
|
|
15
|
+
|
|
16
|
+
例外是**需要一个静止起点的镜头**:反应镜、揭示前的停顿、有意的空拍。这些镜头的静止不是起势帧,
|
|
17
|
+
它本身就是内容。区别在于静止之后是否发生了它承诺的那件事——反应镜的静止之后有反应,
|
|
18
|
+
起势帧之后只是动作终于开始了。
|
|
19
|
+
|
|
20
|
+
## 出点
|
|
21
|
+
|
|
22
|
+
出点取**信息完成之后、缺陷开始之前**。这两个条件经常冲突,冲突时以缺陷为准:把一段拖进
|
|
23
|
+
漂移区,损失的不只是这一段,还有它后面那一刀的可信度。
|
|
24
|
+
|
|
25
|
+
信息完成的判断:这一镜要让观众知道的那件事,最后一次可见是哪一帧。之后的帧要么在重复,
|
|
26
|
+
要么在等下一件事。
|
|
27
|
+
|
|
28
|
+
有台词时出点由声音决定,不由画面决定。见下一节。
|
|
29
|
+
|
|
30
|
+
## 台词优先
|
|
31
|
+
|
|
32
|
+
有台词的段落,边界顺序是:
|
|
33
|
+
|
|
34
|
+
1. 先测这句话的实际发声区间(从第一个音到最后一个音收尾)。
|
|
35
|
+
2. 入点不晚于发声起点,出点不早于发声收尾——两端各留出一点余量,让句尾不被切得发干。
|
|
36
|
+
3. 在这个约束内,才轮到画面上的入出点判断。
|
|
37
|
+
|
|
38
|
+
切在字中间是结构缺陷。半个字听起来像技术故障,观众不会理解成风格。转写工具只用来**定位**
|
|
39
|
+
这句话在时间轴上的位置;字幕文字仍然逐字取自剧本原文。
|
|
40
|
+
|
|
41
|
+
一句台词跨越两段素材时,它属于其中一段——不要在句中换镜。确实需要在这句话上换镜时,
|
|
42
|
+
回上游把它拆成两句,或者接受这一镜承担完整的一句。
|
|
43
|
+
|
|
44
|
+
## 镜序与相邻关系
|
|
45
|
+
|
|
46
|
+
镜序默认跟随分镜。改变它是本阶段的权限,但要说明理由。
|
|
47
|
+
|
|
48
|
+
相邻两段检查三件事,不能三件同时相同:
|
|
49
|
+
|
|
50
|
+
- **景别**(近 / 中 / 远)
|
|
51
|
+
- **机位**(相对被摄主体的方位)
|
|
52
|
+
- **运动方向**(推 / 拉 / 摇的方向,或静止)
|
|
53
|
+
|
|
54
|
+
三者全同的两段接在一起会被看成同一个镜头出了问题,而不是两个镜头。改法优先级:删掉其中一段
|
|
55
|
+
(通常它们本来就在重复信息),其次调整镜序把别的段落插进来,最后才是回上游重新设计镜头。
|
|
56
|
+
|
|
57
|
+
## 重复信息
|
|
58
|
+
|
|
59
|
+
两段承担同一条信息时,删一段,不要两段各留一半。
|
|
60
|
+
|
|
61
|
+
各留一半是最容易做出的选择,因为它看起来两边都保住了。实际结果是两个都不完整的段落连在一起,
|
|
62
|
+
观众第二次看到同一件事、而且两次都没看清。选出更好的那一段,整段留下;另一段整段去掉。
|
|
63
|
+
|
|
64
|
+
## 时长
|
|
65
|
+
|
|
66
|
+
**省下来的时间不要补到别处。**
|
|
67
|
+
|
|
68
|
+
缩短一段之后,成片比目标时长短了,这时候很自然会想把这两秒加到别的段落上去。不要这样做。
|
|
69
|
+
其它段落的出点是按它们各自的信息和缺陷定的,加长它们只会把它们也推进重复区或漂移区。
|
|
70
|
+
成片短于目标时长是一个结果,不是一个需要填平的缺口。
|
|
71
|
+
|
|
72
|
+
目标时长的作用是在**开始剪之前**约束镜头数量和信息密度。剪完之后它就只是一个用来对照的数字,
|
|
73
|
+
差多少写进报告,由创作者决定要不要回上游加内容。
|
|
74
|
+
|
|
75
|
+
## 什么时候停
|
|
76
|
+
|
|
77
|
+
再剪一版能不能更好,几乎总是「能」。判断该不该继续的标准不是「还有没有可改的地方」,
|
|
78
|
+
而是**下一刀要动的是不是观众能看见的东西**。
|
|
79
|
+
|
|
80
|
+
在成片里看不见的地方反复重出和微调,是本阶段最容易发生的浪费:一段素材最终只用了两秒,
|
|
81
|
+
却为它被丢掉的那四秒重出了三次。动手之前先确认,要修的这一帧到底在不在成片里。
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# 交付与验收
|
|
2
|
+
|
|
3
|
+
本阶段的验收只回答**可测的事实**。「这条片子好不好看」不在这里回答,也不能用这里的任何一项
|
|
4
|
+
数字去暗示它。
|
|
5
|
+
|
|
6
|
+
## 可测项
|
|
7
|
+
|
|
8
|
+
渲染完成后逐项测量并回报数字,不回报「通过」:
|
|
9
|
+
|
|
10
|
+
| 项 | 怎么测 | 判据 |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| 成片时长 | 探测输出文件 | 等于各段时长之和;不等说明拼接或转码出了问题 |
|
|
13
|
+
| 每一刀的位置 | 按剪辑单区间反查 | 与文档一致 |
|
|
14
|
+
| 台词完整性 | 在成片上转写,逐句对剧本原文 | 每一句留下来的台词都能找到 |
|
|
15
|
+
| 边界帧 | 抽剪辑点前后各一帧 | 没有黑场帧、白场帧或半渲染帧 |
|
|
16
|
+
| 响度 | 测整片响度 | 落在交付规格声明的目标上 |
|
|
17
|
+
| 字幕对齐 | 抽有字幕的段落的帧 | 字幕在发声区间内出现,位置没有压住画内文字 |
|
|
18
|
+
| 画幅与帧率 | 探测输出文件 | 等于交付规格声明的值 |
|
|
19
|
+
|
|
20
|
+
任何一项测不了(缺工具、缺原文、素材不可读)就如实写「未测」和原因。**不要用相邻的、
|
|
21
|
+
测得到的那一项去替它作证**——渲染成功不能证明台词还在,时长对上不能证明没有黑场帧。
|
|
22
|
+
|
|
23
|
+
最容易漏的是字幕那一行:`verify` 返回一整屏数字,看起来已经查完了,但它测不了字幕长
|
|
24
|
+
什么样。本套件就这样发过一版字号被放大两倍的成片——改完样式只跑了 `verify`,没抽帧看。
|
|
25
|
+
**改动只要影响画面,就必须抽帧看,不管数字多好看。**
|
|
26
|
+
|
|
27
|
+
## 报告什么
|
|
28
|
+
|
|
29
|
+
交付时给出四样东西:
|
|
30
|
+
|
|
31
|
+
1. **成片文件路径**,以及每段切好的中间文件路径。
|
|
32
|
+
2. **上表逐项的实测数字**,包括未测项和原因。
|
|
33
|
+
3. **目标时长与实际时长的差**,以及为什么是这个差。
|
|
34
|
+
4. **仍然存在的取舍选项**——还可以再剪的地方、可以回上游重出的地方,各自的代价。
|
|
35
|
+
列出来交给创作者选,不替他决定要不要再来一版。
|
|
36
|
+
|
|
37
|
+
不要报告的:任何形式的质量结论、「已经可以发布了」、把技术成功写成创作成功。
|
|
38
|
+
|
|
39
|
+
## 交回上游的东西
|
|
40
|
+
|
|
41
|
+
剪辑是第一次同时看到成片和意图的位置,所以它必然会积累一批只有在这里才看得见的发现。
|
|
42
|
+
这些发现不属于剪辑单,但属于本轮报告:
|
|
43
|
+
|
|
44
|
+
- **某一镜的可用带远短于声明时长** → 视频提示词阶段的时长与动作负载不匹配。
|
|
45
|
+
- **两镜信息重复** → 分镜阶段的切镜理由不成立。
|
|
46
|
+
- **某句台词在成片上说不清** → 剧本层面的语速/字数问题,或声音生成的容量问题。
|
|
47
|
+
- **成片整体缺少某种信息**(人物不立、地点没交代、转折没落地)→ 上游结构问题,
|
|
48
|
+
不是剪辑能补的。
|
|
49
|
+
|
|
50
|
+
逐条点名,写清是在哪一段、哪个时间点观察到的,交给对应 owner。不在剪辑阶段自行修改上游文档。
|
|
51
|
+
|
|
52
|
+
## 可继续精修的工程
|
|
53
|
+
|
|
54
|
+
成片是一次交付,不是终点。创作者通常还要在自己的剪辑软件里继续改。因此除了成片,
|
|
55
|
+
把切好的中间文件和剪辑单一起交出去——有了这两样,任何人都能在别的工具里复现这一版,
|
|
56
|
+
并从这一版继续。
|
|
57
|
+
|
|
58
|
+
只交一个成片文件,等于要求下一个人从头再剪一遍。
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# 生成素材的可用带
|
|
2
|
+
|
|
3
|
+
一段实拍素材通常整段可用,导演决定用哪里。一段生成素材通常**不是整段可用**:它有一条可用带,
|
|
4
|
+
带外的帧无论怎么剪都不成立。剪辑第一步不是选精彩瞬间,是先把这条带子划出来。
|
|
5
|
+
|
|
6
|
+
先划带、再选点,顺序不能反。反过来做——先按剧本节奏定好入出点,再去素材里找——会得到一个
|
|
7
|
+
落在缺陷区里的边界,然后花很多时间在「这一刀是不是切得不对」上,而问题根本不在刀口位置。
|
|
8
|
+
|
|
9
|
+
## 先看完整段
|
|
10
|
+
|
|
11
|
+
每个文件从头看到尾一次,逐段记录三件事:
|
|
12
|
+
|
|
13
|
+
1. **这段素材实际有多长。** 供应商返回的时长和账号配置的时长经常不等;以文件测出来的为准。
|
|
14
|
+
2. **可用带的起止。** 画面稳定、动作在进行、身份和光线没有漂移的那一段。
|
|
15
|
+
3. **带外发生了什么。** 这条要具体:写「结尾 0.5 秒整体提亮到接近纯白」,不写「结尾不好」。
|
|
16
|
+
具体的记录能回到上游变成提示词修订;模糊的记录只能留在剪辑里被反复重看。
|
|
17
|
+
|
|
18
|
+
## 常见的带外形态
|
|
19
|
+
|
|
20
|
+
以下是本套件在实测中反复遇到的形态。它们是**该去素材里核对的清单**,不是任何模型的规格,
|
|
21
|
+
也不保证在你的模型和参数下同样出现;每一条都以你自己这一段素材的实测为准。
|
|
22
|
+
|
|
23
|
+
- **起势帧**:开头若干帧接近静止,动作还没开始。入点通常要晚于文件起点。
|
|
24
|
+
- **结尾漂移**:动作完成后画面继续变化——人物姿态回弹、道具位置偏移、镜头继续推。
|
|
25
|
+
- **结尾提亮**:末段整体亮度上抬甚至泛白。它在缩略图和逐帧对比里都很明显,但在正常速度
|
|
26
|
+
播放时容易被当成「一个亮结尾」放过去。
|
|
27
|
+
- **重复表演**:同一个情绪或姿态在一段里演两遍。第二遍通常质量更差,也让这一段显得比实际长。
|
|
28
|
+
- **口型与台词错位**:有声模型在同一次生成里出画面和声音,超出容量的台词会被赶或直接不发声。
|
|
29
|
+
边界必须按实际听到的声音定,不按提示词里写了几个字定。
|
|
30
|
+
|
|
31
|
+
## 划带的具体做法
|
|
32
|
+
|
|
33
|
+
用抽帧对比,不要只靠播放。做法:
|
|
34
|
+
|
|
35
|
+
1. 按固定间隔抽帧(0.25–0.5 秒一帧足够定位大多数问题),拼成一张接触图。
|
|
36
|
+
2. 沿着接触图找第一次出现「和前一帧不属于同一个动作」的位置——那通常就是带的一端。
|
|
37
|
+
3. 在候选边界前后再按 0.1 秒抽一次,把边界收紧到可用的最后一帧。
|
|
38
|
+
|
|
39
|
+
亮度类问题额外测一遍逐帧平均亮度,因为眼睛对缓慢提亮不敏感。姿态与身份漂移则相反:数值不会
|
|
40
|
+
动,必须靠眼睛比对同一处细节(发际线、领口、手里的东西)。**两种方法各有各的盲区,
|
|
41
|
+
需要交叉验证的场合两种都用一次。** 只用其中一种得出的结论,其可靠程度取决于这个问题恰好
|
|
42
|
+
落在哪一边——而这一点事先并不知道。
|
|
43
|
+
|
|
44
|
+
## 带很短怎么办
|
|
45
|
+
|
|
46
|
+
可用带短于上游声明的时长是常态。三条路,按代价排序:
|
|
47
|
+
|
|
48
|
+
1. **接受更短的一段。** 一秒半能把信息说完就用一秒半。这是默认选择,也是成片总时长可以
|
|
49
|
+
低于目标的正当原因。
|
|
50
|
+
2. **换一段素材承担这条信息。** 别的镜头如果已经把这件事说清楚了,这一镜可以整段不用。
|
|
51
|
+
3. **回上游重出。** 只在前两条都不成立时走。重出前先把带外形态写具体——「结尾发白」比
|
|
52
|
+
「重生成一次」更可能真的换来一段能用的素材。
|
|
53
|
+
|
|
54
|
+
不要走第四条:把缺陷帧留在成片里,指望观众不注意。缺陷帧在竖屏全屏播放下比在工作监视器上
|
|
55
|
+
明显得多。
|
|
56
|
+
|
|
57
|
+
## 负面指令的边界
|
|
58
|
+
|
|
59
|
+
想避开某个缺陷时,直觉做法是在重出的提示词里写「不要发白 / 不要泛光」。本套件在实测中见过
|
|
60
|
+
这样的重出反而使该缺陷更重的情况(视觉质地类),也见过同样写法对具体物体不产生影响的情况
|
|
61
|
+
(物体类)。样本很小,不足以下断言。
|
|
62
|
+
|
|
63
|
+
能确定的只有一条方法论:**把它写成正面的目标状态**——「保持中灰、暗部有细节、高光不过曝」,
|
|
64
|
+
而不是「不要发白」。这条在两类情况下都不会更差,所以作为默认写法。真要用负面写法时,
|
|
65
|
+
把它当成一次实验:重出后回来对比同一处的实测数字,别只凭印象说「这次好一点」。
|
|
66
|
+
|
|
67
|
+
上游把这一点写成规则的位置在视频提示词阶段(负面动作意图改写为可见的正面状态)。剪辑阶段
|
|
68
|
+
遇到时,报告回去,不要在剪辑里自己改提示词重投。
|
|
69
|
+
|
|
70
|
+
## 接镜与色彩一致性
|
|
71
|
+
|
|
72
|
+
逐镜生成的素材之间会漂移。同一个人坐在同一张桌子前的两条,回来可能差一档曝光、
|
|
73
|
+
半步白平衡——单看每一条都成立,接在一起就像剪错了。
|
|
74
|
+
|
|
75
|
+
本套件实测过一集里的七镜:亮度从 97 到 131(0–255 均值),蓝红差从 −14.6 到 +4.9。
|
|
76
|
+
其中相邻的两镜(同一个人、同一张桌子、同一场戏)亮度差 15 点、色偏从 −5.5 翻到 +1.5,
|
|
77
|
+
在成片上是看得见的一跳。
|
|
78
|
+
|
|
79
|
+
### 怎么处理
|
|
80
|
+
|
|
81
|
+
1. **先量,再看,两样都做。** 逐镜取整段的平均 RGB 与亮度,把数字排成一列;
|
|
82
|
+
再拼一张接触图用眼睛过一遍。数字会漏掉「只有暗部偏色」这种局部问题,
|
|
83
|
+
眼睛会漏掉缓慢的整体漂移——本套件在这两个方向上都栽过。
|
|
84
|
+
2. **选一条作基准,别求全组一致。** 通常选信息最重的那一镜(有台词的、有转折的)。
|
|
85
|
+
把明显偏离的那一两条拉向它,不要把七条都往中间挪——那会让原本对的镜也被动过。
|
|
86
|
+
3. **在剪辑单里写下来。** 在那一段写 `- 画面:亮度 +0.06;色温 -6`。
|
|
87
|
+
三项的含义:`亮度` 是 −0.25…+0.25 的加法偏移,`饱和` 是倍数,
|
|
88
|
+
`色温` 是 −30…+30,正数偏暖(提红压蓝)。超出范围会被 `check` 拒绝——
|
|
89
|
+
那种幅度不是接镜,是重新调色,应该回上游重出或交给专门的调色工具。
|
|
90
|
+
|
|
91
|
+
### 两条边界
|
|
92
|
+
|
|
93
|
+
- **工具不会自己量一遍然后偷偷改。** 校正只来自剪辑单里写下来的那一行。
|
|
94
|
+
一个没被写下来的校正,没有任何 reviewer 能看见它改了什么、为什么改。
|
|
95
|
+
- **接镜救不了错的镜。** 曝光差一档可以拉回来;人物身份漂了、光的方向变了、
|
|
96
|
+
该有的次级光整个没有——这些回上游重出,不要用色彩校正去盖。
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# 声音、字幕与音乐
|
|
2
|
+
|
|
3
|
+
画面接缝靠取舍解决,声音接缝不会自己解决。逐镜生成的素材各自带着一整套声音,直接拼接会在
|
|
4
|
+
每一个剪辑点留下一道能听见的断层——即使画面切得干净。
|
|
5
|
+
|
|
6
|
+
## 音床硬切
|
|
7
|
+
|
|
8
|
+
有声模型在生成画面的同一次里烧进环境声。两段素材各自的底噪、混响和环境层不同,拼接处就会
|
|
9
|
+
听到一次「换房间」的感觉。这个缺陷在逐镜审片时完全听不出来,只在成片上出现。
|
|
10
|
+
|
|
11
|
+
三条处理路径,按代价排序:
|
|
12
|
+
|
|
13
|
+
1. **在生成阶段避免。** 视频提示词阶段声明非叙事音乐不由单镜承载(对应该阶段的音乐规则),
|
|
14
|
+
让每段素材只带必要的叙事声音。这是最干净的做法,但要在生产之前决定。
|
|
15
|
+
2. **在剪辑点做短交叉淡入。** 只处理音轨,不动画面。适合底噪差异不大的相邻段。
|
|
16
|
+
3. **铺一层统一的环境底。** 把各段原声压低到统一水平,再补一条贯穿全片的环境层。
|
|
17
|
+
代价是丢掉一部分逐段的声音细节,且这是一个明显的创作决定,要写进剪辑单的「声音」行。
|
|
18
|
+
|
|
19
|
+
选哪条取决于差异有多大,先测再选:逐段测底噪水平,差异小的用第 2 条,差异大的才考虑第 3 条。
|
|
20
|
+
|
|
21
|
+
## 台词必须能听见
|
|
22
|
+
|
|
23
|
+
成片里每一句留下来的台词都要完整可听。检查方式是**在成片上**重新转写一遍,逐句对照剧本原文:
|
|
24
|
+
|
|
25
|
+
- 少一句 → 某一刀切掉了它,或者它被别的声音盖住了。
|
|
26
|
+
- 半句 → 边界切在了句中,回去按发声区间重定。
|
|
27
|
+
- 转写结果和原文有出入 → 转写工具的误差,也可能是生成时口型/发音本身就不清楚。
|
|
28
|
+
分辨方法是听,不是看转写文本。转写只是筛子,不是判据。
|
|
29
|
+
|
|
30
|
+
转写做在成片上,不做在逐段素材上。逐段都对、拼起来丢了一句,正是这一步要抓的情况。
|
|
31
|
+
|
|
32
|
+
### 重出一条素材之后,绑在它上面的字幕时间全部作废
|
|
33
|
+
|
|
34
|
+
字幕时间是从**那一条**素材的发声区间反推出来的。重出之后——不管是因为画质、因为动作不对、
|
|
35
|
+
还是只想换个表演——新的一条发声位置几乎一定不同,而旧的窗口还留在剪辑单里。
|
|
36
|
+
|
|
37
|
+
这件事没有任何别的环节会发现:数字仍然落在区间内,`render` 照常成功,成片上字幕就出现在
|
|
38
|
+
没有人说话的时刻。本套件实测过一次:重出后发声区间从素材内 0.90 秒挪到 2.51 秒,
|
|
39
|
+
字幕比口型早了 1.6 秒,是外部审片者看出来的,不是任何检查抓到的。
|
|
40
|
+
|
|
41
|
+
所以:**重出之后先重测发声区间,再改字幕时间,然后才重渲。**
|
|
42
|
+
`check` 会在素材文件比剪辑单新时报出来——那是文件系统能看见的唯一一种陈旧,
|
|
43
|
+
不能代替你自己重测,但至少不让它无声地过去。
|
|
44
|
+
|
|
45
|
+
## 字幕
|
|
46
|
+
|
|
47
|
+
竖屏短剧默认硬字幕。
|
|
48
|
+
|
|
49
|
+
字幕文字**逐字取自 `剧本.md`**,不取自转写结果。转写只提供时间。标点可以按字幕排版惯例调整——
|
|
50
|
+
句末句号通常去掉——但一个字都不能改。这条是结构规则,不是偏好:
|
|
51
|
+
转写会把人名或成语听成同音的另一个词,一旦进了字幕,成片上就出现一句剧本里根本不存在的
|
|
52
|
+
台词,而且没有任何环节会再发现它。
|
|
53
|
+
|
|
54
|
+
其它几条:
|
|
55
|
+
|
|
56
|
+
- 一行的字数按可读性定,不按句子结构定;一句话太长就**断成几条字幕先后显示**,
|
|
57
|
+
不要让一条字幕在屏上堆成三行、挂五秒——那已经不是字幕,是字幕墙。
|
|
58
|
+
- **一镜可以有好几句。** 一次三个来回的对话是一个过肩镜头,不是三个镜头;
|
|
59
|
+
剪辑单里用编号写法把每一句各自写下来并各自带时间。只写一条,另外两句在成片上就没有字幕,
|
|
60
|
+
而且没有任何一步会报错——观众听得见、看不见。
|
|
61
|
+
- **字号写在画面像素里,不要再按画面高度乘一遍。** 字幕文件里的字号已经是相对
|
|
62
|
+
`PlayRes` 的单位,渲染时会再缩放一次。本套件第一版按画面高度算了字号,于是放大了两次:
|
|
63
|
+
1344 高的竖屏上本该 46px 的字变成约 161px,字幕被推到画面中部,长句两端切掉。
|
|
64
|
+
`edit_tool.py` 现在自己写 ASS 并把 `PlayRes` 声明成实际画幅,一个单位就是一个像素。
|
|
65
|
+
- 字幕的出入时间跟随发声区间,不跟随剪辑点。
|
|
66
|
+
- **字幕时间按实际渲染出来的分段累加,不按剪辑单里声明的时长累加。** 每段落在帧边界上,
|
|
67
|
+
比声明值长几毫秒;按声明值累加会一路漂移,八段之后能差三分之一秒,字幕于是在人还没说完时就消失。
|
|
68
|
+
- 画内已有文字(屏幕、招牌、聊天记录)的位置要避开,不要让字幕压在需要看清的信息上。
|
|
69
|
+
- 有画内文字要求的镜头,字幕位置在剪辑单的「字幕」行里写明。
|
|
70
|
+
|
|
71
|
+
### 两条渲染路线
|
|
72
|
+
|
|
73
|
+
`edit_tool.py` 的 `--subtitles` 选哪一条:
|
|
74
|
+
|
|
75
|
+
| | `ffmpeg`(默认) | `remotion` |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| 依赖 | 无 | Node + 一次 `npm install`,工作区在项目外 |
|
|
78
|
+
| 排版 | 白字黑描边,够用 | 字重、描边、行距、安全区、折行、入场动画都可调 |
|
|
79
|
+
| 改样式 | 改 `edit_tool.py` 的 ASS 样式 | 改 CSS,`npx remotion studio` 当场可见 |
|
|
80
|
+
| 开销 | 一次滤镜,秒级 | **成片每一帧都过一遍无头浏览器**,分钟级,吃内存 |
|
|
81
|
+
| 许可 | — | Remotion 个人与小团队免费,超出规模需商业授权 |
|
|
82
|
+
|
|
83
|
+
两条都只渲染字幕层,画面本身不经过浏览器重绘。**默认走 `ffmpeg`**,长片尤其;只有排版
|
|
84
|
+
确实要求更多(加粗、描边层次、逐句入场)、而且片子不长时才换 `remotion`——它的叠层逐帧
|
|
85
|
+
过无头浏览器,并发默认压在 2,调高之前先量本机。装法与代价见
|
|
86
|
+
[Remotion 字幕叠层](../assets/remotion/README.md)。
|
|
87
|
+
|
|
88
|
+
无论走哪条,字幕文字仍然逐字来自 `剧本.md`。
|
|
89
|
+
|
|
90
|
+
## 响度
|
|
91
|
+
|
|
92
|
+
成片统一做一次响度标准化,目标写在剪辑单开头的交付规格里。
|
|
93
|
+
|
|
94
|
+
逐段素材的响度差异很大,因为它们是分别生成的。不做统一的结果是观众在播放中途反复调音量,
|
|
95
|
+
而这件事在工作环境里几乎察觉不到——工作时是逐段听的,逐段听不出整体起伏。
|
|
96
|
+
|
|
97
|
+
标准化在最后一步做,做在已经拼接和混音完成的成片上。对逐段素材分别标准化会破坏段间本来
|
|
98
|
+
正确的相对关系(一段耳语和一段喊叫会被拉到同一响度)。
|
|
99
|
+
|
|
100
|
+
## 时间线音乐
|
|
101
|
+
|
|
102
|
+
生产阶段把音乐的落点、循环、淡入淡出和对白 ducking 交给剪辑,因为供应商通常不能精确承诺
|
|
103
|
+
时长。到这里要做的是:
|
|
104
|
+
|
|
105
|
+
1. 按视频提示词文档里已确认的音乐意图,决定进入点和退出点——通常对着一个画面事件,
|
|
106
|
+
不对着一个整秒。
|
|
107
|
+
2. 长度不够就循环,循环点选在乐句边界上,不选在剪辑点上。
|
|
108
|
+
3. 有台词的段落把音乐压低,在台词发声区间之外恢复。恢复时机跟着句尾停顿走,
|
|
109
|
+
不要在句子中间的换气处就抬起来。
|
|
110
|
+
4. 音乐不填补沉默。剪辑单里写明是沉默的段落就保持沉默——那是一个创作决定,不是待填的空白。
|
|
111
|
+
|
|
112
|
+
音乐素材本身不在本阶段生产。需要新的音乐回 `$short-drama-produce`,歌词与音乐意图回
|
|
113
|
+
`$short-drama-video-prompts`。
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# 剪辑阶段契约
|
|
2
|
+
|
|
3
|
+
本阶段只拥有 `剧集/<EP>/剪辑单.md` 中的 `CUT-...` 项、交付规格章节,以及渲染到
|
|
4
|
+
`剧集/<EP>/制作成果/成片/` 的成片与中间文件。它继承镜序、镜头职责、台词原文和已生产的素材
|
|
5
|
+
字节,不回写剧本、视觉设定、分镜或视频提示词。
|
|
6
|
+
|
|
7
|
+
剪辑单不是第六份创作文档。五文档回答「这一集是什么」,剪辑单只回答「已经拿到的这些素材,
|
|
8
|
+
哪些帧进成片」。因此它可以整镜不用、可以只取一段素材的中间三秒,但不能改变任何一镜的职责、
|
|
9
|
+
台词、起终状态或时长声明——那些改动必须回到拥有它们的上游文档,再重新进入生产。
|
|
10
|
+
|
|
11
|
+
素材与文档不一致是本阶段的正常输入,不是要修好才能开工的前置条件。上游写「三秒推进到特写」,
|
|
12
|
+
生成结果只有前一秒可用,剪辑记录下这个事实并做出取舍;把不一致原样报告回去,比在剪辑里假装
|
|
13
|
+
它不存在更有价值。
|
|
14
|
+
|
|
15
|
+
## 本阶段规则
|
|
16
|
+
|
|
17
|
+
### `EDT`
|
|
18
|
+
|
|
19
|
+
| ID | Class | Knowledge |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| EDT-01 | structural_invariant | Every `CUT-...` binds one existing `MOTION-...` and one currently readable media file; a cut with no material source cannot exist. |
|
|
22
|
+
| EDT-02 | structural_invariant | 入点, 出点 and 时长 are self-consistent (`出点 - 入点 == 时长`), non-negative, and the 出点 does not exceed the source file's measured duration. |
|
|
23
|
+
| EDT-03 | structural_invariant | Editing selects and orders existing frames. It never rewrites dialogue, shot purpose, start/end state, or any upstream declared duration; a needed semantic change is reported to the owning document instead. |
|
|
24
|
+
| EDT-04 | structural_invariant | A dialogue line that survives into the cut survives whole. A cut boundary may not fall inside a spoken word, and a line's audible span is fixed before its picture in/out is chosen. |
|
|
25
|
+
| EDT-05 | structural_invariant | Every line spoken in the cut gets its own subtitle cue — a shot carrying an exchange of three carries three, not one. Every character of a burned subtitle comes from the line as written in `剧本.md`; punctuation may follow subtitle convention (a trailing full stop is normally dropped) but not one character changes. Transcription locates a line in time; it never becomes the line. |
|
|
26
|
+
| EDT-06 | structural_invariant | Two cuts drawn from the same source file do not overlap in source time. Deliberate repetition is declared as repetition and states why the second appearance still earns its place. |
|
|
27
|
+
| EDT-07 | reviewed_invariant | Each cut's in-point and out-point land inside that material's usable band, and 取舍 names what is visible at each boundary rather than citing an abstract need for pace. |
|
|
28
|
+
| EDT-08 | reviewed_invariant | Adjacent cuts do not share shot size, camera position and movement direction all at once; two cuts carrying the same information are resolved by dropping one, not by halving both. |
|
|
29
|
+
| EDT-09 | reviewed_invariant | Time saved by trimming one cut is not redistributed to others to hit a target duration. A shorter film is a result, not a deficit to refill. |
|
|
30
|
+
| EDT-10 | reviewed_invariant | Per-shot generated material carries its own ambience or music bed, so every join is checked for an audible sound-bed hard cut and handled by crossfade, common floor, or an upstream request for a music-free deliverable. |
|
|
31
|
+
| EDT-11 | reviewed_invariant | Unused material is recorded with a reason that distinguishes a missing file from an unusable result; the two look identical in the document but route to different owners. |
|
|
32
|
+
| EDT-12 | craft_default | The delivered film is loudness-normalized to one declared target, and burned subtitles are the default for vertical short drama. |
|
|
33
|
+
| EDT-13 | craft_default | Target duration is intent. The report states the gap between target and actual and why, instead of cutting content to reach a round number. |
|
|
34
|
+
| EDT-14 | taste_option | Cut rhythm, whether a beat is held or clipped, and whether a moment repeats are creator choices; the suite records them and does not treat any of them as defects. |
|
|
35
|
+
| EDT-15 | structural_invariant | Rendering, duration match and file existence are technical outcomes. None of them may be reported as a statement about whether the film is good; quality goes to review or to the creator. |
|
|
36
|
+
| EDT-16 | reviewed_invariant | Generated shots drift in exposure and white balance, so adjacent cuts are compared before delivery and a visible mismatch is corrected. The correction is written in the cut list as a stated creator decision with explicit numbers; the tool never measures a clip and adjusts it on its own, because a correction nobody wrote down is one nobody can review. Shot-matching does not rescue a wrong shot — drifted identity, a changed light direction, or a missing secondary source goes back upstream rather than under a colour correction. |
|
|
37
|
+
| EDT-17 | structural_invariant | Subtitle windows are reverse-engineered from one particular take's audio, so regenerating that material voids every window bound to it. Nothing else catches this: the numbers stay in range, the render succeeds, and the subtitle appears while nobody is speaking. Re-measure the spoken span, rewrite the windows, then re-render. `check` reports material newer than the cut list — the only staleness a file system can see — which does not replace re-measuring but stops it passing in silence. |
|
|
38
|
+
|
|
39
|
+
规则分级由高到低:`structural_invariant`(结构缺陷,阻断)、
|
|
40
|
+
`reviewed_invariant`(需证据判断)、`craft_default`(常用做法,可覆盖)、
|
|
41
|
+
`taste_option`(创作者选择,不作缺陷)。创作者已接受的事实优先于本表。
|
|
42
|
+
|
|
43
|
+
## 与上游阶段的分工
|
|
44
|
+
|
|
45
|
+
| 问题 | 归属 |
|
|
46
|
+
|---|---|
|
|
47
|
+
| 这句台词该怎么说 | `剧本.md` |
|
|
48
|
+
| 这一镜承担什么、起终状态是什么 | `分镜.md` |
|
|
49
|
+
| 这一镜怎么动、生成时说什么 | `视频提示词.md` |
|
|
50
|
+
| 这一段素材怎么来的、花了多少钱 | 生产运行记录 |
|
|
51
|
+
| **这一段素材哪几帧进成片** | **`剪辑单.md`** |
|
|
52
|
+
| 成片好不好看 | 审查,或创作者本人 |
|
|
53
|
+
|
|
54
|
+
生成结果与上游声明不符时,剪辑记录事实并取舍,同时把不符点名报告;不在剪辑单里修改上游声明
|
|
55
|
+
来让它们看起来一致。
|