@glissade/narrate 0.5.0-pre.6 → 0.5.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/dist/index.d.ts CHANGED
@@ -130,9 +130,15 @@ interface CaptionStyle {
130
130
  /** bottom inset as a fraction of scene height; defaults 0.10 (landscape) / 0.18 (portrait) */
131
131
  bottomInsetFrac?: number;
132
132
  lineHeight?: number;
133
- /** lines a caption may use before it auto-shrinks to fit; default 2 */
133
+ /**
134
+ * Opt in to the long-caption fit (auto-shrink + bottom-anchor). OFF by default
135
+ * so captionNode stays byte-identical for existing scenes — enabling it
136
+ * re-flows multi-line burned captions. Recommended for muted 9:16 cutdowns.
137
+ */
138
+ autoFit?: boolean;
139
+ /** lines a caption may use before it auto-shrinks to fit (autoFit only); default 2 */
134
140
  maxLines?: number;
135
- /** floor for auto-shrink, as a fraction of the base font size; default 0.7 */
141
+ /** floor for auto-shrink, as a fraction of the base font size (autoFit only); default 0.7 */
136
142
  minScale?: number;
137
143
  }
138
144
  /**
package/dist/index.js CHANGED
@@ -103,8 +103,6 @@ function captionNode(size, style = {}) {
103
103
  const fontFamily = style.fontFamily ?? "sans-serif";
104
104
  const width = Math.round(size.w * (style.widthFrac ?? .82));
105
105
  const lineHeight = style.lineHeight ?? 1.3;
106
- const maxLines = Math.max(1, style.maxLines ?? 2);
107
- const minFont = Math.max(1, Math.round(baseFont * (style.minScale ?? .7)));
108
106
  const bottomY = Math.round(size.h * (1 - inset));
109
107
  const node = new Text({
110
108
  id: "captions",
@@ -118,27 +116,31 @@ function captionNode(size, style = {}) {
118
116
  position: [size.w / 2, bottomY],
119
117
  filters: style.filters ?? glow("#000000cc", 3, 1)
120
118
  });
121
- const lineCountAt = (font, m) => {
122
- const t = node.text();
123
- if (!t) return 0;
124
- return breakLines(t, {
125
- family: fontFamily,
126
- size: font,
127
- weight: node.fontWeight
128
- }, width > 0 ? width : void 0, m).length;
129
- };
130
- node.fontSize.bindSource(() => {
131
- const m = node.measurerSource?.() ?? estimatingMeasurer;
132
- let font = baseFont;
133
- while (font > minFont && lineCountAt(font, m) > maxLines) font -= 1;
134
- return font;
135
- });
136
- node.position.bindSource(() => {
137
- const m = node.measurerSource?.() ?? estimatingMeasurer;
138
- const lines = Math.max(1, lineCountAt(node.fontSize(), m));
139
- const step = quantize(node.fontSize() * lineHeight);
140
- return [size.w / 2, bottomY - (lines - 1) * step];
141
- });
119
+ if (style.autoFit) {
120
+ const maxLines = Math.max(1, style.maxLines ?? 2);
121
+ const minFont = Math.max(1, Math.round(baseFont * (style.minScale ?? .7)));
122
+ const lineCountAt = (font, m) => {
123
+ const t = node.text();
124
+ if (!t) return 0;
125
+ return breakLines(t, {
126
+ family: fontFamily,
127
+ size: font,
128
+ weight: node.fontWeight
129
+ }, width > 0 ? width : void 0, m).length;
130
+ };
131
+ node.fontSize.bindSource(() => {
132
+ const m = node.measurerSource?.() ?? estimatingMeasurer;
133
+ let font = baseFont;
134
+ while (font > minFont && lineCountAt(font, m) > maxLines) font -= 1;
135
+ return font;
136
+ });
137
+ node.position.bindSource(() => {
138
+ const m = node.measurerSource?.() ?? estimatingMeasurer;
139
+ const lines = Math.max(1, lineCountAt(node.fontSize(), m));
140
+ const step = quantize(node.fontSize() * lineHeight);
141
+ return [size.w / 2, bottomY - (lines - 1) * step];
142
+ });
143
+ }
142
144
  return node;
143
145
  }
144
146
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glissade/narrate",
3
- "version": "0.5.0-pre.6",
3
+ "version": "0.5.0",
4
4
  "description": "glissade narration + captions: TTS at prepare time (gs narrate), deterministic caching, narration-anchored timeline beats, and captions as plain tracks. Render stays offline.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -19,8 +19,8 @@
19
19
  "dist"
20
20
  ],
21
21
  "dependencies": {
22
- "@glissade/core": "0.5.0-pre.6",
23
- "@glissade/scene": "0.5.0-pre.6"
22
+ "@glissade/core": "0.5.0",
23
+ "@glissade/scene": "0.5.0"
24
24
  },
25
25
  "repository": {
26
26
  "type": "git",