vidspotai-shared 1.0.53 → 1.0.55
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/lib/globals/aiModels/providers/alibaba.d.ts +4 -0
- package/lib/globals/aiModels/providers/alibaba.d.ts.map +1 -0
- package/lib/globals/aiModels/providers/alibaba.js +183 -0
- package/lib/globals/aiModels/providers/elevenlabs.d.ts +13 -0
- package/lib/globals/aiModels/providers/elevenlabs.d.ts.map +1 -0
- package/lib/globals/aiModels/providers/elevenlabs.js +25 -0
- package/lib/globals/aiModels/providers/pixverseTemplates.d.ts +36 -0
- package/lib/globals/aiModels/providers/pixverseTemplates.d.ts.map +1 -0
- package/lib/globals/aiModels/providers/pixverseTemplates.js +42 -0
- package/lib/globals/aiModels/tierHelpers.d.ts +27 -0
- package/lib/globals/aiModels/tierHelpers.d.ts.map +1 -0
- package/lib/globals/aiModels/tierHelpers.js +73 -0
- package/lib/globals/ttsModels/providers/minimax.d.ts +8 -0
- package/lib/globals/ttsModels/providers/minimax.d.ts.map +1 -0
- package/lib/globals/ttsModels/providers/minimax.js +18 -0
- package/lib/globals/ttsModels/providers/openai.d.ts +8 -0
- package/lib/globals/ttsModels/providers/openai.d.ts.map +1 -0
- package/lib/globals/ttsModels/providers/openai.js +18 -0
- package/lib/globals/types.d.ts +2 -1
- package/lib/globals/types.d.ts.map +1 -1
- package/lib/globals/types.js +1 -0
- package/lib/models/agent.model.d.ts +117 -0
- package/lib/models/agent.model.d.ts.map +1 -0
- package/lib/models/agent.model.js +13 -0
- package/lib/models/analytics.model.d.ts +4 -0
- package/lib/models/analytics.model.d.ts.map +1 -1
- package/lib/models/cachedAsset.model.d.ts +18 -0
- package/lib/models/cachedAsset.model.d.ts.map +1 -0
- package/lib/models/cachedAsset.model.js +2 -0
- package/lib/models/cachedRawAsset.model.d.ts +20 -0
- package/lib/models/cachedRawAsset.model.d.ts.map +1 -0
- package/lib/models/cachedRawAsset.model.js +2 -0
- package/lib/models/video.model.d.ts +1 -0
- package/lib/models/video.model.d.ts.map +1 -1
- package/lib/schemas/agentPersona.schema.d.ts +10 -0
- package/lib/schemas/agentPersona.schema.d.ts.map +1 -0
- package/lib/schemas/agentPersona.schema.js +11 -0
- package/lib/schemas/brandKit.schema.d.ts +101 -0
- package/lib/schemas/brandKit.schema.d.ts.map +1 -0
- package/lib/schemas/brandKit.schema.js +46 -0
- package/lib/schemas/brief.schema.d.ts +216 -0
- package/lib/schemas/brief.schema.d.ts.map +1 -0
- package/lib/schemas/brief.schema.js +118 -0
- package/lib/schemas/index.d.ts +6 -0
- package/lib/schemas/index.d.ts.map +1 -0
- package/lib/schemas/index.js +21 -0
- package/lib/schemas/project.schema.d.ts +1005 -0
- package/lib/schemas/project.schema.d.ts.map +1 -0
- package/lib/schemas/project.schema.js +238 -0
- package/lib/schemas/videoPlan.schema.d.ts +145 -0
- package/lib/schemas/videoPlan.schema.d.ts.map +1 -0
- package/lib/schemas/videoPlan.schema.js +109 -0
- package/lib/services/agent/beatSnap.d.ts +10 -0
- package/lib/services/agent/beatSnap.d.ts.map +1 -0
- package/lib/services/agent/beatSnap.js +128 -0
- package/lib/services/agent/costPreflight.d.ts +22 -0
- package/lib/services/agent/costPreflight.d.ts.map +1 -0
- package/lib/services/agent/costPreflight.js +75 -0
- package/lib/services/agent/critic.d.ts +103 -0
- package/lib/services/agent/critic.d.ts.map +1 -0
- package/lib/services/agent/critic.js +132 -0
- package/lib/services/agent/eval/index.d.ts +5 -0
- package/lib/services/agent/eval/index.d.ts.map +1 -0
- package/lib/services/agent/eval/index.js +20 -0
- package/lib/services/agent/eval/judge.d.ts +14 -0
- package/lib/services/agent/eval/judge.d.ts.map +1 -0
- package/lib/services/agent/eval/judge.js +95 -0
- package/lib/services/agent/eval/recorder.d.ts +17 -0
- package/lib/services/agent/eval/recorder.d.ts.map +1 -0
- package/lib/services/agent/eval/recorder.js +65 -0
- package/lib/services/agent/eval/seedBriefs.d.ts +16 -0
- package/lib/services/agent/eval/seedBriefs.d.ts.map +1 -0
- package/lib/services/agent/eval/seedBriefs.js +1188 -0
- package/lib/services/agent/eval/types.d.ts +196 -0
- package/lib/services/agent/eval/types.d.ts.map +1 -0
- package/lib/services/agent/eval/types.js +65 -0
- package/lib/services/agent/executor.d.ts +50 -0
- package/lib/services/agent/executor.d.ts.map +1 -0
- package/lib/services/agent/executor.js +188 -0
- package/lib/services/agent/index.d.ts +15 -0
- package/lib/services/agent/index.d.ts.map +1 -0
- package/lib/services/agent/index.js +30 -0
- package/lib/services/agent/llmCaller.d.ts +77 -0
- package/lib/services/agent/llmCaller.d.ts.map +1 -0
- package/lib/services/agent/llmCaller.js +16 -0
- package/lib/services/agent/llmCallerGateway.d.ts +39 -0
- package/lib/services/agent/llmCallerGateway.d.ts.map +1 -0
- package/lib/services/agent/llmCallerGateway.js +246 -0
- package/lib/services/agent/llmCallerRegistry.d.ts +4 -0
- package/lib/services/agent/llmCallerRegistry.d.ts.map +1 -0
- package/lib/services/agent/llmCallerRegistry.js +19 -0
- package/lib/services/agent/modelRouter.d.ts +41 -0
- package/lib/services/agent/modelRouter.d.ts.map +1 -0
- package/lib/services/agent/modelRouter.js +57 -0
- package/lib/services/agent/musicSelect.d.ts +23 -0
- package/lib/services/agent/musicSelect.d.ts.map +1 -0
- package/lib/services/agent/musicSelect.js +65 -0
- package/lib/services/agent/personas.d.ts +60 -0
- package/lib/services/agent/personas.d.ts.map +1 -0
- package/lib/services/agent/personas.js +156 -0
- package/lib/services/agent/planner.d.ts +56 -0
- package/lib/services/agent/planner.d.ts.map +1 -0
- package/lib/services/agent/planner.js +237 -0
- package/lib/services/agent/toolRegistry.d.ts +64 -0
- package/lib/services/agent/toolRegistry.d.ts.map +1 -0
- package/lib/services/agent/toolRegistry.js +78 -0
- package/lib/services/agent/tools/analyzeReference.tool.d.ts +36 -0
- package/lib/services/agent/tools/analyzeReference.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/analyzeReference.tool.js +44 -0
- package/lib/services/agent/tools/animateImage.tool.d.ts +23 -0
- package/lib/services/agent/tools/animateImage.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/animateImage.tool.js +58 -0
- package/lib/services/agent/tools/animateImageWithMotionBrush.tool.d.ts +30 -0
- package/lib/services/agent/tools/animateImageWithMotionBrush.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/animateImageWithMotionBrush.tool.js +90 -0
- package/lib/services/agent/tools/composeScene.tool.d.ts +948 -0
- package/lib/services/agent/tools/composeScene.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/composeScene.tool.js +90 -0
- package/lib/services/agent/tools/estimateCost.tool.d.ts +342 -0
- package/lib/services/agent/tools/estimateCost.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/estimateCost.tool.js +62 -0
- package/lib/services/agent/tools/generateAvatarVideo.tool.d.ts +32 -0
- package/lib/services/agent/tools/generateAvatarVideo.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/generateAvatarVideo.tool.js +112 -0
- package/lib/services/agent/tools/generateImage.tool.d.ts +28 -0
- package/lib/services/agent/tools/generateImage.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/generateImage.tool.js +97 -0
- package/lib/services/agent/tools/generateVideo.tool.d.ts +30 -0
- package/lib/services/agent/tools/generateVideo.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/generateVideo.tool.js +84 -0
- package/lib/services/agent/tools/generateVoiceover.tool.d.ts +18 -0
- package/lib/services/agent/tools/generateVoiceover.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/generateVoiceover.tool.js +72 -0
- package/lib/services/agent/tools/index.d.ts +19 -0
- package/lib/services/agent/tools/index.d.ts.map +1 -0
- package/lib/services/agent/tools/index.js +34 -0
- package/lib/services/agent/tools/planVideo.tool.d.ts +191 -0
- package/lib/services/agent/tools/planVideo.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/planVideo.tool.js +46 -0
- package/lib/services/agent/tools/render.tool.d.ts +357 -0
- package/lib/services/agent/tools/render.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/render.tool.js +48 -0
- package/lib/services/agent/tools/searchMusic.tool.d.ts +49 -0
- package/lib/services/agent/tools/searchMusic.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/searchMusic.tool.js +74 -0
- package/lib/services/agent/tools/searchStock.tool.d.ts +37 -0
- package/lib/services/agent/tools/searchStock.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/searchStock.tool.js +101 -0
- package/lib/services/agent/tools/searchUserLibrary.tool.d.ts +59 -0
- package/lib/services/agent/tools/searchUserLibrary.tool.d.ts.map +1 -0
- package/lib/services/agent/tools/searchUserLibrary.tool.js +58 -0
- package/lib/services/aiGen/canonicalAdapters/cameraControl.types.d.ts +31 -0
- package/lib/services/aiGen/canonicalAdapters/cameraControl.types.d.ts.map +1 -0
- package/lib/services/aiGen/canonicalAdapters/cameraControl.types.js +2 -0
- package/lib/services/aiGen/canonicalAdapters/index.d.ts +3 -0
- package/lib/services/aiGen/canonicalAdapters/index.d.ts.map +1 -0
- package/lib/services/aiGen/canonicalAdapters/index.js +18 -0
- package/lib/services/aiGen/canonicalAdapters/multiShot.types.d.ts +23 -0
- package/lib/services/aiGen/canonicalAdapters/multiShot.types.d.ts.map +1 -0
- package/lib/services/aiGen/canonicalAdapters/multiShot.types.js +12 -0
- package/lib/services/aiGen/providers/elevenlabs/elevenlabs.service.d.ts +18 -0
- package/lib/services/aiGen/providers/elevenlabs/elevenlabs.service.d.ts.map +1 -0
- package/lib/services/aiGen/providers/elevenlabs/elevenlabs.service.js +100 -0
- package/lib/services/aiGen/providers/fal/falImage.service.d.ts +9 -0
- package/lib/services/aiGen/providers/fal/falImage.service.d.ts.map +1 -0
- package/lib/services/aiGen/providers/fal/falImage.service.js +102 -0
- package/lib/services/aiGen/providers/fal/index.d.ts +2 -0
- package/lib/services/aiGen/providers/fal/index.d.ts.map +1 -0
- package/lib/services/aiGen/providers/fal/index.js +17 -0
- package/lib/services/aiGen/providers/kling/cameraAdapter.d.ts +4 -0
- package/lib/services/aiGen/providers/kling/cameraAdapter.d.ts.map +1 -0
- package/lib/services/aiGen/providers/kling/cameraAdapter.js +53 -0
- package/lib/services/aiGen/providers/pexels/index.d.ts +2 -0
- package/lib/services/aiGen/providers/pexels/index.d.ts.map +1 -0
- package/lib/services/aiGen/providers/pexels/index.js +17 -0
- package/lib/services/aiGen/providers/pexels/pexels.service.d.ts +11 -0
- package/lib/services/aiGen/providers/pexels/pexels.service.d.ts.map +1 -0
- package/lib/services/aiGen/providers/pexels/pexels.service.js +118 -0
- package/lib/services/aiGen/providers/runway/cameraAdapter.d.ts +3 -0
- package/lib/services/aiGen/providers/runway/cameraAdapter.d.ts.map +1 -0
- package/lib/services/aiGen/providers/runway/cameraAdapter.js +46 -0
- package/lib/services/analytics.service.d.ts +10 -0
- package/lib/services/analytics.service.d.ts.map +1 -1
- package/lib/services/analytics.service.js +27 -0
- package/lib/services/asr/assemblyai.service.d.ts +72 -0
- package/lib/services/asr/assemblyai.service.d.ts.map +1 -0
- package/lib/services/asr/assemblyai.service.js +89 -0
- package/lib/services/asr/index.d.ts +2 -0
- package/lib/services/asr/index.d.ts.map +1 -0
- package/lib/services/asr/index.js +17 -0
- package/lib/services/assetCache.service.d.ts +54 -0
- package/lib/services/assetCache.service.d.ts.map +1 -0
- package/lib/services/assetCache.service.js +96 -0
- package/lib/services/audioAnalysis/index.d.ts +2 -0
- package/lib/services/audioAnalysis/index.d.ts.map +1 -0
- package/lib/services/audioAnalysis/index.js +17 -0
- package/lib/services/audioAnalysis/onsetDetection.service.d.ts +50 -0
- package/lib/services/audioAnalysis/onsetDetection.service.d.ts.map +1 -0
- package/lib/services/audioAnalysis/onsetDetection.service.js +136 -0
- package/lib/services/editor/designToProject.d.ts +60 -0
- package/lib/services/editor/designToProject.d.ts.map +1 -0
- package/lib/services/editor/designToProject.js +194 -0
- package/lib/services/musicGen/index.d.ts +6 -0
- package/lib/services/musicGen/index.d.ts.map +1 -0
- package/lib/services/musicGen/index.js +26 -0
- package/lib/services/musicGen/musicSearchFactory.service.d.ts +14 -0
- package/lib/services/musicGen/musicSearchFactory.service.d.ts.map +1 -0
- package/lib/services/musicGen/musicSearchFactory.service.js +59 -0
- package/lib/services/musicGen/providers/curated.service.d.ts +22 -0
- package/lib/services/musicGen/providers/curated.service.d.ts.map +1 -0
- package/lib/services/musicGen/providers/curated.service.js +171 -0
- package/lib/services/musicGen/providers/jamendo.service.d.ts +8 -0
- package/lib/services/musicGen/providers/jamendo.service.d.ts.map +1 -0
- package/lib/services/musicGen/providers/jamendo.service.js +93 -0
- package/lib/services/musicGen/providers/mubert.service.d.ts +9 -0
- package/lib/services/musicGen/providers/mubert.service.d.ts.map +1 -0
- package/lib/services/musicGen/providers/mubert.service.js +113 -0
- package/lib/services/musicGen/types.d.ts +42 -0
- package/lib/services/musicGen/types.d.ts.map +1 -0
- package/lib/services/musicGen/types.js +10 -0
- package/lib/services/tts/providers/minimax.service.d.ts +14 -0
- package/lib/services/tts/providers/minimax.service.d.ts.map +1 -0
- package/lib/services/tts/providers/minimax.service.js +78 -0
- package/lib/services/tts/providers/openai.service.d.ts +14 -0
- package/lib/services/tts/providers/openai.service.d.ts.map +1 -0
- package/lib/services/tts/providers/openai.service.js +71 -0
- package/lib/utils/helpers.d.ts +1 -0
- package/lib/utils/helpers.d.ts.map +1 -1
- package/lib/utils/helpers.js +26 -12
- package/package.json +1 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CuratedMusicProvider = exports.CURATED_CATALOG = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Curated CC0 music catalog — always-on, zero-config, zero licensing risk.
|
|
6
|
+
*
|
|
7
|
+
* Seeded with a small spread across the moods/BPMs the 5 personas actually
|
|
8
|
+
* ask for. Tracks live in our own GCS bucket so we control availability and
|
|
9
|
+
* never lose the source. Hand-verified BPM means slice-1 (BPM snap) and
|
|
10
|
+
* slice-3 (onset detection) both have a reliable starting point.
|
|
11
|
+
*
|
|
12
|
+
* Add new tracks by appending to CURATED_CATALOG. Re-deploys pick them up
|
|
13
|
+
* immediately — no DB migration, no provider re-init.
|
|
14
|
+
*
|
|
15
|
+
* Sourcing rule for additions: CC0 / Pixabay license / FMA "no rights
|
|
16
|
+
* reserved" only. No CC-BY without an attribution surface in the UI first.
|
|
17
|
+
*/
|
|
18
|
+
exports.CURATED_CATALOG = [
|
|
19
|
+
{
|
|
20
|
+
id: "curated-energetic-120",
|
|
21
|
+
url: "https://storage.googleapis.com/vidspot-public-music/energetic-pop-120.mp3",
|
|
22
|
+
durationSec: 134,
|
|
23
|
+
bpm: 120,
|
|
24
|
+
mood: "energetic",
|
|
25
|
+
tags: ["pop", "upbeat", "social-recap", "ugc-ad"],
|
|
26
|
+
attribution: "Pixabay (CC0)",
|
|
27
|
+
source: "curated",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "curated-energetic-128",
|
|
31
|
+
url: "https://storage.googleapis.com/vidspot-public-music/energetic-edm-128.mp3",
|
|
32
|
+
durationSec: 142,
|
|
33
|
+
bpm: 128,
|
|
34
|
+
mood: "energetic",
|
|
35
|
+
tags: ["edm", "drop", "social-recap"],
|
|
36
|
+
attribution: "Pixabay (CC0)",
|
|
37
|
+
source: "curated",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "curated-uplifting-110",
|
|
41
|
+
url: "https://storage.googleapis.com/vidspot-public-music/uplifting-corp-110.mp3",
|
|
42
|
+
durationSec: 121,
|
|
43
|
+
bpm: 110,
|
|
44
|
+
mood: "uplifting",
|
|
45
|
+
tags: ["corporate", "ugc-ad", "product-demo"],
|
|
46
|
+
attribution: "Pixabay (CC0)",
|
|
47
|
+
source: "curated",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "curated-cinematic-90",
|
|
51
|
+
url: "https://storage.googleapis.com/vidspot-public-music/cinematic-orch-90.mp3",
|
|
52
|
+
durationSec: 168,
|
|
53
|
+
bpm: 90,
|
|
54
|
+
mood: "cinematic",
|
|
55
|
+
tags: ["orchestral", "trailer", "talking-head"],
|
|
56
|
+
attribution: "Pixabay (CC0)",
|
|
57
|
+
source: "curated",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "curated-calm-80",
|
|
61
|
+
url: "https://storage.googleapis.com/vidspot-public-music/calm-piano-80.mp3",
|
|
62
|
+
durationSec: 156,
|
|
63
|
+
bpm: 80,
|
|
64
|
+
mood: "calm",
|
|
65
|
+
tags: ["piano", "ambient", "talking-head"],
|
|
66
|
+
attribution: "Pixabay (CC0)",
|
|
67
|
+
source: "curated",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: "curated-dark-100",
|
|
71
|
+
url: "https://storage.googleapis.com/vidspot-public-music/dark-trap-100.mp3",
|
|
72
|
+
durationSec: 130,
|
|
73
|
+
bpm: 100,
|
|
74
|
+
mood: "dark",
|
|
75
|
+
tags: ["trap", "moody", "social-recap"],
|
|
76
|
+
attribution: "Pixabay (CC0)",
|
|
77
|
+
source: "curated",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: "curated-acoustic-95",
|
|
81
|
+
url: "https://storage.googleapis.com/vidspot-public-music/acoustic-folk-95.mp3",
|
|
82
|
+
durationSec: 144,
|
|
83
|
+
bpm: 95,
|
|
84
|
+
mood: "acoustic",
|
|
85
|
+
tags: ["folk", "guitar", "ugc-ad"],
|
|
86
|
+
attribution: "Pixabay (CC0)",
|
|
87
|
+
source: "curated",
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: "curated-retro-115",
|
|
91
|
+
url: "https://storage.googleapis.com/vidspot-public-music/retro-synth-115.mp3",
|
|
92
|
+
durationSec: 138,
|
|
93
|
+
bpm: 115,
|
|
94
|
+
mood: "retro",
|
|
95
|
+
tags: ["synthwave", "80s", "product-demo"],
|
|
96
|
+
attribution: "Pixabay (CC0)",
|
|
97
|
+
source: "curated",
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
const MOOD_ALIASES = {
|
|
101
|
+
energetic: "energetic",
|
|
102
|
+
upbeat: "energetic",
|
|
103
|
+
hype: "energetic",
|
|
104
|
+
cinematic: "cinematic",
|
|
105
|
+
epic: "cinematic",
|
|
106
|
+
dramatic: "cinematic",
|
|
107
|
+
calm: "calm",
|
|
108
|
+
chill: "calm",
|
|
109
|
+
ambient: "calm",
|
|
110
|
+
uplifting: "uplifting",
|
|
111
|
+
inspirational: "uplifting",
|
|
112
|
+
dark: "dark",
|
|
113
|
+
moody: "dark",
|
|
114
|
+
acoustic: "acoustic",
|
|
115
|
+
folk: "acoustic",
|
|
116
|
+
retro: "retro",
|
|
117
|
+
vintage: "retro",
|
|
118
|
+
quirky: "retro",
|
|
119
|
+
};
|
|
120
|
+
function tokens(s) {
|
|
121
|
+
if (!s)
|
|
122
|
+
return [];
|
|
123
|
+
return s
|
|
124
|
+
.toLowerCase()
|
|
125
|
+
.replace(/[^a-z0-9\s]+/g, " ")
|
|
126
|
+
.split(/\s+/)
|
|
127
|
+
.filter((t) => t.length >= 2);
|
|
128
|
+
}
|
|
129
|
+
function score(track, params) {
|
|
130
|
+
let s = 0;
|
|
131
|
+
const wantedMood = params.mood ? MOOD_ALIASES[params.mood.toLowerCase()] : undefined;
|
|
132
|
+
if (wantedMood && track.mood === wantedMood)
|
|
133
|
+
s += 50;
|
|
134
|
+
const queryToks = tokens(params.query);
|
|
135
|
+
if (queryToks.length) {
|
|
136
|
+
const hay = [track.mood, ...(track.tags ?? [])].join(" ").toLowerCase();
|
|
137
|
+
for (const t of queryToks)
|
|
138
|
+
if (hay.includes(t))
|
|
139
|
+
s += 5;
|
|
140
|
+
}
|
|
141
|
+
if (params.bpmTarget && track.bpm) {
|
|
142
|
+
const diff = Math.abs(track.bpm - params.bpmTarget);
|
|
143
|
+
s += Math.max(0, 30 - diff); // perfect match = 30, ±30bpm = 0
|
|
144
|
+
}
|
|
145
|
+
if (params.bpmMin && track.bpm && track.bpm < params.bpmMin)
|
|
146
|
+
s -= 20;
|
|
147
|
+
if (params.bpmMax && track.bpm && track.bpm > params.bpmMax)
|
|
148
|
+
s -= 20;
|
|
149
|
+
if (params.durationSecMin && track.durationSec < params.durationSecMin)
|
|
150
|
+
s -= 100;
|
|
151
|
+
return s;
|
|
152
|
+
}
|
|
153
|
+
class CuratedMusicProvider {
|
|
154
|
+
constructor() {
|
|
155
|
+
this.source = "curated";
|
|
156
|
+
}
|
|
157
|
+
isAvailable() {
|
|
158
|
+
return exports.CURATED_CATALOG.length > 0;
|
|
159
|
+
}
|
|
160
|
+
async search(params) {
|
|
161
|
+
const limit = params.limit ?? 5;
|
|
162
|
+
const ranked = exports.CURATED_CATALOG
|
|
163
|
+
.map((t) => ({ t, s: score(t, params) }))
|
|
164
|
+
.filter((r) => r.s > -50)
|
|
165
|
+
.sort((a, b) => b.s - a.s)
|
|
166
|
+
.slice(0, limit)
|
|
167
|
+
.map(({ t }) => t);
|
|
168
|
+
return { tracks: ranked };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
exports.CuratedMusicProvider = CuratedMusicProvider;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MusicSearchParams, MusicSearchProvider, MusicSearchResult } from "../types";
|
|
2
|
+
export declare class JamendoMusicProvider implements MusicSearchProvider {
|
|
3
|
+
readonly source: "jamendo";
|
|
4
|
+
private readonly clientId;
|
|
5
|
+
isAvailable(): boolean;
|
|
6
|
+
search(params: MusicSearchParams): Promise<MusicSearchResult>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=jamendo.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jamendo.service.d.ts","sourceRoot":"","sources":["../../../../src/services/musicGen/providers/jamendo.service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EAElB,MAAM,UAAU,CAAC;AA6ClB,qBAAa,oBAAqB,YAAW,mBAAmB;IAC9D,QAAQ,CAAC,MAAM,EAAG,SAAS,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAE1D,WAAW,IAAI,OAAO;IAIhB,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAwCpE"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.JamendoMusicProvider = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
/**
|
|
9
|
+
* Jamendo Music API v3.
|
|
10
|
+
*
|
|
11
|
+
* Free for app integration via client_id; per-track commercial use requires
|
|
12
|
+
* a Pro license purchased through Jamendo Licensing. We surface tracks here
|
|
13
|
+
* but the host UI must show the license CTA before a user ships a video that
|
|
14
|
+
* uses the track. Track BPM comes back via `musicinfo.bpm` when we request
|
|
15
|
+
* `include=musicinfo`.
|
|
16
|
+
*
|
|
17
|
+
* Env: JAMENDO_CLIENT_ID — provider is unavailable until set.
|
|
18
|
+
*/
|
|
19
|
+
const JAMENDO_TRACKS_URL = "https://api.jamendo.com/v3.0/tracks";
|
|
20
|
+
const MOOD_TO_TAGS = {
|
|
21
|
+
energetic: "energetic+upbeat",
|
|
22
|
+
cinematic: "epic+orchestral",
|
|
23
|
+
calm: "calm+ambient",
|
|
24
|
+
uplifting: "uplifting+inspirational",
|
|
25
|
+
dark: "dark+moody",
|
|
26
|
+
acoustic: "acoustic+folk",
|
|
27
|
+
retro: "retro+synthwave",
|
|
28
|
+
quirky: "quirky+playful",
|
|
29
|
+
};
|
|
30
|
+
class JamendoMusicProvider {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.source = "jamendo";
|
|
33
|
+
this.clientId = process.env.JAMENDO_CLIENT_ID;
|
|
34
|
+
}
|
|
35
|
+
isAvailable() {
|
|
36
|
+
return Boolean(this.clientId);
|
|
37
|
+
}
|
|
38
|
+
async search(params) {
|
|
39
|
+
if (!this.clientId)
|
|
40
|
+
return { tracks: [] };
|
|
41
|
+
const tags = params.mood ? MOOD_TO_TAGS[params.mood.toLowerCase()] : undefined;
|
|
42
|
+
const search = params.query?.trim();
|
|
43
|
+
const res = await axios_1.default.get(JAMENDO_TRACKS_URL, {
|
|
44
|
+
params: {
|
|
45
|
+
client_id: this.clientId,
|
|
46
|
+
format: "json",
|
|
47
|
+
limit: Math.min(params.limit ?? 10, 20),
|
|
48
|
+
include: "musicinfo",
|
|
49
|
+
// Jamendo prefers `tags` for mood and `search` for free-text.
|
|
50
|
+
...(tags ? { tags } : {}),
|
|
51
|
+
...(search ? { search } : {}),
|
|
52
|
+
...(params.bpmMin ? { speed: bpmToSpeed(params.bpmMin) } : {}),
|
|
53
|
+
audioformat: "mp32",
|
|
54
|
+
},
|
|
55
|
+
timeout: 8000,
|
|
56
|
+
});
|
|
57
|
+
const tracks = res.data.results
|
|
58
|
+
.filter((t) => !!t.audio)
|
|
59
|
+
.filter((t) => !params.durationSecMin || t.duration >= params.durationSecMin)
|
|
60
|
+
.map((t) => ({
|
|
61
|
+
id: `jamendo-${t.id}`,
|
|
62
|
+
url: t.audio,
|
|
63
|
+
durationSec: t.duration,
|
|
64
|
+
bpm: t.musicinfo?.bpm,
|
|
65
|
+
mood: params.mood,
|
|
66
|
+
tags: t.musicinfo?.tags?.vartags,
|
|
67
|
+
attribution: `${t.name} — ${t.artist_name} (Jamendo)`,
|
|
68
|
+
source: "jamendo",
|
|
69
|
+
}));
|
|
70
|
+
if (params.bpmTarget) {
|
|
71
|
+
tracks.sort((a, b) => bpmDistance(a, params.bpmTarget) - bpmDistance(b, params.bpmTarget));
|
|
72
|
+
}
|
|
73
|
+
return { tracks };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.JamendoMusicProvider = JamendoMusicProvider;
|
|
77
|
+
function bpmDistance(t, target) {
|
|
78
|
+
if (!t.bpm)
|
|
79
|
+
return 999;
|
|
80
|
+
return Math.abs(t.bpm - target);
|
|
81
|
+
}
|
|
82
|
+
// Jamendo's `speed` param is a coarse 5-bucket bin; map BPM ranges to it.
|
|
83
|
+
function bpmToSpeed(bpm) {
|
|
84
|
+
if (bpm < 70)
|
|
85
|
+
return "verylow";
|
|
86
|
+
if (bpm < 95)
|
|
87
|
+
return "low";
|
|
88
|
+
if (bpm < 120)
|
|
89
|
+
return "medium";
|
|
90
|
+
if (bpm < 145)
|
|
91
|
+
return "high";
|
|
92
|
+
return "veryhigh";
|
|
93
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MusicSearchParams, MusicSearchProvider, MusicSearchResult } from "../types";
|
|
2
|
+
export declare class MubertMusicProvider implements MusicSearchProvider {
|
|
3
|
+
readonly source: "mubert";
|
|
4
|
+
private readonly pat;
|
|
5
|
+
isAvailable(): boolean;
|
|
6
|
+
search(params: MusicSearchParams): Promise<MusicSearchResult>;
|
|
7
|
+
private pollTrackUrl;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=mubert.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mubert.service.d.ts","sourceRoot":"","sources":["../../../../src/services/musicGen/providers/mubert.service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAiDlB,qBAAa,mBAAoB,YAAW,mBAAmB;IAC7D,QAAQ,CAAC,MAAM,EAAG,QAAQ,CAAU;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA0B;IAE9C,WAAW,IAAI,OAAO;IAIhB,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAkDrD,YAAY;CAkB3B"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MubertMusicProvider = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
/**
|
|
9
|
+
* Mubert generative music — pay-per-call, infinite library, BPM-controllable.
|
|
10
|
+
*
|
|
11
|
+
* Conceptually a "search" replacement: instead of looking up an existing
|
|
12
|
+
* track, we generate one from a prompt + BPM + duration. The provider
|
|
13
|
+
* presents the same MusicSearchProvider surface so the planner doesn't have
|
|
14
|
+
* to special-case it.
|
|
15
|
+
*
|
|
16
|
+
* Two-step flow (mirrors our video providers):
|
|
17
|
+
* 1. POST /v3/Public/Tracks → returns a session id
|
|
18
|
+
* 2. Poll /v3/Public/Tracks/{id} until the generated MP3 URL is ready
|
|
19
|
+
*
|
|
20
|
+
* For latency reasons we cap polling at MUBERT_TIMEOUT_MS; on timeout we
|
|
21
|
+
* return an empty result and the caller falls back to the next provider.
|
|
22
|
+
*
|
|
23
|
+
* Env: MUBERT_PAT (Personal Access Token). Provider is unavailable until set.
|
|
24
|
+
*
|
|
25
|
+
* Cost: ~$0.005–0.02/min depending on plan; budget gates live in
|
|
26
|
+
* estimate_cost upstream — this provider just executes when called.
|
|
27
|
+
*/
|
|
28
|
+
const MUBERT_BASE_URL = "https://music-api.mubert.com/api/v3/Public";
|
|
29
|
+
const MUBERT_TIMEOUT_MS = 25000;
|
|
30
|
+
const POLL_INTERVAL_MS = 1500;
|
|
31
|
+
const MOOD_TO_PROMPT = {
|
|
32
|
+
energetic: "energetic upbeat pop",
|
|
33
|
+
cinematic: "cinematic orchestral epic",
|
|
34
|
+
calm: "calm ambient piano",
|
|
35
|
+
uplifting: "uplifting inspirational corporate",
|
|
36
|
+
dark: "dark moody trap",
|
|
37
|
+
acoustic: "acoustic folk guitar",
|
|
38
|
+
retro: "retro synthwave 80s",
|
|
39
|
+
quirky: "quirky playful indie",
|
|
40
|
+
};
|
|
41
|
+
class MubertMusicProvider {
|
|
42
|
+
constructor() {
|
|
43
|
+
this.source = "mubert";
|
|
44
|
+
this.pat = process.env.MUBERT_PAT;
|
|
45
|
+
}
|
|
46
|
+
isAvailable() {
|
|
47
|
+
return Boolean(this.pat);
|
|
48
|
+
}
|
|
49
|
+
async search(params) {
|
|
50
|
+
if (!this.pat)
|
|
51
|
+
return { tracks: [] };
|
|
52
|
+
const prompt = params.query
|
|
53
|
+
?? (params.mood && MOOD_TO_PROMPT[params.mood.toLowerCase()])
|
|
54
|
+
?? "energetic upbeat";
|
|
55
|
+
const duration = Math.max(30, params.durationSecMin ?? 60);
|
|
56
|
+
const bpm = params.bpmTarget;
|
|
57
|
+
try {
|
|
58
|
+
const startResp = await axios_1.default.post(`${MUBERT_BASE_URL}/Tracks`, {
|
|
59
|
+
method: "RecordTrack",
|
|
60
|
+
params: {
|
|
61
|
+
pat: this.pat,
|
|
62
|
+
prompt,
|
|
63
|
+
duration,
|
|
64
|
+
...(bpm ? { bpm } : {}),
|
|
65
|
+
bitrate: 128,
|
|
66
|
+
mode: "track",
|
|
67
|
+
},
|
|
68
|
+
}, { timeout: 8000 });
|
|
69
|
+
const sessionId = startResp.data?.data?.session_id;
|
|
70
|
+
if (!sessionId)
|
|
71
|
+
return { tracks: [] };
|
|
72
|
+
const trackUrl = await this.pollTrackUrl(sessionId);
|
|
73
|
+
if (!trackUrl)
|
|
74
|
+
return { tracks: [] };
|
|
75
|
+
return {
|
|
76
|
+
tracks: [
|
|
77
|
+
{
|
|
78
|
+
id: `mubert-${sessionId}`,
|
|
79
|
+
url: trackUrl,
|
|
80
|
+
durationSec: duration,
|
|
81
|
+
bpm,
|
|
82
|
+
mood: params.mood,
|
|
83
|
+
attribution: "Mubert (generated)",
|
|
84
|
+
source: "mubert",
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// Provider down or rejected the prompt — caller falls through.
|
|
91
|
+
return { tracks: [] };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async pollTrackUrl(sessionId) {
|
|
95
|
+
const deadline = Date.now() + MUBERT_TIMEOUT_MS;
|
|
96
|
+
while (Date.now() < deadline) {
|
|
97
|
+
try {
|
|
98
|
+
const resp = await axios_1.default.get(`${MUBERT_BASE_URL}/Tracks/${sessionId}`, { params: { pat: this.pat }, timeout: 5000 });
|
|
99
|
+
const status = resp.data?.data?.status;
|
|
100
|
+
if (status === "done")
|
|
101
|
+
return resp.data?.data?.track_url;
|
|
102
|
+
if (status === "failed")
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// Transient — retry next tick.
|
|
107
|
+
}
|
|
108
|
+
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.MubertMusicProvider = MubertMusicProvider;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Music search/generation provider surface used by the agent's `search_music`
|
|
3
|
+
* tool and the post-planner `selectMusicForPlan` step.
|
|
4
|
+
*
|
|
5
|
+
* Three sources ship under one interface deliberately — the planner doesn't
|
|
6
|
+
* care whether a track is curated, fetched, or generated; it only needs
|
|
7
|
+
* `{ url, bpm, durationSec }` to drive the beat-snap pass.
|
|
8
|
+
*/
|
|
9
|
+
export type MusicSource = "curated" | "jamendo" | "mubert";
|
|
10
|
+
export interface MusicSearchParams {
|
|
11
|
+
query?: string;
|
|
12
|
+
/** "energetic" / "cinematic" / "calm" / "uplifting" / "dark" / "quirky" / "retro" / "acoustic". */
|
|
13
|
+
mood?: string;
|
|
14
|
+
/** Soft target — providers prefer matches near this BPM but may return others. */
|
|
15
|
+
bpmTarget?: number;
|
|
16
|
+
bpmMin?: number;
|
|
17
|
+
bpmMax?: number;
|
|
18
|
+
/** Required minimum length so the track covers the whole video. */
|
|
19
|
+
durationSecMin?: number;
|
|
20
|
+
/** Cap result count. */
|
|
21
|
+
limit?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface MusicTrack {
|
|
24
|
+
id: string;
|
|
25
|
+
url: string;
|
|
26
|
+
durationSec: number;
|
|
27
|
+
bpm?: number;
|
|
28
|
+
mood?: string;
|
|
29
|
+
tags?: string[];
|
|
30
|
+
attribution?: string;
|
|
31
|
+
source: MusicSource;
|
|
32
|
+
}
|
|
33
|
+
export interface MusicSearchResult {
|
|
34
|
+
tracks: MusicTrack[];
|
|
35
|
+
}
|
|
36
|
+
export interface MusicSearchProvider {
|
|
37
|
+
source: MusicSource;
|
|
38
|
+
/** True when the provider is configured (env vars / catalog) and ready to call. */
|
|
39
|
+
isAvailable(): boolean;
|
|
40
|
+
search(params: MusicSearchParams): Promise<MusicSearchResult>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/musicGen/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE3D,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mGAAmG;IACnG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,WAAW,CAAC;IACpB,mFAAmF;IACnF,WAAW,IAAI,OAAO,CAAC;IACvB,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC/D"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Music search/generation provider surface used by the agent's `search_music`
|
|
4
|
+
* tool and the post-planner `selectMusicForPlan` step.
|
|
5
|
+
*
|
|
6
|
+
* Three sources ship under one interface deliberately — the planner doesn't
|
|
7
|
+
* care whether a track is curated, fetched, or generated; it only needs
|
|
8
|
+
* `{ url, bpm, durationSec }` to drive the beat-snap pass.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseTtsProviderService, ITtsVoiceOption, TtsParams, TtsResult } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* MiniMax Speech-02-HD (T2A v2). Sync — POST /v1/t2a_v2 returns hex-encoded audio
|
|
4
|
+
* inline (decoded into Buffer; same response shape as music-1.5).
|
|
5
|
+
*/
|
|
6
|
+
export declare class MinimaxTtsService extends BaseTtsProviderService {
|
|
7
|
+
private readonly baseUrl;
|
|
8
|
+
private readonly apiKey;
|
|
9
|
+
constructor();
|
|
10
|
+
generate(params: TtsParams): Promise<TtsResult>;
|
|
11
|
+
getVoices(): ITtsVoiceOption[];
|
|
12
|
+
mapLanguageCode(locale: string): string | undefined;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=minimax.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"minimax.service.d.ts","sourceRoot":"","sources":["../../../../src/services/tts/providers/minimax.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEzF;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,sBAAsB;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;IAEpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;;IAU1B,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAuDrD,SAAS,IAAI,eAAe,EAAE;IAI9B,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAGpD"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MinimaxTtsService = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const minimax_1 = require("../../../globals/ttsModels/providers/minimax");
|
|
9
|
+
const voices_1 = require("../../../globals/ttsModels/voices");
|
|
10
|
+
const types_1 = require("../types");
|
|
11
|
+
/**
|
|
12
|
+
* MiniMax Speech-02-HD (T2A v2). Sync — POST /v1/t2a_v2 returns hex-encoded audio
|
|
13
|
+
* inline (decoded into Buffer; same response shape as music-1.5).
|
|
14
|
+
*/
|
|
15
|
+
class MinimaxTtsService extends types_1.BaseTtsProviderService {
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
this.baseUrl = "https://api.minimax.io";
|
|
19
|
+
if (!process.env.MINIMAX_ACCESS_KEY) {
|
|
20
|
+
throw new Error("Missing MINIMAX_ACCESS_KEY in environment variables");
|
|
21
|
+
}
|
|
22
|
+
this.apiKey = process.env.MINIMAX_ACCESS_KEY;
|
|
23
|
+
}
|
|
24
|
+
async generate(params) {
|
|
25
|
+
const voiceId = params.voiceId ?? minimax_1.minimaxTtsConfig.defaultVoiceId;
|
|
26
|
+
const body = {
|
|
27
|
+
model: minimax_1.minimaxTtsConfig.modelId,
|
|
28
|
+
text: params.text,
|
|
29
|
+
voice_setting: {
|
|
30
|
+
voice_id: voiceId,
|
|
31
|
+
speed: 1.0,
|
|
32
|
+
vol: 1.0,
|
|
33
|
+
pitch: 0,
|
|
34
|
+
},
|
|
35
|
+
audio_setting: {
|
|
36
|
+
sample_rate: 32000,
|
|
37
|
+
bitrate: 128000,
|
|
38
|
+
format: "mp3",
|
|
39
|
+
channel: 1,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
const langPair = params.languageCode ? this.mapLanguageCode(params.languageCode) : undefined;
|
|
43
|
+
if (langPair) {
|
|
44
|
+
body.language_boost = langPair;
|
|
45
|
+
}
|
|
46
|
+
const resp = await axios_1.default.post(`${this.baseUrl}/v1/t2a_v2`, body, {
|
|
47
|
+
headers: {
|
|
48
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
49
|
+
"Content-Type": "application/json",
|
|
50
|
+
},
|
|
51
|
+
timeout: 120000,
|
|
52
|
+
validateStatus: () => true,
|
|
53
|
+
});
|
|
54
|
+
if (resp.status < 200 || resp.status >= 300) {
|
|
55
|
+
throw new Error(`MiniMax TTS ${resp.status}: ${JSON.stringify(resp.data)}`);
|
|
56
|
+
}
|
|
57
|
+
const baseResp = resp.data?.base_resp;
|
|
58
|
+
if (baseResp && baseResp.status_code !== 0) {
|
|
59
|
+
throw new Error(`MiniMax TTS error ${baseResp.status_code}: ${baseResp.status_msg}`);
|
|
60
|
+
}
|
|
61
|
+
const audioHex = resp.data?.data?.audio;
|
|
62
|
+
if (!audioHex) {
|
|
63
|
+
throw new Error("MiniMax TTS returned no audio data");
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
audioBuffer: Buffer.from(audioHex, "hex"),
|
|
67
|
+
mimeType: "audio/mpeg",
|
|
68
|
+
extension: "mp3",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
getVoices() {
|
|
72
|
+
return voices_1.MINIMAX_VOICES;
|
|
73
|
+
}
|
|
74
|
+
mapLanguageCode(locale) {
|
|
75
|
+
return voices_1.LANG_TO_MINIMAX_CODE[locale.toLowerCase()];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.MinimaxTtsService = MinimaxTtsService;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseTtsProviderService, ITtsVoiceOption, TtsParams, TtsResult } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* OpenAI gpt-4o-mini-tts. Sync — POST /v1/audio/speech returns mp3 binary.
|
|
4
|
+
* Note: OpenAI auto-detects language from input text; no language_code field.
|
|
5
|
+
*/
|
|
6
|
+
export declare class OpenaiTtsService extends BaseTtsProviderService {
|
|
7
|
+
private readonly baseUrl;
|
|
8
|
+
private readonly apiKey;
|
|
9
|
+
constructor();
|
|
10
|
+
generate(params: TtsParams): Promise<TtsResult>;
|
|
11
|
+
getVoices(): ITtsVoiceOption[];
|
|
12
|
+
mapLanguageCode(_locale: string): string | undefined;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=openai.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.service.d.ts","sourceRoot":"","sources":["../../../../src/services/tts/providers/openai.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEzF;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,sBAAsB;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IAEvD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;;IAU1B,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IA0CrD,SAAS,IAAI,eAAe,EAAE;IAI9B,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAGrD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.OpenaiTtsService = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const openai_1 = require("../../../globals/ttsModels/providers/openai");
|
|
9
|
+
const voices_1 = require("../../../globals/ttsModels/voices");
|
|
10
|
+
const types_1 = require("../types");
|
|
11
|
+
/**
|
|
12
|
+
* OpenAI gpt-4o-mini-tts. Sync — POST /v1/audio/speech returns mp3 binary.
|
|
13
|
+
* Note: OpenAI auto-detects language from input text; no language_code field.
|
|
14
|
+
*/
|
|
15
|
+
class OpenaiTtsService extends types_1.BaseTtsProviderService {
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
this.baseUrl = "https://api.openai.com/v1";
|
|
19
|
+
if (!process.env.OPENAI_API_KEY) {
|
|
20
|
+
throw new Error("Missing OPENAI_API_KEY in environment variables");
|
|
21
|
+
}
|
|
22
|
+
this.apiKey = process.env.OPENAI_API_KEY;
|
|
23
|
+
}
|
|
24
|
+
async generate(params) {
|
|
25
|
+
const voiceId = params.voiceId ?? openai_1.openaiTtsConfig.defaultVoiceId;
|
|
26
|
+
const body = {
|
|
27
|
+
model: openai_1.openaiTtsConfig.modelId,
|
|
28
|
+
input: params.text,
|
|
29
|
+
voice: voiceId,
|
|
30
|
+
response_format: "mp3",
|
|
31
|
+
};
|
|
32
|
+
try {
|
|
33
|
+
const resp = await axios_1.default.post(`${this.baseUrl}/audio/speech`, body, {
|
|
34
|
+
headers: {
|
|
35
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
36
|
+
"Content-Type": "application/json",
|
|
37
|
+
Accept: "audio/mpeg",
|
|
38
|
+
},
|
|
39
|
+
responseType: "arraybuffer",
|
|
40
|
+
timeout: 120000,
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
audioBuffer: Buffer.from(resp.data),
|
|
44
|
+
mimeType: "audio/mpeg",
|
|
45
|
+
extension: "mp3",
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
if (err.response?.data) {
|
|
50
|
+
let detail = "";
|
|
51
|
+
try {
|
|
52
|
+
const bodyStr = Buffer.from(err.response.data).toString("utf8");
|
|
53
|
+
const parsed = JSON.parse(bodyStr);
|
|
54
|
+
detail = parsed?.error?.message ?? bodyStr;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
detail = Buffer.from(err.response.data).toString("utf8");
|
|
58
|
+
}
|
|
59
|
+
throw new Error(`OpenAI TTS ${err.response.status}: ${detail} [voiceId=${voiceId}, textLen=${params.text?.length ?? 0}]`);
|
|
60
|
+
}
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
getVoices() {
|
|
65
|
+
return voices_1.OPENAI_VOICES;
|
|
66
|
+
}
|
|
67
|
+
mapLanguageCode(_locale) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.OpenaiTtsService = OpenaiTtsService;
|
package/lib/utils/helpers.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export declare const getCreditsFromCost: (cost: number, applyFloor?: boolean) =>
|
|
|
19
19
|
*/
|
|
20
20
|
export declare const MULTI_CLIP_DISCOUNT_FACTORS: Partial<Record<EVideoDurationType, number>>;
|
|
21
21
|
export declare function getMultiClipDiscountFactor(durationType: EVideoDurationType): number;
|
|
22
|
+
export declare const TRANSLATION_FAILED = "TRANSLATION_FAILED";
|
|
22
23
|
export declare const getTranslationWrapper: (text: string, from: ELANGUAGE_CODE, to?: ELANGUAGE_CODE, version?: "v1" | "v2") => Promise<string>;
|
|
23
24
|
export declare const detectLang: (text: string) => Promise<IDetectLang>;
|
|
24
25
|
export declare function waitForFile(path: string, timeout?: number, interval?: number): Promise<boolean>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAElB,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAE1B,OAAO,CAAC,MAAM,KAAK,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,eAAO,MAAM,eAAe,GAC1B,SAAS,MAAM,KACd,mBAAmB,GAAG,IASxB,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM,KAAG,kBAAkB,GAAG,IASlE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,MAAM,mBAAmB,EACzB,OAAM,kBAA+C,WAgBtD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,EAAE,oBAAiB,KAAG,MASpE,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B,EAAE,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAInF,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,kBAAkB,GAAG,MAAM,CAEnF;AAED,eAAO,MAAM,qBAAqB,GAChC,MAAM,MAAM,EACZ,MAAM,cAAc,EACpB,KAAI,cAAkC,EACtC,UAAS,IAAI,GAAG,IAAW,KAC1B,OAAO,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAElB,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAE1B,OAAO,CAAC,MAAM,KAAK,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,eAAO,MAAM,eAAe,GAC1B,SAAS,MAAM,KACd,mBAAmB,GAAG,IASxB,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM,KAAG,kBAAkB,GAAG,IASlE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,MAAM,mBAAmB,EACzB,OAAM,kBAA+C,WAgBtD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,EAAE,oBAAiB,KAAG,MASpE,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B,EAAE,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAInF,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,kBAAkB,GAAG,MAAM,CAEnF;AAED,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAEvD,eAAO,MAAM,qBAAqB,GAChC,MAAM,MAAM,EACZ,MAAM,cAAc,EACpB,KAAI,cAAkC,EACtC,UAAS,IAAI,GAAG,IAAW,KAC1B,OAAO,CAAC,MAAM,CA+BhB,CAAC;AAEF,eAAO,MAAM,UAAU,GAAU,MAAM,MAAM,KAAG,OAAO,CAAC,WAAW,CAqBlE,CAAC;AAEF,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,SAAQ,EACf,QAAQ,SAAM,oBAQf;AAGD,wBAAsB,mBAAmB,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;IAC1E,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,EAAE,CAAC,CAAC;IACb,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAGxB,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AA+CrB,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAatE"}
|