venice-video-harness 2.4.0
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/CHANGELOG.md +28 -0
- package/LICENSE +21 -0
- package/README.md +598 -0
- package/dist/assembly/manifest-builder.d.ts +8 -0
- package/dist/assembly/manifest-builder.d.ts.map +1 -0
- package/dist/assembly/manifest-builder.js +196 -0
- package/dist/assembly/manifest-builder.js.map +1 -0
- package/dist/assembly/remotion-scaffold.d.ts +14 -0
- package/dist/assembly/remotion-scaffold.d.ts.map +1 -0
- package/dist/assembly/remotion-scaffold.js +292 -0
- package/dist/assembly/remotion-scaffold.js.map +1 -0
- package/dist/assembly/types.d.ts +67 -0
- package/dist/assembly/types.d.ts.map +1 -0
- package/dist/assembly/types.js +5 -0
- package/dist/assembly/types.js.map +1 -0
- package/dist/characters/describer.d.ts +32 -0
- package/dist/characters/describer.d.ts.map +1 -0
- package/dist/characters/describer.js +309 -0
- package/dist/characters/describer.js.map +1 -0
- package/dist/characters/extractor.d.ts +27 -0
- package/dist/characters/extractor.d.ts.map +1 -0
- package/dist/characters/extractor.js +274 -0
- package/dist/characters/extractor.js.map +1 -0
- package/dist/characters/reference-manager.d.ts +95 -0
- package/dist/characters/reference-manager.d.ts.map +1 -0
- package/dist/characters/reference-manager.js +346 -0
- package/dist/characters/reference-manager.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +310 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +66 -0
- package/dist/config.js.map +1 -0
- package/dist/editing/aligner.d.ts +44 -0
- package/dist/editing/aligner.d.ts.map +1 -0
- package/dist/editing/aligner.js +201 -0
- package/dist/editing/aligner.js.map +1 -0
- package/dist/editing/edl.d.ts +45 -0
- package/dist/editing/edl.d.ts.map +1 -0
- package/dist/editing/edl.js +133 -0
- package/dist/editing/edl.js.map +1 -0
- package/dist/editing/overlays.d.ts +97 -0
- package/dist/editing/overlays.d.ts.map +1 -0
- package/dist/editing/overlays.js +41 -0
- package/dist/editing/overlays.js.map +1 -0
- package/dist/editing/packer.d.ts +52 -0
- package/dist/editing/packer.d.ts.map +1 -0
- package/dist/editing/packer.js +170 -0
- package/dist/editing/packer.js.map +1 -0
- package/dist/editing/providers/whisper-cpp.d.ts +32 -0
- package/dist/editing/providers/whisper-cpp.d.ts.map +1 -0
- package/dist/editing/providers/whisper-cpp.js +239 -0
- package/dist/editing/providers/whisper-cpp.js.map +1 -0
- package/dist/editing/render.d.ts +36 -0
- package/dist/editing/render.d.ts.map +1 -0
- package/dist/editing/render.js +227 -0
- package/dist/editing/render.js.map +1 -0
- package/dist/editing/self-eval.d.ts +48 -0
- package/dist/editing/self-eval.d.ts.map +1 -0
- package/dist/editing/self-eval.js +293 -0
- package/dist/editing/self-eval.js.map +1 -0
- package/dist/editing/silence.d.ts +76 -0
- package/dist/editing/silence.d.ts.map +1 -0
- package/dist/editing/silence.js +189 -0
- package/dist/editing/silence.js.map +1 -0
- package/dist/editing/types.d.ts +178 -0
- package/dist/editing/types.d.ts.map +1 -0
- package/dist/editing/types.js +13 -0
- package/dist/editing/types.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive.d.ts +12 -0
- package/dist/interactive.d.ts.map +1 -0
- package/dist/interactive.js +78 -0
- package/dist/interactive.js.map +1 -0
- package/dist/mini-drama/assembler.d.ts +61 -0
- package/dist/mini-drama/assembler.d.ts.map +1 -0
- package/dist/mini-drama/assembler.js +466 -0
- package/dist/mini-drama/assembler.js.map +1 -0
- package/dist/mini-drama/audio-mix.d.ts +65 -0
- package/dist/mini-drama/audio-mix.d.ts.map +1 -0
- package/dist/mini-drama/audio-mix.js +118 -0
- package/dist/mini-drama/audio-mix.js.map +1 -0
- package/dist/mini-drama/cli.d.ts +3 -0
- package/dist/mini-drama/cli.d.ts.map +1 -0
- package/dist/mini-drama/cli.js +2869 -0
- package/dist/mini-drama/cli.js.map +1 -0
- package/dist/mini-drama/fcpxml-export.d.ts +2 -0
- package/dist/mini-drama/fcpxml-export.d.ts.map +1 -0
- package/dist/mini-drama/fcpxml-export.js +5 -0
- package/dist/mini-drama/fcpxml-export.js.map +1 -0
- package/dist/mini-drama/generation-planner.d.ts +24 -0
- package/dist/mini-drama/generation-planner.d.ts.map +1 -0
- package/dist/mini-drama/generation-planner.js +304 -0
- package/dist/mini-drama/generation-planner.js.map +1 -0
- package/dist/mini-drama/location-generator.d.ts +23 -0
- package/dist/mini-drama/location-generator.d.ts.map +1 -0
- package/dist/mini-drama/location-generator.js +144 -0
- package/dist/mini-drama/location-generator.js.map +1 -0
- package/dist/mini-drama/music-cues.d.ts +96 -0
- package/dist/mini-drama/music-cues.d.ts.map +1 -0
- package/dist/mini-drama/music-cues.js +332 -0
- package/dist/mini-drama/music-cues.js.map +1 -0
- package/dist/mini-drama/panel-fixer.d.ts +12 -0
- package/dist/mini-drama/panel-fixer.d.ts.map +1 -0
- package/dist/mini-drama/panel-fixer.js +319 -0
- package/dist/mini-drama/panel-fixer.js.map +1 -0
- package/dist/mini-drama/prompt-builder.d.ts +149 -0
- package/dist/mini-drama/prompt-builder.d.ts.map +1 -0
- package/dist/mini-drama/prompt-builder.js +722 -0
- package/dist/mini-drama/prompt-builder.js.map +1 -0
- package/dist/mini-drama/reference-slots.d.ts +31 -0
- package/dist/mini-drama/reference-slots.d.ts.map +1 -0
- package/dist/mini-drama/reference-slots.js +161 -0
- package/dist/mini-drama/reference-slots.js.map +1 -0
- package/dist/mini-drama/shot-paths.d.ts +77 -0
- package/dist/mini-drama/shot-paths.d.ts.map +1 -0
- package/dist/mini-drama/shot-paths.js +101 -0
- package/dist/mini-drama/shot-paths.js.map +1 -0
- package/dist/mini-drama/storyboard-reference-generator.d.ts +47 -0
- package/dist/mini-drama/storyboard-reference-generator.d.ts.map +1 -0
- package/dist/mini-drama/storyboard-reference-generator.js +293 -0
- package/dist/mini-drama/storyboard-reference-generator.js.map +1 -0
- package/dist/mini-drama/subtitle-generator.d.ts +12 -0
- package/dist/mini-drama/subtitle-generator.d.ts.map +1 -0
- package/dist/mini-drama/subtitle-generator.js +139 -0
- package/dist/mini-drama/subtitle-generator.js.map +1 -0
- package/dist/mini-drama/timeline-export/davinci-fcpxml.d.ts +3 -0
- package/dist/mini-drama/timeline-export/davinci-fcpxml.d.ts.map +1 -0
- package/dist/mini-drama/timeline-export/davinci-fcpxml.js +150 -0
- package/dist/mini-drama/timeline-export/davinci-fcpxml.js.map +1 -0
- package/dist/mini-drama/timeline-export/fcpxml.d.ts +11 -0
- package/dist/mini-drama/timeline-export/fcpxml.d.ts.map +1 -0
- package/dist/mini-drama/timeline-export/fcpxml.js +140 -0
- package/dist/mini-drama/timeline-export/fcpxml.js.map +1 -0
- package/dist/mini-drama/timeline-export/index.d.ts +13 -0
- package/dist/mini-drama/timeline-export/index.d.ts.map +1 -0
- package/dist/mini-drama/timeline-export/index.js +26 -0
- package/dist/mini-drama/timeline-export/index.js.map +1 -0
- package/dist/mini-drama/timeline-export/premiere-xmeml.d.ts +3 -0
- package/dist/mini-drama/timeline-export/premiere-xmeml.d.ts.map +1 -0
- package/dist/mini-drama/timeline-export/premiere-xmeml.js +211 -0
- package/dist/mini-drama/timeline-export/premiere-xmeml.js.map +1 -0
- package/dist/mini-drama/timeline-export/probe.d.ts +53 -0
- package/dist/mini-drama/timeline-export/probe.d.ts.map +1 -0
- package/dist/mini-drama/timeline-export/probe.js +89 -0
- package/dist/mini-drama/timeline-export/probe.js.map +1 -0
- package/dist/mini-drama/timeline-export/types.d.ts +57 -0
- package/dist/mini-drama/timeline-export/types.d.ts.map +1 -0
- package/dist/mini-drama/timeline-export/types.js +14 -0
- package/dist/mini-drama/timeline-export/types.js.map +1 -0
- package/dist/mini-drama/video-generator.d.ts +22 -0
- package/dist/mini-drama/video-generator.d.ts.map +1 -0
- package/dist/mini-drama/video-generator.js +1305 -0
- package/dist/mini-drama/video-generator.js.map +1 -0
- package/dist/mini-drama/voice-reference.d.ts +42 -0
- package/dist/mini-drama/voice-reference.d.ts.map +1 -0
- package/dist/mini-drama/voice-reference.js +170 -0
- package/dist/mini-drama/voice-reference.js.map +1 -0
- package/dist/output/html-renderer.d.ts +2 -0
- package/dist/output/html-renderer.d.ts.map +1 -0
- package/dist/output/html-renderer.js +37 -0
- package/dist/output/html-renderer.js.map +1 -0
- package/dist/parsers/fountain-parser.d.ts +34 -0
- package/dist/parsers/fountain-parser.d.ts.map +1 -0
- package/dist/parsers/fountain-parser.js +71 -0
- package/dist/parsers/fountain-parser.js.map +1 -0
- package/dist/parsers/pdf-parser.d.ts +24 -0
- package/dist/parsers/pdf-parser.d.ts.map +1 -0
- package/dist/parsers/pdf-parser.js +237 -0
- package/dist/parsers/pdf-parser.js.map +1 -0
- package/dist/parsers/scene-extractor.d.ts +41 -0
- package/dist/parsers/scene-extractor.d.ts.map +1 -0
- package/dist/parsers/scene-extractor.js +400 -0
- package/dist/parsers/scene-extractor.js.map +1 -0
- package/dist/series/manager.d.ts +64 -0
- package/dist/series/manager.d.ts.map +1 -0
- package/dist/series/manager.js +282 -0
- package/dist/series/manager.js.map +1 -0
- package/dist/series/types.d.ts +641 -0
- package/dist/series/types.d.ts.map +1 -0
- package/dist/series/types.js +304 -0
- package/dist/series/types.js.map +1 -0
- package/dist/storyboard/assembler.d.ts +134 -0
- package/dist/storyboard/assembler.d.ts.map +1 -0
- package/dist/storyboard/assembler.js +319 -0
- package/dist/storyboard/assembler.js.map +1 -0
- package/dist/storyboard/prompt-builder.d.ts +113 -0
- package/dist/storyboard/prompt-builder.d.ts.map +1 -0
- package/dist/storyboard/prompt-builder.js +578 -0
- package/dist/storyboard/prompt-builder.js.map +1 -0
- package/dist/storyboard/shot-planner.d.ts +34 -0
- package/dist/storyboard/shot-planner.d.ts.map +1 -0
- package/dist/storyboard/shot-planner.js +446 -0
- package/dist/storyboard/shot-planner.js.map +1 -0
- package/dist/user-config.d.ts +15 -0
- package/dist/user-config.d.ts.map +1 -0
- package/dist/user-config.js +103 -0
- package/dist/user-config.js.map +1 -0
- package/dist/venice/audio-preflight.d.ts +80 -0
- package/dist/venice/audio-preflight.d.ts.map +1 -0
- package/dist/venice/audio-preflight.js +142 -0
- package/dist/venice/audio-preflight.js.map +1 -0
- package/dist/venice/audio.d.ts +88 -0
- package/dist/venice/audio.d.ts.map +1 -0
- package/dist/venice/audio.js +234 -0
- package/dist/venice/audio.js.map +1 -0
- package/dist/venice/client.d.ts +86 -0
- package/dist/venice/client.d.ts.map +1 -0
- package/dist/venice/client.js +375 -0
- package/dist/venice/client.js.map +1 -0
- package/dist/venice/edit.d.ts +57 -0
- package/dist/venice/edit.d.ts.map +1 -0
- package/dist/venice/edit.js +100 -0
- package/dist/venice/edit.js.map +1 -0
- package/dist/venice/generate.d.ts +47 -0
- package/dist/venice/generate.d.ts.map +1 -0
- package/dist/venice/generate.js +150 -0
- package/dist/venice/generate.js.map +1 -0
- package/dist/venice/image-bytes.d.ts +26 -0
- package/dist/venice/image-bytes.d.ts.map +1 -0
- package/dist/venice/image-bytes.js +101 -0
- package/dist/venice/image-bytes.js.map +1 -0
- package/dist/venice/models.d.ts +143 -0
- package/dist/venice/models.d.ts.map +1 -0
- package/dist/venice/models.js +984 -0
- package/dist/venice/models.js.map +1 -0
- package/dist/venice/multi-edit.d.ts +40 -0
- package/dist/venice/multi-edit.d.ts.map +1 -0
- package/dist/venice/multi-edit.js +97 -0
- package/dist/venice/multi-edit.js.map +1 -0
- package/dist/venice/provenance.d.ts +66 -0
- package/dist/venice/provenance.d.ts.map +1 -0
- package/dist/venice/provenance.js +151 -0
- package/dist/venice/provenance.js.map +1 -0
- package/dist/venice/recipe.d.ts +69 -0
- package/dist/venice/recipe.d.ts.map +1 -0
- package/dist/venice/recipe.js +103 -0
- package/dist/venice/recipe.js.map +1 -0
- package/dist/venice/rejection.d.ts +63 -0
- package/dist/venice/rejection.d.ts.map +1 -0
- package/dist/venice/rejection.js +111 -0
- package/dist/venice/rejection.js.map +1 -0
- package/dist/venice/seedance-preflight.d.ts +38 -0
- package/dist/venice/seedance-preflight.d.ts.map +1 -0
- package/dist/venice/seedance-preflight.js +29 -0
- package/dist/venice/seedance-preflight.js.map +1 -0
- package/dist/venice/types.d.ts +212 -0
- package/dist/venice/types.d.ts.map +1 -0
- package/dist/venice/types.js +9 -0
- package/dist/venice/types.js.map +1 -0
- package/dist/venice/video.d.ts +77 -0
- package/dist/venice/video.d.ts.map +1 -0
- package/dist/venice/video.js +163 -0
- package/dist/venice/video.js.map +1 -0
- package/dist/venice/voices.d.ts +40 -0
- package/dist/venice/voices.d.ts.map +1 -0
- package/dist/venice/voices.js +194 -0
- package/dist/venice/voices.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Character description synthesis.
|
|
3
|
+
// Transforms raw CharacterProfile data into structured, prompt-ready
|
|
4
|
+
// descriptions suitable for injection into image generation requests.
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// ---- Extraction patterns --------------------------------------------------
|
|
7
|
+
/**
|
|
8
|
+
* Each entry maps a regex to one or more attribute fields.
|
|
9
|
+
* Patterns are applied against physical-description lines to populate
|
|
10
|
+
* the PhysicalAttributes struct.
|
|
11
|
+
*/
|
|
12
|
+
const ATTRIBUTE_EXTRACTORS = [
|
|
13
|
+
// Age
|
|
14
|
+
{
|
|
15
|
+
pattern: /\b(\d{1,2})s?\s*(?:years?\s*old|year[- ]old)\b/i,
|
|
16
|
+
field: "ageRange",
|
|
17
|
+
transform: (m) => `${m[1]}s`,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
pattern: /\b(early|mid|late)\s*(\d{1,2})s\b/i,
|
|
21
|
+
field: "ageRange",
|
|
22
|
+
transform: (m) => `${m[1]} ${m[2]}s`,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
pattern: /\b(teenage|elderly|middle[- ]aged|young|older|youthful)\b/i,
|
|
26
|
+
field: "ageRange",
|
|
27
|
+
transform: (m) => m[1].toLowerCase(),
|
|
28
|
+
},
|
|
29
|
+
// Hair color
|
|
30
|
+
{
|
|
31
|
+
pattern: /\b(blonde|blond|brunette|brown|black|red|auburn|grey|gray|silver|white|dark|light|sandy|strawberry[- ]blonde|platinum|golden|chestnut|raven)\s*hair\b/i,
|
|
32
|
+
field: "hairColor",
|
|
33
|
+
transform: (m) => m[1].toLowerCase(),
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
pattern: /\bhair\b.*?\b(blonde|blond|brunette|brown|black|red|auburn|grey|gray|silver|white|dark|light|sandy|platinum|golden|chestnut|raven)\b/i,
|
|
37
|
+
field: "hairColor",
|
|
38
|
+
transform: (m) => m[1].toLowerCase(),
|
|
39
|
+
},
|
|
40
|
+
// Hair length
|
|
41
|
+
{
|
|
42
|
+
pattern: /\b(short|long|shoulder[- ]length|cropped|close[- ]cropped|medium[- ]length|waist[- ]length)\s*hair\b/i,
|
|
43
|
+
field: "hairLength",
|
|
44
|
+
transform: (m) => m[1].toLowerCase(),
|
|
45
|
+
},
|
|
46
|
+
// Hair style
|
|
47
|
+
{
|
|
48
|
+
pattern: /\b(curly|straight|wavy|braided|braids|ponytail|bun|dreadlocks|dreads|mohawk|buzz[- ]cut|slicked[- ]back|tousled|messy|neat|pulled[- ]back|afro)\b/i,
|
|
49
|
+
field: "hairStyle",
|
|
50
|
+
transform: (m) => m[1].toLowerCase(),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
pattern: /\bbald\b/i,
|
|
54
|
+
field: "hairStyle",
|
|
55
|
+
transform: () => "bald",
|
|
56
|
+
},
|
|
57
|
+
// Eye color
|
|
58
|
+
{
|
|
59
|
+
pattern: /\b(blue|green|brown|hazel|grey|gray|dark|light|amber|violet|black|ice[- ]blue)\s*eyes?\b/i,
|
|
60
|
+
field: "eyeColor",
|
|
61
|
+
transform: (m) => m[1].toLowerCase(),
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
pattern: /\beyes?\b.*?\b(blue|green|brown|hazel|grey|gray|dark|light|amber|violet|black)\b/i,
|
|
65
|
+
field: "eyeColor",
|
|
66
|
+
transform: (m) => m[1].toLowerCase(),
|
|
67
|
+
},
|
|
68
|
+
// Eye shape
|
|
69
|
+
{
|
|
70
|
+
pattern: /\b(narrow|wide|almond[- ]shaped|deep[- ]set|round|hooded|piercing|bright|sharp|tired|sunken)\s*eyes?\b/i,
|
|
71
|
+
field: "eyeShape",
|
|
72
|
+
transform: (m) => m[1].toLowerCase(),
|
|
73
|
+
},
|
|
74
|
+
// Build
|
|
75
|
+
{
|
|
76
|
+
pattern: /\b(muscular|slender|stocky|thin|heavy|heavyset|lean|athletic|wiry|burly|petite|portly|stout|gaunt|lanky|broad[- ]shouldered|slight)\b/i,
|
|
77
|
+
field: "build",
|
|
78
|
+
transform: (m) => m[1].toLowerCase(),
|
|
79
|
+
},
|
|
80
|
+
// Height
|
|
81
|
+
{
|
|
82
|
+
pattern: /\b(tall|short|average[- ]height|towering|diminutive|petite)\b/i,
|
|
83
|
+
field: "height",
|
|
84
|
+
transform: (m) => m[1].toLowerCase(),
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
pattern: /\b(\d['']?\s*\d{1,2}"?)\b/,
|
|
88
|
+
field: "height",
|
|
89
|
+
transform: (m) => m[1],
|
|
90
|
+
},
|
|
91
|
+
// Ethnicity / appearance
|
|
92
|
+
{
|
|
93
|
+
pattern: /\b(African[- ]American|Black|Caucasian|White|Asian|Latino|Latina|Hispanic|Native\s*American|Indigenous|Middle\s*Eastern|South\s*Asian|East\s*Asian|Pacific\s*Islander|mixed[- ]race|biracial)\b/i,
|
|
94
|
+
field: "ethnicity",
|
|
95
|
+
transform: (m) => m[1],
|
|
96
|
+
},
|
|
97
|
+
// Face features (collected as array)
|
|
98
|
+
{
|
|
99
|
+
pattern: /\b(beard|bearded|mustache|moustache|goatee|stubble|clean[- ]shaven|scar|scarred|freckles|freckled|wrinkles|wrinkled|dimples|dimpled|angular|chiseled|round[- ]faced|square[- ]jawed|high\s*cheekbones)\b/i,
|
|
100
|
+
field: "faceFeatures",
|
|
101
|
+
transform: (m) => m[1].toLowerCase(),
|
|
102
|
+
},
|
|
103
|
+
// Distinguishing features (collected as array)
|
|
104
|
+
{
|
|
105
|
+
pattern: /\b(tattoo|tattooed|piercing|pierced|birthmark|mole|limp|eye[- ]patch|prosthetic|glasses|spectacles|monocle|hearing\s*aid|cane|wheelchair)\b/i,
|
|
106
|
+
field: "distinguishingFeatures",
|
|
107
|
+
transform: (m) => m[1].toLowerCase(),
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
// ---- Wardrobe extraction --------------------------------------------------
|
|
111
|
+
const WARDROBE_PATTERN = /\b(?:wearing|wears|dressed\s+in|clad\s+in|in\s+a|outfit|suit|uniform|shirt|blouse|coat|jacket|jeans|pants|trousers|skirt|dress|boots|shoes|sneakers|heels|sandals|hat|cap|helmet|gloves|scarf|tie|vest|sweater|hoodie|tank\s*top|t-shirt|tuxedo|gown|armor|cloak|robe|overalls|apron)\b/i;
|
|
112
|
+
/**
|
|
113
|
+
* Extract wardrobe-related fragments from a line of text.
|
|
114
|
+
* Returns the full sentence/clause containing the wardrobe keyword.
|
|
115
|
+
*/
|
|
116
|
+
function extractWardrobeFragment(line) {
|
|
117
|
+
if (!WARDROBE_PATTERN.test(line))
|
|
118
|
+
return null;
|
|
119
|
+
// Try to extract just the clause that mentions clothing.
|
|
120
|
+
// Split on common clause delimiters and find the relevant part.
|
|
121
|
+
const clauses = line.split(/[,.;]/).map((c) => c.trim());
|
|
122
|
+
for (const clause of clauses) {
|
|
123
|
+
if (WARDROBE_PATTERN.test(clause) && clause.length > 5) {
|
|
124
|
+
return clause;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return line.trim();
|
|
128
|
+
}
|
|
129
|
+
// ---- Attribute extraction -------------------------------------------------
|
|
130
|
+
function createEmptyAttributes() {
|
|
131
|
+
return {
|
|
132
|
+
ageRange: "unspecified",
|
|
133
|
+
ethnicity: "unspecified",
|
|
134
|
+
hairColor: "unspecified",
|
|
135
|
+
hairLength: "unspecified",
|
|
136
|
+
hairStyle: "unspecified",
|
|
137
|
+
eyeColor: "unspecified",
|
|
138
|
+
eyeShape: "unspecified",
|
|
139
|
+
faceFeatures: [],
|
|
140
|
+
build: "unspecified",
|
|
141
|
+
height: "unspecified",
|
|
142
|
+
distinguishingFeatures: [],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Run all attribute extractors against the provided description lines.
|
|
147
|
+
* First match wins for scalar fields; array fields accumulate.
|
|
148
|
+
*/
|
|
149
|
+
function extractAttributes(lines) {
|
|
150
|
+
const attrs = createEmptyAttributes();
|
|
151
|
+
for (const line of lines) {
|
|
152
|
+
for (const extractor of ATTRIBUTE_EXTRACTORS) {
|
|
153
|
+
const match = line.match(extractor.pattern);
|
|
154
|
+
if (!match)
|
|
155
|
+
continue;
|
|
156
|
+
const value = extractor.transform
|
|
157
|
+
? extractor.transform(match)
|
|
158
|
+
: match[1].toLowerCase();
|
|
159
|
+
const field = extractor.field;
|
|
160
|
+
if (field === "faceFeatures" || field === "distinguishingFeatures") {
|
|
161
|
+
// Array fields -- accumulate unique entries.
|
|
162
|
+
const arr = attrs[field];
|
|
163
|
+
if (!arr.includes(value)) {
|
|
164
|
+
arr.push(value);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
// Scalar fields -- first match wins (don't overwrite).
|
|
169
|
+
if (attrs[field] === "unspecified") {
|
|
170
|
+
attrs[field] = value;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return attrs;
|
|
176
|
+
}
|
|
177
|
+
// ---- Description builders -------------------------------------------------
|
|
178
|
+
/**
|
|
179
|
+
* Build a short 1-2 sentence description from extracted attributes.
|
|
180
|
+
*/
|
|
181
|
+
function buildShortDescription(name, attrs) {
|
|
182
|
+
const parts = [];
|
|
183
|
+
// Age + build/height
|
|
184
|
+
const agePart = attrs.ageRange !== "unspecified" ? attrs.ageRange : null;
|
|
185
|
+
const buildPart = attrs.build !== "unspecified" ? attrs.build : null;
|
|
186
|
+
const heightPart = attrs.height !== "unspecified" ? attrs.height : null;
|
|
187
|
+
if (agePart || buildPart || heightPart) {
|
|
188
|
+
const descriptors = [agePart, heightPart, buildPart].filter(Boolean);
|
|
189
|
+
parts.push(descriptors.join(", "));
|
|
190
|
+
}
|
|
191
|
+
// Hair
|
|
192
|
+
if (attrs.hairColor !== "unspecified" || attrs.hairStyle !== "unspecified") {
|
|
193
|
+
const hairParts = [attrs.hairColor, attrs.hairLength, attrs.hairStyle]
|
|
194
|
+
.filter((v) => v !== "unspecified");
|
|
195
|
+
if (hairParts.length > 0) {
|
|
196
|
+
parts.push(`${hairParts.join(" ")} hair`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Eyes
|
|
200
|
+
if (attrs.eyeColor !== "unspecified") {
|
|
201
|
+
parts.push(`${attrs.eyeColor} eyes`);
|
|
202
|
+
}
|
|
203
|
+
if (parts.length === 0) {
|
|
204
|
+
return `${name}, a character whose physical appearance is not described in the screenplay.`;
|
|
205
|
+
}
|
|
206
|
+
return `${name}: ${parts.join(", ")}.`;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Build an exhaustive paragraph covering all known attributes.
|
|
210
|
+
* Formatted for direct injection into image generation prompts.
|
|
211
|
+
* Unspecified fields are explicitly noted to prevent hallucination
|
|
212
|
+
* by the image model.
|
|
213
|
+
*/
|
|
214
|
+
function buildFullDescription(name, attrs) {
|
|
215
|
+
const sections = [];
|
|
216
|
+
// Identity line
|
|
217
|
+
sections.push(`Character: ${name}.`);
|
|
218
|
+
// Age
|
|
219
|
+
sections.push(attrs.ageRange !== "unspecified"
|
|
220
|
+
? `Age range: ${attrs.ageRange}.`
|
|
221
|
+
: "Age: unspecified.");
|
|
222
|
+
// Ethnicity / general appearance
|
|
223
|
+
sections.push(attrs.ethnicity !== "unspecified"
|
|
224
|
+
? `Ethnicity/appearance: ${attrs.ethnicity}.`
|
|
225
|
+
: "Ethnicity/appearance: unspecified.");
|
|
226
|
+
// Hair
|
|
227
|
+
const hairDescriptors = [attrs.hairColor, attrs.hairLength, attrs.hairStyle]
|
|
228
|
+
.filter((v) => v !== "unspecified");
|
|
229
|
+
if (hairDescriptors.length > 0) {
|
|
230
|
+
sections.push(`Hair: ${hairDescriptors.join(", ")}.`);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
sections.push("Hair: unspecified.");
|
|
234
|
+
}
|
|
235
|
+
// Eyes
|
|
236
|
+
const eyeDescriptors = [attrs.eyeColor, attrs.eyeShape].filter((v) => v !== "unspecified");
|
|
237
|
+
if (eyeDescriptors.length > 0) {
|
|
238
|
+
sections.push(`Eyes: ${eyeDescriptors.join(", ")}.`);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
sections.push("Eyes: unspecified.");
|
|
242
|
+
}
|
|
243
|
+
// Face
|
|
244
|
+
if (attrs.faceFeatures.length > 0) {
|
|
245
|
+
sections.push(`Face features: ${attrs.faceFeatures.join(", ")}.`);
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
sections.push("Face features: unspecified.");
|
|
249
|
+
}
|
|
250
|
+
// Build / Height
|
|
251
|
+
const bodyDescriptors = [
|
|
252
|
+
attrs.build !== "unspecified" ? `build: ${attrs.build}` : null,
|
|
253
|
+
attrs.height !== "unspecified" ? `height: ${attrs.height}` : null,
|
|
254
|
+
].filter(Boolean);
|
|
255
|
+
if (bodyDescriptors.length > 0) {
|
|
256
|
+
sections.push(`Body: ${bodyDescriptors.join(", ")}.`);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
sections.push("Build/height: unspecified.");
|
|
260
|
+
}
|
|
261
|
+
// Distinguishing features
|
|
262
|
+
if (attrs.distinguishingFeatures.length > 0) {
|
|
263
|
+
sections.push(`Distinguishing features: ${attrs.distinguishingFeatures.join(", ")}.`);
|
|
264
|
+
}
|
|
265
|
+
return sections.join(" ");
|
|
266
|
+
}
|
|
267
|
+
// ---- Main export ----------------------------------------------------------
|
|
268
|
+
/**
|
|
269
|
+
* Transform an array of `CharacterProfile` objects into structured
|
|
270
|
+
* `CharacterDescription` entries. Each description synthesizes scattered
|
|
271
|
+
* physical-description fragments into a coherent, prompt-ready format.
|
|
272
|
+
*
|
|
273
|
+
* @param profiles - Array of profiles from `extractCharacterProfiles`.
|
|
274
|
+
* @returns Array of `CharacterDescription` in the same order as input.
|
|
275
|
+
*/
|
|
276
|
+
export function buildCharacterDescriptions(profiles) {
|
|
277
|
+
return profiles.map((profile) => {
|
|
278
|
+
// Extract structured attributes from physical description lines.
|
|
279
|
+
const attrs = extractAttributes(profile.physicalDescriptions);
|
|
280
|
+
// Build the short and full descriptions.
|
|
281
|
+
const shortDescription = buildShortDescription(profile.name, attrs);
|
|
282
|
+
const fullDescription = buildFullDescription(profile.name, attrs);
|
|
283
|
+
// Extract wardrobe -- default and per-scene.
|
|
284
|
+
const wardrobeByScene = new Map();
|
|
285
|
+
const allWardrobeFragments = [];
|
|
286
|
+
// physicalDescriptions and mentions may overlap; deduplicate.
|
|
287
|
+
const allLines = [...profile.physicalDescriptions, ...profile.mentions];
|
|
288
|
+
const uniqueLines = Array.from(new Set(allLines));
|
|
289
|
+
for (const line of uniqueLines) {
|
|
290
|
+
const fragment = extractWardrobeFragment(line);
|
|
291
|
+
if (fragment) {
|
|
292
|
+
allWardrobeFragments.push(fragment);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// Deduplicate wardrobe fragments.
|
|
296
|
+
const uniqueWardrobe = Array.from(new Set(allWardrobeFragments));
|
|
297
|
+
const wardrobe = uniqueWardrobe.length > 0
|
|
298
|
+
? uniqueWardrobe.join("; ")
|
|
299
|
+
: "unspecified";
|
|
300
|
+
return {
|
|
301
|
+
name: profile.name,
|
|
302
|
+
shortDescription,
|
|
303
|
+
fullDescription,
|
|
304
|
+
wardrobe,
|
|
305
|
+
wardrobeByScene,
|
|
306
|
+
};
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=describer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describer.js","sourceRoot":"","sources":["../../src/characters/describer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Scene } from "../parsers/scene-extractor.js";
|
|
2
|
+
/** Aggregated profile for a single character across the entire screenplay. */
|
|
3
|
+
export interface CharacterProfile {
|
|
4
|
+
/** Canonical uppercase character name (e.g. "MARCUS"). */
|
|
5
|
+
name: string;
|
|
6
|
+
/** Every line of action or dialogue text that mentions this character. */
|
|
7
|
+
mentions: string[];
|
|
8
|
+
/** Extracted physical-description fragments found in action lines. */
|
|
9
|
+
physicalDescriptions: string[];
|
|
10
|
+
/** 1-based scene numbers in which the character appears. */
|
|
11
|
+
scenesPresent: number[];
|
|
12
|
+
/** Total number of dialogue lines attributed to this character. */
|
|
13
|
+
dialogueCount: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Extract character profiles from an array of parsed scenes.
|
|
17
|
+
*
|
|
18
|
+
* The function iterates every scene and inspects both dialogue attributions
|
|
19
|
+
* and action/description text to build a comprehensive profile for each
|
|
20
|
+
* unique character. Profiles are sorted by `dialogueCount` descending so
|
|
21
|
+
* that principal characters appear first.
|
|
22
|
+
*
|
|
23
|
+
* @param scenes - Array of `Scene` objects produced by the scene parser.
|
|
24
|
+
* @returns Deduplicated, sorted array of `CharacterProfile` entries.
|
|
25
|
+
*/
|
|
26
|
+
export declare function extractCharacterProfiles(scenes: Scene[]): CharacterProfile[];
|
|
27
|
+
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/characters/extractor.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AAI3D,8EAA8E;AAC9E,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IAEb,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,EAAE,CAAC;IAEnB,sEAAsE;IACtE,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAE/B,4DAA4D;IAC5D,aAAa,EAAE,MAAM,EAAE,CAAC;IAExB,mEAAmE;IACnE,aAAa,EAAE,MAAM,CAAC;CACvB;AAyHD;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,gBAAgB,EAAE,CAsK5E"}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Character profile extraction from parsed screenplay scenes.
|
|
3
|
+
// Scans dialogue, action, and scene headers to build rich character profiles
|
|
4
|
+
// that drive downstream description synthesis and reference image generation.
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// ---- Internal constants ---------------------------------------------------
|
|
7
|
+
/**
|
|
8
|
+
* Keywords that commonly appear in physical descriptions of characters.
|
|
9
|
+
* Used to filter action lines for appearance-related text.
|
|
10
|
+
*/
|
|
11
|
+
const PHYSICAL_KEYWORDS = [
|
|
12
|
+
"hair",
|
|
13
|
+
"eyes",
|
|
14
|
+
"eye",
|
|
15
|
+
"tall",
|
|
16
|
+
"short",
|
|
17
|
+
"wearing",
|
|
18
|
+
"wears",
|
|
19
|
+
"dressed",
|
|
20
|
+
"dress",
|
|
21
|
+
"outfit",
|
|
22
|
+
"suit",
|
|
23
|
+
"shirt",
|
|
24
|
+
"coat",
|
|
25
|
+
"jacket",
|
|
26
|
+
"jeans",
|
|
27
|
+
"pants",
|
|
28
|
+
"skirt",
|
|
29
|
+
"boots",
|
|
30
|
+
"shoes",
|
|
31
|
+
"hat",
|
|
32
|
+
"glasses",
|
|
33
|
+
"age",
|
|
34
|
+
"aged",
|
|
35
|
+
"old",
|
|
36
|
+
"young",
|
|
37
|
+
"elderly",
|
|
38
|
+
"teenage",
|
|
39
|
+
"middle-aged",
|
|
40
|
+
"skin",
|
|
41
|
+
"complexion",
|
|
42
|
+
"build",
|
|
43
|
+
"muscular",
|
|
44
|
+
"slender",
|
|
45
|
+
"stocky",
|
|
46
|
+
"thin",
|
|
47
|
+
"heavy",
|
|
48
|
+
"heavyset",
|
|
49
|
+
"lean",
|
|
50
|
+
"athletic",
|
|
51
|
+
"face",
|
|
52
|
+
"facial",
|
|
53
|
+
"beard",
|
|
54
|
+
"mustache",
|
|
55
|
+
"moustache",
|
|
56
|
+
"clean-shaven",
|
|
57
|
+
"scar",
|
|
58
|
+
"scarred",
|
|
59
|
+
"tattoo",
|
|
60
|
+
"tattooed",
|
|
61
|
+
"piercing",
|
|
62
|
+
"freckles",
|
|
63
|
+
"wrinkles",
|
|
64
|
+
"handsome",
|
|
65
|
+
"beautiful",
|
|
66
|
+
"pretty",
|
|
67
|
+
"rugged",
|
|
68
|
+
"height",
|
|
69
|
+
"weight",
|
|
70
|
+
"blonde",
|
|
71
|
+
"brunette",
|
|
72
|
+
"redhead",
|
|
73
|
+
"bald",
|
|
74
|
+
"curly",
|
|
75
|
+
"straight",
|
|
76
|
+
"shoulder-length",
|
|
77
|
+
"ponytail",
|
|
78
|
+
"braids",
|
|
79
|
+
"uniform",
|
|
80
|
+
"armor",
|
|
81
|
+
"cloak",
|
|
82
|
+
"robe",
|
|
83
|
+
];
|
|
84
|
+
/** Pre-compiled regex for matching any physical keyword in a line. */
|
|
85
|
+
const PHYSICAL_KEYWORD_PATTERN = new RegExp(`\\b(?:${PHYSICAL_KEYWORDS.join("|")})\\b`, "i");
|
|
86
|
+
// ---- Helpers --------------------------------------------------------------
|
|
87
|
+
/**
|
|
88
|
+
* Normalise a character name to a canonical uppercase form.
|
|
89
|
+
* Strips parenthetical extensions like "(V.O.)" or "(CONT'D)".
|
|
90
|
+
*/
|
|
91
|
+
function canonicalizeName(raw) {
|
|
92
|
+
return raw
|
|
93
|
+
.replace(/\s*\(.*?\)\s*/g, "")
|
|
94
|
+
.trim()
|
|
95
|
+
.toUpperCase();
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Test whether an action line contains the character name as a whole word.
|
|
99
|
+
* Uses a word-boundary regex so "MARK" does not match inside "MARKET".
|
|
100
|
+
*/
|
|
101
|
+
function lineContainsName(line, name) {
|
|
102
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
103
|
+
const pattern = new RegExp(`\\b${escaped}\\b`, "i");
|
|
104
|
+
return pattern.test(line);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Determine whether an action line that mentions a character also contains
|
|
108
|
+
* physical-description content worth extracting.
|
|
109
|
+
*/
|
|
110
|
+
function hasPhysicalDescription(line) {
|
|
111
|
+
return PHYSICAL_KEYWORD_PATTERN.test(line);
|
|
112
|
+
}
|
|
113
|
+
// ---- Core extraction ------------------------------------------------------
|
|
114
|
+
/**
|
|
115
|
+
* Extract character profiles from an array of parsed scenes.
|
|
116
|
+
*
|
|
117
|
+
* The function iterates every scene and inspects both dialogue attributions
|
|
118
|
+
* and action/description text to build a comprehensive profile for each
|
|
119
|
+
* unique character. Profiles are sorted by `dialogueCount` descending so
|
|
120
|
+
* that principal characters appear first.
|
|
121
|
+
*
|
|
122
|
+
* @param scenes - Array of `Scene` objects produced by the scene parser.
|
|
123
|
+
* @returns Deduplicated, sorted array of `CharacterProfile` entries.
|
|
124
|
+
*/
|
|
125
|
+
export function extractCharacterProfiles(scenes) {
|
|
126
|
+
const profileMap = new Map();
|
|
127
|
+
/** Retrieve or create a fresh profile entry for the given name. */
|
|
128
|
+
function getOrCreate(name) {
|
|
129
|
+
const canonical = canonicalizeName(name);
|
|
130
|
+
let profile = profileMap.get(canonical);
|
|
131
|
+
if (!profile) {
|
|
132
|
+
profile = {
|
|
133
|
+
name: canonical,
|
|
134
|
+
mentions: [],
|
|
135
|
+
physicalDescriptions: [],
|
|
136
|
+
scenesPresent: [],
|
|
137
|
+
dialogueCount: 0,
|
|
138
|
+
};
|
|
139
|
+
profileMap.set(canonical, profile);
|
|
140
|
+
}
|
|
141
|
+
return profile;
|
|
142
|
+
}
|
|
143
|
+
for (const scene of scenes) {
|
|
144
|
+
const sceneNum = scene.number;
|
|
145
|
+
// --- Dialogue pass ---
|
|
146
|
+
// Each dialogue entry attributes a line to a named character.
|
|
147
|
+
if (scene.dialogue) {
|
|
148
|
+
for (const entry of scene.dialogue) {
|
|
149
|
+
const profile = getOrCreate(entry.character);
|
|
150
|
+
// Track scene presence (deduplicated later).
|
|
151
|
+
if (!profile.scenesPresent.includes(sceneNum)) {
|
|
152
|
+
profile.scenesPresent.push(sceneNum);
|
|
153
|
+
}
|
|
154
|
+
// Each DialogueLine represents one dialogue line.
|
|
155
|
+
profile.dialogueCount += 1;
|
|
156
|
+
// Dialogue lines themselves can sometimes contain self-referential
|
|
157
|
+
// physical description ("I cut my hair"), but we focus on action
|
|
158
|
+
// lines for more reliable extraction.
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// --- Action / description pass ---
|
|
162
|
+
// Scan action lines for character name mentions and physical descriptors.
|
|
163
|
+
const actionLines = scene.action ?? [];
|
|
164
|
+
// Collect all known character names so far (including those just discovered
|
|
165
|
+
// in dialogue above) to search action text against.
|
|
166
|
+
const knownNames = Array.from(profileMap.keys());
|
|
167
|
+
for (const line of actionLines) {
|
|
168
|
+
for (const name of knownNames) {
|
|
169
|
+
if (!lineContainsName(line, name)) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
const profile = getOrCreate(name);
|
|
173
|
+
// Record the mention.
|
|
174
|
+
profile.mentions.push(line);
|
|
175
|
+
// Track scene presence.
|
|
176
|
+
if (!profile.scenesPresent.includes(sceneNum)) {
|
|
177
|
+
profile.scenesPresent.push(sceneNum);
|
|
178
|
+
}
|
|
179
|
+
// Check for physical description content.
|
|
180
|
+
if (hasPhysicalDescription(line)) {
|
|
181
|
+
profile.physicalDescriptions.push(line);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// --- Second discovery pass ---
|
|
186
|
+
// Some characters appear only in action text (e.g. background characters
|
|
187
|
+
// whose names are introduced in ALL CAPS inline). Screenplay convention
|
|
188
|
+
// introduces a character name in uppercase the first time they appear in
|
|
189
|
+
// action. We detect standalone uppercase words (2+ letters, not scene
|
|
190
|
+
// slugline terms) that could be character introductions.
|
|
191
|
+
for (const line of actionLines) {
|
|
192
|
+
// Match words that are fully uppercase and at least 2 characters,
|
|
193
|
+
// filtering out common screenplay terms and slugline fragments.
|
|
194
|
+
const uppercaseWords = line.match(/\b[A-Z][A-Z'-]{1,}\b/g);
|
|
195
|
+
if (!uppercaseWords)
|
|
196
|
+
continue;
|
|
197
|
+
const sluglineNoise = new Set([
|
|
198
|
+
"INT",
|
|
199
|
+
"EXT",
|
|
200
|
+
"DAY",
|
|
201
|
+
"NIGHT",
|
|
202
|
+
"MORNING",
|
|
203
|
+
"EVENING",
|
|
204
|
+
"DAWN",
|
|
205
|
+
"DUSK",
|
|
206
|
+
"LATER",
|
|
207
|
+
"CONTINUOUS",
|
|
208
|
+
"CONT",
|
|
209
|
+
"CUT",
|
|
210
|
+
"FADE",
|
|
211
|
+
"DISSOLVE",
|
|
212
|
+
"SMASH",
|
|
213
|
+
"MATCH",
|
|
214
|
+
"ANGLE",
|
|
215
|
+
"CLOSE",
|
|
216
|
+
"WIDE",
|
|
217
|
+
"POV",
|
|
218
|
+
"INSERT",
|
|
219
|
+
"FLASHBACK",
|
|
220
|
+
"INTERCUT",
|
|
221
|
+
"SUPER",
|
|
222
|
+
"TITLE",
|
|
223
|
+
"THE",
|
|
224
|
+
"AND",
|
|
225
|
+
"WITH",
|
|
226
|
+
"FROM",
|
|
227
|
+
"BACK",
|
|
228
|
+
"END",
|
|
229
|
+
"OVER",
|
|
230
|
+
"ON",
|
|
231
|
+
"TO",
|
|
232
|
+
"IN",
|
|
233
|
+
"AT",
|
|
234
|
+
"OF",
|
|
235
|
+
"OS",
|
|
236
|
+
"VO",
|
|
237
|
+
]);
|
|
238
|
+
for (const word of uppercaseWords) {
|
|
239
|
+
if (sluglineNoise.has(word))
|
|
240
|
+
continue;
|
|
241
|
+
if (profileMap.has(word)) {
|
|
242
|
+
// Already known -- just make sure this action line is recorded.
|
|
243
|
+
const profile = profileMap.get(word);
|
|
244
|
+
if (!profile.mentions.includes(line)) {
|
|
245
|
+
profile.mentions.push(line);
|
|
246
|
+
}
|
|
247
|
+
if (!profile.scenesPresent.includes(sceneNum)) {
|
|
248
|
+
profile.scenesPresent.push(sceneNum);
|
|
249
|
+
}
|
|
250
|
+
if (hasPhysicalDescription(line)) {
|
|
251
|
+
if (!profile.physicalDescriptions.includes(line)) {
|
|
252
|
+
profile.physicalDescriptions.push(line);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// We intentionally do NOT create new profiles for every uppercase word
|
|
257
|
+
// found here -- that would produce excessive false positives ("FBI",
|
|
258
|
+
// "CIA", location names, etc.). New character creation is limited to
|
|
259
|
+
// dialogue attributions, which are the most reliable signal.
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// Sort by dialogue count descending (main characters first), with a
|
|
264
|
+
// secondary alphabetical sort for stability.
|
|
265
|
+
const profiles = Array.from(profileMap.values());
|
|
266
|
+
profiles.sort((a, b) => {
|
|
267
|
+
if (b.dialogueCount !== a.dialogueCount) {
|
|
268
|
+
return b.dialogueCount - a.dialogueCount;
|
|
269
|
+
}
|
|
270
|
+
return a.name.localeCompare(b.name);
|
|
271
|
+
});
|
|
272
|
+
return profiles;
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/characters/extractor.ts"],"names":[],"mappings":"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"}
|