@mulingai-npm/redis 3.2.2 → 3.4.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.
|
@@ -5,6 +5,7 @@ const mulingstream_chunk_manager_1 = require("../managers/mulingstream-chunk-man
|
|
|
5
5
|
const defaults = {
|
|
6
6
|
chunkId: false,
|
|
7
7
|
chunkNumber: true,
|
|
8
|
+
audioFilePath: true,
|
|
8
9
|
roomId: false,
|
|
9
10
|
processLength: false,
|
|
10
11
|
language: false,
|
|
@@ -61,6 +62,8 @@ class MulingstreamChunkLogger extends mulingstream_chunk_manager_1.MulingstreamC
|
|
|
61
62
|
out.roomId = chunk.roomId;
|
|
62
63
|
if (o.chunkNumber)
|
|
63
64
|
out.chunkNumber = chunk.chunkNumber;
|
|
65
|
+
if (o.audioFilePath)
|
|
66
|
+
out.audioFilePath = chunk.audioChunk.audioFilePath;
|
|
64
67
|
if (o.processLength)
|
|
65
68
|
out.processLength = Date.now() - chunk.createdAt + 'ms';
|
|
66
69
|
if (o.language)
|
|
@@ -22,8 +22,7 @@ export type MulingstreamChunkData = {
|
|
|
22
22
|
duration: number;
|
|
23
23
|
isFirst: boolean;
|
|
24
24
|
isLast: boolean;
|
|
25
|
-
|
|
26
|
-
processingStart: number;
|
|
25
|
+
audioFilePath: string;
|
|
27
26
|
};
|
|
28
27
|
stt: {
|
|
29
28
|
[service: string]: {
|
|
@@ -43,7 +42,6 @@ export type MulingstreamChunkData = {
|
|
|
43
42
|
ttsAudioPath: string;
|
|
44
43
|
status: StepStatus;
|
|
45
44
|
isEmitted: boolean;
|
|
46
|
-
totalCheck: number;
|
|
47
45
|
};
|
|
48
46
|
};
|
|
49
47
|
};
|
|
@@ -70,46 +68,44 @@ export declare class MulingstreamChunkManager {
|
|
|
70
68
|
duration: number;
|
|
71
69
|
isFirst: boolean;
|
|
72
70
|
isLast: boolean;
|
|
73
|
-
theme: string;
|
|
74
71
|
sttProviders: SttProvider[];
|
|
75
72
|
targetLanguages: string[];
|
|
76
73
|
shortCodeTargetLanguages: string[];
|
|
77
|
-
}): Promise<
|
|
74
|
+
}): Promise<MulingstreamChunkData>;
|
|
78
75
|
private getChunkId;
|
|
79
76
|
getMulingstreamChunkById(roomId: string, n: number): Promise<MulingstreamChunkData>;
|
|
80
77
|
private withChunk;
|
|
78
|
+
updateAudioFilePath(roomId: string, chunkNumber: number, audioFilePath: string): Promise<MulingstreamChunkData | null>;
|
|
81
79
|
updateStt(roomId: string, n: number, service: SttService, opt: {
|
|
82
80
|
transcription?: string;
|
|
83
81
|
sttStatus?: StepStatus;
|
|
84
|
-
}): Promise<
|
|
82
|
+
}): Promise<MulingstreamChunkData | null>;
|
|
85
83
|
updateSttObject(roomId: string, n: number, newStt: Record<string, {
|
|
86
84
|
transcription: string;
|
|
87
85
|
model?: string;
|
|
88
86
|
status: StepStatus;
|
|
89
|
-
}>): Promise<
|
|
90
|
-
discardStt(roomId: string, n: number): Promise<
|
|
87
|
+
}>): Promise<MulingstreamChunkData | null>;
|
|
88
|
+
discardStt(roomId: string, n: number): Promise<MulingstreamChunkData | null>;
|
|
91
89
|
updateFinalTranscription(roomId: string, n: number, opt: {
|
|
92
90
|
transcription?: string;
|
|
93
91
|
sttStatus?: StepStatus;
|
|
94
|
-
}): Promise<MulingstreamChunkData>;
|
|
95
|
-
discardPostStt(roomId: string, n: number): Promise<
|
|
96
|
-
discardLanguage(roomId: string, n: number, lang: string): Promise<
|
|
92
|
+
}): Promise<MulingstreamChunkData | null>;
|
|
93
|
+
discardPostStt(roomId: string, n: number): Promise<MulingstreamChunkData | null>;
|
|
94
|
+
discardLanguage(roomId: string, n: number, lang: string): Promise<MulingstreamChunkData | null>;
|
|
97
95
|
discardLanguages(roomId: string, n: number, opt: {
|
|
98
96
|
translation?: string[];
|
|
99
97
|
tts?: string[];
|
|
100
|
-
}): Promise<MulingstreamChunkData>;
|
|
98
|
+
}): Promise<MulingstreamChunkData | null>;
|
|
101
99
|
updateTranslation(roomId: string, n: number, lang: string, opt: {
|
|
102
100
|
translation?: string;
|
|
103
101
|
status?: StepStatus;
|
|
104
|
-
}): Promise<MulingstreamChunkData>;
|
|
105
|
-
updateTranslationInBulk(roomId: string, n: number, dict: Record<string, string>, status?: StepStatus): Promise<MulingstreamChunkData>;
|
|
102
|
+
}): Promise<MulingstreamChunkData | null>;
|
|
103
|
+
updateTranslationInBulk(roomId: string, n: number, dict: Record<string, string>, status?: StepStatus): Promise<MulingstreamChunkData | null>;
|
|
106
104
|
updateTts(roomId: string, n: number, lang: string, opt: {
|
|
107
105
|
ttsAudioPath?: string;
|
|
108
106
|
status?: StepStatus;
|
|
109
107
|
isEmitted?: boolean;
|
|
110
|
-
|
|
111
|
-
}): Promise<MulingstreamChunkData>;
|
|
112
|
-
increaseTotalCheck(roomId: string, n: number, lang: string): Promise<MulingstreamChunkData>;
|
|
108
|
+
}): Promise<MulingstreamChunkData | null>;
|
|
113
109
|
areTranslationsProcessed(roomId: string, n: number): Promise<boolean>;
|
|
114
110
|
getAllReadyTts(roomId: string, lang: string): Promise<MulingstreamChunkData[]>;
|
|
115
111
|
}
|
|
@@ -2,19 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MulingstreamChunkManager = void 0;
|
|
4
4
|
const uuid_1 = require("uuid");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
/* -------------------------------------------------------------------------- */
|
|
8
|
-
const EXPIRATION = 12 * 60 * 60; // 12 h
|
|
9
|
-
const ROOM_ARRAY_LENGTH = 50; // keep last 50 chunks
|
|
10
|
-
/* -------------------------------------------------------------------------- */
|
|
11
|
-
/* Main class */
|
|
12
|
-
/* -------------------------------------------------------------------------- */
|
|
5
|
+
const EXPIRATION = 12 * 60 * 60;
|
|
6
|
+
const ROOM_ARRAY_LENGTH = 50;
|
|
13
7
|
class MulingstreamChunkManager {
|
|
14
8
|
constructor(redisClient) {
|
|
15
9
|
this.redisClient = redisClient;
|
|
16
10
|
}
|
|
17
|
-
/* ----------------------------- key helpers ----------------------------- */
|
|
18
11
|
roomZsetKey(roomId) {
|
|
19
12
|
return `room:${roomId}:chunks`;
|
|
20
13
|
}
|
|
@@ -24,7 +17,6 @@ class MulingstreamChunkManager {
|
|
|
24
17
|
generateChunkId(roomId, chunkNumber) {
|
|
25
18
|
return `[${roomId}]-[${chunkNumber}]-[${(0, uuid_1.v4)()}]`;
|
|
26
19
|
}
|
|
27
|
-
/* --------------------------- (de)serialization -------------------------- */
|
|
28
20
|
serialize(value) {
|
|
29
21
|
return JSON.stringify(value);
|
|
30
22
|
}
|
|
@@ -49,14 +41,9 @@ class MulingstreamChunkManager {
|
|
|
49
41
|
tts: this.deserialize(h.tts)
|
|
50
42
|
};
|
|
51
43
|
}
|
|
52
|
-
/* ------------------------------ timeouts ------------------------------- */
|
|
53
44
|
getTimeout(start, end) {
|
|
54
|
-
return
|
|
45
|
+
return 25000;
|
|
55
46
|
}
|
|
56
|
-
/* ---------------------------------------------------------------------- */
|
|
57
|
-
/* Public API (same) */
|
|
58
|
-
/* ---------------------------------------------------------------------- */
|
|
59
|
-
/* Room helpers ---------------------------------------------------------- */
|
|
60
47
|
async initRoom(roomId) {
|
|
61
48
|
const exists = await this.redisClient.exists(this.roomZsetKey(roomId));
|
|
62
49
|
if (exists)
|
|
@@ -82,10 +69,9 @@ class MulingstreamChunkManager {
|
|
|
82
69
|
getRoomById(roomId) {
|
|
83
70
|
return this.getMulingstreamChunksByRoom(roomId);
|
|
84
71
|
}
|
|
85
|
-
/* ------------------------- chunk insertion ---------------------------- */
|
|
86
72
|
async addMulingstreamChunk(params) {
|
|
87
73
|
var _a, _b;
|
|
88
|
-
const { roomId, chunkNumber, language, start, end, duration, isFirst, isLast,
|
|
74
|
+
const { roomId, chunkNumber, language, start, end, duration, isFirst, isLast, sttProviders, targetLanguages, shortCodeTargetLanguages } = params;
|
|
89
75
|
if (chunkNumber === 1) {
|
|
90
76
|
const old = await this.redisClient.zrange(this.roomZsetKey(roomId), 0, -1);
|
|
91
77
|
if (old.length) {
|
|
@@ -105,15 +91,32 @@ class MulingstreamChunkManager {
|
|
|
105
91
|
}
|
|
106
92
|
}
|
|
107
93
|
const chunkId = this.generateChunkId(roomId, chunkNumber);
|
|
108
|
-
const audioChunk = { start, end, duration, isFirst, isLast,
|
|
94
|
+
const audioChunk = { start, end, duration, isFirst, isLast, audioFilePath: '' };
|
|
109
95
|
const stt = {};
|
|
110
96
|
sttProviders.forEach((p) => (stt[p.service] = { transcription: '', model: p.model, status: 'INIT' }));
|
|
111
97
|
const translation = {};
|
|
112
98
|
const tts = {};
|
|
113
99
|
shortCodeTargetLanguages.forEach((l) => {
|
|
114
100
|
translation[l] = { translation: '', status: 'INIT' };
|
|
115
|
-
tts[l] = { ttsAudioPath: '', status: 'INIT', isEmitted: false
|
|
101
|
+
tts[l] = { ttsAudioPath: '', status: 'INIT', isEmitted: false };
|
|
116
102
|
});
|
|
103
|
+
const createdAt = Date.now();
|
|
104
|
+
const chunk = {
|
|
105
|
+
chunkId,
|
|
106
|
+
roomId,
|
|
107
|
+
chunkNumber,
|
|
108
|
+
language,
|
|
109
|
+
sttProviders,
|
|
110
|
+
targetLanguages,
|
|
111
|
+
shortCodeTargetLanguages,
|
|
112
|
+
finalTranscription: '',
|
|
113
|
+
sttStatus: 'INIT',
|
|
114
|
+
createdAt,
|
|
115
|
+
audioChunk,
|
|
116
|
+
stt,
|
|
117
|
+
translation,
|
|
118
|
+
tts
|
|
119
|
+
};
|
|
117
120
|
const hash = {
|
|
118
121
|
chunkId,
|
|
119
122
|
roomId,
|
|
@@ -124,7 +127,7 @@ class MulingstreamChunkManager {
|
|
|
124
127
|
shortCodeTargetLanguages: this.serialize(shortCodeTargetLanguages),
|
|
125
128
|
finalTranscription: '',
|
|
126
129
|
sttStatus: 'INIT',
|
|
127
|
-
createdAt: String(
|
|
130
|
+
createdAt: String(createdAt),
|
|
128
131
|
audioChunk: this.serialize(audioChunk),
|
|
129
132
|
stt: this.serialize(stt),
|
|
130
133
|
translation: this.serialize(translation),
|
|
@@ -147,8 +150,8 @@ class MulingstreamChunkManager {
|
|
|
147
150
|
oldIds.forEach((cid) => trim.unlink(this.chunkHashKey(cid)));
|
|
148
151
|
await trim.exec();
|
|
149
152
|
}
|
|
153
|
+
return chunk;
|
|
150
154
|
}
|
|
151
|
-
/* --------------------------- helper lookup ---------------------------- */
|
|
152
155
|
async getChunkId(roomId, n) {
|
|
153
156
|
const ids = await this.redisClient.zrangebyscore(this.roomZsetKey(roomId), n, n);
|
|
154
157
|
return ids.length ? ids[0] : null;
|
|
@@ -160,8 +163,6 @@ class MulingstreamChunkManager {
|
|
|
160
163
|
const raw = await this.redisClient.hgetall(this.chunkHashKey(cid));
|
|
161
164
|
return raw.chunkId ? this.hashToChunk(raw) : null;
|
|
162
165
|
}
|
|
163
|
-
/* ------------------------------ Updaters ------------------------------ */
|
|
164
|
-
/* helper to fetch-mutate-save one chunk */
|
|
165
166
|
async withChunk(roomId, n, fn) {
|
|
166
167
|
const cid = await this.getChunkId(roomId, n);
|
|
167
168
|
if (!cid)
|
|
@@ -171,46 +172,49 @@ class MulingstreamChunkManager {
|
|
|
171
172
|
if (!raw.chunkId)
|
|
172
173
|
return null;
|
|
173
174
|
const chunk = this.hashToChunk(raw);
|
|
174
|
-
|
|
175
|
+
await fn(chunk);
|
|
175
176
|
const p = this.redisClient.pipeline();
|
|
176
177
|
p.hset(key, {
|
|
177
178
|
finalTranscription: chunk.finalTranscription,
|
|
178
179
|
sttStatus: chunk.sttStatus,
|
|
179
180
|
stt: this.serialize(chunk.stt),
|
|
180
181
|
translation: this.serialize(chunk.translation),
|
|
181
|
-
tts: this.serialize(chunk.tts)
|
|
182
|
+
tts: this.serialize(chunk.tts),
|
|
183
|
+
audioChunk: this.serialize(chunk.audioChunk)
|
|
182
184
|
});
|
|
183
185
|
p.expire(key, EXPIRATION);
|
|
184
186
|
await p.exec();
|
|
185
|
-
return
|
|
187
|
+
return chunk;
|
|
188
|
+
}
|
|
189
|
+
async updateAudioFilePath(roomId, chunkNumber, audioFilePath) {
|
|
190
|
+
return this.withChunk(roomId, chunkNumber, (chunk) => {
|
|
191
|
+
chunk.audioChunk.audioFilePath = audioFilePath;
|
|
192
|
+
});
|
|
186
193
|
}
|
|
187
194
|
async updateStt(roomId, n, service, opt) {
|
|
188
|
-
return
|
|
195
|
+
return this.withChunk(roomId, n, (c) => {
|
|
189
196
|
if (!c.stt[service])
|
|
190
|
-
return
|
|
197
|
+
return;
|
|
191
198
|
if (opt.transcription !== undefined)
|
|
192
199
|
c.stt[service].transcription = opt.transcription;
|
|
193
200
|
if (opt.sttStatus !== undefined)
|
|
194
201
|
c.stt[service].status = opt.sttStatus;
|
|
195
|
-
|
|
196
|
-
})) === true);
|
|
202
|
+
});
|
|
197
203
|
}
|
|
198
204
|
async updateSttObject(roomId, n, newStt) {
|
|
199
|
-
return
|
|
205
|
+
return this.withChunk(roomId, n, (c) => {
|
|
200
206
|
c.stt = newStt;
|
|
201
|
-
|
|
202
|
-
})) === true);
|
|
207
|
+
});
|
|
203
208
|
}
|
|
204
209
|
async discardStt(roomId, n) {
|
|
205
|
-
return
|
|
210
|
+
return this.withChunk(roomId, n, (c) => {
|
|
206
211
|
Object.keys(c.stt).forEach((p) => {
|
|
207
212
|
c.stt[p].transcription = '';
|
|
208
213
|
c.stt[p].status = 'DISCARDED';
|
|
209
214
|
});
|
|
210
215
|
c.finalTranscription = '';
|
|
211
216
|
c.sttStatus = 'DISCARDED';
|
|
212
|
-
|
|
213
|
-
})) === true);
|
|
217
|
+
});
|
|
214
218
|
}
|
|
215
219
|
async updateFinalTranscription(roomId, n, opt) {
|
|
216
220
|
return this.withChunk(roomId, n, (c) => {
|
|
@@ -218,24 +222,21 @@ class MulingstreamChunkManager {
|
|
|
218
222
|
c.finalTranscription = opt.transcription;
|
|
219
223
|
if (opt.sttStatus !== undefined)
|
|
220
224
|
c.sttStatus = opt.sttStatus;
|
|
221
|
-
return c;
|
|
222
225
|
});
|
|
223
226
|
}
|
|
224
227
|
async discardPostStt(roomId, n) {
|
|
225
|
-
return
|
|
228
|
+
return this.withChunk(roomId, n, (c) => {
|
|
226
229
|
Object.values(c.translation).forEach((t) => (t.status = 'DISCARDED'));
|
|
227
230
|
Object.values(c.tts).forEach((t) => (t.status = 'DISCARDED'));
|
|
228
|
-
|
|
229
|
-
})) === true);
|
|
231
|
+
});
|
|
230
232
|
}
|
|
231
233
|
async discardLanguage(roomId, n, lang) {
|
|
232
|
-
return
|
|
234
|
+
return this.withChunk(roomId, n, (c) => {
|
|
233
235
|
if (c.translation[lang])
|
|
234
236
|
c.translation[lang].status = 'DISCARDED';
|
|
235
237
|
if (c.tts[lang])
|
|
236
238
|
c.tts[lang].status = 'DISCARDED';
|
|
237
|
-
|
|
238
|
-
})) === true);
|
|
239
|
+
});
|
|
239
240
|
}
|
|
240
241
|
async discardLanguages(roomId, n, opt) {
|
|
241
242
|
return this.withChunk(roomId, n, (c) => {
|
|
@@ -250,19 +251,17 @@ class MulingstreamChunkManager {
|
|
|
250
251
|
if (e && e.status === 'INIT')
|
|
251
252
|
e.status = 'DISCARDED';
|
|
252
253
|
});
|
|
253
|
-
return c;
|
|
254
254
|
});
|
|
255
255
|
}
|
|
256
256
|
async updateTranslation(roomId, n, lang, opt) {
|
|
257
257
|
return this.withChunk(roomId, n, (c) => {
|
|
258
258
|
const e = c.translation[lang];
|
|
259
259
|
if (!e)
|
|
260
|
-
return
|
|
260
|
+
return;
|
|
261
261
|
if (opt.translation !== undefined)
|
|
262
262
|
e.translation = opt.translation;
|
|
263
263
|
if (opt.status !== undefined)
|
|
264
264
|
e.status = opt.status;
|
|
265
|
-
return c;
|
|
266
265
|
});
|
|
267
266
|
}
|
|
268
267
|
async updateTranslationInBulk(roomId, n, dict, status = 'READY') {
|
|
@@ -273,38 +272,25 @@ class MulingstreamChunkManager {
|
|
|
273
272
|
c.translation[l].translation = txt;
|
|
274
273
|
c.translation[l].status = status;
|
|
275
274
|
});
|
|
276
|
-
return c;
|
|
277
275
|
});
|
|
278
276
|
}
|
|
279
277
|
async updateTts(roomId, n, lang, opt) {
|
|
280
278
|
return this.withChunk(roomId, n, (c) => {
|
|
281
279
|
const e = c.tts[lang];
|
|
282
280
|
if (!e)
|
|
283
|
-
return
|
|
281
|
+
return;
|
|
284
282
|
if (opt.ttsAudioPath !== undefined)
|
|
285
283
|
e.ttsAudioPath = opt.ttsAudioPath;
|
|
286
284
|
if (opt.status !== undefined)
|
|
287
285
|
e.status = opt.status;
|
|
288
286
|
if (opt.isEmitted !== undefined)
|
|
289
287
|
e.isEmitted = opt.isEmitted;
|
|
290
|
-
if (opt.totalCheck !== undefined)
|
|
291
|
-
e.totalCheck = opt.totalCheck;
|
|
292
|
-
return c;
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
async increaseTotalCheck(roomId, n, lang) {
|
|
296
|
-
return this.withChunk(roomId, n, (c) => {
|
|
297
|
-
if (!c.tts[lang])
|
|
298
|
-
return null;
|
|
299
|
-
c.tts[lang].totalCheck += 1;
|
|
300
|
-
return c;
|
|
301
288
|
});
|
|
302
289
|
}
|
|
303
290
|
async areTranslationsProcessed(roomId, n) {
|
|
304
291
|
const c = await this.getMulingstreamChunkById(roomId, n);
|
|
305
292
|
return !!c && Object.values(c.translation).every((t) => t.status !== 'INIT');
|
|
306
293
|
}
|
|
307
|
-
/* -------------------------- READY-TTS sequence ------------------------- */
|
|
308
294
|
async getAllReadyTts(roomId, lang) {
|
|
309
295
|
var _a;
|
|
310
296
|
const chunks = (_a = (await this.getMulingstreamChunksByRoom(roomId))) !== null && _a !== void 0 ? _a : [];
|