@stellartech/voice-widget-directus 1.0.8 → 1.0.10
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.js +38 -19
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -456,6 +456,29 @@ const VOICE_MODELS = [
|
|
|
456
456
|
];
|
|
457
457
|
const SAMPLE_TEXT = "Hello! This is a sample of my voice. I hope you enjoy listening to how I sound.";
|
|
458
458
|
const DEFAULT_FLOW_ID = "7fa08903-ed7d-4632-81fc-f422d873b8f8";
|
|
459
|
+
function splitMarkdownBySeparator(mdText, sep = "## ") {
|
|
460
|
+
const text = String(mdText || "");
|
|
461
|
+
if (!text.includes(sep)) {
|
|
462
|
+
return [text];
|
|
463
|
+
}
|
|
464
|
+
const sections = [];
|
|
465
|
+
let buffer = [];
|
|
466
|
+
let sawHeader = false;
|
|
467
|
+
for (const line of text.split("\n")) {
|
|
468
|
+
if (line.startsWith(sep)) {
|
|
469
|
+
if (sawHeader) sections.push(buffer.join("\n"));
|
|
470
|
+
sawHeader = true;
|
|
471
|
+
buffer = [line];
|
|
472
|
+
} else {
|
|
473
|
+
buffer.push(line);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (sawHeader) sections.push(buffer.join("\n"));
|
|
477
|
+
return sections.filter((s) => s.trim().length > 0);
|
|
478
|
+
}
|
|
479
|
+
function audioFilesCollection(collection) {
|
|
480
|
+
return collection?.startsWith("NX_") ? "NX_AudioFiles" : "AudioFiles";
|
|
481
|
+
}
|
|
459
482
|
function useVoicingApi(api) {
|
|
460
483
|
async function fetchVoices(collection = "Voices") {
|
|
461
484
|
try {
|
|
@@ -538,8 +561,7 @@ function useVoicingApi(api) {
|
|
|
538
561
|
provider,
|
|
539
562
|
preprocessing: false,
|
|
540
563
|
title: `Voice Sample - ${voiceId}`,
|
|
541
|
-
audio_files_collection:
|
|
542
|
-
// Include lesson context for callback tracking
|
|
564
|
+
audio_files_collection: audioFilesCollection(collection),
|
|
543
565
|
lesson_id: lessonId || null,
|
|
544
566
|
collection,
|
|
545
567
|
voice_config: {
|
|
@@ -575,7 +597,7 @@ function useVoicingApi(api) {
|
|
|
575
597
|
}
|
|
576
598
|
console.log("[Voice Widget] Extracted audioFileId:", audioFileId);
|
|
577
599
|
if (audioFileId) {
|
|
578
|
-
const url = await resolveAudioFileUrl(audioFileId);
|
|
600
|
+
const url = await resolveAudioFileUrl(audioFileId, collection);
|
|
579
601
|
return { url, audioFileId };
|
|
580
602
|
}
|
|
581
603
|
console.log("[Voice Widget] Sample processing async, callback will update Voices.example");
|
|
@@ -606,10 +628,7 @@ function useVoicingApi(api) {
|
|
|
606
628
|
if (!textContent.trim()) {
|
|
607
629
|
throw new Error("No text content available for voiceover generation");
|
|
608
630
|
}
|
|
609
|
-
texts = textContent
|
|
610
|
-
if (texts.length === 0) {
|
|
611
|
-
texts = [textContent];
|
|
612
|
-
}
|
|
631
|
+
texts = splitMarkdownBySeparator(textContent);
|
|
613
632
|
console.log(`[Voice Widget] Generating voiceover for "${lessonTitle}" with ${texts.length} text segments`);
|
|
614
633
|
} catch (e) {
|
|
615
634
|
console.error("Failed to fetch lesson text content:", e);
|
|
@@ -628,8 +647,7 @@ function useVoicingApi(api) {
|
|
|
628
647
|
provider: request.provider,
|
|
629
648
|
preprocessing: request.preprocessing,
|
|
630
649
|
title: `Voiceover - ${lessonTitle}`,
|
|
631
|
-
audio_files_collection:
|
|
632
|
-
// Pass these so the flow can include them in callback_data
|
|
650
|
+
audio_files_collection: audioFilesCollection(collection),
|
|
633
651
|
lesson_id: request.lessonId,
|
|
634
652
|
collection,
|
|
635
653
|
voice_config: voiceConfig
|
|
@@ -672,9 +690,10 @@ function useVoicingApi(api) {
|
|
|
672
690
|
function getAudioUrl(fileId) {
|
|
673
691
|
return `/assets/${fileId}`;
|
|
674
692
|
}
|
|
675
|
-
async function resolveAudioFileUrl(audioFilesRecordId) {
|
|
693
|
+
async function resolveAudioFileUrl(audioFilesRecordId, collection) {
|
|
694
|
+
const afCollection = collection ? audioFilesCollection(collection) : "AudioFiles";
|
|
676
695
|
try {
|
|
677
|
-
const response = await api.get(`/items
|
|
696
|
+
const response = await api.get(`/items/${afCollection}/${audioFilesRecordId}`, {
|
|
678
697
|
params: { fields: ["file"] }
|
|
679
698
|
});
|
|
680
699
|
const fileField = response.data.data?.file;
|
|
@@ -1161,7 +1180,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1161
1180
|
for (const v of allVariants.value) {
|
|
1162
1181
|
if (v.audio_file_id) {
|
|
1163
1182
|
const isUuid = v.audio_file_id?.includes("-");
|
|
1164
|
-
v.audioUrl = isUuid ? getAudioUrl(v.audio_file_id) : await resolveAudioFileUrl(v.audio_file_id);
|
|
1183
|
+
v.audioUrl = isUuid ? getAudioUrl(v.audio_file_id) : await resolveAudioFileUrl(v.audio_file_id, props.collection);
|
|
1165
1184
|
}
|
|
1166
1185
|
}
|
|
1167
1186
|
currentVariantIndex.value = 0;
|
|
@@ -1340,7 +1359,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1340
1359
|
allVariants.value = variants;
|
|
1341
1360
|
for (const v of allVariants.value) {
|
|
1342
1361
|
const isUuid = v.audio_file_id?.includes("-");
|
|
1343
|
-
v.audioUrl = isUuid ? getAudioUrl(v.audio_file_id) : await resolveAudioFileUrl(v.audio_file_id);
|
|
1362
|
+
v.audioUrl = isUuid ? getAudioUrl(v.audio_file_id) : await resolveAudioFileUrl(v.audio_file_id, props.collection);
|
|
1344
1363
|
}
|
|
1345
1364
|
currentVariantIndex.value = 0;
|
|
1346
1365
|
hasExistingVoices.value = variants.length > 0;
|
|
@@ -1358,7 +1377,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1358
1377
|
const audioFileId = variant.audio_file_id;
|
|
1359
1378
|
generatedAudioId.value = audioFileId;
|
|
1360
1379
|
const isUuid = audioFileId.includes("-");
|
|
1361
|
-
generatedAudioUrl.value = isUuid ? getAudioUrl(audioFileId) : await resolveAudioFileUrl(audioFileId);
|
|
1380
|
+
generatedAudioUrl.value = isUuid ? getAudioUrl(audioFileId) : await resolveAudioFileUrl(audioFileId, props.collection);
|
|
1362
1381
|
const config = variant.voice_config;
|
|
1363
1382
|
if (config) {
|
|
1364
1383
|
isRestoringFromVariant.value = true;
|
|
@@ -1428,7 +1447,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1428
1447
|
allVariants.value = variants;
|
|
1429
1448
|
for (const v of allVariants.value) {
|
|
1430
1449
|
const isUuid = v.audio_file_id?.includes("-");
|
|
1431
|
-
v.audioUrl = isUuid ? getAudioUrl(v.audio_file_id) : await resolveAudioFileUrl(v.audio_file_id);
|
|
1450
|
+
v.audioUrl = isUuid ? getAudioUrl(v.audio_file_id) : await resolveAudioFileUrl(v.audio_file_id, props.collection);
|
|
1432
1451
|
}
|
|
1433
1452
|
currentVariantIndex.value = 0;
|
|
1434
1453
|
await loadVariantAtIndex(0);
|
|
@@ -1517,7 +1536,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1517
1536
|
for (const v of allVariants.value) {
|
|
1518
1537
|
if (v.audio_file_id) {
|
|
1519
1538
|
const isUuid = v.audio_file_id?.includes("-");
|
|
1520
|
-
v.audioUrl = isUuid ? getAudioUrl(v.audio_file_id) : await resolveAudioFileUrl(v.audio_file_id);
|
|
1539
|
+
v.audioUrl = isUuid ? getAudioUrl(v.audio_file_id) : await resolveAudioFileUrl(v.audio_file_id, props.collection);
|
|
1521
1540
|
}
|
|
1522
1541
|
}
|
|
1523
1542
|
currentVariantIndex.value = 0;
|
|
@@ -1567,7 +1586,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1567
1586
|
generatedAudioUrl.value = getAudioUrl(audioFileId);
|
|
1568
1587
|
} else {
|
|
1569
1588
|
generatedAudioId.value = audioFileId;
|
|
1570
|
-
generatedAudioUrl.value = await resolveAudioFileUrl(audioFileId);
|
|
1589
|
+
generatedAudioUrl.value = await resolveAudioFileUrl(audioFileId, props.collection);
|
|
1571
1590
|
}
|
|
1572
1591
|
}
|
|
1573
1592
|
}
|
|
@@ -2053,10 +2072,10 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
2053
2072
|
}
|
|
2054
2073
|
});
|
|
2055
2074
|
|
|
2056
|
-
var css = "\n.voice-widget[data-v-
|
|
2075
|
+
var css = "\n.voice-widget[data-v-6d27bc73] {\n font-family: var(--theme--fonts--sans--font-family);\n padding: 16px;\n border: 1px solid var(--theme--form--field--input--border-color);\n border-radius: var(--theme--border-radius);\n background: var(--theme--background);\n}\n.widget__header[data-v-6d27bc73] {\n margin-bottom: 20px;\n}\n.widget__header-row[data-v-6d27bc73] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n}\n.widget__header-text[data-v-6d27bc73] {\n flex: 1;\n}\n.widget__title[data-v-6d27bc73] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0 0 4px 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--theme--foreground);\n}\n.widget__collapse-btn[data-v-6d27bc73] {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: var(--theme--foreground-subdued);\n border-radius: 4px;\n}\n.widget__collapse-btn[data-v-6d27bc73]:hover {\n background: var(--theme--background-accent);\n}\n.widget__subtitle[data-v-6d27bc73] {\n margin: 0;\n font-size: 14px;\n color: var(--theme--foreground-subdued);\n}\n.widget__header-controls[data-v-6d27bc73] {\n display: flex;\n gap: 16px;\n align-items: center;\n}\n.widget__url-input[data-v-6d27bc73] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.widget__url-label[data-v-6d27bc73] {\n font-size: 12px;\n color: var(--theme--foreground-subdued);\n white-space: nowrap;\n}\n.widget__url-field[data-v-6d27bc73] {\n padding: 6px 10px;\n border: 1px solid var(--theme--form--field--input--border-color);\n border-radius: var(--theme--border-radius);\n font-size: 12px;\n width: 280px;\n background: var(--theme--form--field--input--background);\n color: var(--theme--foreground);\n}\n.widget__section[data-v-6d27bc73] {\n margin-bottom: 20px;\n}\n.widget__section-label[data-v-6d27bc73] {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--theme--foreground);\n}\n.widget__model-buttons[data-v-6d27bc73] {\n display: flex;\n gap: 8px;\n}\n.widget__model-btn[data-v-6d27bc73] {\n padding: 8px 16px;\n border: 1px solid var(--theme--form--field--input--border-color);\n border-radius: var(--theme--border-radius);\n background: var(--theme--background);\n color: var(--theme--foreground);\n cursor: pointer;\n font-size: 14px;\n transition: all 0.15s ease;\n}\n.widget__model-btn[data-v-6d27bc73]:hover {\n border-color: var(--theme--primary);\n}\n.widget__model-btn--active[data-v-6d27bc73] {\n background: var(--theme--primary);\n border-color: var(--theme--primary);\n color: var(--theme--primary-foreground, #fff);\n}\n.widget__voice-list[data-v-6d27bc73] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.widget__section--toggle[data-v-6d27bc73] {\n padding: 12px;\n background: var(--theme--background-subdued);\n border-radius: var(--theme--border-radius);\n}\n.widget__toggle[data-v-6d27bc73] {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n}\n.widget__toggle input[data-v-6d27bc73] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n.widget__toggle-label[data-v-6d27bc73] {\n font-size: 14px;\n font-weight: 500;\n color: var(--theme--foreground);\n}\n.widget__toggle-note[data-v-6d27bc73] {\n margin: 4px 0 0 24px;\n font-size: 12px;\n color: var(--theme--foreground-subdued);\n}\n.widget__footer[data-v-6d27bc73] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-top: 16px;\n border-top: 1px solid var(--theme--border-color-subdued);\n margin-top: 20px;\n}\n.widget__footer-left[data-v-6d27bc73],\n.widget__footer-right[data-v-6d27bc73] {\n display: flex;\n gap: 8px;\n}\n.widget__variant-nav[data-v-6d27bc73] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n margin-bottom: 16px;\n padding: 8px 0;\n}\n.widget__variant-counter[data-v-6d27bc73] {\n font-size: 14px;\n font-weight: 500;\n color: var(--theme--foreground-subdued);\n min-width: 60px;\n text-align: center;\n}\n.widget__btn--icon[data-v-6d27bc73] {\n padding: 6px;\n min-width: 32px;\n min-height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.widget__result-date[data-v-6d27bc73] {\n margin-top: 8px;\n font-size: 12px;\n color: var(--theme--foreground-subdued);\n}\n.widget__btn[data-v-6d27bc73] {\n padding: 8px 16px;\n border: none;\n border-radius: var(--theme--border-radius);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.widget__btn[data-v-6d27bc73]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.widget__btn--primary[data-v-6d27bc73] {\n background: var(--theme--primary);\n color: var(--theme--primary-foreground, #fff);\n}\n.widget__btn--primary[data-v-6d27bc73]:hover:not(:disabled) {\n background: var(--theme--primary-accent);\n}\n.widget__btn--secondary[data-v-6d27bc73] {\n background: var(--theme--background-accent);\n color: var(--theme--foreground);\n border: 1px solid var(--theme--form--field--input--border-color);\n}\n.widget__btn--secondary[data-v-6d27bc73]:hover:not(:disabled) {\n background: var(--theme--background-normal);\n}\n\n/* Processing State */\n.widget__processing[data-v-6d27bc73] {\n padding: 40px 20px;\n text-align: center;\n}\n.widget__progress[data-v-6d27bc73] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n margin-bottom: 16px;\n font-size: 16px;\n color: var(--theme--foreground);\n}\n.widget__progress-bar[data-v-6d27bc73] {\n height: 8px;\n background: var(--theme--background-accent);\n border-radius: 4px;\n overflow: hidden;\n max-width: 400px;\n margin: 0 auto;\n}\n.widget__progress-fill[data-v-6d27bc73] {\n height: 100%;\n background: var(--theme--primary);\n transition: width 0.3s ease;\n}\n\n/* Error State */\n.widget__error[data-v-6d27bc73] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n padding: 20px;\n color: var(--theme--danger);\n text-align: center;\n}\n.widget__error-actions[data-v-6d27bc73] {\n display: flex;\n gap: 8px;\n margin-top: 8px;\n}\n.widget__retry[data-v-6d27bc73] {\n padding: 6px 12px;\n background: var(--theme--danger);\n color: #fff;\n border: none;\n border-radius: var(--theme--border-radius);\n cursor: pointer;\n}\n\n/* Loading State */\n.widget__loading[data-v-6d27bc73] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 40px 20px;\n color: var(--theme--foreground-subdued);\n}\n\n/* Result State */\n.widget__result[data-v-6d27bc73] {\n padding: 20px;\n background: var(--theme--background-subdued);\n border-radius: var(--theme--border-radius);\n margin-bottom: 20px;\n}\n.widget__result-info[data-v-6d27bc73] {\n margin-top: 16px;\n padding-top: 16px;\n border-top: 1px solid var(--theme--border-color-subdued);\n}\n.widget__result-info p[data-v-6d27bc73] {\n margin: 4px 0;\n font-size: 14px;\n color: var(--theme--foreground-subdued);\n}\n.widget__result-info strong[data-v-6d27bc73] {\n color: var(--theme--foreground);\n}\n\n/* Variants List View */\n.widget__variants-list[data-v-6d27bc73] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n max-height: 400px;\n overflow-y: auto;\n margin-bottom: 16px;\n}\n.widget__variant-item[data-v-6d27bc73] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n border: 1px solid var(--theme--border-color-subdued);\n border-radius: var(--theme--border-radius);\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.widget__variant-item[data-v-6d27bc73]:hover {\n border-color: var(--theme--primary);\n}\n.widget__variant-item--selected[data-v-6d27bc73] {\n border-color: var(--theme--primary);\n background: var(--theme--primary-background);\n}\n.widget__variant-radio[data-v-6d27bc73] {\n flex-shrink: 0;\n}\n.widget__variant-radio input[data-v-6d27bc73] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n}\n.widget__variant-player[data-v-6d27bc73] {\n flex: 1;\n min-width: 200px;\n}\n.widget__variant-meta[data-v-6d27bc73] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 120px;\n}\n.widget__variant-voice[data-v-6d27bc73] {\n font-size: 13px;\n font-weight: 500;\n color: var(--theme--foreground);\n}\n.widget__variant-date[data-v-6d27bc73] {\n font-size: 11px;\n color: var(--theme--foreground-subdued);\n}\n.widget__btn--danger[data-v-6d27bc73] {\n color: var(--theme--danger);\n background: transparent;\n border: none;\n}\n.widget__btn--danger[data-v-6d27bc73]:hover {\n background: var(--theme--danger-background);\n}\n.widget__selected-info[data-v-6d27bc73] {\n padding: 12px;\n background: var(--theme--background-subdued);\n border-radius: var(--theme--border-radius);\n margin-bottom: 16px;\n}\n.widget__selected-info p[data-v-6d27bc73] {\n margin: 4px 0;\n font-size: 14px;\n color: var(--theme--foreground-subdued);\n}\n.widget__selected-info strong[data-v-6d27bc73] {\n color: var(--theme--foreground);\n}\n.widget__progress-status[data-v-6d27bc73] {\n text-align: center;\n font-size: 12px;\n color: var(--theme--foreground-subdued);\n margin-top: 8px;\n}\n\n/* Animations */\n.spinning[data-v-6d27bc73] {\n animation: spin-6d27bc73 1s linear infinite;\n}\n@keyframes spin-6d27bc73 {\nfrom { transform: rotate(0deg);\n}\nto { transform: rotate(360deg);\n}\n}\n";
|
|
2057
2076
|
n(css,{});
|
|
2058
2077
|
|
|
2059
|
-
var InterfaceComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
2078
|
+
var InterfaceComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-6d27bc73"], ["__file", "interface.vue"]]);
|
|
2060
2079
|
|
|
2061
2080
|
var index = defineInterface({
|
|
2062
2081
|
id: "voice-widget",
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stellartech/voice-widget-directus",
|
|
3
3
|
"description": "Voice generation widget with model/voice selection and audio preview for Directus",
|
|
4
4
|
"icon": "mic",
|
|
5
|
-
"version": "1.0.
|
|
5
|
+
"version": "1.0.10",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"readme": "README.md",
|
|
8
8
|
"repository": {
|