@runnerpro/backend 1.34.1 → 1.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/index.js +8 -2
- package/lib/cjs/mediaProcessing/audio.js +169 -155
- package/lib/cjs/mediaProcessing/azureSpeech.js +114 -0
- package/lib/cjs/mediaProcessing/azureTranscribe.js +73 -0
- package/lib/cjs/mediaProcessing/correccionTranscripcion.js +313 -0
- package/lib/cjs/mediaProcessing/ffmpegUtils.js +41 -2
- package/lib/cjs/mediaProcessing/index.js +157 -32
- package/lib/cjs/mediaProcessing/video.js +4 -4
- package/lib/cjs/types/index.d.ts +3 -2
- package/lib/cjs/types/index.d.ts.map +1 -1
- package/lib/cjs/types/mediaProcessing/audio.d.ts +31 -36
- package/lib/cjs/types/mediaProcessing/audio.d.ts.map +1 -1
- package/lib/cjs/types/mediaProcessing/azureSpeech.d.ts +38 -0
- package/lib/cjs/types/mediaProcessing/azureSpeech.d.ts.map +1 -0
- package/lib/cjs/types/mediaProcessing/azureTranscribe.d.ts +26 -0
- package/lib/cjs/types/mediaProcessing/azureTranscribe.d.ts.map +1 -0
- package/lib/cjs/types/mediaProcessing/correccionTranscripcion.d.ts +49 -0
- package/lib/cjs/types/mediaProcessing/correccionTranscripcion.d.ts.map +1 -0
- package/lib/cjs/types/mediaProcessing/ffmpegUtils.d.ts +20 -1
- package/lib/cjs/types/mediaProcessing/ffmpegUtils.d.ts.map +1 -1
- package/lib/cjs/types/mediaProcessing/index.d.ts +42 -8
- package/lib/cjs/types/mediaProcessing/index.d.ts.map +1 -1
- package/lib/cjs/types/mediaProcessing/video.d.ts +2 -1
- package/lib/cjs/types/mediaProcessing/video.d.ts.map +1 -1
- package/package.json +1 -2
|
@@ -19,8 +19,8 @@ const ffmpegUtils_1 = require("./ffmpegUtils");
|
|
|
19
19
|
const image_1 = require("./image");
|
|
20
20
|
const audio_1 = require("./audio");
|
|
21
21
|
const index_1 = require("../err/index");
|
|
22
|
-
// ✅ La pista se
|
|
23
|
-
//
|
|
22
|
+
// ✅ La pista se recorta para acotar coste y latencia del análisis de un vídeo de chat; el motor de
|
|
23
|
+
// transcripción (Azure Speech) admitiría mucho más.
|
|
24
24
|
const AUDIO_TRACK_MAX_SECONDS = 55;
|
|
25
25
|
const VIDEO_FRAME_PROMPT = `Esto es un fotograma extraído de un vídeo enviado en un chat de entrenamiento.
|
|
26
26
|
Describe lo que se ve de forma directa en un solo párrafo continuo, sin introducciones ni listas.
|
|
@@ -89,7 +89,7 @@ const formatDuration = (seconds) => {
|
|
|
89
89
|
* // "Vídeo de 12 s. Imagen: corredor de perfil sobre cinta... Audio: mira cómo apoyo el talón..."
|
|
90
90
|
* ```
|
|
91
91
|
*/
|
|
92
|
-
const describeVideo = (fileBuffer, mimetype, filename) => __awaiter(void 0, void 0, void 0, function* () {
|
|
92
|
+
const describeVideo = (fileBuffer, mimetype, filename, contexto) => __awaiter(void 0, void 0, void 0, function* () {
|
|
93
93
|
try {
|
|
94
94
|
return yield (0, ffmpegUtils_1.withTempDir)((dir) => __awaiter(void 0, void 0, void 0, function* () {
|
|
95
95
|
// ffmpeg detecta el formato por contenido, así que la extensión solo es cosmética
|
|
@@ -123,7 +123,7 @@ const describeVideo = (fileBuffer, mimetype, filename) => __awaiter(void 0, void
|
|
|
123
123
|
const [imageText, audioText] = yield Promise.all([
|
|
124
124
|
frameBuffer ? (0, image_1.describeImage)(frameBuffer, 'image/jpeg', VIDEO_FRAME_PROMPT) : Promise.resolve(null),
|
|
125
125
|
// ⭐ La pista ya sale de ffmpeg en WAV mono 16 kHz, así que no hay que volver a convertirla
|
|
126
|
-
audioBuffer ? (0, audio_1.transcribeWav16k)(audioBuffer) : Promise.resolve(null),
|
|
126
|
+
audioBuffer ? (0, audio_1.transcribeWav16k)(audioBuffer, contexto) : Promise.resolve(null),
|
|
127
127
|
]);
|
|
128
128
|
const header = `Vídeo${formatDuration(duration) ? ` de ${formatDuration(duration)}` : ''}`;
|
|
129
129
|
const parts = [];
|
package/lib/cjs/types/index.d.ts
CHANGED
|
@@ -22,8 +22,9 @@ import { saveDoneStructuraWorkout } from './workout/estructuraWorkout';
|
|
|
22
22
|
import { getZone } from './workout/paceZone';
|
|
23
23
|
import { saveResponseTime } from './chat/saveResponseTime';
|
|
24
24
|
import { updateSenderView } from './chat/api/conversation';
|
|
25
|
-
import { transcribeAudio, describeImage, describeVideo, describePdf, describeTextFile, analyzeFile, processMediaFile, reprocessRecentMedia } from './mediaProcessing';
|
|
25
|
+
import { transcribeAudio, describeImage, describeVideo, describePdf, describeTextFile, analyzeFile, processMediaFile, reprocessRecentMedia, reprocessMediaByIds, corregirTranscripcion, GLOSARIO_RUNNING, MARCADOR_SIN_VOZ, MARCADOR_NO_TRANSCRITO, MARCADORES_AUDIO } from './mediaProcessing';
|
|
26
|
+
export type { ContextoTranscripcion } from './mediaProcessing';
|
|
26
27
|
import { generateObject, generateText, createGoogleModel, createGoogleModelFromString, createBedrockModelFromString, createAzureModelFromString, createModelFromString, runWithCostTracking, runWithModels, MODEL_TIER, AI_MODELS, GOOGLE_MODELS, AZURE_PREFIX, AZURE_GPT_5_5_DEPLOYMENT, AZURE_GPT_5_6_SOL_DEPLOYMENT, AZURE_GPT_5_6_TERRA_DEPLOYMENT, AZURE_GPT_5_6_LUNA_DEPLOYMENT, AZURE_GPT_5_4_MINI_DEPLOYMENT, AZURE_GPT_5_4_NANO_DEPLOYMENT, AZURE_DEEPSEEK_V4_PRO_DEPLOYMENT, AZURE_DEEPSEEK_V4_FLASH_DEPLOYMENT, AZURE_GPT_5_5, AZURE_GPT_5_6_SOL, AZURE_GPT_5_6_TERRA, AZURE_GPT_5_6_LUNA, AZURE_GPT_5_4_MINI, AZURE_GPT_5_4_NANO, AZURE_DEEPSEEK_V4_PRO, AZURE_DEEPSEEK_V4_FLASH, AZURE_PRIMARY_MODELS, AZURE_FALLBACK_MODELS, PRODUCTION_MODELS, FALLBACK_MODELS, BEDROCK_CLAUDE_OPUS, BEDROCK_CLAUDE_SONNET, BEDROCK_CLAUDE_OPUS_4_5, BEDROCK_CLAUDE_OPUS_4_1, BEDROCK_CLAUDE_SONNET_4_5, BEDROCK_CLAUDE_SONNET_4, BEDROCK_CLAUDE_HAIKU, AISTUDIO_PREFIX, MODEL_PRICING, calculateCost } from './prompt';
|
|
27
28
|
export { Storage as StorageAzure, Contenedor, Archivo, urlPublica, TIPO_POR_DEFECTO, } from './almacenamiento';
|
|
28
|
-
export { sendNotification, sleep, query, queryWithClient, longRunningQuery, batchQuery, toPgArray, pool, sendMail, err, fetchIA, notifySlack, CHANNEL_SLACK, translate, LANGUAGES, useTranslation, getExerciseTranslatedDescription, chat, chatApi, chatExposed, getCountNotificaciones, notionGetUsers, notionGetDatabase, notionAddPage, notionEditPage, NOTION_DATABASES_ID, readSheet, findCellByValue, writeSheet, appendSheet, getNumberByLetter, getLetter, reduceSizeImage, generateShareMap, getDefaultWorkoutImage, sendWorkoutToWatch, getPlanificacionPrueba7dias, saveWorkoutAplication, saveWorkoutLaps, evaluateAchievements, evaluateAchievementsBounded, getUnlockedAchievements, computeStreakStats, saveDoneStructuraWorkout, getZone, saveResponseTime, updateSenderView, transcribeAudio, describeImage, describeVideo, describePdf, describeTextFile, analyzeFile, processMediaFile, reprocessRecentMedia, generateObject, generateText, createGoogleModel, createGoogleModelFromString, createBedrockModelFromString, createAzureModelFromString, createModelFromString, runWithCostTracking, runWithModels, MODEL_TIER, AI_MODELS, GOOGLE_MODELS, AZURE_PREFIX, AZURE_GPT_5_5_DEPLOYMENT, AZURE_GPT_5_6_SOL_DEPLOYMENT, AZURE_GPT_5_6_TERRA_DEPLOYMENT, AZURE_GPT_5_6_LUNA_DEPLOYMENT, AZURE_GPT_5_4_MINI_DEPLOYMENT, AZURE_GPT_5_4_NANO_DEPLOYMENT, AZURE_DEEPSEEK_V4_PRO_DEPLOYMENT, AZURE_DEEPSEEK_V4_FLASH_DEPLOYMENT, AZURE_GPT_5_5, AZURE_GPT_5_6_SOL, AZURE_GPT_5_6_TERRA, AZURE_GPT_5_6_LUNA, AZURE_GPT_5_4_MINI, AZURE_GPT_5_4_NANO, AZURE_DEEPSEEK_V4_PRO, AZURE_DEEPSEEK_V4_FLASH, AZURE_PRIMARY_MODELS, AZURE_FALLBACK_MODELS, PRODUCTION_MODELS, FALLBACK_MODELS, BEDROCK_CLAUDE_OPUS, BEDROCK_CLAUDE_SONNET, BEDROCK_CLAUDE_OPUS_4_5, BEDROCK_CLAUDE_OPUS_4_1, BEDROCK_CLAUDE_SONNET_4_5, BEDROCK_CLAUDE_SONNET_4, BEDROCK_CLAUDE_HAIKU, AISTUDIO_PREFIX, MODEL_PRICING, calculateCost, };
|
|
29
|
+
export { sendNotification, sleep, query, queryWithClient, longRunningQuery, batchQuery, toPgArray, pool, sendMail, err, fetchIA, notifySlack, CHANNEL_SLACK, translate, LANGUAGES, useTranslation, getExerciseTranslatedDescription, chat, chatApi, chatExposed, getCountNotificaciones, notionGetUsers, notionGetDatabase, notionAddPage, notionEditPage, NOTION_DATABASES_ID, readSheet, findCellByValue, writeSheet, appendSheet, getNumberByLetter, getLetter, reduceSizeImage, generateShareMap, getDefaultWorkoutImage, sendWorkoutToWatch, getPlanificacionPrueba7dias, saveWorkoutAplication, saveWorkoutLaps, evaluateAchievements, evaluateAchievementsBounded, getUnlockedAchievements, computeStreakStats, saveDoneStructuraWorkout, getZone, saveResponseTime, updateSenderView, transcribeAudio, describeImage, describeVideo, describePdf, describeTextFile, analyzeFile, processMediaFile, reprocessRecentMedia, reprocessMediaByIds, corregirTranscripcion, GLOSARIO_RUNNING, MARCADOR_SIN_VOZ, MARCADOR_NO_TRANSCRITO, MARCADORES_AUDIO, generateObject, generateText, createGoogleModel, createGoogleModelFromString, createBedrockModelFromString, createAzureModelFromString, createModelFromString, runWithCostTracking, runWithModels, MODEL_TIER, AI_MODELS, GOOGLE_MODELS, AZURE_PREFIX, AZURE_GPT_5_5_DEPLOYMENT, AZURE_GPT_5_6_SOL_DEPLOYMENT, AZURE_GPT_5_6_TERRA_DEPLOYMENT, AZURE_GPT_5_6_LUNA_DEPLOYMENT, AZURE_GPT_5_4_MINI_DEPLOYMENT, AZURE_GPT_5_4_NANO_DEPLOYMENT, AZURE_DEEPSEEK_V4_PRO_DEPLOYMENT, AZURE_DEEPSEEK_V4_FLASH_DEPLOYMENT, AZURE_GPT_5_5, AZURE_GPT_5_6_SOL, AZURE_GPT_5_6_TERRA, AZURE_GPT_5_6_LUNA, AZURE_GPT_5_4_MINI, AZURE_GPT_5_4_NANO, AZURE_DEEPSEEK_V4_PRO, AZURE_DEEPSEEK_V4_FLASH, AZURE_PRIMARY_MODELS, AZURE_FALLBACK_MODELS, PRODUCTION_MODELS, FALLBACK_MODELS, BEDROCK_CLAUDE_OPUS, BEDROCK_CLAUDE_SONNET, BEDROCK_CLAUDE_OPUS_4_5, BEDROCK_CLAUDE_OPUS_4_1, BEDROCK_CLAUDE_SONNET_4_5, BEDROCK_CLAUDE_SONNET_4, BEDROCK_CLAUDE_HAIKU, AISTUDIO_PREFIX, MODEL_PRICING, calculateCost, };
|
|
29
30
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
|
|
3
|
-
declare const
|
|
2
|
+
import { ContextoTranscripcion } from './correccionTranscripcion';
|
|
3
|
+
declare const TRANSCRIPTION_MAX_SECONDS = 600;
|
|
4
|
+
declare const MAX_CARACTERES_POR_SEGUNDO = 25;
|
|
5
|
+
declare const MARCADOR_SIN_VOZ = "[Audio sin voz reconocible]";
|
|
6
|
+
declare const MARCADOR_NO_TRANSCRITO = "[Audio no transcrito]";
|
|
7
|
+
declare const MARCADOR_ANTIGUO = "[Audio sin contenido reconocible]";
|
|
8
|
+
declare const MARCADORES_AUDIO: string[];
|
|
4
9
|
/**
|
|
5
|
-
*
|
|
6
|
-
* no reconoce y, sobre todo, los audios de más de 60s, que el modo síncrono no admite.
|
|
7
|
-
*
|
|
8
|
-
* @param wavBuffer - Buffer WAV mono 16 kHz
|
|
9
|
-
* @returns Promise<string | null> - Transcripción, o null si no hay voz
|
|
10
|
-
*/
|
|
11
|
-
declare const transcribeWithModel: (wavBuffer: Buffer) => Promise<string | null>;
|
|
12
|
-
/**
|
|
13
|
-
* Convierte cualquier audio al formato que espera Speech-to-Text (WAV PCM mono 16 kHz)
|
|
10
|
+
* Convierte cualquier audio a WAV PCM mono 16 kHz, recortado a 10 minutos
|
|
14
11
|
*
|
|
15
12
|
* @param fileBuffer - Buffer del audio original
|
|
16
13
|
* @param filename - Nombre original del archivo
|
|
@@ -23,41 +20,39 @@ declare const convertToWav16k: (fileBuffer: Buffer, filename?: string) => Promis
|
|
|
23
20
|
/**
|
|
24
21
|
* Transcribe una nota de voz.
|
|
25
22
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
23
|
+
* Cadena, toda en Azure: medir duración y volumen con ffmpeg → si no hay voz, marcador sin llamar
|
|
24
|
+
* a nadie → Azure AI Speech con el locale del cliente y una lista de frases (nombres + jerga) →
|
|
25
|
+
* si falla o no oye nada, gpt-4o-mini-transcribe sin prompt → si el texto es físicamente imposible
|
|
26
|
+
* (más de 25 caracteres por segundo), marcador → corrección de jerga y nombres con el modelo LITE
|
|
27
|
+
* detrás de un filtro determinista.
|
|
31
28
|
*
|
|
32
|
-
* ⚠️
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* - modelo multimodal: 14 de 14.
|
|
37
|
-
* Y a la inversa, convertir a WAV SIN respetar el límite de 55s rompe los audios largos que hoy
|
|
38
|
-
* sí funcionan (4 de 4 medidos): con LINEAR16 la API deduce la duración exacta y los rechaza,
|
|
39
|
-
* mientras que con un códec comprimido declarado se saltaba esa comprobación.
|
|
29
|
+
* ⚠️ Medido sobre 74 notas de voz reales (06-sep-2026): Google Speech-to-Text cambiaba a inglés al
|
|
30
|
+
* azar en 2 de 74 (la identificación multi-idioma) y dejaba vacíos 3 audios con voz; los modelos
|
|
31
|
+
* generativos (Gemini, gpt-audio, transcribe con prompt) escribían una nota entera ante clips en
|
|
32
|
+
* silencio. Azure Speech: 0 invenciones, 0 vacíos con voz, p50 1,2 s.
|
|
40
33
|
*
|
|
41
|
-
* @param fileBuffer - Buffer del archivo de audio
|
|
34
|
+
* @param fileBuffer - Buffer del archivo de audio (aac, m4a, mp3, wav, ogg…)
|
|
42
35
|
* @param mimetype - Tipo MIME del archivo (ej: 'audio/aac', 'audio/x-m4a')
|
|
43
36
|
* @param filename - Nombre original del archivo
|
|
44
|
-
* @
|
|
37
|
+
* @param contexto - Idioma, nombres y últimos mensajes del cliente (opcional)
|
|
38
|
+
* @returns Promise<string> - Transcripción, o un marcador si no hay voz o no se pudo transcribir
|
|
45
39
|
*
|
|
46
40
|
* @example
|
|
47
41
|
* ```typescript
|
|
48
|
-
* const transcription = await transcribeAudio(audioBuffer, 'audio/aac', 'audio.aac');
|
|
49
|
-
* // Resultado: "Hola, quería comentarte que hoy me duele un poco la rodilla..."
|
|
42
|
+
* const transcription = await transcribeAudio(audioBuffer, 'audio/aac', 'audio.aac', { idioma: 'es', nombres: ['Ana', 'Rubén'] });
|
|
43
|
+
* // Resultado: "Hola Rubén, quería comentarte que hoy me duele un poco la rodilla..."
|
|
50
44
|
* ```
|
|
51
45
|
*/
|
|
52
|
-
declare const transcribeAudio: (fileBuffer: Buffer, mimetype: string, filename?: string) => Promise<string>;
|
|
46
|
+
declare const transcribeAudio: (fileBuffer: Buffer, mimetype: string, filename?: string, contexto?: ContextoTranscripcion | null) => Promise<string>;
|
|
53
47
|
/**
|
|
54
|
-
* Transcribe un WAV que ya viene en el
|
|
55
|
-
*
|
|
56
|
-
* que extrae la pista así y ya la recorta.
|
|
48
|
+
* Transcribe un WAV que ya viene en PCM 16 bits, mono, 16 kHz. Lo usa el análisis de vídeo, que
|
|
49
|
+
* extrae la pista así y ya la recorta.
|
|
57
50
|
*
|
|
58
|
-
* @param wavBuffer - Buffer WAV mono 16 kHz
|
|
59
|
-
* @
|
|
51
|
+
* @param wavBuffer - Buffer WAV mono 16 kHz
|
|
52
|
+
* @param contexto - Idioma, nombres y últimos mensajes del cliente (opcional)
|
|
53
|
+
* @returns Promise<string> - Transcripción, o un marcador
|
|
60
54
|
*/
|
|
61
|
-
declare const transcribeWav16k: (wavBuffer: Buffer) => Promise<string>;
|
|
62
|
-
export { transcribeAudio, transcribeWav16k,
|
|
55
|
+
declare const transcribeWav16k: (wavBuffer: Buffer, contexto?: ContextoTranscripcion | null) => Promise<string>;
|
|
56
|
+
export { transcribeAudio, transcribeWav16k, convertToWav16k, MARCADOR_SIN_VOZ, MARCADOR_NO_TRANSCRITO, MARCADOR_ANTIGUO, MARCADORES_AUDIO, TRANSCRIPTION_MAX_SECONDS, MAX_CARACTERES_POR_SEGUNDO, };
|
|
57
|
+
export type { ContextoTranscripcion };
|
|
63
58
|
//# sourceMappingURL=audio.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/audio.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/audio.ts"],"names":[],"mappings":";AAKA,OAAO,EAA2C,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAG3G,QAAA,MAAM,yBAAyB,MAAM,CAAC;AAItC,QAAA,MAAM,0BAA0B,KAAK,CAAC;AAKtC,QAAA,MAAM,gBAAgB,gCAAgC,CAAC;AACvD,QAAA,MAAM,sBAAsB,0BAA0B,CAAC;AACvD,QAAA,MAAM,gBAAgB,sCAAsC,CAAC;AAC7D,QAAA,MAAM,gBAAgB,UAA+D,CAAC;AAMtF;;;;;;GAMG;AACH,QAAA,MAAM,eAAe,eAAgB,MAAM,aAAa,MAAM,KAAG,QAAQ;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAuBtG,CAAC;AAgJL;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,QAAA,MAAM,eAAe,eAAsB,MAAM,YAAY,MAAM,aAAa,MAAM,aAAa,qBAAqB,GAAG,IAAI,KAAG,QAAQ,MAAM,CAG/I,CAAC;AAEF;;;;;;;GAOG;AACH,QAAA,MAAM,gBAAgB,cAAqB,MAAM,aAAa,qBAAqB,GAAG,IAAI,KAAG,QAAQ,MAAM,CAK1G,CAAC;AAEF,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAChB,yBAAyB,EACzB,0BAA0B,GAC3B,CAAC;AACF,YAAY,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
declare const SPEECH_API_VERSION = "2025-10-15";
|
|
3
|
+
type ResultadoSpeech = {
|
|
4
|
+
text: string;
|
|
5
|
+
confidence: number | null;
|
|
6
|
+
durationMs: number | null;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Traduce el idioma preferido del cliente (`CLIENTE."PREFERRED LANGUAGE"`) al locale de Speech
|
|
10
|
+
*
|
|
11
|
+
* @param lang - Código de idioma ('es', 'en', 'ca'…), o vacío
|
|
12
|
+
* @returns Locale BCP-47; 'es-ES' si no se reconoce
|
|
13
|
+
*/
|
|
14
|
+
declare const localeFromPreferredLanguage: (lang?: string | null) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Transcribe un audio con la transcripción rápida de Azure AI Speech.
|
|
17
|
+
*
|
|
18
|
+
* Acepta el archivo tal cual (aac, m4a, mp3, wav, ogg…): Speech detecta el formato por contenido,
|
|
19
|
+
* así que no hace falta convertir a WAV. Sin filtro de palabrotas, porque «joder» forma parte de
|
|
20
|
+
* lo que el cliente dijo y el entrenador tiene que verlo.
|
|
21
|
+
*
|
|
22
|
+
* @param audio - Buffer del audio
|
|
23
|
+
* @param opts - locale del cliente, frases a reforzar (nombres, jerga) y MIME type si se conoce
|
|
24
|
+
* @returns Texto, confianza media de las frases y duración detectada
|
|
25
|
+
* @throws Error si la API responde con error (tras un reintento en 429/5xx)
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const { text } = await transcribeWithAzureSpeech(buffer, { locale: 'es-ES', phrases: ['Rubén', 'fartlek'] });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
declare const transcribeWithAzureSpeech: (audio: Buffer, opts: {
|
|
33
|
+
locale: string;
|
|
34
|
+
phrases?: string[];
|
|
35
|
+
mimetype?: string;
|
|
36
|
+
}) => Promise<ResultadoSpeech>;
|
|
37
|
+
export { transcribeWithAzureSpeech, localeFromPreferredLanguage, SPEECH_API_VERSION };
|
|
38
|
+
//# sourceMappingURL=azureSpeech.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azureSpeech.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/azureSpeech.ts"],"names":[],"mappings":";AAKA,QAAA,MAAM,kBAAkB,eAAe,CAAC;AAoBxC,KAAK,eAAe,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,2BAA2B,UAAW,MAAM,GAAG,IAAI,KAAG,MAA8E,CAAC;AAoB3I;;;;;;;;;;;;;;;;GAgBG;AACH,QAAA,MAAM,yBAAyB,UAAiB,MAAM,QAAQ;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,QAAQ,eAAe,CAoChJ,CAAC;AAEF,OAAO,EAAE,yBAAyB,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
declare const TRANSCRIBE_API_VERSION = "2025-04-01-preview";
|
|
3
|
+
/**
|
|
4
|
+
* URL y clave del despliegue de transcripción de Azure OpenAI
|
|
5
|
+
*
|
|
6
|
+
* @returns URL completa del endpoint y clave
|
|
7
|
+
* @throws Error si falta AZURE_BASE_URL o AZURE_API_KEY
|
|
8
|
+
*/
|
|
9
|
+
declare const getTranscribeConfig: () => {
|
|
10
|
+
url: string;
|
|
11
|
+
key: string;
|
|
12
|
+
deployment: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Transcribe un WAV con el despliegue de transcripción de Azure OpenAI, sin prompt.
|
|
16
|
+
*
|
|
17
|
+
* @param wav - Buffer WAV (mono 16 kHz, como sale de `convertToWav16k`)
|
|
18
|
+
* @param opts - Idioma en código de dos letras ('es', 'en'…)
|
|
19
|
+
* @returns Texto transcrito; cadena vacía si el modelo no oyó nada (un "." suelto cuenta como vacío)
|
|
20
|
+
* @throws Error si la API responde con error (tras un reintento en 429/5xx)
|
|
21
|
+
*/
|
|
22
|
+
declare const transcribeWithAzureOpenAI: (wav: Buffer, opts: {
|
|
23
|
+
language: string;
|
|
24
|
+
}) => Promise<string>;
|
|
25
|
+
export { transcribeWithAzureOpenAI, getTranscribeConfig, TRANSCRIBE_API_VERSION };
|
|
26
|
+
//# sourceMappingURL=azureTranscribe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azureTranscribe.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/azureTranscribe.ts"],"names":[],"mappings":";AAMA,QAAA,MAAM,sBAAsB,uBAAuB,CAAC;AAMpD;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB;SAAc,MAAM;SAAO,MAAM;gBAAc,MAAM;CAM7E,CAAC;AAEF;;;;;;;GAOG;AACH,QAAA,MAAM,yBAAyB,QAAe,MAAM,QAAQ;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAG,QAAQ,MAAM,CA2BhG,CAAC;AAEF,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
declare const GLOSARIO_RUNNING: string[];
|
|
2
|
+
type MensajePrevio = {
|
|
3
|
+
quien: 'cliente' | 'entrenador';
|
|
4
|
+
texto: string;
|
|
5
|
+
};
|
|
6
|
+
type ContextoTranscripcion = {
|
|
7
|
+
/** Solo para el log */
|
|
8
|
+
idMensaje?: number;
|
|
9
|
+
/** CLIENTE."PREFERRED LANGUAGE" */
|
|
10
|
+
idioma?: string | null;
|
|
11
|
+
/** Cliente y entrenadores: refuerzan el reconocimiento y habilitan sus nombres en el filtro */
|
|
12
|
+
nombres?: string[];
|
|
13
|
+
/** Últimos mensajes del chat, del más antiguo al más reciente */
|
|
14
|
+
previos?: MensajePrevio[];
|
|
15
|
+
};
|
|
16
|
+
type Sustitucion = {
|
|
17
|
+
de: string;
|
|
18
|
+
a: string;
|
|
19
|
+
aceptada: boolean;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Normaliza para comparar: minúsculas, sin acentos, solo letras, dígitos y espacios
|
|
23
|
+
*
|
|
24
|
+
* @param texto - Texto de entrada
|
|
25
|
+
* @returns Texto normalizado
|
|
26
|
+
*/
|
|
27
|
+
declare const normalizar: (texto: string) => string;
|
|
28
|
+
/**
|
|
29
|
+
* Corrige jerga y nombres de una transcripción con el modelo LITE, dejando pasar solo las
|
|
30
|
+
* sustituciones que el filtro determinista acepta. Nunca lanza: ante cualquier fallo devuelve el
|
|
31
|
+
* texto tal cual.
|
|
32
|
+
*
|
|
33
|
+
* @param texto - Transcripción tal como sale del reconocedor
|
|
34
|
+
* @param contexto - Nombres y últimos mensajes del chat
|
|
35
|
+
* @returns Texto corregido y la lista de sustituciones propuestas con su veredicto
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const { texto, sustituciones } = await corregirTranscripcion('Hoy he hecho Farley con el garam', { nombres: ['Ana', 'Rubén'] });
|
|
40
|
+
* // texto: 'Hoy he hecho fartlek con el Garmin'
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
declare const corregirTranscripcion: (texto: string, contexto?: ContextoTranscripcion | null) => Promise<{
|
|
44
|
+
texto: string;
|
|
45
|
+
sustituciones: Sustitucion[];
|
|
46
|
+
}>;
|
|
47
|
+
export { corregirTranscripcion, GLOSARIO_RUNNING, normalizar };
|
|
48
|
+
export type { ContextoTranscripcion, MensajePrevio, Sustitucion };
|
|
49
|
+
//# sourceMappingURL=correccionTranscripcion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correccionTranscripcion.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/correccionTranscripcion.ts"],"names":[],"mappings":"AAWA,QAAA,MAAM,gBAAgB,EAAE,MAAM,EAqD7B,CAAC;AAWF,KAAK,aAAa,GAAG;IAAE,KAAK,EAAE,SAAS,GAAG,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,KAAK,qBAAqB,GAAG;IAC3B,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,iEAAiE;IACjE,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;CAC3B,CAAC;AAEF,KAAK,WAAW,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAIhE;;;;;GAKG;AACH,QAAA,MAAM,UAAU,UAAW,MAAM,KAAG,MAOzB,CAAC;AAiKZ;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,qBAAqB,UAAiB,MAAM,aAAa,qBAAqB,GAAG,IAAI;WAAoB,MAAM;mBAAiB,WAAW,EAAE;EAqClJ,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC;AAC/D,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import ffmpeg from 'fluent-ffmpeg';
|
|
2
2
|
declare const FFMPEG_TIMEOUT_MS = 120000;
|
|
3
3
|
declare const SPEECH_SAMPLE_RATE = 16000;
|
|
4
|
+
declare const SIN_VOZ_DURACION_MAX_S = 2;
|
|
5
|
+
declare const SIN_VOZ_DB_CLIP_CORTO = -40;
|
|
6
|
+
declare const SIN_VOZ_DB = -60;
|
|
4
7
|
/**
|
|
5
8
|
* Ejecuta un comando de ffmpeg como promesa, matándolo si se pasa del tiempo máximo
|
|
6
9
|
*
|
|
@@ -19,6 +22,22 @@ declare const probeMedia: (inputPath: string) => Promise<{
|
|
|
19
22
|
hasAudio: boolean;
|
|
20
23
|
hasVideo: boolean;
|
|
21
24
|
}>;
|
|
25
|
+
/**
|
|
26
|
+
* Mide el volumen medio de un audio con el filtro `volumedetect` de ffmpeg. Nunca lanza.
|
|
27
|
+
*
|
|
28
|
+
* @param inputPath - Ruta del audio en disco (cualquier formato que ffmpeg decodifique)
|
|
29
|
+
* @returns Volumen medio en dB, o null si no se pudo medir
|
|
30
|
+
*/
|
|
31
|
+
declare const measureLoudness: (inputPath: string) => Promise<number | null>;
|
|
32
|
+
/**
|
|
33
|
+
* Decide si un audio no tiene voz que transcribir: muy corto y bajo, o directamente en silencio.
|
|
34
|
+
* Sin medida de volumen nunca se marca: mejor transcribir de más que callar un audio con voz.
|
|
35
|
+
*
|
|
36
|
+
* @param duration - Duración en segundos (0 si no se conoce)
|
|
37
|
+
* @param meanDb - Volumen medio en dB, o null si no se pudo medir
|
|
38
|
+
* @returns true si no merece la pena llamar a ningún motor
|
|
39
|
+
*/
|
|
40
|
+
declare const esAudioSinVoz: (duration: number, meanDb: number | null) => boolean;
|
|
22
41
|
/**
|
|
23
42
|
* Crea un directorio temporal, ejecuta el trabajo y lo borra pase lo que pase.
|
|
24
43
|
* En Cloud Run el temporal vive en RAM, así que dejarlo sin borrar cuesta memoria.
|
|
@@ -27,5 +46,5 @@ declare const probeMedia: (inputPath: string) => Promise<{
|
|
|
27
46
|
* @returns Lo que devuelva `work`
|
|
28
47
|
*/
|
|
29
48
|
declare const withTempDir: <T>(work: (dir: string) => Promise<T>) => Promise<T>;
|
|
30
|
-
export { ffmpeg, runFfmpeg, probeMedia, withTempDir, FFMPEG_TIMEOUT_MS, SPEECH_SAMPLE_RATE };
|
|
49
|
+
export { ffmpeg, runFfmpeg, probeMedia, measureLoudness, esAudioSinVoz, withTempDir, FFMPEG_TIMEOUT_MS, SPEECH_SAMPLE_RATE, SIN_VOZ_DURACION_MAX_S, SIN_VOZ_DB_CLIP_CORTO, SIN_VOZ_DB, };
|
|
31
50
|
//# sourceMappingURL=ffmpegUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ffmpegUtils.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/ffmpegUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ffmpegUtils.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/ffmpegUtils.ts"],"names":[],"mappings":"AAIA,OAAO,MAAM,MAAM,eAAe,CAAC;AASnC,QAAA,MAAM,iBAAiB,SAAS,CAAC;AAGjC,QAAA,MAAM,kBAAkB,QAAQ,CAAC;AAMjC,QAAA,MAAM,sBAAsB,IAAI,CAAC;AACjC,QAAA,MAAM,qBAAqB,MAAM,CAAC;AAClC,QAAA,MAAM,UAAU,MAAM,CAAC;AAEvB;;;;;GAKG;AACH,QAAA,MAAM,SAAS,YAAa,GAAG,SAAS,MAAM,KAAG,QAAQ,IAAI,CAqBzD,CAAC;AAEL;;;;;GAKG;AACH,QAAA,MAAM,UAAU,cAAe,MAAM,KAAG,QAAQ;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAetG,CAAC;AAEL;;;;;GAKG;AACH,QAAA,MAAM,eAAe,cAAe,MAAM,KAAG,QAAQ,MAAM,GAAG,IAAI,CAgB9D,CAAC;AAEL;;;;;;;GAOG;AACH,QAAA,MAAM,aAAa,aAAc,MAAM,UAAU,MAAM,GAAG,IAAI,KAAG,OACkE,CAAC;AAEpI;;;;;;GAMG;AAEH,QAAA,MAAM,WAAW,kBAAyB,MAAM,8BAW/C,CAAC;AAEF,OAAO,EACL,MAAM,EACN,SAAS,EACT,UAAU,EACV,eAAe,EACf,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,UAAU,GACX,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { transcribeAudio } from './audio';
|
|
2
|
+
import { transcribeAudio, ContextoTranscripcion } from './audio';
|
|
3
3
|
import { describeImage } from './image';
|
|
4
4
|
import { describeVideo } from './video';
|
|
5
5
|
import { describePdf, describeTextFile, describeOpaqueFile } from './documents';
|
|
@@ -33,6 +33,7 @@ declare const classifyFile: (mimetype: string, filename: string | undefined, fil
|
|
|
33
33
|
* @param fileBuffer - Buffer del archivo
|
|
34
34
|
* @param mimetype - Tipo MIME del archivo
|
|
35
35
|
* @param filename - Nombre original del archivo
|
|
36
|
+
* @param contexto - Idioma, nombres y últimos mensajes del cliente; solo lo usan audio y vídeo
|
|
36
37
|
* @returns Promise<string> - Transcripción, descripción, resumen o ficha del archivo
|
|
37
38
|
*
|
|
38
39
|
* @example
|
|
@@ -41,7 +42,7 @@ declare const classifyFile: (mimetype: string, filename: string | undefined, fil
|
|
|
41
42
|
* // "Analítica de sangre del 3 de junio con ferritina de 28 ng/ml..."
|
|
42
43
|
* ```
|
|
43
44
|
*/
|
|
44
|
-
declare const analyzeFile: (fileBuffer: Buffer, mimetype: string, filename?: string) => Promise<string>;
|
|
45
|
+
declare const analyzeFile: (fileBuffer: Buffer, mimetype: string, filename?: string, contexto?: ContextoTranscripcion | null) => Promise<string>;
|
|
45
46
|
/**
|
|
46
47
|
* Procesa un adjunto de chat y guarda su texto en la base de datos.
|
|
47
48
|
* Pensado para llamarse sin await (fire-and-forget) desde el envío del archivo.
|
|
@@ -59,22 +60,55 @@ declare const analyzeFile: (fileBuffer: Buffer, mimetype: string, filename?: str
|
|
|
59
60
|
* ```
|
|
60
61
|
*/
|
|
61
62
|
declare const processMediaFile: (idMessage: number, fileBuffer: Buffer, mimetype: string, filename?: string) => Promise<void>;
|
|
63
|
+
type ResultadoReprocesado = {
|
|
64
|
+
id: number;
|
|
65
|
+
antes: string | null;
|
|
66
|
+
despues: string;
|
|
67
|
+
guardado: boolean;
|
|
68
|
+
};
|
|
62
69
|
/**
|
|
63
|
-
* Reprocesa los adjuntos recientes (últimos 2 días) que no tienen FILE TEXT
|
|
64
|
-
* sea cual sea su tipo. Útil
|
|
70
|
+
* Reprocesa los adjuntos recientes (últimos 2 días) que no tienen FILE TEXT o cuya transcripción
|
|
71
|
+
* quedó en un marcador de fallo transitorio, sea cual sea su tipo. Útil tras un deploy o una caída
|
|
72
|
+
* del motor de transcripción. El marcador «sin voz» no se reintenta: es definitivo.
|
|
65
73
|
*
|
|
66
|
-
* @param bucket -
|
|
74
|
+
* @param bucket - Contenedor con `file(ruta).exists()` y `download()`; si no se pasa, el del propio servicio
|
|
67
75
|
* @returns Promise<{ processed: number; errors: number }> - Estadísticas del reprocesamiento
|
|
68
76
|
*
|
|
69
77
|
* @example
|
|
70
78
|
* ```typescript
|
|
71
|
-
* const stats = await reprocessRecentMedia(
|
|
79
|
+
* const stats = await reprocessRecentMedia();
|
|
72
80
|
* // Resultado: { processed: 5, errors: 1 }
|
|
73
81
|
* ```
|
|
74
82
|
*/
|
|
75
|
-
declare const reprocessRecentMedia: (bucket
|
|
83
|
+
declare const reprocessRecentMedia: (bucket?: any) => Promise<{
|
|
84
|
+
processed: number;
|
|
85
|
+
errors: number;
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* Reprocesa una lista concreta de adjuntos (p. ej. transcripciones que se sabe que salieron mal)
|
|
89
|
+
* con el pipeline actual. Con `dryRun` calcula el texto nuevo sin guardarlo, para ver antes y
|
|
90
|
+
* después. Sin `dryRun` escribe FILE TEXT: ejecutar a mano y con criterio.
|
|
91
|
+
*
|
|
92
|
+
* @param ids - IDs de CHAT MESSAGE
|
|
93
|
+
* @param opts - `dryRun` para simular; `bucket` para usar otro almacenamiento que el del propio servicio
|
|
94
|
+
* @returns Estadísticas y, por mensaje, texto anterior y nuevo
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const { resultados } = await reprocessMediaByIds([523437, 501309], { dryRun: true });
|
|
99
|
+
* // resultados[0]: { id: 523437, antes: 'Hola Víctor…', despues: '[Audio sin voz reconocible]', guardado: false }
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
declare const reprocessMediaByIds: (ids: number[], opts?: {
|
|
103
|
+
bucket?: any;
|
|
104
|
+
dryRun?: boolean;
|
|
105
|
+
}) => Promise<{
|
|
76
106
|
processed: number;
|
|
77
107
|
errors: number;
|
|
108
|
+
resultados: ResultadoReprocesado[];
|
|
78
109
|
}>;
|
|
79
|
-
export { transcribeAudio, describeImage, describeVideo, describePdf, describeTextFile, describeOpaqueFile, classifyFile, analyzeFile, processMediaFile, reprocessRecentMedia, FILE_KIND, };
|
|
110
|
+
export { transcribeAudio, describeImage, describeVideo, describePdf, describeTextFile, describeOpaqueFile, classifyFile, analyzeFile, processMediaFile, reprocessRecentMedia, reprocessMediaByIds, FILE_KIND, };
|
|
111
|
+
export { corregirTranscripcion, GLOSARIO_RUNNING } from './correccionTranscripcion';
|
|
112
|
+
export { MARCADOR_SIN_VOZ, MARCADOR_NO_TRANSCRITO, MARCADORES_AUDIO } from './audio';
|
|
113
|
+
export type { ContextoTranscripcion } from './audio';
|
|
80
114
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/index.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/index.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAA4C,MAAM,SAAS,CAAC;AAC3G,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,kBAAkB,EAAuC,MAAM,aAAa,CAAC;AAGrH,QAAA,MAAM,SAAS;;;;;;;CAOL,CAAC;AAEX,KAAK,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAiC3D;;;;;;;;GAQG;AACH,QAAA,MAAM,YAAY,aAAc,MAAM,YAAY,MAAM,GAAG,SAAS,cAAc,MAAM,KAAG,QA0B1F,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,QAAA,MAAM,WAAW,eAAsB,MAAM,YAAY,MAAM,aAAa,MAAM,aAAa,qBAAqB,GAAG,IAAI,KAAG,QAAQ,MAAM,CA8B3I,CAAC;AA2CF;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,gBAAgB,cAAqB,MAAM,cAAc,MAAM,YAAY,MAAM,aAAa,MAAM,KAAG,QAAQ,IAAI,CAaxH,CAAC;AAIF,KAAK,oBAAoB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAwCrG;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,oBAAoB,YAAmB,GAAG;eAAwB,MAAM;YAAU,MAAM;EAmC7F,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,mBAAmB,QAClB,MAAM,EAAE,SACP;IAAE,MAAM,CAAC,EAAE,GAAG,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE;eAClB,MAAM;YAAU,MAAM;gBAAc,oBAAoB,EAAE;EAoCjF,CAAC;AAEF,OAAO,EACL,eAAe,EACf,aAAa,EACb,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,SAAS,GACV,CAAC;AACF,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACrF,YAAY,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
import { ContextoTranscripcion } from './audio';
|
|
2
3
|
/**
|
|
3
4
|
* Analiza un vídeo descomponiéndolo en lo que sí sabemos leer: un fotograma
|
|
4
5
|
* representativo (descrito por el modelo de visión) y su pista de audio
|
|
@@ -16,6 +17,6 @@
|
|
|
16
17
|
* // "Vídeo de 12 s. Imagen: corredor de perfil sobre cinta... Audio: mira cómo apoyo el talón..."
|
|
17
18
|
* ```
|
|
18
19
|
*/
|
|
19
|
-
declare const describeVideo: (fileBuffer: Buffer, mimetype: string, filename?: string) => Promise<string>;
|
|
20
|
+
declare const describeVideo: (fileBuffer: Buffer, mimetype: string, filename?: string, contexto?: ContextoTranscripcion | null) => Promise<string>;
|
|
20
21
|
export { describeVideo };
|
|
21
22
|
//# sourceMappingURL=video.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/video.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../../../src/mediaProcessing/video.ts"],"names":[],"mappings":";AAIA,OAAO,EAAoB,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAkElE;;;;;;;;;;;;;;;;GAgBG;AACH,QAAA,MAAM,aAAa,eAAsB,MAAM,YAAY,MAAM,aAAa,MAAM,aAAa,qBAAqB,GAAG,IAAI,KAAG,QAAQ,MAAM,CAyD7I,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runnerpro/backend",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.35.0",
|
|
4
4
|
"description": "A collection of common backend functions",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./lib/cjs/index.js"
|
|
@@ -70,7 +70,6 @@
|
|
|
70
70
|
"@ai-sdk/google": "^3.0.43",
|
|
71
71
|
"@ai-sdk/google-vertex": "^4.0.102",
|
|
72
72
|
"@azure/storage-blob": "^12.32.0",
|
|
73
|
-
"@google-cloud/speech": "^7.2.1",
|
|
74
73
|
"@google-cloud/storage": "^7.11.3",
|
|
75
74
|
"@google-cloud/translate": "^8.3.0",
|
|
76
75
|
"@notionhq/client": "^2.2.15",
|