@aws-amplify/predictions 5.5.6-api-v6-models.b3abc9b.0 → 6.0.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/README.md +3 -0
- package/lib/Predictions.d.ts +11 -45
- package/lib/Predictions.js +24 -132
- package/lib/errors/PredictionsError.d.ts +4 -0
- package/lib/errors/PredictionsError.js +15 -0
- package/lib/errors/types/validation.d.ts +14 -0
- package/lib/errors/types/validation.js +50 -0
- package/lib/errors/utils/assertValidationError.d.ts +2 -0
- package/lib/errors/utils/assertValidationError.js +14 -0
- package/lib/index.d.ts +2 -4
- package/lib/index.js +2 -9
- package/{lib-esm/Providers → lib/providers}/AmazonAIConvertPredictionsProvider.d.ts +6 -7
- package/lib/providers/AmazonAIConvertPredictionsProvider.js +307 -0
- package/lib/{Providers → providers}/AmazonAIIdentifyPredictionsProvider.d.ts +5 -6
- package/lib/providers/AmazonAIIdentifyPredictionsProvider.js +334 -0
- package/lib/{Providers → providers}/AmazonAIInterpretPredictionsProvider.d.ts +3 -4
- package/lib/providers/AmazonAIInterpretPredictionsProvider.js +208 -0
- package/lib/providers/IdentifyTextUtils.d.ts +16 -0
- package/lib/{Providers → providers}/IdentifyTextUtils.js +97 -148
- package/lib/{Providers → providers}/Utils.d.ts +2 -2
- package/lib/{Providers → providers}/Utils.js +11 -12
- package/lib/{Providers → providers}/index.d.ts +1 -2
- package/lib/providers/index.js +11 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/lib/types/AWSTypes.d.ts +8 -9
- package/lib/types/AWSTypes.js +0 -1
- package/lib/types/Predictions.d.ts +63 -59
- package/lib/types/Predictions.js +41 -28
- package/lib/types/index.js +1 -2
- package/lib-esm/Predictions.d.ts +11 -45
- package/lib-esm/Predictions.js +23 -133
- package/lib-esm/errors/PredictionsError.d.ts +4 -0
- package/lib-esm/errors/PredictionsError.js +11 -0
- package/lib-esm/errors/types/validation.d.ts +14 -0
- package/lib-esm/errors/types/validation.js +47 -0
- package/lib-esm/errors/utils/assertValidationError.d.ts +2 -0
- package/lib-esm/errors/utils/assertValidationError.js +10 -0
- package/lib-esm/index.d.ts +2 -4
- package/lib-esm/index.js +1 -5
- package/{lib/Providers → lib-esm/providers}/AmazonAIConvertPredictionsProvider.d.ts +6 -7
- package/lib-esm/providers/AmazonAIConvertPredictionsProvider.js +303 -0
- package/lib-esm/{Providers → providers}/AmazonAIIdentifyPredictionsProvider.d.ts +5 -6
- package/lib-esm/providers/AmazonAIIdentifyPredictionsProvider.js +330 -0
- package/lib-esm/{Providers → providers}/AmazonAIInterpretPredictionsProvider.d.ts +3 -4
- package/lib-esm/providers/AmazonAIInterpretPredictionsProvider.js +204 -0
- package/lib-esm/providers/IdentifyTextUtils.d.ts +16 -0
- package/lib-esm/providers/IdentifyTextUtils.js +264 -0
- package/lib-esm/{Providers → providers}/Utils.d.ts +2 -2
- package/lib-esm/{Providers → providers}/Utils.js +10 -12
- package/lib-esm/{Providers → providers}/index.d.ts +1 -2
- package/lib-esm/{Providers → providers}/index.js +1 -3
- package/lib-esm/tsconfig.tsbuildinfo +1 -0
- package/lib-esm/types/AWSTypes.d.ts +8 -9
- package/lib-esm/types/AWSTypes.js +1 -1
- package/lib-esm/types/Predictions.d.ts +63 -59
- package/lib-esm/types/Predictions.js +34 -27
- package/lib-esm/types/index.js +0 -1
- package/package.json +39 -48
- package/src/Predictions.ts +33 -220
- package/src/errors/PredictionsError.ts +16 -0
- package/src/errors/types/validation.ts +51 -0
- package/src/errors/utils/assertValidationError.ts +18 -0
- package/src/index.ts +16 -16
- package/src/{Providers → providers}/AmazonAIConvertPredictionsProvider.ts +210 -171
- package/src/{Providers → providers}/AmazonAIIdentifyPredictionsProvider.ts +244 -246
- package/src/providers/AmazonAIInterpretPredictionsProvider.ts +293 -0
- package/src/{Providers → providers}/IdentifyTextUtils.ts +69 -52
- package/src/{Providers → providers}/Utils.ts +2 -2
- package/src/{Providers → providers}/index.ts +0 -2
- package/src/types/AWSTypes.ts +5 -6
- package/src/types/Predictions.ts +107 -62
- package/lib/.tsbuildinfo +0 -3
- package/lib/Predictions.js.map +0 -1
- package/lib/Providers/AmazonAIConvertPredictionsProvider.js +0 -377
- package/lib/Providers/AmazonAIConvertPredictionsProvider.js.map +0 -1
- package/lib/Providers/AmazonAIIdentifyPredictionsProvider.js +0 -441
- package/lib/Providers/AmazonAIIdentifyPredictionsProvider.js.map +0 -1
- package/lib/Providers/AmazonAIInterpretPredictionsProvider.js +0 -321
- package/lib/Providers/AmazonAIInterpretPredictionsProvider.js.map +0 -1
- package/lib/Providers/AmazonAIPredictionsProvider.d.ts +0 -14
- package/lib/Providers/AmazonAIPredictionsProvider.js +0 -43
- package/lib/Providers/AmazonAIPredictionsProvider.js.map +0 -1
- package/lib/Providers/IdentifyTextUtils.d.ts +0 -40
- package/lib/Providers/IdentifyTextUtils.js.map +0 -1
- package/lib/Providers/Utils.js.map +0 -1
- package/lib/Providers/index.js +0 -13
- package/lib/Providers/index.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/types/AWSTypes.js.map +0 -1
- package/lib/types/Predictions.js.map +0 -1
- package/lib/types/Providers/AbstractConvertPredictionsProvider.d.ts +0 -9
- package/lib/types/Providers/AbstractConvertPredictionsProvider.js +0 -44
- package/lib/types/Providers/AbstractConvertPredictionsProvider.js.map +0 -1
- package/lib/types/Providers/AbstractIdentifyPredictionsProvider.d.ts +0 -9
- package/lib/types/Providers/AbstractIdentifyPredictionsProvider.js +0 -44
- package/lib/types/Providers/AbstractIdentifyPredictionsProvider.js.map +0 -1
- package/lib/types/Providers/AbstractInterpretPredictionsProvider.d.ts +0 -7
- package/lib/types/Providers/AbstractInterpretPredictionsProvider.js +0 -27
- package/lib/types/Providers/AbstractInterpretPredictionsProvider.js.map +0 -1
- package/lib/types/Providers/AbstractPredictionsProvider.d.ts +0 -7
- package/lib/types/Providers/AbstractPredictionsProvider.js +0 -16
- package/lib/types/Providers/AbstractPredictionsProvider.js.map +0 -1
- package/lib/types/Providers/index.d.ts +0 -4
- package/lib/types/Providers/index.js +0 -10
- package/lib/types/Providers/index.js.map +0 -1
- package/lib/types/index.js.map +0 -1
- package/lib-esm/.tsbuildinfo +0 -3
- package/lib-esm/Predictions.js.map +0 -1
- package/lib-esm/Providers/AmazonAIConvertPredictionsProvider.js +0 -375
- package/lib-esm/Providers/AmazonAIConvertPredictionsProvider.js.map +0 -1
- package/lib-esm/Providers/AmazonAIIdentifyPredictionsProvider.js +0 -439
- package/lib-esm/Providers/AmazonAIIdentifyPredictionsProvider.js.map +0 -1
- package/lib-esm/Providers/AmazonAIInterpretPredictionsProvider.js +0 -319
- package/lib-esm/Providers/AmazonAIInterpretPredictionsProvider.js.map +0 -1
- package/lib-esm/Providers/AmazonAIPredictionsProvider.d.ts +0 -14
- package/lib-esm/Providers/AmazonAIPredictionsProvider.js +0 -41
- package/lib-esm/Providers/AmazonAIPredictionsProvider.js.map +0 -1
- package/lib-esm/Providers/IdentifyTextUtils.d.ts +0 -40
- package/lib-esm/Providers/IdentifyTextUtils.js +0 -313
- package/lib-esm/Providers/IdentifyTextUtils.js.map +0 -1
- package/lib-esm/Providers/Utils.js.map +0 -1
- package/lib-esm/Providers/index.js.map +0 -1
- package/lib-esm/index.js.map +0 -1
- package/lib-esm/types/AWSTypes.js.map +0 -1
- package/lib-esm/types/Predictions.js.map +0 -1
- package/lib-esm/types/Providers/AbstractConvertPredictionsProvider.d.ts +0 -9
- package/lib-esm/types/Providers/AbstractConvertPredictionsProvider.js +0 -42
- package/lib-esm/types/Providers/AbstractConvertPredictionsProvider.js.map +0 -1
- package/lib-esm/types/Providers/AbstractIdentifyPredictionsProvider.d.ts +0 -9
- package/lib-esm/types/Providers/AbstractIdentifyPredictionsProvider.js +0 -42
- package/lib-esm/types/Providers/AbstractIdentifyPredictionsProvider.js.map +0 -1
- package/lib-esm/types/Providers/AbstractInterpretPredictionsProvider.d.ts +0 -7
- package/lib-esm/types/Providers/AbstractInterpretPredictionsProvider.js +0 -25
- package/lib-esm/types/Providers/AbstractInterpretPredictionsProvider.js.map +0 -1
- package/lib-esm/types/Providers/AbstractPredictionsProvider.d.ts +0 -7
- package/lib-esm/types/Providers/AbstractPredictionsProvider.js +0 -14
- package/lib-esm/types/Providers/AbstractPredictionsProvider.js.map +0 -1
- package/lib-esm/types/Providers/index.d.ts +0 -4
- package/lib-esm/types/Providers/index.js +0 -7
- package/lib-esm/types/Providers/index.js.map +0 -1
- package/lib-esm/types/index.js.map +0 -1
- package/src/Providers/AmazonAIInterpretPredictionsProvider.ts +0 -281
- package/src/Providers/AmazonAIPredictionsProvider.ts +0 -69
- package/src/types/Providers/AbstractConvertPredictionsProvider.ts +0 -55
- package/src/types/Providers/AbstractIdentifyPredictionsProvider.ts +0 -57
- package/src/types/Providers/AbstractInterpretPredictionsProvider.ts +0 -26
- package/src/types/Providers/AbstractPredictionsProvider.ts +0 -20
- package/src/types/Providers/index.ts +0 -6
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AmazonAIConvertPredictionsProvider = void 0;
|
|
4
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
5
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
const core_1 = require("@aws-amplify/core");
|
|
7
|
+
const utils_1 = require("@aws-amplify/core/internals/utils");
|
|
8
|
+
const client_polly_1 = require("@aws-sdk/client-polly");
|
|
9
|
+
const client_translate_1 = require("@aws-sdk/client-translate");
|
|
10
|
+
const eventstream_codec_1 = require("@smithy/eventstream-codec");
|
|
11
|
+
const util_utf8_1 = require("@smithy/util-utf8");
|
|
12
|
+
const buffer_1 = require("buffer");
|
|
13
|
+
const validation_1 = require("../errors/types/validation");
|
|
14
|
+
const assertValidationError_1 = require("../errors/utils/assertValidationError");
|
|
15
|
+
const types_1 = require("../types");
|
|
16
|
+
const logger = new core_1.ConsoleLogger('AmazonAIConvertPredictionsProvider');
|
|
17
|
+
const eventBuilder = new eventstream_codec_1.EventStreamCodec(util_utf8_1.toUtf8, util_utf8_1.fromUtf8);
|
|
18
|
+
const LANGUAGES_CODE_IN_8KHZ = ['fr-FR', 'en-AU', 'en-GB', 'fr-CA'];
|
|
19
|
+
class AmazonAIConvertPredictionsProvider {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.inputSampleRate = 44100;
|
|
22
|
+
}
|
|
23
|
+
getProviderName() {
|
|
24
|
+
return 'AmazonAIConvertPredictionsProvider';
|
|
25
|
+
}
|
|
26
|
+
convert(input) {
|
|
27
|
+
(0, assertValidationError_1.assertValidationError)((0, types_1.isValidConvertInput)(input), validation_1.PredictionsValidationErrorCode.InvalidInput);
|
|
28
|
+
if ((0, types_1.isTranslateTextInput)(input)) {
|
|
29
|
+
logger.debug('translateText');
|
|
30
|
+
return this.translateText(input);
|
|
31
|
+
}
|
|
32
|
+
else if ((0, types_1.isTextToSpeechInput)(input)) {
|
|
33
|
+
logger.debug('textToSpeech');
|
|
34
|
+
return this.convertTextToSpeech(input);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
logger.debug('textToSpeech');
|
|
38
|
+
return this.convertSpeechToText(input);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async translateText(input) {
|
|
42
|
+
logger.debug('Starting translation');
|
|
43
|
+
const { translateText = {} } = core_1.Amplify.getConfig().Predictions?.convert ?? {};
|
|
44
|
+
(0, assertValidationError_1.assertValidationError)(!!translateText.region, validation_1.PredictionsValidationErrorCode.NoRegion);
|
|
45
|
+
const { defaults = {}, region } = translateText;
|
|
46
|
+
const { credentials } = await (0, core_1.fetchAuthSession)();
|
|
47
|
+
(0, assertValidationError_1.assertValidationError)(!!credentials, validation_1.PredictionsValidationErrorCode.NoCredentials);
|
|
48
|
+
const { sourceLanguage, targetLanguage } = defaults;
|
|
49
|
+
const sourceLanguageCode = input.translateText?.source?.language ?? sourceLanguage;
|
|
50
|
+
const targetLanguageCode = input.translateText?.targetLanguage ?? targetLanguage;
|
|
51
|
+
(0, assertValidationError_1.assertValidationError)(!!sourceLanguageCode, validation_1.PredictionsValidationErrorCode.NoSourceLanguage);
|
|
52
|
+
(0, assertValidationError_1.assertValidationError)(!!targetLanguageCode, validation_1.PredictionsValidationErrorCode.NoTargetLanguage);
|
|
53
|
+
this.translateClient = new client_translate_1.TranslateClient({
|
|
54
|
+
region,
|
|
55
|
+
credentials,
|
|
56
|
+
customUserAgent: (0, utils_1.getAmplifyUserAgentObject)({
|
|
57
|
+
category: utils_1.Category.Predictions,
|
|
58
|
+
action: utils_1.PredictionsAction.Convert,
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
const translateTextCommand = new client_translate_1.TranslateTextCommand({
|
|
62
|
+
SourceLanguageCode: sourceLanguageCode,
|
|
63
|
+
TargetLanguageCode: targetLanguageCode,
|
|
64
|
+
Text: input.translateText?.source?.text,
|
|
65
|
+
});
|
|
66
|
+
const data = await this.translateClient.send(translateTextCommand);
|
|
67
|
+
return {
|
|
68
|
+
text: data.TranslatedText,
|
|
69
|
+
language: data.TargetLanguageCode,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async convertTextToSpeech(input) {
|
|
73
|
+
const { credentials } = await (0, core_1.fetchAuthSession)();
|
|
74
|
+
(0, assertValidationError_1.assertValidationError)(!!credentials, validation_1.PredictionsValidationErrorCode.NoCredentials);
|
|
75
|
+
(0, assertValidationError_1.assertValidationError)(!!input.textToSpeech?.source, validation_1.PredictionsValidationErrorCode.NoSource);
|
|
76
|
+
const { speechGenerator } = core_1.Amplify.getConfig().Predictions?.convert ?? {};
|
|
77
|
+
(0, assertValidationError_1.assertValidationError)(!!speechGenerator?.region, validation_1.PredictionsValidationErrorCode.NoRegion);
|
|
78
|
+
const { defaults = {}, region } = speechGenerator;
|
|
79
|
+
const { voiceId: defaultVoiceId } = defaults;
|
|
80
|
+
const voiceId = input.textToSpeech?.voiceId ?? defaultVoiceId;
|
|
81
|
+
(0, assertValidationError_1.assertValidationError)(!!voiceId, validation_1.PredictionsValidationErrorCode.NoVoiceId);
|
|
82
|
+
this.pollyClient = new client_polly_1.PollyClient({
|
|
83
|
+
region,
|
|
84
|
+
credentials,
|
|
85
|
+
customUserAgent: (0, utils_1.getAmplifyUserAgentObject)({
|
|
86
|
+
category: utils_1.Category.Predictions,
|
|
87
|
+
action: utils_1.PredictionsAction.Convert,
|
|
88
|
+
}),
|
|
89
|
+
});
|
|
90
|
+
const synthesizeSpeechCommand = new client_polly_1.SynthesizeSpeechCommand({
|
|
91
|
+
OutputFormat: 'mp3',
|
|
92
|
+
Text: input.textToSpeech?.source?.text,
|
|
93
|
+
VoiceId: voiceId,
|
|
94
|
+
TextType: 'text',
|
|
95
|
+
SampleRate: '24000',
|
|
96
|
+
// tslint:disable-next-line: align
|
|
97
|
+
});
|
|
98
|
+
const data = await this.pollyClient.send(synthesizeSpeechCommand);
|
|
99
|
+
const response = new Response(data.AudioStream);
|
|
100
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
101
|
+
const blob = new Blob([arrayBuffer], {
|
|
102
|
+
type: data.ContentType,
|
|
103
|
+
});
|
|
104
|
+
const url = URL.createObjectURL(blob);
|
|
105
|
+
return {
|
|
106
|
+
speech: { url },
|
|
107
|
+
audioStream: arrayBuffer,
|
|
108
|
+
text: input.textToSpeech?.source?.text,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
async convertSpeechToText(input) {
|
|
112
|
+
logger.debug('starting transcription..');
|
|
113
|
+
const { credentials } = await (0, core_1.fetchAuthSession)();
|
|
114
|
+
(0, assertValidationError_1.assertValidationError)(!!credentials, validation_1.PredictionsValidationErrorCode.NoCredentials);
|
|
115
|
+
const { transcription } = core_1.Amplify.getConfig().Predictions?.convert ?? {};
|
|
116
|
+
(0, assertValidationError_1.assertValidationError)(!!transcription?.region, validation_1.PredictionsValidationErrorCode.NoRegion);
|
|
117
|
+
const { defaults, region } = transcription;
|
|
118
|
+
const language = input.transcription?.language ?? defaults?.language;
|
|
119
|
+
(0, assertValidationError_1.assertValidationError)(!!language, validation_1.PredictionsValidationErrorCode.NoLanguage);
|
|
120
|
+
const source = input.transcription?.source;
|
|
121
|
+
(0, assertValidationError_1.assertValidationError)((0, types_1.isConvertBytesSource)(source), validation_1.PredictionsValidationErrorCode.InvalidSource);
|
|
122
|
+
const connection = await this.openConnectionWithTranscribe({
|
|
123
|
+
credentials,
|
|
124
|
+
region,
|
|
125
|
+
languageCode: language,
|
|
126
|
+
});
|
|
127
|
+
const fullText = await this.sendDataToTranscribe({
|
|
128
|
+
connection,
|
|
129
|
+
raw: source.bytes,
|
|
130
|
+
languageCode: language,
|
|
131
|
+
});
|
|
132
|
+
return {
|
|
133
|
+
transcription: {
|
|
134
|
+
fullText,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
static serializeDataFromTranscribe(message) {
|
|
139
|
+
let decodedMessage = '';
|
|
140
|
+
const transcribeMessage = eventBuilder.decode(buffer_1.Buffer.from(message.data));
|
|
141
|
+
const transcribeMessageJson = JSON.parse((0, util_utf8_1.toUtf8)(transcribeMessage.body));
|
|
142
|
+
if (transcribeMessage.headers[':message-type'].value === 'exception') {
|
|
143
|
+
logger.debug('exception', JSON.stringify(transcribeMessageJson.Message, null, 2));
|
|
144
|
+
throw new Error(transcribeMessageJson.Message);
|
|
145
|
+
}
|
|
146
|
+
else if (transcribeMessage.headers[':message-type'].value === 'event') {
|
|
147
|
+
if (transcribeMessageJson.Transcript.Results.length > 0) {
|
|
148
|
+
if (transcribeMessageJson.Transcript.Results[0].Alternatives.length > 0) {
|
|
149
|
+
if (transcribeMessageJson.Transcript.Results[0].Alternatives[0]
|
|
150
|
+
.Transcript.length > 0) {
|
|
151
|
+
if (transcribeMessageJson.Transcript.Results[0].IsPartial === false) {
|
|
152
|
+
decodedMessage =
|
|
153
|
+
transcribeMessageJson.Transcript.Results[0].Alternatives[0]
|
|
154
|
+
.Transcript + '\n';
|
|
155
|
+
logger.debug({ decodedMessage });
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
logger.debug({
|
|
159
|
+
transcript: transcribeMessageJson.Transcript.Results[0].Alternatives[0],
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return decodedMessage;
|
|
167
|
+
}
|
|
168
|
+
sendDataToTranscribe({ connection, raw, languageCode, }) {
|
|
169
|
+
return new Promise((res, rej) => {
|
|
170
|
+
let fullText = '';
|
|
171
|
+
connection.onmessage = message => {
|
|
172
|
+
try {
|
|
173
|
+
const decodedMessage = AmazonAIConvertPredictionsProvider.serializeDataFromTranscribe(message);
|
|
174
|
+
if (decodedMessage) {
|
|
175
|
+
fullText += decodedMessage + ' ';
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch (err) {
|
|
179
|
+
logger.debug(err);
|
|
180
|
+
rej(err);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
connection.onerror = errorEvent => {
|
|
184
|
+
logger.debug({ errorEvent });
|
|
185
|
+
rej('failed to transcribe, network error');
|
|
186
|
+
};
|
|
187
|
+
connection.onclose = closeEvent => {
|
|
188
|
+
logger.debug({ closeEvent });
|
|
189
|
+
return res(fullText.trim());
|
|
190
|
+
};
|
|
191
|
+
logger.debug({ raw });
|
|
192
|
+
if (Array.isArray(raw)) {
|
|
193
|
+
for (let i = 0; i < raw.length - 1023; i += 1024) {
|
|
194
|
+
const data = raw.slice(i, i + 1024);
|
|
195
|
+
this.sendEncodedDataToTranscribe(connection, data, languageCode);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
// If Buffer
|
|
200
|
+
this.sendEncodedDataToTranscribe(connection, raw, languageCode);
|
|
201
|
+
}
|
|
202
|
+
// sending end frame
|
|
203
|
+
const endFrameEventMessage = this.getAudioEventMessage(buffer_1.Buffer.from([]));
|
|
204
|
+
const endFrameBinary = eventBuilder.encode(endFrameEventMessage);
|
|
205
|
+
connection.send(endFrameBinary);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
sendEncodedDataToTranscribe(connection, data, languageCode) {
|
|
209
|
+
const downsampledBuffer = this.downsampleBuffer({
|
|
210
|
+
buffer: data,
|
|
211
|
+
outputSampleRate: LANGUAGES_CODE_IN_8KHZ.includes(languageCode)
|
|
212
|
+
? 8000
|
|
213
|
+
: 16000,
|
|
214
|
+
});
|
|
215
|
+
const pcmEncodedBuffer = this.pcmEncode(downsampledBuffer);
|
|
216
|
+
const audioEventMessage = this.getAudioEventMessage(buffer_1.Buffer.from(pcmEncodedBuffer));
|
|
217
|
+
const binary = eventBuilder.encode(audioEventMessage);
|
|
218
|
+
connection.send(binary);
|
|
219
|
+
}
|
|
220
|
+
getAudioEventMessage(buffer) {
|
|
221
|
+
const audioEventMessage = {
|
|
222
|
+
body: buffer,
|
|
223
|
+
headers: {
|
|
224
|
+
':message-type': {
|
|
225
|
+
type: 'string',
|
|
226
|
+
value: 'event',
|
|
227
|
+
},
|
|
228
|
+
':event-type': {
|
|
229
|
+
type: 'string',
|
|
230
|
+
value: 'AudioEvent',
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
return audioEventMessage;
|
|
235
|
+
}
|
|
236
|
+
pcmEncode(input) {
|
|
237
|
+
let offset = 0;
|
|
238
|
+
// ArrayBuffer cannot be processed using length property
|
|
239
|
+
if (input instanceof ArrayBuffer) {
|
|
240
|
+
return input;
|
|
241
|
+
}
|
|
242
|
+
const buffer = new ArrayBuffer(input.length * 2);
|
|
243
|
+
const view = new DataView(buffer);
|
|
244
|
+
for (let i = 0; i < input.length; i++, offset += 2) {
|
|
245
|
+
const s = Math.max(-1, Math.min(1, input[i]));
|
|
246
|
+
view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);
|
|
247
|
+
}
|
|
248
|
+
return buffer;
|
|
249
|
+
}
|
|
250
|
+
downsampleBuffer({ buffer, outputSampleRate = 16000, }) {
|
|
251
|
+
// Cannot process ArrayBuffer using length property
|
|
252
|
+
if (outputSampleRate === this.inputSampleRate ||
|
|
253
|
+
buffer instanceof ArrayBuffer) {
|
|
254
|
+
return buffer;
|
|
255
|
+
}
|
|
256
|
+
const sampleRateRatio = this.inputSampleRate / outputSampleRate;
|
|
257
|
+
const newLength = Math.round(buffer.length / sampleRateRatio);
|
|
258
|
+
const result = new Float32Array(newLength);
|
|
259
|
+
let offsetResult = 0;
|
|
260
|
+
let offsetBuffer = 0;
|
|
261
|
+
while (offsetResult < result.length) {
|
|
262
|
+
const nextOffsetBuffer = Math.round((offsetResult + 1) * sampleRateRatio);
|
|
263
|
+
let accum = 0, count = 0;
|
|
264
|
+
for (let i = offsetBuffer; i < nextOffsetBuffer && i < buffer.length; i++) {
|
|
265
|
+
accum += buffer[i];
|
|
266
|
+
count++;
|
|
267
|
+
}
|
|
268
|
+
result[offsetResult] = accum / count;
|
|
269
|
+
offsetResult++;
|
|
270
|
+
offsetBuffer = nextOffsetBuffer;
|
|
271
|
+
}
|
|
272
|
+
return result;
|
|
273
|
+
}
|
|
274
|
+
openConnectionWithTranscribe({ credentials, region, languageCode, }) {
|
|
275
|
+
return new Promise(async (res, rej) => {
|
|
276
|
+
const signedUrl = this.generateTranscribeUrl({
|
|
277
|
+
credentials,
|
|
278
|
+
region,
|
|
279
|
+
languageCode,
|
|
280
|
+
});
|
|
281
|
+
logger.debug('connecting...');
|
|
282
|
+
const connection = new WebSocket(signedUrl);
|
|
283
|
+
connection.binaryType = 'arraybuffer';
|
|
284
|
+
connection.onopen = () => {
|
|
285
|
+
logger.debug('connected');
|
|
286
|
+
res(connection);
|
|
287
|
+
};
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
generateTranscribeUrl({ credentials: { accessKeyId, secretAccessKey, sessionToken }, region, languageCode, }) {
|
|
291
|
+
const credentials = {
|
|
292
|
+
access_key: accessKeyId,
|
|
293
|
+
secret_key: secretAccessKey,
|
|
294
|
+
session_token: sessionToken,
|
|
295
|
+
};
|
|
296
|
+
const url = [
|
|
297
|
+
`wss://transcribestreaming.${region}.amazonaws.com:8443`,
|
|
298
|
+
'/stream-transcription-websocket?',
|
|
299
|
+
`media-encoding=pcm&`,
|
|
300
|
+
`sample-rate=${LANGUAGES_CODE_IN_8KHZ.includes(languageCode) ? '8000' : '16000'}&`,
|
|
301
|
+
`language-code=${languageCode}`,
|
|
302
|
+
].join('');
|
|
303
|
+
const signedUrl = utils_1.Signer.signUrl(url, credentials, { region, service: 'transcribe' }, 300);
|
|
304
|
+
return signedUrl;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
exports.AmazonAIConvertPredictionsProvider = AmazonAIConvertPredictionsProvider;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
private
|
|
5
|
-
private textractClient;
|
|
6
|
-
constructor();
|
|
1
|
+
import { IdentifyEntitiesInput, IdentifyEntitiesOutput, IdentifyLabelsInput, IdentifyLabelsOutput, IdentifyTextInput, IdentifyTextOutput } from '../types';
|
|
2
|
+
export declare class AmazonAIIdentifyPredictionsProvider {
|
|
3
|
+
private rekognitionClient?;
|
|
4
|
+
private textractClient?;
|
|
7
5
|
getProviderName(): string;
|
|
6
|
+
identify(input: IdentifyTextInput | IdentifyLabelsInput | IdentifyEntitiesInput): Promise<IdentifyTextOutput | IdentifyLabelsOutput | IdentifyEntitiesOutput>;
|
|
8
7
|
/**
|
|
9
8
|
* Verify user input source and converts it into source object readable by Rekognition and Textract.
|
|
10
9
|
* Note that Rekognition and Textract use the same source interface, so we need not worry about types.
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AmazonAIIdentifyPredictionsProvider = void 0;
|
|
4
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
5
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
const core_1 = require("@aws-amplify/core");
|
|
7
|
+
const utils_1 = require("@aws-amplify/core/internals/utils");
|
|
8
|
+
const storage_1 = require("@aws-amplify/storage");
|
|
9
|
+
const client_rekognition_1 = require("@aws-sdk/client-rekognition");
|
|
10
|
+
const client_textract_1 = require("@aws-sdk/client-textract");
|
|
11
|
+
const validation_1 = require("../errors/types/validation");
|
|
12
|
+
const assertValidationError_1 = require("../errors/utils/assertValidationError");
|
|
13
|
+
const types_1 = require("../types");
|
|
14
|
+
const IdentifyTextUtils_1 = require("./IdentifyTextUtils");
|
|
15
|
+
const Utils_1 = require("./Utils");
|
|
16
|
+
const logger = new core_1.ConsoleLogger('AmazonAIIdentifyPredictionsProvider');
|
|
17
|
+
class AmazonAIIdentifyPredictionsProvider {
|
|
18
|
+
getProviderName() {
|
|
19
|
+
return 'AmazonAIIdentifyPredictionsProvider';
|
|
20
|
+
}
|
|
21
|
+
identify(input) {
|
|
22
|
+
(0, assertValidationError_1.assertValidationError)((0, types_1.isValidIdentifyInput)(input), validation_1.PredictionsValidationErrorCode.InvalidInput);
|
|
23
|
+
if ((0, types_1.isIdentifyTextInput)(input)) {
|
|
24
|
+
logger.debug('identifyText');
|
|
25
|
+
return this.identifyText(input);
|
|
26
|
+
}
|
|
27
|
+
else if ((0, types_1.isIdentifyLabelsInput)(input)) {
|
|
28
|
+
logger.debug('identifyLabels');
|
|
29
|
+
return this.identifyLabels(input);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
logger.debug('identifyEntities');
|
|
33
|
+
return this.identifyEntities(input);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Verify user input source and converts it into source object readable by Rekognition and Textract.
|
|
38
|
+
* Note that Rekognition and Textract use the same source interface, so we need not worry about types.
|
|
39
|
+
* @param {IdentifySource} source - User input source that directs to the object user wants
|
|
40
|
+
* to identify (storage, file, or bytes).
|
|
41
|
+
* @return {Promise<Image>} - Promise resolving to the converted source object.
|
|
42
|
+
*/
|
|
43
|
+
configureSource(source) {
|
|
44
|
+
return new Promise((res, rej) => {
|
|
45
|
+
if ((0, types_1.isStorageSource)(source)) {
|
|
46
|
+
const storageConfig = {
|
|
47
|
+
accessLevel: source.level,
|
|
48
|
+
targetIdentityId: source.identityId,
|
|
49
|
+
};
|
|
50
|
+
(0, storage_1.getUrl)({ key: source.key, options: storageConfig })
|
|
51
|
+
.then(value => {
|
|
52
|
+
const parser = /https:\/\/([a-zA-Z0-9%\-_.]+)\.s3\.[A-Za-z0-9%\-._~]+\/([a-zA-Z0-9%\-._~/]+)\?/;
|
|
53
|
+
const parsedURL = value.url.toString().match(parser) ?? '';
|
|
54
|
+
if (parsedURL.length < 3)
|
|
55
|
+
rej('Invalid S3 key was given.');
|
|
56
|
+
res({
|
|
57
|
+
S3Object: {
|
|
58
|
+
Bucket: parsedURL[1],
|
|
59
|
+
Name: decodeURIComponent(parsedURL[2]),
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
})
|
|
63
|
+
.catch(err => rej(err));
|
|
64
|
+
}
|
|
65
|
+
else if ((0, types_1.isFileSource)(source)) {
|
|
66
|
+
(0, Utils_1.blobToArrayBuffer)(source.file)
|
|
67
|
+
.then(buffer => {
|
|
68
|
+
res({ Bytes: new Uint8Array(buffer) });
|
|
69
|
+
})
|
|
70
|
+
.catch(err => rej(err));
|
|
71
|
+
}
|
|
72
|
+
else if ((0, types_1.isIdentifyBytesSource)(source)) {
|
|
73
|
+
const bytes = source.bytes;
|
|
74
|
+
if (bytes instanceof Blob) {
|
|
75
|
+
(0, Utils_1.blobToArrayBuffer)(bytes)
|
|
76
|
+
.then(buffer => {
|
|
77
|
+
res({ Bytes: new Uint8Array(buffer) });
|
|
78
|
+
})
|
|
79
|
+
.catch(err => rej(err));
|
|
80
|
+
}
|
|
81
|
+
if (bytes instanceof ArrayBuffer || bytes instanceof Buffer) {
|
|
82
|
+
res({ Bytes: new Uint8Array(bytes) });
|
|
83
|
+
}
|
|
84
|
+
// everything else can be directly passed to Rekognition / Textract.
|
|
85
|
+
res({ Bytes: bytes });
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
rej('Input source is not configured correctly.');
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Recognize text from real-world images and documents (plain text, forms and tables). Detects text in the input
|
|
94
|
+
* image and converts it into machine-readable text.
|
|
95
|
+
* @param {IdentifySource} source - Object containing the source image and feature types to analyze.
|
|
96
|
+
* @return {Promise<IdentifyTextOutput>} - Promise resolving to object containing identified texts.
|
|
97
|
+
*/
|
|
98
|
+
async identifyText(input) {
|
|
99
|
+
const { credentials } = await (0, core_1.fetchAuthSession)();
|
|
100
|
+
(0, assertValidationError_1.assertValidationError)(!!credentials, validation_1.PredictionsValidationErrorCode.NoCredentials);
|
|
101
|
+
const { identifyText = {} } = core_1.Amplify.getConfig().Predictions?.identify ?? {};
|
|
102
|
+
const { region = '', defaults = {} } = identifyText;
|
|
103
|
+
const { format: configFormat = 'PLAIN' } = defaults;
|
|
104
|
+
this.rekognitionClient = new client_rekognition_1.RekognitionClient({
|
|
105
|
+
region,
|
|
106
|
+
credentials,
|
|
107
|
+
customUserAgent: _getPredictionsIdentifyAmplifyUserAgent(),
|
|
108
|
+
});
|
|
109
|
+
this.textractClient = new client_textract_1.TextractClient({
|
|
110
|
+
region,
|
|
111
|
+
credentials,
|
|
112
|
+
customUserAgent: _getPredictionsIdentifyAmplifyUserAgent(),
|
|
113
|
+
});
|
|
114
|
+
let inputDocument;
|
|
115
|
+
inputDocument = await this.configureSource(input.text?.source);
|
|
116
|
+
// get default value if format isn't specified in the input.
|
|
117
|
+
const format = input.text?.format ?? configFormat;
|
|
118
|
+
const featureTypes = []; // structures we want to analyze (e.g. [TABLES, FORMS]).
|
|
119
|
+
if (format === 'FORM' || format === 'ALL')
|
|
120
|
+
featureTypes.push('FORMS');
|
|
121
|
+
if (format === 'TABLE' || format === 'ALL')
|
|
122
|
+
featureTypes.push('TABLES');
|
|
123
|
+
if (featureTypes.length === 0) {
|
|
124
|
+
/**
|
|
125
|
+
* Empty featureTypes indicates that we will identify plain text. We will use rekognition (suitable
|
|
126
|
+
* for everyday images but has 50 word limit) first and see if reaches its word limit. If it does, then
|
|
127
|
+
* we call textract and use the data that identify more words.
|
|
128
|
+
*/
|
|
129
|
+
const textractParam = {
|
|
130
|
+
Document: inputDocument,
|
|
131
|
+
};
|
|
132
|
+
const rekognitionParam = {
|
|
133
|
+
Image: inputDocument,
|
|
134
|
+
};
|
|
135
|
+
const detectTextCommand = new client_rekognition_1.DetectTextCommand(rekognitionParam);
|
|
136
|
+
const rekognitionData = await this.rekognitionClient.send(detectTextCommand);
|
|
137
|
+
const rekognitionResponse = (0, IdentifyTextUtils_1.categorizeRekognitionBlocks)(rekognitionData.TextDetections);
|
|
138
|
+
if (rekognitionResponse.text.words.length < 50) {
|
|
139
|
+
// did not hit the word limit, return the data
|
|
140
|
+
return rekognitionResponse;
|
|
141
|
+
}
|
|
142
|
+
const detectDocumentTextCommand = new client_textract_1.DetectDocumentTextCommand(textractParam);
|
|
143
|
+
const { Blocks } = await this.textractClient.send(detectDocumentTextCommand);
|
|
144
|
+
if ((rekognitionData.TextDetections?.length ?? 0) > (Blocks?.length ?? 0)) {
|
|
145
|
+
return rekognitionResponse;
|
|
146
|
+
}
|
|
147
|
+
return (0, IdentifyTextUtils_1.categorizeTextractBlocks)(Blocks);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
const param = {
|
|
151
|
+
Document: inputDocument,
|
|
152
|
+
FeatureTypes: featureTypes,
|
|
153
|
+
};
|
|
154
|
+
const analyzeDocumentCommand = new client_textract_1.AnalyzeDocumentCommand(param);
|
|
155
|
+
const { Blocks } = await this.textractClient.send(analyzeDocumentCommand);
|
|
156
|
+
return (0, IdentifyTextUtils_1.categorizeTextractBlocks)(Blocks);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Identify instances of real world entities from an image and if it contains unsafe content.
|
|
161
|
+
* @param {IdentifyLabelsInput} input - Object containing the source image and entity type to identify.
|
|
162
|
+
* @return {Promise<IdentifyLabelsOutput>} - Promise resolving to an array of identified entities.
|
|
163
|
+
*/
|
|
164
|
+
async identifyLabels(input) {
|
|
165
|
+
const { credentials } = await (0, core_1.fetchAuthSession)();
|
|
166
|
+
(0, assertValidationError_1.assertValidationError)(!!credentials, validation_1.PredictionsValidationErrorCode.NoCredentials);
|
|
167
|
+
const { identifyLabels = {} } = core_1.Amplify.getConfig().Predictions?.identify ?? {};
|
|
168
|
+
const { region = '', defaults = {} } = identifyLabels;
|
|
169
|
+
const { type = 'LABELS' } = defaults;
|
|
170
|
+
this.rekognitionClient = new client_rekognition_1.RekognitionClient({
|
|
171
|
+
region,
|
|
172
|
+
credentials,
|
|
173
|
+
customUserAgent: _getPredictionsIdentifyAmplifyUserAgent(),
|
|
174
|
+
});
|
|
175
|
+
const inputImage = await this.configureSource(input.labels?.source);
|
|
176
|
+
const param = { Image: inputImage };
|
|
177
|
+
const servicePromises = [];
|
|
178
|
+
// get default argument
|
|
179
|
+
const entityType = input.labels?.type ?? type;
|
|
180
|
+
if (entityType === 'LABELS' || entityType === 'ALL') {
|
|
181
|
+
servicePromises.push(this.detectLabels(param));
|
|
182
|
+
}
|
|
183
|
+
if (entityType === 'UNSAFE' || entityType === 'ALL') {
|
|
184
|
+
servicePromises.push(this.detectModerationLabels(param));
|
|
185
|
+
}
|
|
186
|
+
return Promise.all(servicePromises).then(data => {
|
|
187
|
+
let identifyResult = {};
|
|
188
|
+
// concatenate resolved promises to a single object
|
|
189
|
+
data.forEach(val => {
|
|
190
|
+
identifyResult = { ...identifyResult, ...val };
|
|
191
|
+
});
|
|
192
|
+
return identifyResult;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Calls Rekognition.detectLabels and organizes the returned data.
|
|
197
|
+
* @param {DetectLabelsInput} param - parameter to be passed onto Rekognition
|
|
198
|
+
* @return {Promise<IdentifyLabelsOutput>} - Promise resolving to organized detectLabels response.
|
|
199
|
+
*/
|
|
200
|
+
async detectLabels(param) {
|
|
201
|
+
const detectLabelsCommand = new client_rekognition_1.DetectLabelsCommand(param);
|
|
202
|
+
const data = await this.rekognitionClient.send(detectLabelsCommand);
|
|
203
|
+
if (!data.Labels)
|
|
204
|
+
return {}; // no image was detected
|
|
205
|
+
const detectLabelData = data.Labels.map(label => {
|
|
206
|
+
const boxes = label.Instances?.map(instance => (0, Utils_1.makeCamelCase)(instance.BoundingBox)) || [];
|
|
207
|
+
return {
|
|
208
|
+
name: label.Name,
|
|
209
|
+
boundingBoxes: boxes,
|
|
210
|
+
metadata: {
|
|
211
|
+
confidence: label.Confidence,
|
|
212
|
+
parents: (0, Utils_1.makeCamelCaseArray)(label.Parents),
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
return { labels: detectLabelData };
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Calls Rekognition.detectModerationLabels and organizes the returned data.
|
|
220
|
+
* @param {Rekognition.DetectLabelsRequest} param - Parameter to be passed onto Rekognition
|
|
221
|
+
* @return {Promise<IdentifyLabelsOutput>} - Promise resolving to organized detectModerationLabels response.
|
|
222
|
+
*/
|
|
223
|
+
async detectModerationLabels(param) {
|
|
224
|
+
const detectModerationLabelsCommand = new client_rekognition_1.DetectModerationLabelsCommand(param);
|
|
225
|
+
const data = await this.rekognitionClient.send(detectModerationLabelsCommand);
|
|
226
|
+
if (data.ModerationLabels?.length !== 0) {
|
|
227
|
+
return { unsafe: 'YES' };
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
return { unsafe: 'NO' };
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Identify faces within an image that is provided as input, and match faces from a collection
|
|
235
|
+
* or identify celebrities.
|
|
236
|
+
* @param {IdentifyEntityInput} input - object containing the source image and face match options.
|
|
237
|
+
* @return {Promise<IdentifyEntityOutput>} Promise resolving to identify results.
|
|
238
|
+
*/
|
|
239
|
+
async identifyEntities(input) {
|
|
240
|
+
const { credentials } = await (0, core_1.fetchAuthSession)();
|
|
241
|
+
(0, assertValidationError_1.assertValidationError)(!!credentials, validation_1.PredictionsValidationErrorCode.NoCredentials);
|
|
242
|
+
const { identifyEntities = {} } = core_1.Amplify.getConfig().Predictions?.identify ?? {};
|
|
243
|
+
const { region = '', celebrityDetectionEnabled = false, defaults = {}, } = identifyEntities;
|
|
244
|
+
const { collectionId: collectionIdConfig = '', maxEntities: maxFacesConfig = 50, } = defaults;
|
|
245
|
+
// default arguments
|
|
246
|
+
this.rekognitionClient = new client_rekognition_1.RekognitionClient({
|
|
247
|
+
region,
|
|
248
|
+
credentials,
|
|
249
|
+
customUserAgent: _getPredictionsIdentifyAmplifyUserAgent(),
|
|
250
|
+
});
|
|
251
|
+
const inputImage = await this.configureSource(input.entities?.source);
|
|
252
|
+
const param = { Attributes: ['ALL'], Image: inputImage };
|
|
253
|
+
if ((0, types_1.isIdentifyCelebrities)(input.entities) &&
|
|
254
|
+
input.entities.celebrityDetection) {
|
|
255
|
+
(0, assertValidationError_1.assertValidationError)(celebrityDetectionEnabled, validation_1.PredictionsValidationErrorCode.CelebrityDetectionNotEnabled);
|
|
256
|
+
const recognizeCelebritiesCommand = new client_rekognition_1.RecognizeCelebritiesCommand(param);
|
|
257
|
+
const data = await this.rekognitionClient.send(recognizeCelebritiesCommand);
|
|
258
|
+
const faces = data.CelebrityFaces?.map(celebrity => ({
|
|
259
|
+
boundingBox: (0, Utils_1.makeCamelCase)(celebrity.Face?.BoundingBox),
|
|
260
|
+
landmarks: (0, Utils_1.makeCamelCaseArray)(celebrity.Face?.Landmarks),
|
|
261
|
+
metadata: {
|
|
262
|
+
...(0, Utils_1.makeCamelCase)(celebrity, ['Id', 'Name', 'Urls']),
|
|
263
|
+
pose: (0, Utils_1.makeCamelCase)(celebrity.Face?.Pose),
|
|
264
|
+
},
|
|
265
|
+
})) ?? [];
|
|
266
|
+
return { entities: faces };
|
|
267
|
+
}
|
|
268
|
+
else if ((0, types_1.isIdentifyFromCollection)(input.entities) &&
|
|
269
|
+
input.entities.collection) {
|
|
270
|
+
const { collectionId = collectionIdConfig, maxEntities: maxFaces = maxFacesConfig, } = input.entities;
|
|
271
|
+
// Concatenate additional parameters
|
|
272
|
+
const updatedParam = {
|
|
273
|
+
...param,
|
|
274
|
+
CollectionId: collectionId,
|
|
275
|
+
MaxFaces: maxFaces,
|
|
276
|
+
};
|
|
277
|
+
const searchFacesByImageCommand = new client_rekognition_1.SearchFacesByImageCommand(updatedParam);
|
|
278
|
+
const data = await this.rekognitionClient.send(searchFacesByImageCommand);
|
|
279
|
+
const faces = data.FaceMatches?.map(match => {
|
|
280
|
+
const externalImageId = match.Face?.ExternalImageId
|
|
281
|
+
? this.decodeExternalImageId(match.Face.ExternalImageId)
|
|
282
|
+
: undefined;
|
|
283
|
+
return {
|
|
284
|
+
boundingBox: (0, Utils_1.makeCamelCase)(match.Face?.BoundingBox),
|
|
285
|
+
metadata: {
|
|
286
|
+
externalImageId,
|
|
287
|
+
similarity: match.Similarity,
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
}) ?? [];
|
|
291
|
+
return { entities: faces };
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
const detectFacesCommand = new client_rekognition_1.DetectFacesCommand(param);
|
|
295
|
+
const data = await this.rekognitionClient.send(detectFacesCommand);
|
|
296
|
+
const faces = data.FaceDetails?.map(detail => {
|
|
297
|
+
// face attributes keys we want to extract from Rekognition's response
|
|
298
|
+
const attributeKeys = [
|
|
299
|
+
'Smile',
|
|
300
|
+
'Eyeglasses',
|
|
301
|
+
'Sunglasses',
|
|
302
|
+
'Gender',
|
|
303
|
+
'Beard',
|
|
304
|
+
'Mustache',
|
|
305
|
+
'EyesOpen',
|
|
306
|
+
'MouthOpen',
|
|
307
|
+
];
|
|
308
|
+
const faceAttributes = (0, Utils_1.makeCamelCase)(detail, attributeKeys);
|
|
309
|
+
faceAttributes.emotions = detail.Emotions?.map(emotion => emotion.Type);
|
|
310
|
+
return {
|
|
311
|
+
boundingBox: (0, Utils_1.makeCamelCase)(detail.BoundingBox),
|
|
312
|
+
landmarks: (0, Utils_1.makeCamelCaseArray)(detail.Landmarks),
|
|
313
|
+
ageRange: (0, Utils_1.makeCamelCase)(detail.AgeRange),
|
|
314
|
+
attributes: faceAttributes,
|
|
315
|
+
metadata: {
|
|
316
|
+
confidence: detail.Confidence,
|
|
317
|
+
pose: (0, Utils_1.makeCamelCase)(detail.Pose),
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
}) ?? [];
|
|
321
|
+
return { entities: faces };
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
decodeExternalImageId(externalImageId) {
|
|
325
|
+
return ('' + externalImageId).replace(/::/g, '/');
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
exports.AmazonAIIdentifyPredictionsProvider = AmazonAIIdentifyPredictionsProvider;
|
|
329
|
+
function _getPredictionsIdentifyAmplifyUserAgent() {
|
|
330
|
+
return (0, utils_1.getAmplifyUserAgentObject)({
|
|
331
|
+
category: utils_1.Category.Predictions,
|
|
332
|
+
action: utils_1.PredictionsAction.Identify,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { AbstractInterpretPredictionsProvider } from '../types/Providers';
|
|
2
1
|
import { InterpretTextInput, InterpretTextOutput } from '../types';
|
|
3
|
-
export declare class AmazonAIInterpretPredictionsProvider
|
|
4
|
-
private comprehendClient
|
|
5
|
-
constructor();
|
|
2
|
+
export declare class AmazonAIInterpretPredictionsProvider {
|
|
3
|
+
private comprehendClient?;
|
|
6
4
|
getProviderName(): string;
|
|
5
|
+
interpret(input: InterpretTextInput): Promise<InterpretTextOutput>;
|
|
7
6
|
interpretText(input: InterpretTextInput): Promise<InterpretTextOutput>;
|
|
8
7
|
private detectKeyPhrases;
|
|
9
8
|
private detectSyntax;
|