@ssml-builder-js/ssml-editor-react 2.7.0 → 2.8.1

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 CHANGED
@@ -1,5 +1,20 @@
1
1
  # @ssml-builder-js/ssml-editor-react
2
2
 
3
+ ## 2.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - ba09a72: Prepare the v2.8.1 patch release.
8
+ - Updated dependencies [ba09a72]
9
+ - @ssml-builder-js/ssml-core@2.8.1
10
+
11
+ ## 2.8.0
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies [c7c8cb4]
16
+ - @ssml-builder-js/ssml-core@2.8.0
17
+
3
18
  ## 2.7.0
4
19
 
5
20
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -3,7 +3,7 @@ import { ReactNode, CSSProperties } from 'react';
3
3
  import { SsmlDocument } from '@ssml-builder-js/ssml-core';
4
4
  import { OnMount, Monaco } from '@monaco-editor/react';
5
5
 
6
- type SsmlEditorInsertionButton = "break" | "emphasis" | "rate" | "pitch" | "volume" | "emotion" | "say-as" | "phoneme" | "audio" | "sub" | "lang" | "mark" | "bookmark" | "mstts:silence" | "mstts:viseme" | (string & {});
6
+ type SsmlEditorInsertionButton = "break" | "emphasis" | "rate" | "pitch" | "volume" | "emotion" | "say-as" | "phoneme" | "audio" | "sub" | "lang" | "mark" | "bookmark" | "mstts:silence" | "mstts:audioduration" | "mstts:viseme" | (string & {});
7
7
  type SsmlEditorButton = "help" | SsmlEditorInsertionButton | "undo" | "redo" | "clearAll" | "format" | "decorations" | (string & {});
8
8
  type SsmlEditorButtonVisibility = Readonly<Partial<Record<string, boolean>>>;
9
9
 
@@ -274,8 +274,8 @@ declare function updateTagAttribute(text: string, tagRange: SsmlTagRange, attrib
274
274
 
275
275
  type SsmlCodeLensAction = {
276
276
  type: "attribute";
277
- insertionId: "rate" | "pitch" | "break";
278
- attributeName: "rate" | "pitch" | "time";
277
+ insertionId: "rate" | "pitch" | "break" | "mstts:audioduration";
278
+ attributeName: "rate" | "pitch" | "time" | "value";
279
279
  tagRange: SsmlTagRange;
280
280
  } | {
281
281
  type: "unwrap" | "delete";
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { ReactNode, CSSProperties } from 'react';
3
3
  import { SsmlDocument } from '@ssml-builder-js/ssml-core';
4
4
  import { OnMount, Monaco } from '@monaco-editor/react';
5
5
 
6
- type SsmlEditorInsertionButton = "break" | "emphasis" | "rate" | "pitch" | "volume" | "emotion" | "say-as" | "phoneme" | "audio" | "sub" | "lang" | "mark" | "bookmark" | "mstts:silence" | "mstts:viseme" | (string & {});
6
+ type SsmlEditorInsertionButton = "break" | "emphasis" | "rate" | "pitch" | "volume" | "emotion" | "say-as" | "phoneme" | "audio" | "sub" | "lang" | "mark" | "bookmark" | "mstts:silence" | "mstts:audioduration" | "mstts:viseme" | (string & {});
7
7
  type SsmlEditorButton = "help" | SsmlEditorInsertionButton | "undo" | "redo" | "clearAll" | "format" | "decorations" | (string & {});
8
8
  type SsmlEditorButtonVisibility = Readonly<Partial<Record<string, boolean>>>;
9
9
 
@@ -274,8 +274,8 @@ declare function updateTagAttribute(text: string, tagRange: SsmlTagRange, attrib
274
274
 
275
275
  type SsmlCodeLensAction = {
276
276
  type: "attribute";
277
- insertionId: "rate" | "pitch" | "break";
278
- attributeName: "rate" | "pitch" | "time";
277
+ insertionId: "rate" | "pitch" | "break" | "mstts:audioduration";
278
+ attributeName: "rate" | "pitch" | "time" | "value";
279
279
  tagRange: SsmlTagRange;
280
280
  } | {
281
281
  type: "unwrap" | "delete";
package/dist/index.js CHANGED
@@ -54,6 +54,8 @@ function isSsmlEditorButtonVisible(buttonVisibility, button) {
54
54
  // src/constants/ssmlPresets.ts
55
55
  var ssmlPresets_exports = {};
56
56
  __export(ssmlPresets_exports, {
57
+ AUDIO_DURATION_DESCRIPTIONS: () => AUDIO_DURATION_DESCRIPTIONS,
58
+ AUDIO_DURATION_PRESETS: () => AUDIO_DURATION_PRESETS,
57
59
  BREAK_STRENGTH_PRESETS: () => BREAK_STRENGTH_PRESETS,
58
60
  BREAK_TIME_DESCRIPTIONS: () => BREAK_TIME_DESCRIPTIONS,
59
61
  BREAK_TIME_PRESETS: () => BREAK_TIME_PRESETS,
@@ -86,6 +88,103 @@ __export(ssmlPresets_exports, {
86
88
  getExpressAsStyleCategory: () => getExpressAsStyleCategory,
87
89
  resolveExpressAsStyles: () => resolveExpressAsStyles
88
90
  });
91
+
92
+ // src/constants/azureVoiceStyleMap.generated.ts
93
+ var AZURE_VOICE_STYLE_MAP = {
94
+ "de-DE-ConradNeural": ["cheerful", "sad"],
95
+ "de-DE-KatjaNeural": ["cheerful", "sad"],
96
+ "en-US-AndrewNeural": ["empathetic", "relieved"],
97
+ "en-US-GuyNeural": [
98
+ "angry",
99
+ "cheerful",
100
+ "excited",
101
+ "friendly",
102
+ "hopeful",
103
+ "newscast",
104
+ "sad",
105
+ "shouting",
106
+ "terrified",
107
+ "unfriendly",
108
+ "whispering"
109
+ ],
110
+ "en-US-JennyMultilingualNeural": [
111
+ "cheerful",
112
+ "empathetic",
113
+ "excited",
114
+ "friendly",
115
+ "hopeful",
116
+ "sad",
117
+ "shouting",
118
+ "terrified",
119
+ "unfriendly",
120
+ "whispering"
121
+ ],
122
+ "en-US-JennyNeural": [
123
+ "assistant",
124
+ "chat",
125
+ "customerservice",
126
+ "newscast",
127
+ "cheerful",
128
+ "empathetic",
129
+ "excited",
130
+ "friendly",
131
+ "hopeful",
132
+ "sad",
133
+ "shouting",
134
+ "terrified",
135
+ "unfriendly",
136
+ "whispering"
137
+ ],
138
+ "es-ES-ElviraNeural": [],
139
+ "fil-PH-AngeloNeural": [],
140
+ "fr-FR-DeniseNeural": ["cheerful", "sad"],
141
+ "fr-FR-HenriNeural": ["cheerful", "sad"],
142
+ "id-ID-GadisNeural": [],
143
+ "it-IT-ElsaNeural": ["cheerful", "sad"],
144
+ "ja-JP-KeitaNeural": ["chat"],
145
+ "ja-JP-MayuNeural": ["calm", "cheerful", "sad"],
146
+ "ja-JP-NanamiNeural": ["chat", "customerservice", "cheerful", "whispering", "sad"],
147
+ "ko-KR-SunHiNeural": ["cheerful", "sad"],
148
+ "ms-MY-YasminNeural": [],
149
+ "pt-BR-FranciscaNeural": ["calm"],
150
+ "ru-RU-SvetlanaNeural": ["cheerful", "sad", "angry", "disgruntled", "embarrassed", "fearful"],
151
+ "th-TH-PremwadeeNeural": [],
152
+ "vi-VN-HoaiMyNeural": [],
153
+ "zh-CN-XiaoxiaoNeural": [
154
+ "assistant",
155
+ "chat",
156
+ "customerservice",
157
+ "newscast",
158
+ "cheerful",
159
+ "empathetic",
160
+ "excited",
161
+ "friendly",
162
+ "hopeful",
163
+ "sad",
164
+ "terrified",
165
+ "whispering",
166
+ "poetry-reading",
167
+ "sports_commentary",
168
+ "sports_commentary_excited",
169
+ "story"
170
+ ],
171
+ "zh-CN-YunxiNeural": [
172
+ "narration-relaxed",
173
+ "embarrassed",
174
+ "fearful",
175
+ "sad",
176
+ "disgruntled",
177
+ "serious",
178
+ "angry",
179
+ "depressed",
180
+ "chat",
181
+ "cheerful",
182
+ "assistant"
183
+ ],
184
+ "zh-TW-HsiaoChenNeural": []
185
+ };
186
+
187
+ // src/constants/ssmlPresets.ts
89
188
  var SSML_PRESETS = [
90
189
  {
91
190
  id: "basic",
@@ -185,7 +284,7 @@ function getExpressAsStyleCategory(style) {
185
284
  }
186
285
  return "other";
187
286
  }
188
- var VOICE_STYLE_MAP = {
287
+ var LEGACY_VOICE_STYLE_MAP = {
189
288
  "ja-JP-MayuNeural": ["calm", "cheerful", "sad"],
190
289
  "ja-JP-KeitaNeural": ["chat"],
191
290
  "ja-JP-NanamiNeural": ["chat", "customerservice", "cheerful", "whispering", "sad"],
@@ -271,6 +370,7 @@ var VOICE_STYLE_MAP = {
271
370
  "de-DE-ConradNeural": ["cheerful", "sad"],
272
371
  "ru-RU-SvetlanaNeural": ["cheerful", "sad", "angry", "disgruntled", "embarrassed", "fearful"]
273
372
  };
373
+ var VOICE_STYLE_MAP = Object.keys(AZURE_VOICE_STYLE_MAP).length > 0 ? AZURE_VOICE_STYLE_MAP : LEGACY_VOICE_STYLE_MAP;
274
374
  var VOICE_STYLE_MAP_BY_NORMALIZED_NAME = new Map(
275
375
  Object.entries(VOICE_STYLE_MAP).map(([voiceName, styles]) => [voiceName.toLowerCase(), styles])
276
376
  );
@@ -313,6 +413,7 @@ var SAY_AS_PRESETS = [
313
413
  ];
314
414
  var LANGUAGE_PRESETS = ["ja-JP", "en-US", "de-DE", "fr-FR"];
315
415
  var SILENCE_VALUE_PRESETS = ["300ms", "500ms", "1s"];
416
+ var AUDIO_DURATION_PRESETS = ["5s", "10s", "30s"];
316
417
  var SILENCE_TYPE_PRESETS = [
317
418
  "Leading",
318
419
  "Tailing",
@@ -321,6 +422,11 @@ var SILENCE_TYPE_PRESETS = [
321
422
  "Semicolon",
322
423
  "Enumerationcomma"
323
424
  ];
425
+ var AUDIO_DURATION_DESCRIPTIONS = {
426
+ "5s": { ja: "5\u79D2", en: "5 seconds" },
427
+ "10s": { ja: "10\u79D2", en: "10 seconds" },
428
+ "30s": { ja: "30\u79D2", en: "30 seconds" }
429
+ };
324
430
  var PHONEME_ALPHABET_PRESETS = ["ipa", "sapi", "ups", "x-sampa"];
325
431
  var VISEME_TYPE_PRESETS = ["redlips_front", "FacialExpression"];
326
432
  var SSML_ATTRIBUTE_PRESETS = {
@@ -364,6 +470,9 @@ var SSML_ATTRIBUTE_PRESETS = {
364
470
  type: SILENCE_TYPE_PRESETS,
365
471
  value: SILENCE_VALUE_PRESETS
366
472
  },
473
+ "mstts:audioduration": {
474
+ value: AUDIO_DURATION_PRESETS
475
+ },
367
476
  silence: {
368
477
  type: SILENCE_TYPE_PRESETS,
369
478
  value: SILENCE_VALUE_PRESETS
@@ -910,6 +1019,13 @@ var SSML_HOVER_COPY = {
910
1019
  parameters: {
911
1020
  type: { title: "type", description: "\u30D3\u30BC\u30FC\u30E0\u30A4\u30D9\u30F3\u30C8\u306E\u5F62\u5F0F\u3002" }
912
1021
  }
1022
+ },
1023
+ "mstts:audioduration": {
1024
+ title: "\u97F3\u58F0\u9577",
1025
+ description: "\u5408\u6210\u97F3\u58F0\u306E\u76EE\u6A19\u6642\u9593\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
1026
+ parameters: {
1027
+ value: { title: "value", description: "\u76EE\u6A19\u6642\u9593\u3002\u4F8B: `10s`\u3001`5000ms`\u3001`00:00:10`\u3002" }
1028
+ }
913
1029
  }
914
1030
  }
915
1031
  },
@@ -1067,6 +1183,13 @@ var SSML_HOVER_COPY = {
1067
1183
  parameters: {
1068
1184
  type: { title: "type", description: "The viseme event format." }
1069
1185
  }
1186
+ },
1187
+ "mstts:audioduration": {
1188
+ title: "Audio duration",
1189
+ description: "Sets the target duration of synthesized audio.",
1190
+ parameters: {
1191
+ value: { title: "value", description: "The target duration, such as `10s`, `5000ms`, or `00:00:10`." }
1192
+ }
1070
1193
  }
1071
1194
  }
1072
1195
  }
@@ -1604,6 +1727,7 @@ var INTRINSICALLY_EMPTY_ELEMENTS = /* @__PURE__ */ new Set([
1604
1727
  "lexicon",
1605
1728
  "mark",
1606
1729
  "mstts:silence",
1730
+ "mstts:audioduration",
1607
1731
  "mstts:viseme",
1608
1732
  "silence",
1609
1733
  "viseme"
@@ -2450,7 +2574,7 @@ function findSsmlVoiceContext(source, offset) {
2450
2574
  }
2451
2575
 
2452
2576
  // src/hooks/useSsmlEditorState.ts
2453
- var TIMING_INSERTION_TAGS = /* @__PURE__ */ new Set(["break", "mstts:silence"]);
2577
+ var TIMING_INSERTION_TAGS = /* @__PURE__ */ new Set(["break", "mstts:silence", "mstts:audioduration"]);
2454
2578
  var PROSODY_INSERTION_TAGS = /* @__PURE__ */ new Set(["prosody", "mstts:express-as", "voice", "emphasis"]);
2455
2579
  var TEXT_INSERTION_TAGS = /* @__PURE__ */ new Set(["sub", "say-as", "phoneme", "w", "lang"]);
2456
2580
  var EMPTY_SELECTION_OVERLAY = {
@@ -3172,6 +3296,10 @@ var SSML_COMPLETION_SNIPPETS = [
3172
3296
  label: "mstts:express-as",
3173
3297
  insertText: `<mstts:express-as style="cheerful">\${1:text}</mstts:express-as>`
3174
3298
  },
3299
+ {
3300
+ label: "mstts:audioduration",
3301
+ insertText: '<mstts:audioduration value="10s" />'
3302
+ },
3175
3303
  {
3176
3304
  label: "sub",
3177
3305
  insertText: `<sub alias="\${1:\u8AAD\u307F}">\${2:\u6F22\u5B57}</sub>`
@@ -3447,7 +3575,7 @@ function registerSsmlCodeLens(monaco, editor, onOpenPopover) {
3447
3575
  break;
3448
3576
  }
3449
3577
  const tag = source.slice(tagStart, tagEnd + 1);
3450
- const tagName = tag.match(/^<\s*(prosody|break)\b/i)?.[1]?.toLowerCase();
3578
+ const tagName = tag.match(/^<\s*(prosody|break|mstts:audioduration)\b/i)?.[1]?.toLowerCase();
3451
3579
  index = tagEnd + 1;
3452
3580
  if (!tagName) {
3453
3581
  continue;
@@ -3477,7 +3605,22 @@ function registerSsmlCodeLens(monaco, editor, onOpenPopover) {
3477
3605
  elementRange
3478
3606
  })
3479
3607
  );
3480
- } else if (/\/\s*>$/.test(tag)) {
3608
+ } else if (tagName === "mstts:audioduration" && /\/\s*>$/.test(tag)) {
3609
+ lenses.push(
3610
+ createLens(
3611
+ model,
3612
+ tagStart,
3613
+ tagEnd + 1,
3614
+ `\u26A1 Duration: ${getAttributeValue(tag, "value") ?? "default"} (Click to edit)`,
3615
+ { type: "attribute", insertionId: "mstts:audioduration", attributeName: "value", tagRange }
3616
+ ),
3617
+ createLens(model, tagStart, tagEnd + 1, "Delete", {
3618
+ type: "delete",
3619
+ tagRange,
3620
+ elementRange
3621
+ })
3622
+ );
3623
+ } else if (tagName === "break" && /\/\s*>$/.test(tag)) {
3481
3624
  lenses.push(
3482
3625
  createLens(
3483
3626
  model,
@@ -3813,6 +3956,17 @@ var SSML_TAG_DEFINITIONS = [
3813
3956
  values: VISEME_TYPE_PRESETS2
3814
3957
  }
3815
3958
  ]
3959
+ },
3960
+ {
3961
+ name: "mstts:audioduration",
3962
+ description: "Sets the target duration of synthesized audio.",
3963
+ parameters: [
3964
+ {
3965
+ name: "value",
3966
+ description: "The target duration, such as `10s`, `5000ms`, or `00:00:10`.",
3967
+ example: "10s"
3968
+ }
3969
+ ]
3816
3970
  }
3817
3971
  ];
3818
3972
  var definitionsByName = /* @__PURE__ */ new Map();
@@ -4420,7 +4574,7 @@ function useSsmlMonaco({
4420
4574
  // src/SsmlEditor.tsx
4421
4575
  var import_jsx_runtime6 = require("react/jsx-runtime");
4422
4576
  var UNGROUPED_TOOLBAR_GROUP = "__ssml-editor-ungrouped__";
4423
- var TIMING_POPOVER_TAGS = /* @__PURE__ */ new Set(["break", "mstts:silence"]);
4577
+ var TIMING_POPOVER_TAGS = /* @__PURE__ */ new Set(["break", "mstts:silence", "mstts:audioduration"]);
4424
4578
  var PROSODY_POPOVER_TAGS = /* @__PURE__ */ new Set(["prosody", "mstts:express-as", "voice", "emphasis"]);
4425
4579
  var TEXT_POPOVER_TAGS = /* @__PURE__ */ new Set(["sub", "say-as", "phoneme", "w", "lang"]);
4426
4580
  function localizedText(value) {
@@ -4648,13 +4802,34 @@ var SSML_INSERTIONS = [
4648
4802
  suffix: "",
4649
4803
  mode: "insert"
4650
4804
  })
4805
+ },
4806
+ {
4807
+ id: "mstts:audioduration",
4808
+ icon: "\u25F7",
4809
+ tagName: "mstts:audioduration",
4810
+ selfClosing: true,
4811
+ labels: { ja: "\u97F3\u58F0\u9577", en: "Audio duration" },
4812
+ descriptions: {
4813
+ ja: "\u5408\u6210\u97F3\u58F0\u306E\u76EE\u6A19\u6642\u9593\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
4814
+ en: "Sets the target duration of synthesized audio."
4815
+ },
4816
+ parameterDescription: {
4817
+ ja: "\u76EE\u6A19\u6642\u9593\u3092\u9078\u629E\u3057\u307E\u3059\u3002",
4818
+ en: "Selects the target duration."
4819
+ },
4820
+ options: createInsertionOptions(AUDIO_DURATION_PRESETS, AUDIO_DURATION_DESCRIPTIONS),
4821
+ createTemplate: (value) => ({
4822
+ prefix: `<mstts:audioduration value="${value}"/>`,
4823
+ suffix: "",
4824
+ mode: "insert"
4825
+ })
4651
4826
  }
4652
4827
  ];
4653
4828
  var DEFAULT_INSERTION_GROUPS = [
4654
4829
  {
4655
4830
  id: "pauses",
4656
4831
  labels: { ja: "\u9593\u30FB\u7121\u97F3", en: "Pauses" },
4657
- insertionIds: ["break", "mstts:silence"]
4832
+ insertionIds: ["break", "mstts:silence", "mstts:audioduration"]
4658
4833
  },
4659
4834
  {
4660
4835
  id: "prosody",