vidspotai-shared 1.0.29 → 1.0.31

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.
Files changed (108) hide show
  1. package/lib/globals/aiModels/enums.d.ts +40 -0
  2. package/lib/globals/aiModels/enums.d.ts.map +1 -0
  3. package/lib/globals/aiModels/enums.js +46 -0
  4. package/lib/globals/aiModels/index.d.ts +6 -0
  5. package/lib/globals/aiModels/index.d.ts.map +1 -0
  6. package/lib/globals/aiModels/index.js +35 -0
  7. package/lib/globals/aiModels/providers/bytedance.d.ts +4 -0
  8. package/lib/globals/aiModels/providers/bytedance.d.ts.map +1 -0
  9. package/lib/globals/aiModels/providers/bytedance.js +65 -0
  10. package/lib/globals/aiModels/providers/google.d.ts +4 -0
  11. package/lib/globals/aiModels/providers/google.d.ts.map +1 -0
  12. package/lib/globals/aiModels/providers/google.js +111 -0
  13. package/lib/globals/aiModels/providers/kling.d.ts +4 -0
  14. package/lib/globals/aiModels/providers/kling.d.ts.map +1 -0
  15. package/lib/globals/aiModels/providers/kling.js +129 -0
  16. package/lib/globals/aiModels/providers/minimax.d.ts +4 -0
  17. package/lib/globals/aiModels/providers/minimax.d.ts.map +1 -0
  18. package/lib/globals/aiModels/providers/minimax.js +66 -0
  19. package/lib/globals/aiModels/providers/openai.d.ts +4 -0
  20. package/lib/globals/aiModels/providers/openai.d.ts.map +1 -0
  21. package/lib/globals/aiModels/providers/openai.js +82 -0
  22. package/lib/globals/aiModels/providers/pixverse.d.ts +4 -0
  23. package/lib/globals/aiModels/providers/pixverse.d.ts.map +1 -0
  24. package/lib/globals/aiModels/providers/pixverse.js +108 -0
  25. package/lib/globals/aiModels/providers/runway.d.ts +4 -0
  26. package/lib/globals/aiModels/providers/runway.d.ts.map +1 -0
  27. package/lib/globals/aiModels/providers/runway.js +52 -0
  28. package/lib/globals/aiModels/types.d.ts +45 -0
  29. package/lib/globals/aiModels/types.d.ts.map +1 -0
  30. package/lib/globals/aiModels/types.js +2 -0
  31. package/lib/globals/index.d.ts +1 -0
  32. package/lib/globals/index.d.ts.map +1 -1
  33. package/lib/globals/index.js +1 -0
  34. package/lib/globals/ttsModels/index.d.ts +6 -0
  35. package/lib/globals/ttsModels/index.d.ts.map +1 -0
  36. package/lib/globals/ttsModels/index.js +25 -0
  37. package/lib/globals/ttsModels/providers/elevenlabs.d.ts +3 -0
  38. package/lib/globals/ttsModels/providers/elevenlabs.d.ts.map +1 -0
  39. package/lib/globals/ttsModels/providers/elevenlabs.js +13 -0
  40. package/lib/globals/ttsModels/types.d.ts +15 -0
  41. package/lib/globals/ttsModels/types.d.ts.map +1 -0
  42. package/lib/globals/ttsModels/types.js +2 -0
  43. package/lib/globals/ttsModels/voices.d.ts +21 -0
  44. package/lib/globals/ttsModels/voices.d.ts.map +1 -0
  45. package/lib/globals/ttsModels/voices.js +135 -0
  46. package/lib/models/user.model.d.ts +2 -0
  47. package/lib/models/user.model.d.ts.map +1 -1
  48. package/lib/models/video.model.d.ts +14 -0
  49. package/lib/models/video.model.d.ts.map +1 -1
  50. package/lib/services/aiGen/aiGenFactory.service.d.ts.map +1 -1
  51. package/lib/services/aiGen/aiGenFactory.service.js +36 -12
  52. package/lib/services/aiGen/providers/bytedance/bytedance.service.d.ts +9 -0
  53. package/lib/services/aiGen/providers/bytedance/bytedance.service.d.ts.map +1 -0
  54. package/lib/services/aiGen/providers/bytedance/bytedance.service.js +188 -0
  55. package/lib/services/aiGen/providers/bytedance/constants.d.ts +2 -0
  56. package/lib/services/aiGen/providers/bytedance/constants.d.ts.map +1 -0
  57. package/lib/services/aiGen/providers/bytedance/constants.js +27 -0
  58. package/lib/services/aiGen/providers/bytedance/index.d.ts +2 -0
  59. package/lib/services/aiGen/providers/bytedance/index.d.ts.map +1 -0
  60. package/lib/services/aiGen/providers/bytedance/index.js +17 -0
  61. package/lib/services/aiGen/providers/bytedance/types.d.ts +5 -0
  62. package/lib/services/aiGen/providers/bytedance/types.d.ts.map +1 -0
  63. package/lib/services/aiGen/providers/bytedance/types.js +1 -0
  64. package/lib/services/aiGen/providers/google/google.service.js +1 -1
  65. package/lib/services/aiGen/providers/kling/kling.service.d.ts +7 -2
  66. package/lib/services/aiGen/providers/kling/kling.service.d.ts.map +1 -1
  67. package/lib/services/aiGen/providers/kling/kling.service.js +126 -10
  68. package/lib/services/aiGen/providers/kling/types.d.ts +13 -0
  69. package/lib/services/aiGen/providers/kling/types.d.ts.map +1 -1
  70. package/lib/services/aiGen/providers/pixverse/pixverse.service.d.ts +9 -0
  71. package/lib/services/aiGen/providers/pixverse/pixverse.service.d.ts.map +1 -0
  72. package/lib/services/aiGen/providers/pixverse/pixverse.service.js +188 -0
  73. package/lib/services/aiGen/providers/runway/runway.service.d.ts.map +1 -1
  74. package/lib/services/aiGen/providers/runway/runway.service.js +16 -4
  75. package/lib/services/aiGen/providers/types.d.ts +6 -0
  76. package/lib/services/aiGen/providers/types.d.ts.map +1 -1
  77. package/lib/services/credit.service.d.ts +1 -0
  78. package/lib/services/credit.service.d.ts.map +1 -1
  79. package/lib/services/credit.service.js +17 -0
  80. package/lib/services/gcp/gsheet.service.d.ts +7 -0
  81. package/lib/services/gcp/gsheet.service.d.ts.map +1 -1
  82. package/lib/services/gcp/gsheet.service.js +46 -0
  83. package/lib/services/index.d.ts +1 -0
  84. package/lib/services/index.d.ts.map +1 -1
  85. package/lib/services/index.js +1 -0
  86. package/lib/services/tts/index.d.ts +4 -0
  87. package/lib/services/tts/index.d.ts.map +1 -0
  88. package/lib/services/tts/index.js +19 -0
  89. package/lib/services/tts/providers/elevenlabs.service.d.ts +7 -0
  90. package/lib/services/tts/providers/elevenlabs.service.d.ts.map +1 -0
  91. package/lib/services/tts/providers/elevenlabs.service.js +44 -0
  92. package/lib/services/tts/ttsFactory.service.d.ts +4 -0
  93. package/lib/services/tts/ttsFactory.service.d.ts.map +1 -0
  94. package/lib/services/tts/ttsFactory.service.js +12 -0
  95. package/lib/services/tts/types.d.ts +14 -0
  96. package/lib/services/tts/types.d.ts.map +1 -0
  97. package/lib/services/tts/types.js +6 -0
  98. package/lib/utils/helpers.js +2 -2
  99. package/lib/utils/index.d.ts +1 -0
  100. package/lib/utils/index.d.ts.map +1 -1
  101. package/lib/utils/index.js +1 -0
  102. package/lib/utils/logger.d.ts +2 -1
  103. package/lib/utils/logger.d.ts.map +1 -1
  104. package/lib/utils/logger.js +2 -0
  105. package/lib/utils/ttsUtils.d.ts +11 -0
  106. package/lib/utils/ttsUtils.d.ts.map +1 -0
  107. package/lib/utils/ttsUtils.js +16 -0
  108. package/package.json +1 -1
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ // pixverse.service.ts
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.PixVerseService = void 0;
8
+ const baseAiGenProvider_service_1 = require("../baseAiGenProvider.service");
9
+ const helpers_1 = require("../../helpers");
10
+ const aiModels_1 = require("../../../../globals/aiModels");
11
+ const types_1 = require("../../../../globals/types");
12
+ const firebase_1 = require("../../../../libs/firebase");
13
+ const helpers_2 = require("../../../../utils/helpers");
14
+ const logger_1 = require("../../../../utils/logger");
15
+ const crypto_1 = __importDefault(require("crypto"));
16
+ class PixVerseService extends baseAiGenProvider_service_1.BaseAiGenProviderService {
17
+ constructor() {
18
+ super(...arguments);
19
+ this.baseUrl = "https://app-api.pixverse.ai/openapi/v2/video";
20
+ }
21
+ // =========================================================
22
+ // GENERATE VIDEO
23
+ // =========================================================
24
+ async generateVideo(params) {
25
+ (0, helpers_1.validateParams)(params);
26
+ const modelConfig = aiModels_1.aiModelConfigs[params.modelKey];
27
+ const modelId = modelConfig.modelId;
28
+ const traceId = crypto_1.default.randomUUID();
29
+ const body = {
30
+ aspect_ratio: params.aspectRatio,
31
+ duration: params.duration,
32
+ model: modelId,
33
+ prompt: params.prompt,
34
+ quality: params.resolution,
35
+ };
36
+ // Optional negative prompt
37
+ if (params.negativePrompt) {
38
+ body.negative_prompt = params.negativePrompt;
39
+ }
40
+ // Optional audio support (v5.5 / v5.6)
41
+ if (params.audio !== undefined) {
42
+ body.generate_audio_switch = Boolean(params.audio);
43
+ }
44
+ // Multi clip (v5.5 only)
45
+ if (params.multiClip !== undefined) {
46
+ body.generate_multi_clip_switch = Boolean(params.multiClip);
47
+ }
48
+ const resp = await fetch(`${this.baseUrl}/text/generate`, {
49
+ method: "POST",
50
+ headers: {
51
+ "Content-Type": "application/json",
52
+ "API-KEY": process.env.PIXVERSE_API_KEY,
53
+ "Ai-trace-id": traceId,
54
+ },
55
+ body: JSON.stringify(body),
56
+ });
57
+ if (!resp.ok) {
58
+ const errText = await resp.text();
59
+ throw new Error(`PixVerse generateVideo failed (${resp.status}): ${errText}`);
60
+ }
61
+ const data = await resp.json();
62
+ if (data.ErrCode !== 0) {
63
+ throw new Error(`PixVerse API error: ${data.ErrMsg || "Unknown error"}`);
64
+ }
65
+ const videoId = data?.Resp?.video_id;
66
+ if (!videoId) {
67
+ throw new Error("PixVerse API did not return video_id");
68
+ }
69
+ return {
70
+ task: String(videoId),
71
+ status: types_1.EVideoSceneStatus.TRIGGERED,
72
+ };
73
+ }
74
+ // =========================================================
75
+ // CHECK STATUS
76
+ // =========================================================
77
+ async checkVideoStatus({ task, outputFilename, outputFilePath = "videos", }) {
78
+ const traceId = crypto_1.default.randomUUID();
79
+ const resp = await fetch(`${this.baseUrl}/result/${task}`, {
80
+ method: "GET",
81
+ headers: {
82
+ "API-KEY": process.env.PIXVERSE_API_KEY,
83
+ "Ai-trace-id": traceId,
84
+ },
85
+ });
86
+ if (!resp.ok) {
87
+ const errText = await resp.text();
88
+ throw new Error(`PixVerse checkVideoStatus failed (${resp.status}): ${errText}`);
89
+ }
90
+ const data = await resp.json();
91
+ if (data.ErrCode !== 0) {
92
+ throw new Error(`PixVerse API error: ${data.ErrMsg || "Unknown error"}`);
93
+ }
94
+ const status = data?.Resp?.status;
95
+ // ---- Status Mapping ----
96
+ switch (status) {
97
+ case 5: // Generating
98
+ return { status: types_1.EVideoSceneStatus.PENDING };
99
+ case 7: // moderation failed
100
+ case 8: // generation failed
101
+ return {
102
+ status: types_1.EVideoSceneStatus.FAILED,
103
+ errorMessage: "PixVerse video generation failed",
104
+ };
105
+ case 1: // success
106
+ break;
107
+ default:
108
+ return {
109
+ status: types_1.EVideoSceneStatus.FAILED,
110
+ errorMessage: `Unknown PixVerse status: ${status}`,
111
+ };
112
+ }
113
+ const sourceVideoUrl = data?.Resp?.url;
114
+ if (!sourceVideoUrl) {
115
+ return {
116
+ status: types_1.EVideoSceneStatus.FAILED,
117
+ errorMessage: "PixVerse response missing video url",
118
+ };
119
+ }
120
+ // Download generated video
121
+ const videoResp = await fetch(sourceVideoUrl);
122
+ if (!videoResp.ok) {
123
+ throw new Error(`Failed to download PixVerse video (${videoResp.status})`);
124
+ }
125
+ const buffer = Buffer.from(await videoResp.arrayBuffer());
126
+ // ---- Upload to Firebase ----
127
+ const filePath = `${outputFilePath}/${outputFilename}.mp4`;
128
+ const bucket = (0, firebase_1.getBucket)();
129
+ const file = bucket.file(filePath);
130
+ const downloadToken = crypto_1.default.randomUUID();
131
+ await file.save(buffer, {
132
+ contentType: "video/mp4",
133
+ resumable: false,
134
+ metadata: {
135
+ cacheControl: "public, max-age=31536000",
136
+ metadata: {
137
+ firebaseStorageDownloadTokens: downloadToken,
138
+ },
139
+ },
140
+ });
141
+ const publicVideoUrl = `https://firebasestorage.googleapis.com/v0/b/${bucket.name}` +
142
+ `/o/${encodeURIComponent(filePath)}?alt=media&token=${downloadToken}`;
143
+ return {
144
+ videoUrl: publicVideoUrl,
145
+ status: types_1.EVideoSceneStatus.COMPLETED,
146
+ };
147
+ }
148
+ // =========================================================
149
+ // CREDIT CALCULATION
150
+ // =========================================================
151
+ getCreditUsed(params) {
152
+ const modelConfig = aiModels_1.aiModelConfigs[params.modelKey];
153
+ if (!params.resolution || !params.duration) {
154
+ logger_1.logger.warn(`Missing resolution/duration for PixVerse credit calculation`);
155
+ return 10;
156
+ }
157
+ const hasAudio = Boolean(params.audio);
158
+ const multiClip = Boolean(params.multiClip);
159
+ try {
160
+ let cost;
161
+ if (modelConfig.cost?.audio || modelConfig.cost?.noAudio) {
162
+ const costGroup = hasAudio
163
+ ? modelConfig.cost.audio
164
+ : modelConfig.cost.noAudio;
165
+ // v5.5 structure (singleClip / multiClip)
166
+ if ("singleClip" in costGroup) {
167
+ const clipType = multiClip ? "multiClip" : "singleClip";
168
+ cost =
169
+ costGroup[clipType]?.table?.[params.resolution]?.[params.duration];
170
+ }
171
+ else {
172
+ // v5 / v5.6 structure
173
+ cost = costGroup?.table?.[params.resolution]?.[params.duration];
174
+ }
175
+ }
176
+ if (!cost) {
177
+ logger_1.logger.warn(`Unsupported combination for PixVerse credit calc: ${JSON.stringify(params)}`);
178
+ return 10;
179
+ }
180
+ return (0, helpers_2.getCreditsFromCost)(cost);
181
+ }
182
+ catch (err) {
183
+ logger_1.logger.error(`PixVerse credit calculation failed`, err);
184
+ return 10;
185
+ }
186
+ }
187
+ }
188
+ exports.PixVerseService = PixVerseService;
@@ -1 +1 @@
1
- {"version":3,"file":"runway.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/runway/runway.service.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAGlB,qBAAa,aAAc,SAAQ,wBAAwB;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;;YAUlB,OAAO;IA+Bf,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IAuC3B,gBAAgB,CAAC,EACrB,IAAI,EACJ,cAAc,EACd,cAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA4DjD,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAY,EAAE,EAAE,iBAAiB,GAAG,MAAM;CAIrE"}
1
+ {"version":3,"file":"runway.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/runway/runway.service.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAGlB,qBAAa,aAAc,SAAQ,wBAAwB;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAC7D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;;YAUlB,OAAO;IAgCf,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IAqD3B,gBAAgB,CAAC,EACrB,IAAI,EACJ,cAAc,EACd,cAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA4DjD,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAY,EAAE,EAAE,iBAAiB,GAAG,MAAM;CAIrE"}
@@ -14,7 +14,7 @@ const baseAiGenProvider_service_1 = require("../baseAiGenProvider.service");
14
14
  class RunwayService extends baseAiGenProvider_service_1.BaseAiGenProviderService {
15
15
  constructor() {
16
16
  super();
17
- this.baseUrl = "https://api.runwayml.com/v1";
17
+ this.baseUrl = "https://api.dev.runwayml.com/v1";
18
18
  if (!process.env.RUNWAYML_API_SECRET) {
19
19
  throw new Error("Missing RUNWAYML_API_SECRET in environment variables");
20
20
  }
@@ -25,6 +25,7 @@ class RunwayService extends baseAiGenProvider_service_1.BaseAiGenProviderService
25
25
  const headers = {
26
26
  Authorization: `Bearer ${this.apiKey}`,
27
27
  "Content-Type": "application/json",
28
+ "X-Runway-Version": "2024-11-06",
28
29
  };
29
30
  const response = await (0, axios_1.default)({
30
31
  url,
@@ -45,8 +46,19 @@ class RunwayService extends baseAiGenProvider_service_1.BaseAiGenProviderService
45
46
  if (!modelId)
46
47
  throw new Error(`Unknown modelKey: ${params.modelKey}`);
47
48
  let run;
48
- // IMAGE → VIDEO
49
- if (modelId === "gen4_turbo") {
49
+ // TEXT → VIDEO (gen4.5)
50
+ if (modelId === "gen4.5") {
51
+ const ratio = (params.aspectRatio || "1280x720").replace("x", ":");
52
+ const body = {
53
+ model: "gen4.5",
54
+ promptText: params.prompt,
55
+ ratio,
56
+ duration: params.duration || 5,
57
+ };
58
+ run = await this.request("/text_to_video", "POST", body);
59
+ }
60
+ // IMAGE → VIDEO (gen4_turbo)
61
+ else if (modelId === "gen4_turbo") {
50
62
  const body = {
51
63
  model: "gen4_turbo",
52
64
  promptText: params.prompt,
@@ -56,7 +68,7 @@ class RunwayService extends baseAiGenProvider_service_1.BaseAiGenProviderService
56
68
  };
57
69
  run = await this.request("/image-to-video", "POST", body);
58
70
  }
59
- // VIDEO → VIDEO
71
+ // VIDEO → VIDEO (gen4_aleph)
60
72
  else if (modelId === "gen4_aleph") {
61
73
  const body = {
62
74
  model: "gen4_aleph",
@@ -10,8 +10,12 @@ export interface VideoGenerationParams {
10
10
  duration?: number;
11
11
  inputVideoUrl?: string;
12
12
  inputImageUrl?: string;
13
+ inputAudioUrl?: string;
13
14
  mode?: EVideoMode;
14
15
  type?: "text-to-video" | "image-to-video" | "video-to-video";
16
+ audio?: boolean;
17
+ negativePrompt?: string;
18
+ multiClip?: boolean;
15
19
  }
16
20
  export interface VideoGenerationResult {
17
21
  status: EVideoSceneStatus.TRIGGERED;
@@ -45,5 +49,7 @@ export interface CreditUsageParams {
45
49
  aspectRatio?: string;
46
50
  inputType?: "text" | "image" | "video";
47
51
  outputType?: "text" | "image" | "video";
52
+ audio?: boolean;
53
+ multiClip?: boolean;
48
54
  }
49
55
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/services/aiGen/providers/types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EACL,iBAAiB,EACjB,aAAa,EACd,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,eAAe,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,eAAe,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;CAC9D;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,iBAAiB,CAAC,SAAS,CAAC;IACpC,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CAEvB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,QAAQ,EAAE,eAAe,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CAMzB;AAED,MAAM,WAAW,oBAAoB;IAEnC,KAAK,EAAE,GAAG,CAAC;IACX,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,eAAe,GAAG,cAAc,CAAC;IAC3C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;CACzC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/services/aiGen/providers/types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EACL,iBAAiB,EACjB,aAAa,EACd,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,eAAe,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,eAAe,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;IAE7D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,iBAAiB,CAAC,SAAS,CAAC;IACpC,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CAEvB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,QAAQ,EAAE,eAAe,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CAMzB;AAED,MAAM,WAAW,oBAAoB;IAEnC,KAAK,EAAE,GAAG,CAAC;IACX,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,eAAe,GAAG,cAAc,CAAC;IAC3C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IACxC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB"}
@@ -1,4 +1,5 @@
1
1
  export declare class CreditService {
2
2
  static consumeCredits(userId: string, creditsToConsume: number): Promise<void>;
3
+ static refundCredits(userId: string, creditsToRefund: number): Promise<void>;
3
4
  }
4
5
  //# sourceMappingURL=credit.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"credit.service.d.ts","sourceRoot":"","sources":["../../src/services/credit.service.ts"],"names":[],"mappings":"AAGA,qBAAa,aAAa;WACX,cAAc,CACzB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC;CAwBjB"}
1
+ {"version":3,"file":"credit.service.d.ts","sourceRoot":"","sources":["../../src/services/credit.service.ts"],"names":[],"mappings":"AAGA,qBAAa,aAAa;WACX,cAAc,CACzB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC;WAyBH,aAAa,CACxB,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC;CAoBjB"}
@@ -25,5 +25,22 @@ class CreditService {
25
25
  });
26
26
  });
27
27
  }
28
+ static async refundCredits(userId, creditsToRefund) {
29
+ if (creditsToRefund <= 0)
30
+ return;
31
+ await firebase_1.firestore.runTransaction(async (tx) => {
32
+ const userRef = firestore_service_1.FirestoreService.usersCol.doc(userId);
33
+ const snap = await tx.get(userRef);
34
+ if (!snap.exists) {
35
+ throw new Error("USER_NOT_FOUND");
36
+ }
37
+ const consumed = snap.data()?.credits?.consumed ?? 0;
38
+ // Never let consumed go below 0
39
+ const newConsumed = Math.max(0, consumed - creditsToRefund);
40
+ tx.update(userRef, {
41
+ "credits.consumed": newConsumed,
42
+ });
43
+ });
44
+ }
28
45
  }
29
46
  exports.CreditService = CreditService;
@@ -12,5 +12,12 @@ export declare class GSheetService extends GCPService {
12
12
  private mergeHeaders;
13
13
  private ensureSheetExists;
14
14
  private columnLetter;
15
+ upsertRowByKey<T extends Record<string, any>>({ spreadsheetId, sheetName, header, row, keyColumn, }: {
16
+ spreadsheetId: string;
17
+ sheetName: string;
18
+ header: string[];
19
+ row: T;
20
+ keyColumn: string;
21
+ }): Promise<void>;
15
22
  }
16
23
  //# sourceMappingURL=gsheet.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"gsheet.service.d.ts","sourceRoot":"","sources":["../../../src/services/gcp/gsheet.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAEvD,qBAAa,aAAc,SAAQ,UAAU;IAC3C,OAAO,CAAC,MAAM,CAAmB;;IAWjC;;OAEG;IACG,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACtD,MAAM,EAAE,4BAA4B,CAAC,CAAC,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC;YAsDF,SAAS;YAYT,WAAW;IAezB,OAAO,CAAC,YAAY;YAMN,iBAAiB;IA4B/B,OAAO,CAAC,YAAY;CASrB"}
1
+ {"version":3,"file":"gsheet.service.d.ts","sourceRoot":"","sources":["../../../src/services/gcp/gsheet.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAEvD,qBAAa,aAAc,SAAQ,UAAU;IAC3C,OAAO,CAAC,MAAM,CAAmB;;IAWjC;;OAEG;IACG,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACtD,MAAM,EAAE,4BAA4B,CAAC,CAAC,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC;YAsDF,SAAS;YAYT,WAAW;IAezB,OAAO,CAAC,YAAY;YAMN,iBAAiB;IA4B/B,OAAO,CAAC,YAAY;IAUd,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAClD,aAAa,EACb,SAAS,EACT,MAAM,EACN,GAAG,EACH,SAAS,GACV,EAAE;QACD,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,GAAG,EAAE,CAAC,CAAC;QACP,SAAS,EAAE,MAAM,CAAC;KACnB;CA2DF"}
@@ -99,5 +99,51 @@ class GSheetService extends gcp_service_1.GCPService {
99
99
  }
100
100
  return letter;
101
101
  }
102
+ async upsertRowByKey({ spreadsheetId, sheetName, header, row, keyColumn, }) {
103
+ await this.ensureSheetExists(spreadsheetId, sheetName);
104
+ const existingHeader = await this.getHeader(spreadsheetId, sheetName);
105
+ const finalHeader = existingHeader.length === 0
106
+ ? header
107
+ : this.mergeHeaders(existingHeader, header);
108
+ if (existingHeader.length === 0) {
109
+ await this.writeHeader(spreadsheetId, sheetName, finalHeader);
110
+ }
111
+ const keyIndex = finalHeader.indexOf(keyColumn);
112
+ if (keyIndex === -1) {
113
+ throw new Error(`Key column ${keyColumn} not found in header`);
114
+ }
115
+ // Get all data
116
+ const res = await this.sheets.spreadsheets.values.get({
117
+ spreadsheetId,
118
+ range: `${sheetName}!A2:${this.columnLetter(finalHeader.length)}`,
119
+ });
120
+ const rows = res.data.values ?? [];
121
+ const existingRowIndex = rows.findIndex((r) => r[keyIndex] === row[keyColumn]);
122
+ const values = finalHeader.map((col) => row[col] !== undefined ? row[col] : "");
123
+ if (existingRowIndex >= 0) {
124
+ // UPDATE existing row
125
+ const actualRowNumber = existingRowIndex + 2;
126
+ await this.sheets.spreadsheets.values.update({
127
+ spreadsheetId,
128
+ range: `${sheetName}!A${actualRowNumber}`,
129
+ valueInputOption: "USER_ENTERED",
130
+ requestBody: {
131
+ values: [values],
132
+ },
133
+ });
134
+ }
135
+ else {
136
+ // APPEND new row
137
+ await this.sheets.spreadsheets.values.append({
138
+ spreadsheetId,
139
+ range: `${sheetName}!A:${this.columnLetter(finalHeader.length)}`,
140
+ valueInputOption: "USER_ENTERED",
141
+ insertDataOption: "INSERT_ROWS",
142
+ requestBody: {
143
+ values: [values],
144
+ },
145
+ });
146
+ }
147
+ }
102
148
  }
103
149
  exports.GSheetService = GSheetService;
@@ -4,4 +4,5 @@ export * from "./aiGen";
4
4
  export * from "./bullmq.service";
5
5
  export * from "./gcp";
6
6
  export * from "./credit.service";
7
+ export * from "./tts";
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AACjC,cAAc,OAAO,CAAC;AACtB,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AACjC,cAAc,OAAO,CAAC;AACtB,cAAc,kBAAkB,CAAC;AACjC,cAAc,OAAO,CAAC"}
@@ -20,3 +20,4 @@ __exportStar(require("./aiGen"), exports);
20
20
  __exportStar(require("./bullmq.service"), exports);
21
21
  __exportStar(require("./gcp"), exports);
22
22
  __exportStar(require("./credit.service"), exports);
23
+ __exportStar(require("./tts"), exports);
@@ -0,0 +1,4 @@
1
+ export * from "./types";
2
+ export * from "./providers/elevenlabs.service";
3
+ export * from "./ttsFactory.service";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/tts/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./providers/elevenlabs.service"), exports);
19
+ __exportStar(require("./ttsFactory.service"), exports);
@@ -0,0 +1,7 @@
1
+ import { BaseTtsProviderService, TtsParams, TtsResult } from "../types";
2
+ export declare class ElevenLabsService extends BaseTtsProviderService {
3
+ private readonly baseUrl;
4
+ constructor();
5
+ generate(params: TtsParams): Promise<TtsResult>;
6
+ }
7
+ //# sourceMappingURL=elevenlabs.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elevenlabs.service.d.ts","sourceRoot":"","sources":["../../../../src/services/tts/providers/elevenlabs.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAExE,qBAAa,iBAAkB,SAAQ,sBAAsB;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;;IASpD,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;CA+BtD"}
@@ -0,0 +1,44 @@
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.ElevenLabsService = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const elevenlabs_1 = require("../../../globals/ttsModels/providers/elevenlabs");
9
+ const types_1 = require("../types");
10
+ class ElevenLabsService extends types_1.BaseTtsProviderService {
11
+ constructor() {
12
+ super();
13
+ this.baseUrl = "https://api.elevenlabs.io/v1";
14
+ if (!process.env.ELEVENLABS_API_KEY) {
15
+ throw new Error("Missing ELEVENLABS_API_KEY in environment variables");
16
+ }
17
+ }
18
+ async generate(params) {
19
+ const voiceId = params.voiceId ?? elevenlabs_1.elevenlabsConfig.defaultVoiceId;
20
+ const response = await axios_1.default.post(`${this.baseUrl}/text-to-speech/${voiceId}`, {
21
+ text: params.text,
22
+ model_id: elevenlabs_1.elevenlabsConfig.modelId,
23
+ language_code: params.languageCode,
24
+ voice_settings: {
25
+ stability: 0.5,
26
+ similarity_boost: 0.75,
27
+ },
28
+ }, {
29
+ headers: {
30
+ "xi-api-key": process.env.ELEVENLABS_API_KEY,
31
+ "Content-Type": "application/json",
32
+ Accept: "audio/mpeg",
33
+ },
34
+ responseType: "arraybuffer",
35
+ timeout: 60000,
36
+ });
37
+ return {
38
+ audioBuffer: Buffer.from(response.data),
39
+ mimeType: "audio/mpeg",
40
+ extension: "mp3",
41
+ };
42
+ }
43
+ }
44
+ exports.ElevenLabsService = ElevenLabsService;
@@ -0,0 +1,4 @@
1
+ import { TtsProvider } from "../../globals/ttsModels/types";
2
+ import { BaseTtsProviderService } from "./types";
3
+ export declare function getTtsProviderService(provider?: TtsProvider): BaseTtsProviderService;
4
+ //# sourceMappingURL=ttsFactory.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ttsFactory.service.d.ts","sourceRoot":"","sources":["../../../src/services/tts/ttsFactory.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAE5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEjD,wBAAgB,qBAAqB,CAAC,QAAQ,GAAE,WAA0B,GAAG,sBAAsB,CAOlG"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTtsProviderService = getTtsProviderService;
4
+ const elevenlabs_service_1 = require("./providers/elevenlabs.service");
5
+ function getTtsProviderService(provider = "elevenlabs") {
6
+ switch (provider) {
7
+ case "elevenlabs":
8
+ return new elevenlabs_service_1.ElevenLabsService();
9
+ default:
10
+ throw new Error(`Unknown TTS provider: ${provider}`);
11
+ }
12
+ }
@@ -0,0 +1,14 @@
1
+ export interface TtsParams {
2
+ text: string;
3
+ voiceId?: string;
4
+ languageCode?: string;
5
+ }
6
+ export interface TtsResult {
7
+ audioBuffer: Buffer;
8
+ mimeType: string;
9
+ extension: string;
10
+ }
11
+ export declare abstract class BaseTtsProviderService {
12
+ abstract generate(params: TtsParams): Promise<TtsResult>;
13
+ }
14
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/tts/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,8BAAsB,sBAAsB;IAC1C,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;CACzD"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseTtsProviderService = void 0;
4
+ class BaseTtsProviderService {
5
+ }
6
+ exports.BaseTtsProviderService = BaseTtsProviderService;
@@ -49,8 +49,8 @@ const getPriceIdByType = (type, freq = types_1.ERENEWAL_FREQUENCY.MONTHLY) => {
49
49
  };
50
50
  exports.getPriceIdByType = getPriceIdByType;
51
51
  const getCreditsFromCost = (cost) => {
52
- const margin = 0.2;
53
- const costPerCredit = 0.1;
52
+ const margin = 0.2; // 20% margin
53
+ const costPerCredit = 0.1; // multiple
54
54
  const minCredits = 10;
55
55
  if (cost <= 0)
56
56
  return 0;
@@ -1,3 +1,4 @@
1
1
  export * from "./helpers";
2
2
  export * from "./logger";
3
+ export * from "./ttsUtils";
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC"}
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./helpers"), exports);
18
18
  __exportStar(require("./logger"), exports);
19
+ __exportStar(require("./ttsUtils"), exports);
@@ -1,6 +1,7 @@
1
- import { Logger } from "winston";
1
+ import winston, { Logger } from "winston";
2
2
  /**
3
3
  * Logger factory
4
4
  */
5
5
  export declare function createLogger(serviceName: string): Logger;
6
+ export declare const logger: winston.Logger;
6
7
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AA0B1C;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAsExD"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AA0B1C;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAsExD;AAED,eAAO,MAAM,MAAM,gBAAyB,CAAC"}
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.logger = void 0;
6
7
  exports.createLogger = createLogger;
7
8
  const winston_1 = __importDefault(require("winston"));
8
9
  const winston_slack_webhook_transport_1 = __importDefault(require("winston-slack-webhook-transport"));
@@ -83,3 +84,4 @@ function createLogger(serviceName) {
83
84
  exitOnError: false,
84
85
  });
85
86
  }
87
+ exports.logger = createLogger("shared");
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Estimates the spoken duration of a TTS text in seconds.
3
+ *
4
+ * Uses the provider's average words-per-second speaking rate.
5
+ * Callers are responsible for clamping to model-specific min/max limits.
6
+ *
7
+ * @param text - The TTS input text
8
+ * @param wordsPerSecond - Speaking rate from the TTS provider config
9
+ */
10
+ export declare function estimateTtsDurationSeconds(text: string, wordsPerSecond: number): number;
11
+ //# sourceMappingURL=ttsUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ttsUtils.d.ts","sourceRoot":"","sources":["../../src/utils/ttsUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAGvF"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.estimateTtsDurationSeconds = estimateTtsDurationSeconds;
4
+ /**
5
+ * Estimates the spoken duration of a TTS text in seconds.
6
+ *
7
+ * Uses the provider's average words-per-second speaking rate.
8
+ * Callers are responsible for clamping to model-specific min/max limits.
9
+ *
10
+ * @param text - The TTS input text
11
+ * @param wordsPerSecond - Speaking rate from the TTS provider config
12
+ */
13
+ function estimateTtsDurationSeconds(text, wordsPerSecond) {
14
+ const words = text.trim().split(/\s+/).length;
15
+ return Math.ceil(words / wordsPerSecond);
16
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vidspotai-shared",
3
- "version": "1.0.29",
3
+ "version": "1.0.31",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "exports": {