@mulingai-npm/redis 1.14.1 → 2.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.
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
import { RedisClient } from '../redis-client';
|
|
2
2
|
export type StepStatus = 'INIT' | 'DISCARDED' | 'READY' | 'USED';
|
|
3
|
-
export type MulingstreamChunkStatus = 'INIT' | 'STARTED' | 'FINISHED' | 'CANCELED' | 'USED';
|
|
4
|
-
export type MulingstreamChunkStep = 'RECEIVED' | 'STT' | 'TRANSLATION' | 'TTS' | 'EMITTED';
|
|
5
3
|
export type SttProvider = 'azure' | 'whisper' | 'google' | 'aws';
|
|
6
4
|
export type MulingstreamChunkData = {
|
|
7
|
-
mulingstreamChunkId: string;
|
|
8
|
-
roomId: string;
|
|
9
5
|
chunkNumber: number;
|
|
10
6
|
language: string;
|
|
11
7
|
sttProviders: SttProvider[];
|
|
12
8
|
targetLanguages: string[];
|
|
13
9
|
finalTranscription: string;
|
|
14
|
-
|
|
15
|
-
mulingstreamChunkStep: MulingstreamChunkStep;
|
|
10
|
+
sttStatus: StepStatus;
|
|
16
11
|
audioChunk: {
|
|
17
12
|
start: number;
|
|
18
13
|
end: number;
|
|
@@ -45,7 +40,31 @@ export type MulingstreamChunkData = {
|
|
|
45
40
|
export declare class MulingstreamChunkManager {
|
|
46
41
|
private redisClient;
|
|
47
42
|
constructor(redisClient: RedisClient);
|
|
48
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Initializes a room in Redis as an empty JSON array.
|
|
45
|
+
* If the key [roomId] already exists, we do NOT overwrite it.
|
|
46
|
+
* Returns true if room was created, false if room already existed.
|
|
47
|
+
*/
|
|
48
|
+
initRoom(roomId: string): Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* Returns all rooms. This is naive if you store many other keys in Redis,
|
|
51
|
+
* because we search keys for pattern "[*]".
|
|
52
|
+
* Adjust as needed if you have a separate naming prefix.
|
|
53
|
+
*/
|
|
54
|
+
getRooms(): Promise<string[]>;
|
|
55
|
+
/**
|
|
56
|
+
* Returns the entire array of chunks for the given roomId,
|
|
57
|
+
* or null if the room doesn't exist in Redis.
|
|
58
|
+
*/
|
|
59
|
+
getMulingstreamChunksByRoom(roomId: string): Promise<MulingstreamChunkData[] | null>;
|
|
60
|
+
/**
|
|
61
|
+
* Returns the room array "as is" for debugging
|
|
62
|
+
* (same as getMulingstreamChunksByRoom in this example).
|
|
63
|
+
*/
|
|
64
|
+
getRoomById(roomId: string): Promise<MulingstreamChunkData[] | null>;
|
|
65
|
+
/**
|
|
66
|
+
* Adds a new Mulingstream chunk to the array stored at [${roomId}].
|
|
67
|
+
*/
|
|
49
68
|
addMulingstreamChunk(params: {
|
|
50
69
|
roomId: string;
|
|
51
70
|
chunkNumber: number;
|
|
@@ -58,28 +77,31 @@ export declare class MulingstreamChunkManager {
|
|
|
58
77
|
theme: string;
|
|
59
78
|
sttProviders: SttProvider[];
|
|
60
79
|
targetLanguages: string[];
|
|
61
|
-
}): Promise<
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
*
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
*
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
}): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Given roomId and chunkNumber, return the single chunk from the array
|
|
83
|
+
* or null if not found.
|
|
84
|
+
*/
|
|
85
|
+
getMulingstreamChunkById(roomId: string, chunkNumber: number): Promise<MulingstreamChunkData | null>;
|
|
86
|
+
/**
|
|
87
|
+
* Update STT fields for a given chunk.
|
|
88
|
+
* If transcription or sttStatus is null, skip that field.
|
|
89
|
+
*/
|
|
90
|
+
updateStt(roomId: string, chunkNumber: number, sttProvider: SttProvider, options: {
|
|
91
|
+
transcription?: string;
|
|
92
|
+
sttStatus?: StepStatus;
|
|
93
|
+
}): Promise<boolean>;
|
|
94
|
+
/**
|
|
95
|
+
* Update the final transcription field for a chunk.
|
|
96
|
+
*/
|
|
97
|
+
updateFinalTranscription(roomId: string, chunkNumber: number, transcription: string, sttStatus: StepStatus): Promise<boolean>;
|
|
98
|
+
/**
|
|
99
|
+
* Discards all post-STT steps for a given chunk:
|
|
100
|
+
* sets all translation[].status & tts[].status to "DISCARDED".
|
|
101
|
+
*/
|
|
102
|
+
discardPostStt(roomId: string, chunkNumber: number): Promise<boolean>;
|
|
103
|
+
/**
|
|
104
|
+
* Discards a specific language in both translation and tts for a chunk.
|
|
105
|
+
*/
|
|
106
|
+
discardLanguage(roomId: string, chunkNumber: number, language: string): Promise<boolean>;
|
|
85
107
|
}
|
|
@@ -1,44 +1,64 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MulingstreamChunkManager = void 0;
|
|
4
|
-
const uuid_1 = require("uuid");
|
|
5
4
|
const EXPIRATION = 12 * 60 * 60; // 12 hours in seconds
|
|
6
5
|
class MulingstreamChunkManager {
|
|
7
6
|
constructor(redisClient) {
|
|
8
7
|
this.redisClient = redisClient;
|
|
9
8
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Initializes a room in Redis as an empty JSON array.
|
|
11
|
+
* If the key [roomId] already exists, we do NOT overwrite it.
|
|
12
|
+
* Returns true if room was created, false if room already existed.
|
|
13
|
+
*/
|
|
14
|
+
async initRoom(roomId) {
|
|
15
|
+
// Check if the key already exists (JSON.GET)
|
|
16
|
+
const existing = await this.redisClient.jsonGet(`[${roomId}]`, '.');
|
|
17
|
+
if (existing !== null) {
|
|
18
|
+
// Already exists
|
|
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; // room not found
|
|
47
|
+
return chunks;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Returns the room array "as is" for debugging
|
|
51
|
+
* (same as getMulingstreamChunksByRoom in this example).
|
|
52
|
+
*/
|
|
53
|
+
async getRoomById(roomId) {
|
|
54
|
+
return this.getMulingstreamChunksByRoom(roomId);
|
|
33
55
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
// - Applies an expiration (12h).
|
|
56
|
+
/**
|
|
57
|
+
* Adds a new Mulingstream chunk to the array stored at [${roomId}].
|
|
58
|
+
*/
|
|
38
59
|
async addMulingstreamChunk(params) {
|
|
39
60
|
const { roomId, chunkNumber, language, start, end, duration, isFirst, isLast, theme, sttProviders, targetLanguages } = params;
|
|
40
|
-
|
|
41
|
-
// Prepare the nested objects
|
|
61
|
+
// Build the chunk
|
|
42
62
|
const audioChunk = {
|
|
43
63
|
start,
|
|
44
64
|
end,
|
|
@@ -48,16 +68,15 @@ class MulingstreamChunkManager {
|
|
|
48
68
|
theme,
|
|
49
69
|
processingStart: Date.now()
|
|
50
70
|
};
|
|
51
|
-
// Build
|
|
52
|
-
// For each service in `services`, create { transcription: '', status: 'INIT' }
|
|
71
|
+
// Build stt object
|
|
53
72
|
const stt = {};
|
|
54
|
-
for (const
|
|
55
|
-
stt[
|
|
73
|
+
for (const svc of sttProviders) {
|
|
74
|
+
stt[svc] = {
|
|
56
75
|
transcription: '',
|
|
57
76
|
status: 'INIT'
|
|
58
77
|
};
|
|
59
78
|
}
|
|
60
|
-
// Build translation
|
|
79
|
+
// Build translation and tts objects
|
|
61
80
|
const translation = {};
|
|
62
81
|
const tts = {};
|
|
63
82
|
for (const lang of targetLanguages) {
|
|
@@ -71,217 +90,123 @@ class MulingstreamChunkManager {
|
|
|
71
90
|
isEmitted: false
|
|
72
91
|
};
|
|
73
92
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// Store the data in a Redis hash
|
|
77
|
-
await this.redisClient.hset(`mulingstreamChunk:${mulingstreamChunkId}`, {
|
|
78
|
-
mulingstreamChunkId,
|
|
79
|
-
roomId,
|
|
80
|
-
chunkNumber: chunkNumber.toString(),
|
|
93
|
+
const newChunk = {
|
|
94
|
+
chunkNumber,
|
|
81
95
|
language,
|
|
82
|
-
sttProviders
|
|
83
|
-
targetLanguages
|
|
84
|
-
finalTranscription,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
return mulingstreamChunkId;
|
|
95
|
-
}
|
|
96
|
-
// Retrieves all mulingstream chunks by scanning keys `mulingstreamChunk:*`.
|
|
97
|
-
async getMulingstreamChunks() {
|
|
98
|
-
const keys = await this.redisClient.keys('mulingstreamChunk:*');
|
|
99
|
-
if (!keys || keys.length === 0) {
|
|
100
|
-
return [];
|
|
101
|
-
}
|
|
102
|
-
const results = [];
|
|
103
|
-
for (const key of keys) {
|
|
104
|
-
const data = await this.redisClient.hgetall(key);
|
|
105
|
-
if (data && data.mulingstreamChunkId) {
|
|
106
|
-
results.push(this.parseHashData(data));
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return results;
|
|
110
|
-
}
|
|
111
|
-
// Retrieves a single mulingstream chunk by ID.
|
|
112
|
-
async getMulingstreamChunk(mulingstreamChunkId) {
|
|
113
|
-
const data = await this.redisClient.hgetall(`mulingstreamChunk:${mulingstreamChunkId}`);
|
|
114
|
-
if (!data || !data.mulingstreamChunkId) {
|
|
115
|
-
return null;
|
|
116
|
-
}
|
|
117
|
-
return this.parseHashData(data);
|
|
118
|
-
}
|
|
119
|
-
// Retrieves all mulingstream chunks for a specific room by pattern matching keys `mulingstreamChunk:[roomId]-*`.
|
|
120
|
-
async getMulingstreamChunksByRoom(roomId) {
|
|
121
|
-
const pattern = `mulingstreamChunk:[${roomId}]-*`;
|
|
122
|
-
const keys = await this.redisClient.keys(pattern);
|
|
123
|
-
if (!keys || keys.length === 0) {
|
|
124
|
-
return [];
|
|
125
|
-
}
|
|
126
|
-
const results = [];
|
|
127
|
-
for (const key of keys) {
|
|
128
|
-
const data = await this.redisClient.hgetall(key);
|
|
129
|
-
if (!data || !data.mulingstreamChunkId) {
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
results.push(this.parseHashData(data));
|
|
133
|
-
}
|
|
134
|
-
return results;
|
|
96
|
+
sttProviders,
|
|
97
|
+
targetLanguages,
|
|
98
|
+
finalTranscription: '',
|
|
99
|
+
sttStatus: 'INIT',
|
|
100
|
+
audioChunk,
|
|
101
|
+
stt,
|
|
102
|
+
translation,
|
|
103
|
+
tts
|
|
104
|
+
};
|
|
105
|
+
// Append it to the array
|
|
106
|
+
await this.redisClient.jsonArrAppend(`[${roomId}]`, '.', // the root of the JSON document (the array)
|
|
107
|
+
newChunk);
|
|
135
108
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Given roomId and chunkNumber, return the single chunk from the array
|
|
111
|
+
* or null if not found.
|
|
112
|
+
*/
|
|
113
|
+
async getMulingstreamChunkById(roomId, chunkNumber) {
|
|
114
|
+
// Retrieve the entire array
|
|
115
|
+
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
116
|
+
if (!chunks)
|
|
142
117
|
return null;
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (!data || !data.mulingstreamChunkId) {
|
|
147
|
-
return null;
|
|
148
|
-
}
|
|
149
|
-
return this.parseHashData(data);
|
|
150
|
-
}
|
|
151
|
-
async updateMulingstreamChunkStatus(mulingstreamChunkId, mulingstreamChunkStep, mulingstreamChunkStatus) {
|
|
152
|
-
// Fetch the chunk data first
|
|
153
|
-
const data = await this.redisClient.hgetall(`mulingstreamChunk:${mulingstreamChunkId}`);
|
|
154
|
-
if (!data || !data.mulingstreamChunkId) {
|
|
155
|
-
return false; // The chunk may not exist or has expired
|
|
156
|
-
}
|
|
157
|
-
// Update only the chunk status and step
|
|
158
|
-
await this.redisClient.hset(`mulingstreamChunk:${mulingstreamChunkId}`, {
|
|
159
|
-
mulingstreamChunkStatus,
|
|
160
|
-
mulingstreamChunkStep
|
|
161
|
-
});
|
|
162
|
-
return true;
|
|
118
|
+
// Find by chunkNumber
|
|
119
|
+
const chunk = chunks.find((c) => c.chunkNumber === chunkNumber);
|
|
120
|
+
return chunk || null;
|
|
163
121
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
await this.redisClient.hset(`mulingstreamChunk:${mulingstreamChunkId}`, {
|
|
172
|
-
finalTranscription
|
|
173
|
-
});
|
|
174
|
-
return true;
|
|
175
|
-
}
|
|
176
|
-
// Updates the STT status for a given service in the chunk's STT data.
|
|
177
|
-
async updateSttStatus(mulingstreamChunkId, service, status) {
|
|
178
|
-
const data = await this.redisClient.hgetall(`mulingstreamChunk:${mulingstreamChunkId}`);
|
|
179
|
-
if (!data || !data.mulingstreamChunkId) {
|
|
122
|
+
/**
|
|
123
|
+
* Update STT fields for a given chunk.
|
|
124
|
+
* If transcription or sttStatus is null, skip that field.
|
|
125
|
+
*/
|
|
126
|
+
async updateStt(roomId, chunkNumber, sttProvider, options) {
|
|
127
|
+
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
128
|
+
if (!chunks)
|
|
180
129
|
return false;
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
if (
|
|
184
|
-
return false; // service not in stt object
|
|
185
|
-
}
|
|
186
|
-
stt[service].status = status;
|
|
187
|
-
await this.redisClient.hset(`mulingstreamChunk:${mulingstreamChunkId}`, {
|
|
188
|
-
stt: JSON.stringify(stt)
|
|
189
|
-
});
|
|
190
|
-
return true;
|
|
191
|
-
}
|
|
192
|
-
// Updates the transcription + status for a given service in the chunk's STT data.
|
|
193
|
-
async updateTranscription(mulingstreamChunkId, service, transcription, sttStatus) {
|
|
194
|
-
const data = await this.redisClient.hgetall(`mulingstreamChunk:${mulingstreamChunkId}`);
|
|
195
|
-
if (!data || !data.mulingstreamChunkId) {
|
|
130
|
+
// Find the chunk
|
|
131
|
+
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
132
|
+
if (chunkIndex === -1)
|
|
196
133
|
return false;
|
|
134
|
+
const chunk = chunks[chunkIndex];
|
|
135
|
+
// If this stt provider doesn't exist, ignore
|
|
136
|
+
if (!chunk.stt[sttProvider])
|
|
137
|
+
return false;
|
|
138
|
+
// Update
|
|
139
|
+
if (options.transcription != null) {
|
|
140
|
+
chunk.stt[sttProvider].transcription = options.transcription;
|
|
197
141
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
return false; // service not in stt object
|
|
142
|
+
if (options.sttStatus != null) {
|
|
143
|
+
chunk.stt[sttProvider].status = options.sttStatus;
|
|
201
144
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
await this.redisClient.
|
|
205
|
-
stt: JSON.stringify(stt)
|
|
206
|
-
});
|
|
145
|
+
// Write back
|
|
146
|
+
chunks[chunkIndex] = chunk;
|
|
147
|
+
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
207
148
|
return true;
|
|
208
149
|
}
|
|
209
|
-
|
|
210
|
-
*
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
const data = await this.redisClient.hgetall(`mulingstreamChunk:${mulingstreamChunkId}`);
|
|
216
|
-
if (!data || !data.mulingstreamChunkId) {
|
|
150
|
+
/**
|
|
151
|
+
* Update the final transcription field for a chunk.
|
|
152
|
+
*/
|
|
153
|
+
async updateFinalTranscription(roomId, chunkNumber, transcription, sttStatus) {
|
|
154
|
+
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
155
|
+
if (!chunks)
|
|
217
156
|
return false;
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
translation[lang].status = 'DISCARDED';
|
|
225
|
-
}
|
|
226
|
-
// Set every language status to DISCARDED in tts
|
|
227
|
-
for (const lang of Object.keys(tts)) {
|
|
228
|
-
tts[lang].status = 'DISCARDED';
|
|
229
|
-
}
|
|
157
|
+
// Find the chunk
|
|
158
|
+
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
159
|
+
if (chunkIndex === -1)
|
|
160
|
+
return false;
|
|
161
|
+
chunks[chunkIndex].finalTranscription = transcription;
|
|
162
|
+
chunks[chunkIndex].sttStatus = sttStatus;
|
|
230
163
|
// Write back
|
|
231
|
-
await this.redisClient.
|
|
232
|
-
translation: JSON.stringify(translation),
|
|
233
|
-
tts: JSON.stringify(tts)
|
|
234
|
-
});
|
|
164
|
+
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
235
165
|
return true;
|
|
236
166
|
}
|
|
237
|
-
|
|
238
|
-
* Discards all post-
|
|
239
|
-
* all tts[].status to "DISCARDED"
|
|
240
|
-
|
|
241
|
-
async
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
167
|
+
/**
|
|
168
|
+
* Discards all post-STT steps for a given chunk:
|
|
169
|
+
* sets all translation[].status & tts[].status to "DISCARDED".
|
|
170
|
+
*/
|
|
171
|
+
async discardPostStt(roomId, chunkNumber) {
|
|
172
|
+
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
173
|
+
if (!chunks)
|
|
174
|
+
return false;
|
|
175
|
+
// Find chunk
|
|
176
|
+
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
177
|
+
if (chunkIndex === -1)
|
|
245
178
|
return false;
|
|
179
|
+
// Discard translation & TTS statuses
|
|
180
|
+
const chunk = chunks[chunkIndex];
|
|
181
|
+
for (const lang of Object.keys(chunk.translation)) {
|
|
182
|
+
chunk.translation[lang].status = 'DISCARDED';
|
|
246
183
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
// Set every language status to DISCARDED in tts
|
|
250
|
-
for (const lang of Object.keys(tts)) {
|
|
251
|
-
tts[lang].status = 'DISCARDED';
|
|
184
|
+
for (const lang of Object.keys(chunk.tts)) {
|
|
185
|
+
chunk.tts[lang].status = 'DISCARDED';
|
|
252
186
|
}
|
|
253
|
-
|
|
254
|
-
await this.redisClient.
|
|
255
|
-
tts: JSON.stringify(tts)
|
|
256
|
-
});
|
|
187
|
+
chunks[chunkIndex] = chunk;
|
|
188
|
+
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
257
189
|
return true;
|
|
258
190
|
}
|
|
259
|
-
|
|
260
|
-
* Discards a specific language in both
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
const data = await this.redisClient.hgetall(`mulingstreamChunk:${mulingstreamChunkId}`);
|
|
266
|
-
if (!data || !data.mulingstreamChunkId) {
|
|
191
|
+
/**
|
|
192
|
+
* Discards a specific language in both translation and tts for a chunk.
|
|
193
|
+
*/
|
|
194
|
+
async discardLanguage(roomId, chunkNumber, language) {
|
|
195
|
+
const chunks = await this.getMulingstreamChunksByRoom(roomId);
|
|
196
|
+
if (!chunks)
|
|
267
197
|
return false;
|
|
198
|
+
const chunkIndex = chunks.findIndex((c) => c.chunkNumber === chunkNumber);
|
|
199
|
+
if (chunkIndex === -1)
|
|
200
|
+
return false;
|
|
201
|
+
const chunk = chunks[chunkIndex];
|
|
202
|
+
if (chunk.translation[language]) {
|
|
203
|
+
chunk.translation[language].status = 'DISCARDED';
|
|
268
204
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const tts = JSON.parse(data.tts);
|
|
272
|
-
// If the language exists in translation, discard
|
|
273
|
-
if (translation[language]) {
|
|
274
|
-
translation[language].status = 'DISCARDED';
|
|
275
|
-
}
|
|
276
|
-
// If the language exists in tts, discard
|
|
277
|
-
if (tts[language]) {
|
|
278
|
-
tts[language].status = 'DISCARDED';
|
|
205
|
+
if (chunk.tts[language]) {
|
|
206
|
+
chunk.tts[language].status = 'DISCARDED';
|
|
279
207
|
}
|
|
280
|
-
|
|
281
|
-
await this.redisClient.
|
|
282
|
-
translation: JSON.stringify(translation),
|
|
283
|
-
tts: JSON.stringify(tts)
|
|
284
|
-
});
|
|
208
|
+
chunks[chunkIndex] = chunk;
|
|
209
|
+
await this.redisClient.jsonSet(`[${roomId}]`, '.', chunks);
|
|
285
210
|
return true;
|
|
286
211
|
}
|
|
287
212
|
}
|
package/dist/redis-client.d.ts
CHANGED
|
@@ -19,4 +19,8 @@ export declare class RedisClient {
|
|
|
19
19
|
flushAll(): Promise<string>;
|
|
20
20
|
flushDb(): Promise<string>;
|
|
21
21
|
expire(key: string, seconds: number): Promise<number>;
|
|
22
|
+
jsonSet<T>(key: string, path: string, value: T): Promise<string>;
|
|
23
|
+
jsonGet<T>(key: string, path: string): Promise<T | null>;
|
|
24
|
+
jsonDel(key: string, path: string): Promise<number>;
|
|
25
|
+
jsonArrAppend<T>(key: string, path: string, ...values: T[]): Promise<number>;
|
|
22
26
|
}
|
package/dist/redis-client.js
CHANGED
|
@@ -61,5 +61,25 @@ class RedisClient {
|
|
|
61
61
|
async expire(key, seconds) {
|
|
62
62
|
return this.client.expire(key, seconds);
|
|
63
63
|
}
|
|
64
|
+
async jsonSet(key, path, value) {
|
|
65
|
+
const result = await this.client.call('JSON.SET', key, path, JSON.stringify(value));
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
async jsonGet(key, path) {
|
|
69
|
+
const result = (await this.client.call('JSON.GET', key, path));
|
|
70
|
+
if (!result) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
return JSON.parse(result);
|
|
74
|
+
}
|
|
75
|
+
async jsonDel(key, path) {
|
|
76
|
+
const result = await this.client.call('JSON.DEL', key, path);
|
|
77
|
+
return Number(result);
|
|
78
|
+
}
|
|
79
|
+
async jsonArrAppend(key, path, ...values) {
|
|
80
|
+
const stringifiedValues = values.map((v) => JSON.stringify(v));
|
|
81
|
+
const result = await this.client.call('JSON.ARRAPPEND', key, path, ...stringifiedValues);
|
|
82
|
+
return Number(result);
|
|
83
|
+
}
|
|
64
84
|
}
|
|
65
85
|
exports.RedisClient = RedisClient;
|