@mulingai-npm/redis 2.3.1 → 2.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.
- package/dist/enums/redis-database.d.ts +5 -4
- package/dist/enums/redis-database.js +9 -8
- package/dist/managers/mulingstream-chunk-manager.d.ts +107 -107
- package/dist/managers/mulingstream-chunk-manager.js +242 -242
- package/dist/managers/mulingstream-listener-manager.d.ts +29 -29
- package/dist/managers/mulingstream-listener-manager.js +169 -169
- package/dist/managers/mulingstream-speaker-manager.d.ts +28 -0
- package/dist/managers/mulingstream-speaker-manager.js +107 -0
- package/dist/redis-client.d.ts +28 -28
- package/dist/redis-client.js +95 -95
- package/package.json +34 -34
|
@@ -1,242 +1,242 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MulingstreamChunkManager = void 0;
|
|
4
|
-
const EXPIRATION = 12 * 60 * 60; // 12 hours in seconds
|
|
5
|
-
const ROOM_ARRAY_LENGTH = 50; // keep only the last 5 elements
|
|
6
|
-
class MulingstreamChunkManager {
|
|
7
|
-
constructor(redisClient) {
|
|
8
|
-
this.redisClient = redisClient;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Initializes a room in Redis as an empty JSON array.
|
|
12
|
-
* If the key [roomId] already exists, we do NOT overwrite it.
|
|
13
|
-
* Returns true if room was created, false if room already existed.
|
|
14
|
-
*/
|
|
15
|
-
async initRoom(roomId) {
|
|
16
|
-
// Check if the key already exists (JSON.GET)
|
|
17
|
-
const isRoomExisting = await this.redisClient.jsonGet(`[${roomId}]`, '.');
|
|
18
|
-
if (isRoomExisting !== null) {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
// Create an empty array at the root
|
|
22
|
-
await this.redisClient.jsonSet(`[${roomId}]`, '.', []);
|
|
23
|
-
await this.redisClient.expire(`[${roomId}]`, EXPIRATION);
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Returns all rooms. This is naive if you store many other keys in Redis,
|
|
28
|
-
* because we search keys for pattern "[*]".
|
|
29
|
-
* Adjust as needed if you have a separate naming prefix.
|
|
30
|
-
*/
|
|
31
|
-
async getRooms() {
|
|
32
|
-
// e.g., if we store everything as [foo], [bar], etc., we do:
|
|
33
|
-
const rooms = await this.redisClient.keys('\\[*\\]');
|
|
34
|
-
// This returns the raw keys, e.g. ['[myRoom]', '[anotherRoom]']
|
|
35
|
-
// We might want to strip off the brackets:
|
|
36
|
-
return rooms.map((k) => k.replace(/^\[|\]$/g, ''));
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Returns the entire array of chunks for the given roomId,
|
|
40
|
-
* or null if the room doesn't exist in Redis.
|
|
41
|
-
*/
|
|
42
|
-
async getMulingstreamChunksByRoom(roomId) {
|
|
43
|
-
// JSON.GET [roomId] .
|
|
44
|
-
const chunks = await this.redisClient.jsonGet(`[${roomId}]`, '.');
|
|
45
|
-
if (chunks === null) {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
return chunks;
|
|
49
|
-
}
|
|
50
|
-
async getRoomById(roomId) {
|
|
51
|
-
return this.getMulingstreamChunksByRoom(roomId);
|
|
52
|
-
}
|
|
53
|
-
async addMulingstreamChunk(params) {
|
|
54
|
-
var _a;
|
|
55
|
-
const { roomId, chunkNumber, language, start, end, duration, isFirst, isLast, theme, sttProviders, targetLanguages, shortCodeTargetLanguages } = params;
|
|
56
|
-
const audioChunk = {
|
|
57
|
-
start,
|
|
58
|
-
end,
|
|
59
|
-
duration,
|
|
60
|
-
isFirst,
|
|
61
|
-
isLast,
|
|
62
|
-
theme,
|
|
63
|
-
processingStart: Date.now()
|
|
64
|
-
};
|
|
65
|
-
const stt = {};
|
|
66
|
-
for (const sttProvider of sttProviders) {
|
|
67
|
-
stt[sttProvider] = {
|
|
68
|
-
transcription: '',
|
|
69
|
-
status: 'INIT'
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
const translation = {};
|
|
73
|
-
const tts = {};
|
|
74
|
-
for (const lang of shortCodeTargetLanguages) {
|
|
75
|
-
translation[lang] = {
|
|
76
|
-
translation: '',
|
|
77
|
-
status: 'INIT'
|
|
78
|
-
};
|
|
79
|
-
tts[lang] = {
|
|
80
|
-
ttsAudioPath: '',
|
|
81
|
-
status: 'INIT',
|
|
82
|
-
isEmitted: false
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
const newChunk = {
|
|
86
|
-
roomId,
|
|
87
|
-
chunkNumber,
|
|
88
|
-
language,
|
|
89
|
-
sttProviders,
|
|
90
|
-
targetLanguages,
|
|
91
|
-
shortCodeTargetLanguages,
|
|
92
|
-
finalTranscription: '',
|
|
93
|
-
sttStatus: 'INIT',
|
|
94
|
-
audioChunk,
|
|
95
|
-
stt,
|
|
96
|
-
translation,
|
|
97
|
-
tts
|
|
98
|
-
};
|
|
99
|
-
const chunks = (_a = (await this.redisClient.jsonGet(`[${roomId}]`, '.'))) !== null && _a !== void 0 ? _a : [];
|
|
100
|
-
const idx = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
101
|
-
if (idx !== -1) {
|
|
102
|
-
chunks[idx] = newChunk;
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
chunks.push(newChunk);
|
|
106
|
-
if (chunks.length > ROOM_ARRAY_LENGTH) {
|
|
107
|
-
chunks.shift();
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
111
|
-
await this.redisClient.expire(`[${roomId}]`, EXPIRATION);
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Given roomId and chunkNumber, return the single chunk from the array
|
|
115
|
-
* or null if not found.
|
|
116
|
-
*/
|
|
117
|
-
async getMulingstreamChunkById(roomId, chunkNumber) {
|
|
118
|
-
// Retrieve the entire array
|
|
119
|
-
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
120
|
-
if (!chunks)
|
|
121
|
-
return null;
|
|
122
|
-
// Find by chunkNumber
|
|
123
|
-
const chunk = chunks.find((c) => c.chunkNumber === chunkNumber);
|
|
124
|
-
return chunk || null;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Update STT fields for a given chunk.
|
|
128
|
-
* If transcription or sttStatus is null, skip that field.
|
|
129
|
-
*/
|
|
130
|
-
async updateStt(roomId, chunkNumber, sttProvider, options) {
|
|
131
|
-
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
132
|
-
if (!chunks)
|
|
133
|
-
return false;
|
|
134
|
-
// Find the chunk
|
|
135
|
-
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
136
|
-
if (chunkIndex === -1)
|
|
137
|
-
return false;
|
|
138
|
-
const chunk = chunks[chunkIndex];
|
|
139
|
-
// If this stt provider doesn't exist, ignore
|
|
140
|
-
if (!chunk.stt[sttProvider])
|
|
141
|
-
return false;
|
|
142
|
-
// Update
|
|
143
|
-
if (options.transcription != null) {
|
|
144
|
-
chunk.stt[sttProvider].transcription = options.transcription;
|
|
145
|
-
}
|
|
146
|
-
if (options.sttStatus != null) {
|
|
147
|
-
chunk.stt[sttProvider].status = options.sttStatus;
|
|
148
|
-
}
|
|
149
|
-
// Write back
|
|
150
|
-
chunks[chunkIndex] = chunk;
|
|
151
|
-
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
152
|
-
return true;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Update the final transcription field for a chunk.
|
|
156
|
-
*/
|
|
157
|
-
async updateFinalTranscription(roomId, chunkNumber, transcription, sttStatus) {
|
|
158
|
-
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
159
|
-
if (!chunks)
|
|
160
|
-
return false;
|
|
161
|
-
// Find the chunk
|
|
162
|
-
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
163
|
-
if (chunkIndex === -1)
|
|
164
|
-
return false;
|
|
165
|
-
chunks[chunkIndex].finalTranscription = transcription;
|
|
166
|
-
chunks[chunkIndex].sttStatus = sttStatus;
|
|
167
|
-
// Write back
|
|
168
|
-
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
169
|
-
return true;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Discards all post-STT steps for a given chunk:
|
|
173
|
-
* sets all translation[].status & tts[].status to "DISCARDED".
|
|
174
|
-
*/
|
|
175
|
-
async discardPostStt(roomId, chunkNumber) {
|
|
176
|
-
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
177
|
-
if (!chunks)
|
|
178
|
-
return false;
|
|
179
|
-
// Find chunk
|
|
180
|
-
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
181
|
-
if (chunkIndex === -1)
|
|
182
|
-
return false;
|
|
183
|
-
// Discard translation & TTS statuses
|
|
184
|
-
const chunk = chunks[chunkIndex];
|
|
185
|
-
for (const lang of Object.keys(chunk.translation)) {
|
|
186
|
-
chunk.translation[lang].status = 'DISCARDED';
|
|
187
|
-
}
|
|
188
|
-
for (const lang of Object.keys(chunk.tts)) {
|
|
189
|
-
chunk.tts[lang].status = 'DISCARDED';
|
|
190
|
-
}
|
|
191
|
-
chunks[chunkIndex] = chunk;
|
|
192
|
-
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
193
|
-
return true;
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Discards a specific language in both translation and tts for a chunk.
|
|
197
|
-
*/
|
|
198
|
-
async discardLanguage(roomId, chunkNumber, language) {
|
|
199
|
-
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
200
|
-
if (!chunks)
|
|
201
|
-
return false;
|
|
202
|
-
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
203
|
-
if (chunkIndex === -1)
|
|
204
|
-
return false;
|
|
205
|
-
const chunk = chunks[chunkIndex];
|
|
206
|
-
if (chunk.translation[language]) {
|
|
207
|
-
chunk.translation[language].status = 'DISCARDED';
|
|
208
|
-
}
|
|
209
|
-
if (chunk.tts[language]) {
|
|
210
|
-
chunk.tts[language].status = 'DISCARDED';
|
|
211
|
-
}
|
|
212
|
-
chunks[chunkIndex] = chunk;
|
|
213
|
-
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
214
|
-
return true;
|
|
215
|
-
}
|
|
216
|
-
async updateTranslation(roomId, chunkNumber, language, options) {
|
|
217
|
-
// Fetch all chunks for this room
|
|
218
|
-
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
219
|
-
if (!chunks)
|
|
220
|
-
return false;
|
|
221
|
-
// Locate the target chunk
|
|
222
|
-
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
223
|
-
if (chunkIndex === -1)
|
|
224
|
-
return false;
|
|
225
|
-
const chunk = chunks[chunkIndex];
|
|
226
|
-
// Make sure the requested language exists in this chunk
|
|
227
|
-
if (!chunk.translation[language]) {
|
|
228
|
-
return false;
|
|
229
|
-
}
|
|
230
|
-
if (options.translation !== undefined) {
|
|
231
|
-
chunk.translation[language].translation = options.translation;
|
|
232
|
-
}
|
|
233
|
-
if (options.status !== undefined) {
|
|
234
|
-
chunk.translation[language].status = options.status;
|
|
235
|
-
}
|
|
236
|
-
// Persist the whole array back to Redis
|
|
237
|
-
chunks[chunkIndex] = chunk;
|
|
238
|
-
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
239
|
-
return true;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
exports.MulingstreamChunkManager = MulingstreamChunkManager;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MulingstreamChunkManager = void 0;
|
|
4
|
+
const EXPIRATION = 12 * 60 * 60; // 12 hours in seconds
|
|
5
|
+
const ROOM_ARRAY_LENGTH = 50; // keep only the last 5 elements
|
|
6
|
+
class MulingstreamChunkManager {
|
|
7
|
+
constructor(redisClient) {
|
|
8
|
+
this.redisClient = redisClient;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Initializes a room in Redis as an empty JSON array.
|
|
12
|
+
* If the key [roomId] already exists, we do NOT overwrite it.
|
|
13
|
+
* Returns true if room was created, false if room already existed.
|
|
14
|
+
*/
|
|
15
|
+
async initRoom(roomId) {
|
|
16
|
+
// Check if the key already exists (JSON.GET)
|
|
17
|
+
const isRoomExisting = await this.redisClient.jsonGet(`[${roomId}]`, '.');
|
|
18
|
+
if (isRoomExisting !== null) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
// Create an empty array at the root
|
|
22
|
+
await this.redisClient.jsonSet(`[${roomId}]`, '.', []);
|
|
23
|
+
await this.redisClient.expire(`[${roomId}]`, EXPIRATION);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns all rooms. This is naive if you store many other keys in Redis,
|
|
28
|
+
* because we search keys for pattern "[*]".
|
|
29
|
+
* Adjust as needed if you have a separate naming prefix.
|
|
30
|
+
*/
|
|
31
|
+
async getRooms() {
|
|
32
|
+
// e.g., if we store everything as [foo], [bar], etc., we do:
|
|
33
|
+
const rooms = await this.redisClient.keys('\\[*\\]');
|
|
34
|
+
// This returns the raw keys, e.g. ['[myRoom]', '[anotherRoom]']
|
|
35
|
+
// We might want to strip off the brackets:
|
|
36
|
+
return rooms.map((k) => k.replace(/^\[|\]$/g, ''));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Returns the entire array of chunks for the given roomId,
|
|
40
|
+
* or null if the room doesn't exist in Redis.
|
|
41
|
+
*/
|
|
42
|
+
async getMulingstreamChunksByRoom(roomId) {
|
|
43
|
+
// JSON.GET [roomId] .
|
|
44
|
+
const chunks = await this.redisClient.jsonGet(`[${roomId}]`, '.');
|
|
45
|
+
if (chunks === null) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return chunks;
|
|
49
|
+
}
|
|
50
|
+
async getRoomById(roomId) {
|
|
51
|
+
return this.getMulingstreamChunksByRoom(roomId);
|
|
52
|
+
}
|
|
53
|
+
async addMulingstreamChunk(params) {
|
|
54
|
+
var _a;
|
|
55
|
+
const { roomId, chunkNumber, language, start, end, duration, isFirst, isLast, theme, sttProviders, targetLanguages, shortCodeTargetLanguages } = params;
|
|
56
|
+
const audioChunk = {
|
|
57
|
+
start,
|
|
58
|
+
end,
|
|
59
|
+
duration,
|
|
60
|
+
isFirst,
|
|
61
|
+
isLast,
|
|
62
|
+
theme,
|
|
63
|
+
processingStart: Date.now()
|
|
64
|
+
};
|
|
65
|
+
const stt = {};
|
|
66
|
+
for (const sttProvider of sttProviders) {
|
|
67
|
+
stt[sttProvider] = {
|
|
68
|
+
transcription: '',
|
|
69
|
+
status: 'INIT'
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const translation = {};
|
|
73
|
+
const tts = {};
|
|
74
|
+
for (const lang of shortCodeTargetLanguages) {
|
|
75
|
+
translation[lang] = {
|
|
76
|
+
translation: '',
|
|
77
|
+
status: 'INIT'
|
|
78
|
+
};
|
|
79
|
+
tts[lang] = {
|
|
80
|
+
ttsAudioPath: '',
|
|
81
|
+
status: 'INIT',
|
|
82
|
+
isEmitted: false
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const newChunk = {
|
|
86
|
+
roomId,
|
|
87
|
+
chunkNumber,
|
|
88
|
+
language,
|
|
89
|
+
sttProviders,
|
|
90
|
+
targetLanguages,
|
|
91
|
+
shortCodeTargetLanguages,
|
|
92
|
+
finalTranscription: '',
|
|
93
|
+
sttStatus: 'INIT',
|
|
94
|
+
audioChunk,
|
|
95
|
+
stt,
|
|
96
|
+
translation,
|
|
97
|
+
tts
|
|
98
|
+
};
|
|
99
|
+
const chunks = (_a = (await this.redisClient.jsonGet(`[${roomId}]`, '.'))) !== null && _a !== void 0 ? _a : [];
|
|
100
|
+
const idx = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
101
|
+
if (idx !== -1) {
|
|
102
|
+
chunks[idx] = newChunk;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
chunks.push(newChunk);
|
|
106
|
+
if (chunks.length > ROOM_ARRAY_LENGTH) {
|
|
107
|
+
chunks.shift();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
111
|
+
await this.redisClient.expire(`[${roomId}]`, EXPIRATION);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Given roomId and chunkNumber, return the single chunk from the array
|
|
115
|
+
* or null if not found.
|
|
116
|
+
*/
|
|
117
|
+
async getMulingstreamChunkById(roomId, chunkNumber) {
|
|
118
|
+
// Retrieve the entire array
|
|
119
|
+
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
120
|
+
if (!chunks)
|
|
121
|
+
return null;
|
|
122
|
+
// Find by chunkNumber
|
|
123
|
+
const chunk = chunks.find((c) => c.chunkNumber === chunkNumber);
|
|
124
|
+
return chunk || null;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Update STT fields for a given chunk.
|
|
128
|
+
* If transcription or sttStatus is null, skip that field.
|
|
129
|
+
*/
|
|
130
|
+
async updateStt(roomId, chunkNumber, sttProvider, options) {
|
|
131
|
+
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
132
|
+
if (!chunks)
|
|
133
|
+
return false;
|
|
134
|
+
// Find the chunk
|
|
135
|
+
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
136
|
+
if (chunkIndex === -1)
|
|
137
|
+
return false;
|
|
138
|
+
const chunk = chunks[chunkIndex];
|
|
139
|
+
// If this stt provider doesn't exist, ignore
|
|
140
|
+
if (!chunk.stt[sttProvider])
|
|
141
|
+
return false;
|
|
142
|
+
// Update
|
|
143
|
+
if (options.transcription != null) {
|
|
144
|
+
chunk.stt[sttProvider].transcription = options.transcription;
|
|
145
|
+
}
|
|
146
|
+
if (options.sttStatus != null) {
|
|
147
|
+
chunk.stt[sttProvider].status = options.sttStatus;
|
|
148
|
+
}
|
|
149
|
+
// Write back
|
|
150
|
+
chunks[chunkIndex] = chunk;
|
|
151
|
+
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Update the final transcription field for a chunk.
|
|
156
|
+
*/
|
|
157
|
+
async updateFinalTranscription(roomId, chunkNumber, transcription, sttStatus) {
|
|
158
|
+
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
159
|
+
if (!chunks)
|
|
160
|
+
return false;
|
|
161
|
+
// Find the chunk
|
|
162
|
+
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
163
|
+
if (chunkIndex === -1)
|
|
164
|
+
return false;
|
|
165
|
+
chunks[chunkIndex].finalTranscription = transcription;
|
|
166
|
+
chunks[chunkIndex].sttStatus = sttStatus;
|
|
167
|
+
// Write back
|
|
168
|
+
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Discards all post-STT steps for a given chunk:
|
|
173
|
+
* sets all translation[].status & tts[].status to "DISCARDED".
|
|
174
|
+
*/
|
|
175
|
+
async discardPostStt(roomId, chunkNumber) {
|
|
176
|
+
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
177
|
+
if (!chunks)
|
|
178
|
+
return false;
|
|
179
|
+
// Find chunk
|
|
180
|
+
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
181
|
+
if (chunkIndex === -1)
|
|
182
|
+
return false;
|
|
183
|
+
// Discard translation & TTS statuses
|
|
184
|
+
const chunk = chunks[chunkIndex];
|
|
185
|
+
for (const lang of Object.keys(chunk.translation)) {
|
|
186
|
+
chunk.translation[lang].status = 'DISCARDED';
|
|
187
|
+
}
|
|
188
|
+
for (const lang of Object.keys(chunk.tts)) {
|
|
189
|
+
chunk.tts[lang].status = 'DISCARDED';
|
|
190
|
+
}
|
|
191
|
+
chunks[chunkIndex] = chunk;
|
|
192
|
+
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Discards a specific language in both translation and tts for a chunk.
|
|
197
|
+
*/
|
|
198
|
+
async discardLanguage(roomId, chunkNumber, language) {
|
|
199
|
+
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
200
|
+
if (!chunks)
|
|
201
|
+
return false;
|
|
202
|
+
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
203
|
+
if (chunkIndex === -1)
|
|
204
|
+
return false;
|
|
205
|
+
const chunk = chunks[chunkIndex];
|
|
206
|
+
if (chunk.translation[language]) {
|
|
207
|
+
chunk.translation[language].status = 'DISCARDED';
|
|
208
|
+
}
|
|
209
|
+
if (chunk.tts[language]) {
|
|
210
|
+
chunk.tts[language].status = 'DISCARDED';
|
|
211
|
+
}
|
|
212
|
+
chunks[chunkIndex] = chunk;
|
|
213
|
+
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
async updateTranslation(roomId, chunkNumber, language, options) {
|
|
217
|
+
// Fetch all chunks for this room
|
|
218
|
+
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
219
|
+
if (!chunks)
|
|
220
|
+
return false;
|
|
221
|
+
// Locate the target chunk
|
|
222
|
+
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
223
|
+
if (chunkIndex === -1)
|
|
224
|
+
return false;
|
|
225
|
+
const chunk = chunks[chunkIndex];
|
|
226
|
+
// Make sure the requested language exists in this chunk
|
|
227
|
+
if (!chunk.translation[language]) {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
if (options.translation !== undefined) {
|
|
231
|
+
chunk.translation[language].translation = options.translation;
|
|
232
|
+
}
|
|
233
|
+
if (options.status !== undefined) {
|
|
234
|
+
chunk.translation[language].status = options.status;
|
|
235
|
+
}
|
|
236
|
+
// Persist the whole array back to Redis
|
|
237
|
+
chunks[chunkIndex] = chunk;
|
|
238
|
+
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
exports.MulingstreamChunkManager = MulingstreamChunkManager;
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { RedisClient } from '../redis-client';
|
|
2
|
-
export type MulingstreamListenerData = {
|
|
3
|
-
listenerId: string;
|
|
4
|
-
roomId: string;
|
|
5
|
-
socketId?: string;
|
|
6
|
-
token: string;
|
|
7
|
-
name?: string;
|
|
8
|
-
firstJoined: number;
|
|
9
|
-
language?: string;
|
|
10
|
-
isActive?: boolean;
|
|
11
|
-
};
|
|
12
|
-
export declare class MulingstreamListenerManager {
|
|
13
|
-
private redisClient;
|
|
14
|
-
constructor(redisClient: RedisClient);
|
|
15
|
-
private parseHashData;
|
|
16
|
-
addListener(listenerData: Omit<MulingstreamListenerData, 'listenerId'>): Promise<string>;
|
|
17
|
-
getAllListeners(): Promise<MulingstreamListenerData[]>;
|
|
18
|
-
getListenersByRoom(roomId: string): Promise<MulingstreamListenerData[]>;
|
|
19
|
-
getListener(listenerIdOrToken: string): Promise<MulingstreamListenerData | null>;
|
|
20
|
-
removeListenerByToken(token: string): Promise<boolean>;
|
|
21
|
-
updateNameLanguage(listenerIdOrToken: string, name: string, language: string): Promise<boolean>;
|
|
22
|
-
updateSocketId(listenerIdOrToken: string, socketId: string): Promise<boolean>;
|
|
23
|
-
getTargetSocketIdsByRoomLanguage(roomId: string, language: string): Promise<string[]>;
|
|
24
|
-
/**
|
|
25
|
-
* Returns an array of unique languages for the given room, from highest frequency to lowest.
|
|
26
|
-
* If a listener has no language (empty string / undefined), it is ignored.
|
|
27
|
-
*/
|
|
28
|
-
getUniqueLanguagesByRoom(roomId: string): Promise<string[]>;
|
|
29
|
-
}
|
|
1
|
+
import { RedisClient } from '../redis-client';
|
|
2
|
+
export type MulingstreamListenerData = {
|
|
3
|
+
listenerId: string;
|
|
4
|
+
roomId: string;
|
|
5
|
+
socketId?: string;
|
|
6
|
+
token: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
firstJoined: number;
|
|
9
|
+
language?: string;
|
|
10
|
+
isActive?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare class MulingstreamListenerManager {
|
|
13
|
+
private redisClient;
|
|
14
|
+
constructor(redisClient: RedisClient);
|
|
15
|
+
private parseHashData;
|
|
16
|
+
addListener(listenerData: Omit<MulingstreamListenerData, 'listenerId'>): Promise<string>;
|
|
17
|
+
getAllListeners(): Promise<MulingstreamListenerData[]>;
|
|
18
|
+
getListenersByRoom(roomId: string): Promise<MulingstreamListenerData[]>;
|
|
19
|
+
getListener(listenerIdOrToken: string): Promise<MulingstreamListenerData | null>;
|
|
20
|
+
removeListenerByToken(token: string): Promise<boolean>;
|
|
21
|
+
updateNameLanguage(listenerIdOrToken: string, name: string, language: string): Promise<boolean>;
|
|
22
|
+
updateSocketId(listenerIdOrToken: string, socketId: string): Promise<boolean>;
|
|
23
|
+
getTargetSocketIdsByRoomLanguage(roomId: string, language: string): Promise<string[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Returns an array of unique languages for the given room, from highest frequency to lowest.
|
|
26
|
+
* If a listener has no language (empty string / undefined), it is ignored.
|
|
27
|
+
*/
|
|
28
|
+
getUniqueLanguagesByRoom(roomId: string): Promise<string[]>;
|
|
29
|
+
}
|