@vertesia/workflow 0.80.0 → 0.81.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/activities/index-dsl.js +11 -9
- package/lib/cjs/activities/index-dsl.js.map +1 -1
- package/lib/cjs/activities/media/saveGladiaTranscription.js +81 -0
- package/lib/cjs/activities/media/saveGladiaTranscription.js.map +1 -0
- package/lib/cjs/activities/media/transcribeMediaWithGladia.js +7 -9
- package/lib/cjs/activities/media/transcribeMediaWithGladia.js.map +1 -1
- package/lib/esm/activities/index-dsl.js +5 -4
- package/lib/esm/activities/index-dsl.js.map +1 -1
- package/lib/esm/activities/media/saveGladiaTranscription.js +78 -0
- package/lib/esm/activities/media/saveGladiaTranscription.js.map +1 -0
- package/lib/esm/activities/media/transcribeMediaWithGladia.js +7 -9
- package/lib/esm/activities/media/transcribeMediaWithGladia.js.map +1 -1
- package/lib/types/activities/index-dsl.d.ts +6 -4
- package/lib/types/activities/index-dsl.d.ts.map +1 -1
- package/lib/types/activities/media/saveGladiaTranscription.d.ts +14 -0
- package/lib/types/activities/media/saveGladiaTranscription.d.ts.map +1 -0
- package/lib/types/activities/media/transcribeMediaWithGladia.d.ts +5 -0
- package/lib/types/activities/media/transcribeMediaWithGladia.d.ts.map +1 -1
- package/lib/workflows-bundle.js +87 -39
- package/package.json +6 -6
- package/src/activities/index-dsl.ts +7 -4
- package/src/activities/media/saveGladiaTranscription.ts +128 -0
- package/src/activities/media/transcribeMediaWithGladia.ts +13 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vertesia/workflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.81.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vertesia workflow DSL",
|
|
6
6
|
"main": "./lib/esm/index.js",
|
|
@@ -44,11 +44,11 @@
|
|
|
44
44
|
"tmp": "^0.2.4",
|
|
45
45
|
"tmp-promise": "^3.0.3",
|
|
46
46
|
"yaml": "^2.6.0",
|
|
47
|
-
"@llumiverse/common": "0.
|
|
48
|
-
"@vertesia/common": "0.
|
|
49
|
-
"@vertesia/client": "0.
|
|
50
|
-
"@vertesia/api-fetch-client": "0.
|
|
51
|
-
"@vertesia/memory": "0.
|
|
47
|
+
"@llumiverse/common": "0.24.0",
|
|
48
|
+
"@vertesia/common": "0.81.0",
|
|
49
|
+
"@vertesia/client": "0.81.0",
|
|
50
|
+
"@vertesia/api-fetch-client": "0.81.0",
|
|
51
|
+
"@vertesia/memory": "0.81.0"
|
|
52
52
|
},
|
|
53
53
|
"ts_dual_module": {
|
|
54
54
|
"outDir": "lib",
|
|
@@ -8,14 +8,17 @@ export { executeInteraction } from "./executeInteraction.js";
|
|
|
8
8
|
export { extractDocumentText } from "./extractDocumentText.js";
|
|
9
9
|
export { generateDocumentProperties } from "./generateDocumentProperties.js";
|
|
10
10
|
export { generateEmbeddings } from "./generateEmbeddings.js";
|
|
11
|
-
export { generateImageRendition } from "./renditions/generateImageRendition.js";
|
|
12
|
-
export { generateVideoRendition } from "./renditions/generateVideoRendition.js";
|
|
13
11
|
export { generateOrAssignContentType } from "./generateOrAssignContentType.js";
|
|
14
12
|
export { getObjectFromStore } from "./getObjectFromStore.js";
|
|
15
13
|
export { handleDslError } from "./handleError.js";
|
|
14
|
+
export { prepareVideo } from "./media/prepareVideo.js";
|
|
16
15
|
export { convertPdfToStructuredText } from "./media/processPdfWithTextract.js";
|
|
16
|
+
export { saveGladiaTranscription } from "./media/saveGladiaTranscription.js";
|
|
17
17
|
export { transcribeMedia } from "./media/transcribeMediaWithGladia.js";
|
|
18
|
-
export {
|
|
18
|
+
export type { TranscriptMediaResult } from "./media/transcribeMediaWithGladia.js";
|
|
19
19
|
export { notifyWebhook } from "./notifyWebhook.js";
|
|
20
|
-
export { setDocumentStatus } from "./setDocumentStatus.js";
|
|
21
20
|
export { checkRateLimit } from "./rateLimiter.js";
|
|
21
|
+
export { generateImageRendition } from "./renditions/generateImageRendition.js";
|
|
22
|
+
export { generateVideoRendition } from "./renditions/generateVideoRendition.js";
|
|
23
|
+
export { setDocumentStatus } from "./setDocumentStatus.js";
|
|
24
|
+
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { log } from "@temporalio/activity";
|
|
2
|
+
import { FetchClient } from "@vertesia/api-fetch-client";
|
|
3
|
+
import { AudioMetadata, DSLActivityExecutionPayload, DSLActivitySpec, GladiaConfiguration, SupportedIntegrations, TranscriptSegment, VideoMetadata } from "@vertesia/common";
|
|
4
|
+
import { setupActivity } from "../../dsl/setup/ActivityContext.js";
|
|
5
|
+
import { TextExtractionResult, TextExtractionStatus } from "../../result-types.js";
|
|
6
|
+
|
|
7
|
+
export interface SaveGladiaTranscriptionParams {
|
|
8
|
+
gladiaTranscriptionId: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface SaveGladiaTranscription extends DSLActivitySpec<SaveGladiaTranscriptionParams> {
|
|
12
|
+
name: 'SaveGladiaTranscription';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const GLADIA_URL = "https://api.gladia.io/v2";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Fetches transcription results from Gladia and saves them to the content object.
|
|
19
|
+
* This activity is called after transcribeMedia completes via webhook callback.
|
|
20
|
+
*/
|
|
21
|
+
export async function saveGladiaTranscription(payload: DSLActivityExecutionPayload<SaveGladiaTranscriptionParams>): Promise<TextExtractionResult> {
|
|
22
|
+
const { params, client, objectId } = await setupActivity<SaveGladiaTranscriptionParams>(payload);
|
|
23
|
+
|
|
24
|
+
const gladiaConfig = await client.projects.integrations.retrieve(payload.project_id, SupportedIntegrations.gladia) as GladiaConfiguration | undefined;
|
|
25
|
+
if (!gladiaConfig || !gladiaConfig.enabled) {
|
|
26
|
+
return {
|
|
27
|
+
hasText: false,
|
|
28
|
+
objectId,
|
|
29
|
+
status: TextExtractionStatus.error,
|
|
30
|
+
error: "Gladia integration not enabled",
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const gladiaClient = new FetchClient(gladiaConfig.url ?? GLADIA_URL);
|
|
35
|
+
gladiaClient.withHeaders({ "x-gladia-key": gladiaConfig.api_key });
|
|
36
|
+
|
|
37
|
+
log.info(`Fetching transcription result from Gladia`, { objectId, transcriptionId: params.gladiaTranscriptionId });
|
|
38
|
+
|
|
39
|
+
const transcriptionResult = await gladiaClient.get(`/transcription/${params.gladiaTranscriptionId}`) as GladiaTranscriptionResult;
|
|
40
|
+
|
|
41
|
+
if (transcriptionResult.status === 'error') {
|
|
42
|
+
log.error(`Gladia transcription failed`, { objectId, error: transcriptionResult });
|
|
43
|
+
return {
|
|
44
|
+
hasText: false,
|
|
45
|
+
objectId,
|
|
46
|
+
status: TextExtractionStatus.error,
|
|
47
|
+
error: "Gladia transcription failed",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (transcriptionResult.status !== 'done') {
|
|
52
|
+
log.warn(`Gladia transcription not ready`, { objectId, status: transcriptionResult.status });
|
|
53
|
+
return {
|
|
54
|
+
hasText: false,
|
|
55
|
+
objectId,
|
|
56
|
+
status: TextExtractionStatus.error,
|
|
57
|
+
error: `Gladia transcription not ready: ${transcriptionResult.status}`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const object = await client.objects.retrieve(objectId, "+text");
|
|
62
|
+
|
|
63
|
+
const segments = processUtterances(transcriptionResult.result.transcription.utterances);
|
|
64
|
+
const fullText = transcriptionResult.result.transcription.full_transcript;
|
|
65
|
+
|
|
66
|
+
await client.objects.update(objectId, {
|
|
67
|
+
text: fullText,
|
|
68
|
+
text_etag: object.content?.etag,
|
|
69
|
+
transcript: {
|
|
70
|
+
segments,
|
|
71
|
+
etag: object.content?.etag
|
|
72
|
+
},
|
|
73
|
+
metadata: {
|
|
74
|
+
...object.metadata,
|
|
75
|
+
duration: transcriptionResult.result.metadata.audio_duration,
|
|
76
|
+
languages: transcriptionResult.result.transcription.languages
|
|
77
|
+
} as AudioMetadata | VideoMetadata
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
log.info(`Saved transcription for object`, { objectId, textLength: fullText?.length, segmentCount: segments.length });
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
hasText: (fullText?.length ?? 0) > 0,
|
|
84
|
+
objectId,
|
|
85
|
+
status: TextExtractionStatus.success,
|
|
86
|
+
message: `Transcription saved with ${segments.length} segments`
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function processUtterances(utterances: GladiaUtterance[]): TranscriptSegment[] {
|
|
91
|
+
return utterances.map(u => ({
|
|
92
|
+
start: u.start,
|
|
93
|
+
end: u.end,
|
|
94
|
+
text: u.text,
|
|
95
|
+
speaker: u.speaker,
|
|
96
|
+
confidence: u.confidence,
|
|
97
|
+
language: u.language
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Gladia API response types
|
|
102
|
+
interface GladiaTranscriptionResult {
|
|
103
|
+
id: string;
|
|
104
|
+
status: 'queued' | 'processing' | 'done' | 'error';
|
|
105
|
+
result: {
|
|
106
|
+
metadata: {
|
|
107
|
+
audio_duration: number;
|
|
108
|
+
number_of_distinct_channels: number;
|
|
109
|
+
billing_time: number;
|
|
110
|
+
transcription_time: number;
|
|
111
|
+
};
|
|
112
|
+
transcription: {
|
|
113
|
+
full_transcript: string;
|
|
114
|
+
languages: string[];
|
|
115
|
+
utterances: GladiaUtterance[];
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface GladiaUtterance {
|
|
121
|
+
language: string;
|
|
122
|
+
start: number;
|
|
123
|
+
end: number;
|
|
124
|
+
confidence: number;
|
|
125
|
+
channel: number;
|
|
126
|
+
speaker: number;
|
|
127
|
+
text: string;
|
|
128
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DSLActivityExecutionPayload, DSLActivitySpec, GladiaConfiguration, SupportedIntegrations, AUDIO_RENDITION_NAME, VideoMetadata, ContentNature } from "@vertesia/common";
|
|
2
1
|
import { activityInfo, CompleteAsyncError, log } from "@temporalio/activity";
|
|
3
2
|
import { FetchClient, RequestError } from "@vertesia/api-fetch-client";
|
|
3
|
+
import { AUDIO_RENDITION_NAME, ContentNature, DSLActivityExecutionPayload, DSLActivitySpec, GladiaConfiguration, SupportedIntegrations, VideoMetadata } from "@vertesia/common";
|
|
4
4
|
import { setupActivity } from "../../dsl/setup/ActivityContext.js";
|
|
5
5
|
import { DocumentNotFoundError } from "../../errors.js";
|
|
6
6
|
import { TextExtractionResult, TextExtractionStatus } from "../../index.js";
|
|
@@ -17,6 +17,11 @@ export interface TranscriptMedia extends DSLActivitySpec<TranscriptMediaParams>
|
|
|
17
17
|
|
|
18
18
|
export interface TranscriptMediaResult extends TextExtractionResult {
|
|
19
19
|
message?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Gladia transcription ID for fetching results in a follow-up activity.
|
|
22
|
+
* Present when async media transcription completes successfully.
|
|
23
|
+
*/
|
|
24
|
+
gladiaTranscriptionId?: string;
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
const GLADIA_URL = "https://api.gladia.io/v2";
|
|
@@ -68,7 +73,7 @@ export async function transcribeMedia(payload: DSLActivityExecutionPayload<Trans
|
|
|
68
73
|
log.info(`Using media URL for transcription`, { objectId, mediaUrl: mediaSource });
|
|
69
74
|
|
|
70
75
|
const taskToken = Buffer.from(activityInfo().taskToken).toString('base64url');
|
|
71
|
-
const callbackUrl = generateCallbackUrlForGladia(client.store.baseUrl,
|
|
76
|
+
const callbackUrl = generateCallbackUrlForGladia(client.store.baseUrl, taskToken, objectId);
|
|
72
77
|
|
|
73
78
|
log.info(`Transcribing media ${mediaUrl} with Gladia`, { objectId, callbackUrl });
|
|
74
79
|
|
|
@@ -85,10 +90,7 @@ export async function transcribeMedia(payload: DSLActivityExecutionPayload<Trans
|
|
|
85
90
|
}
|
|
86
91
|
}
|
|
87
92
|
}) as GladiaTranscriptRequestResponse;
|
|
88
|
-
|
|
89
93
|
log.info(`Transcription request sent to Gladia`, { objectId, res });
|
|
90
|
-
throw new CompleteAsyncError();
|
|
91
|
-
|
|
92
94
|
} catch (error: any) {
|
|
93
95
|
if (error instanceof RequestError && error.status === 422) {
|
|
94
96
|
return {
|
|
@@ -97,15 +99,16 @@ export async function transcribeMedia(payload: DSLActivityExecutionPayload<Trans
|
|
|
97
99
|
status: TextExtractionStatus.error,
|
|
98
100
|
error: `Gladia transcription error: ${error.message}`,
|
|
99
101
|
}
|
|
100
|
-
} else {
|
|
101
|
-
log.error(`Error sending transcription request to Gladia for object ${objectId}`, { error });
|
|
102
|
-
throw error;
|
|
103
102
|
}
|
|
103
|
+
log.error(`Error sending transcription request to Gladia for object ${objectId}`, { error });
|
|
104
|
+
throw error;
|
|
104
105
|
}
|
|
106
|
+
|
|
107
|
+
throw new CompleteAsyncError();
|
|
105
108
|
}
|
|
106
109
|
|
|
107
|
-
function generateCallbackUrlForGladia(baseUrl: string,
|
|
108
|
-
return `${baseUrl}/
|
|
110
|
+
function generateCallbackUrlForGladia(baseUrl: string, taskToken: string, objectId: string) {
|
|
111
|
+
return `${baseUrl}/webhooks/gladia/${objectId}?task_token=${taskToken}`;
|
|
109
112
|
}
|
|
110
113
|
|
|
111
114
|
interface GladiaTranscriptRequestResponse {
|