stream-chat-angular 5.3.2 → 5.4.1
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/assets/i18n/en.d.ts +4 -0
- package/assets/version.d.ts +1 -1
- package/esm2020/assets/i18n/en.mjs +5 -1
- package/esm2020/assets/version.mjs +2 -2
- package/esm2020/lib/attachment-list/attachment-list.component.mjs +4 -4
- package/esm2020/lib/attachment-preview-list/attachment-preview-list.component.mjs +5 -5
- package/esm2020/lib/attachment.service.mjs +60 -10
- package/esm2020/lib/channel-list/channel-list.component.mjs +3 -3
- package/esm2020/lib/channel-preview/channel-preview.component.mjs +1 -1
- package/esm2020/lib/file-utils.mjs +35 -0
- package/esm2020/lib/format-duration.mjs +16 -0
- package/esm2020/lib/icon/icon-placeholder/icon-placeholder.component.mjs +28 -0
- package/esm2020/lib/icon/icon.component.mjs +1 -1
- package/esm2020/lib/icon/icon.module.mjs +37 -0
- package/esm2020/lib/{loading-indicator → icon/loading-indicator}/loading-indicator.component.mjs +1 -1
- package/esm2020/lib/{loading-indicator-placeholder → icon/loading-indicator-placeholder}/loading-indicator-placeholder.component.mjs +2 -2
- package/esm2020/lib/is-safari.mjs +2 -0
- package/esm2020/lib/message/message.component.mjs +6 -6
- package/esm2020/lib/message-input/message-input-config.service.mjs +6 -1
- package/esm2020/lib/message-input/message-input.component.mjs +57 -14
- package/esm2020/lib/message-input/voice-recorder.service.mjs +27 -0
- package/esm2020/lib/message-list/message-list.component.mjs +9 -9
- package/esm2020/lib/modal/modal.component.mjs +1 -1
- package/esm2020/lib/paginated-list/paginated-list.component.mjs +1 -1
- package/esm2020/lib/stream-chat.module.mjs +21 -35
- package/esm2020/lib/thread/thread.component.mjs +1 -1
- package/esm2020/lib/types.mjs +1 -1
- package/esm2020/lib/voice-recorder/amplitude-recorder.service.mjs +119 -0
- package/esm2020/lib/voice-recorder/audio-recorder.service.mjs +79 -0
- package/esm2020/lib/voice-recorder/media-recorder.mjs +190 -0
- package/esm2020/lib/voice-recorder/mp3-transcoder.mjs +61 -0
- package/esm2020/lib/voice-recorder/transcoder.service.mjs +121 -0
- package/esm2020/lib/voice-recorder/voice-recorder-wavebar/voice-recorder-wavebar.component.mjs +35 -0
- package/esm2020/lib/voice-recorder/voice-recorder.component.mjs +80 -0
- package/esm2020/lib/voice-recorder/voice-recorder.module.mjs +34 -0
- package/esm2020/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.mjs +4 -75
- package/esm2020/lib/voice-recording/voice-recording.component.mjs +4 -15
- package/esm2020/lib/voice-recording/voice-recording.module.mjs +21 -0
- package/esm2020/lib/wave-form-sampler.mjs +72 -0
- package/esm2020/public-api.mjs +18 -5
- package/fesm2015/stream-chat-angular.mjs +1055 -145
- package/fesm2015/stream-chat-angular.mjs.map +1 -1
- package/fesm2020/stream-chat-angular.mjs +1006 -140
- package/fesm2020/stream-chat-angular.mjs.map +1 -1
- package/lib/attachment.service.d.ts +7 -1
- package/lib/file-utils.d.ts +9 -0
- package/lib/format-duration.d.ts +1 -0
- package/lib/{icon-placeholder → icon/icon-placeholder}/icon-placeholder.component.d.ts +3 -3
- package/lib/icon/icon.component.d.ts +1 -1
- package/lib/icon/icon.module.d.ts +11 -0
- package/lib/{loading-indicator-placeholder → icon/loading-indicator-placeholder}/loading-indicator-placeholder.component.d.ts +1 -1
- package/lib/is-safari.d.ts +1 -0
- package/lib/message-input/message-input-config.service.d.ts +5 -0
- package/lib/message-input/message-input.component.d.ts +19 -5
- package/lib/message-input/voice-recorder.service.d.ts +19 -0
- package/lib/message-list/message-list.component.d.ts +0 -1
- package/lib/stream-chat.module.d.ts +20 -24
- package/lib/types.d.ts +11 -1
- package/lib/voice-recorder/amplitude-recorder.service.d.ts +71 -0
- package/lib/voice-recorder/audio-recorder.service.d.ts +46 -0
- package/lib/voice-recorder/media-recorder.d.ts +46 -0
- package/lib/voice-recorder/mp3-transcoder.d.ts +1 -0
- package/lib/voice-recorder/transcoder.service.d.ts +40 -0
- package/lib/voice-recorder/voice-recorder-wavebar/voice-recorder-wavebar.component.d.ts +21 -0
- package/lib/voice-recorder/voice-recorder.component.d.ts +30 -0
- package/lib/voice-recorder/voice-recorder.module.d.ts +12 -0
- package/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.d.ts +0 -7
- package/lib/voice-recording/voice-recording.component.d.ts +0 -1
- package/lib/voice-recording/voice-recording.module.d.ts +11 -0
- package/lib/wave-form-sampler.d.ts +1 -0
- package/package.json +8 -1
- package/public-api.d.ts +17 -4
- package/src/assets/assets/icons/stream-chat-icons.eot +0 -0
- package/src/assets/assets/icons/stream-chat-icons.svg +4 -0
- package/src/assets/assets/icons/stream-chat-icons.ttf +0 -0
- package/src/assets/assets/icons/stream-chat-icons.woff +0 -0
- package/src/assets/assets/icons/stream-chat-icons.woff2 +0 -0
- package/src/assets/i18n/en.ts +6 -0
- package/src/assets/styles/css/index.css +1 -1
- package/src/assets/styles/css/index.layout.css +1 -1
- package/src/assets/styles/scss/AudioRecorder/AudioRecorder-layout.scss +64 -14
- package/src/assets/styles/scss/AudioRecorder/AudioRecorder-theme.scss +11 -1
- package/src/assets/styles/scss/Icon/Icon-layout.scss +6 -1
- package/src/assets/styles/scss/MessageInput/MessageInput-layout.scss +1 -0
- package/src/assets/styles/scss/MessageInput/MessageInput-theme.scss +1 -0
- package/src/assets/version.ts +1 -1
- package/esm2020/lib/icon-placeholder/icon-placeholder.component.mjs +0 -28
- package/esm2020/lib/is-image-file.mjs +0 -5
- package/lib/is-image-file.d.ts +0 -1
- /package/lib/{loading-indicator → icon/loading-indicator}/loading-indicator.component.d.ts +0 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { BehaviorSubject } from 'rxjs';
|
|
2
|
+
import { createFileFromBlobs, createUriFromBlob, getExtensionFromMimeType, } from '../file-utils';
|
|
3
|
+
import fixWebmDuration from 'fix-webm-duration';
|
|
4
|
+
export var MediaRecordingState;
|
|
5
|
+
(function (MediaRecordingState) {
|
|
6
|
+
MediaRecordingState["PAUSED"] = "paused";
|
|
7
|
+
MediaRecordingState["RECORDING"] = "recording";
|
|
8
|
+
MediaRecordingState["STOPPED"] = "stopped";
|
|
9
|
+
MediaRecordingState["ERROR"] = "error";
|
|
10
|
+
})(MediaRecordingState || (MediaRecordingState = {}));
|
|
11
|
+
export class MultimediaRecorder {
|
|
12
|
+
constructor(notificationService, chatService, transcoder) {
|
|
13
|
+
this.notificationService = notificationService;
|
|
14
|
+
this.chatService = chatService;
|
|
15
|
+
this.transcoder = transcoder;
|
|
16
|
+
this.recordingSubject = new BehaviorSubject(undefined);
|
|
17
|
+
this.recordedChunkDurations = [];
|
|
18
|
+
this.recordingStateSubject = new BehaviorSubject(MediaRecordingState.STOPPED);
|
|
19
|
+
this.generateRecordingTitle = (mimeType) => {
|
|
20
|
+
if (this.customGenerateRecordingTitle) {
|
|
21
|
+
return this.customGenerateRecordingTitle({ mimeType });
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
return `${this.mediaType}_recording_${new Date().toISOString()}.${getExtensionFromMimeType(mimeType)}`; // extension needed so that desktop Safari can play the asset
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
this.handleErrorEvent = (e) => {
|
|
28
|
+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-argument */
|
|
29
|
+
this.logError(e.error);
|
|
30
|
+
this.recordingStateSubject.next(MediaRecordingState.ERROR);
|
|
31
|
+
this.notificationService.addTemporaryNotification('streamChat.An error has occurred during recording');
|
|
32
|
+
void this.stop({ cancel: true });
|
|
33
|
+
};
|
|
34
|
+
this.handleDataavailableEvent = (e) => {
|
|
35
|
+
if (!e.data.size)
|
|
36
|
+
return;
|
|
37
|
+
void this.makeRecording(e.data);
|
|
38
|
+
};
|
|
39
|
+
this.recording$ = this.recordingSubject.asObservable();
|
|
40
|
+
this.recordingState$ = this.recordingStateSubject.asObservable();
|
|
41
|
+
}
|
|
42
|
+
get durationMs() {
|
|
43
|
+
return (this.recordedChunkDurations.reduce((acc, val) => acc + val, 0) +
|
|
44
|
+
(this.startTime ? Date.now() - this.startTime : 0));
|
|
45
|
+
}
|
|
46
|
+
get mediaType() {
|
|
47
|
+
return this.config.mimeType.split('/')?.[0] || 'unknown';
|
|
48
|
+
}
|
|
49
|
+
get isRecording() {
|
|
50
|
+
return (this.recordingStateSubject.value === MediaRecordingState.RECORDING ||
|
|
51
|
+
this.recordingStateSubject.value === MediaRecordingState.PAUSED);
|
|
52
|
+
}
|
|
53
|
+
async makeRecording(blob) {
|
|
54
|
+
const { mimeType } = this.config;
|
|
55
|
+
try {
|
|
56
|
+
if (mimeType.includes('webm')) {
|
|
57
|
+
// The browser does not include duration metadata with the recorded blob
|
|
58
|
+
blob = await fixWebmDuration(blob, this.durationMs, {
|
|
59
|
+
logger: () => null, // prevents polluting the browser console
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
blob = await this.transcoder.transcode(blob);
|
|
63
|
+
if (!blob)
|
|
64
|
+
return;
|
|
65
|
+
const file = createFileFromBlobs({
|
|
66
|
+
blobsArray: [blob],
|
|
67
|
+
fileName: this.generateRecordingTitle(blob.type),
|
|
68
|
+
mimeType: blob.type,
|
|
69
|
+
});
|
|
70
|
+
const previewUrl = await createUriFromBlob(file);
|
|
71
|
+
const extraData = this.enrichWithExtraData();
|
|
72
|
+
this.recordingSubject.next({
|
|
73
|
+
recording: file,
|
|
74
|
+
duration: this.durationMs / 1000,
|
|
75
|
+
asset_url: previewUrl,
|
|
76
|
+
mime_type: mimeType,
|
|
77
|
+
...extraData,
|
|
78
|
+
});
|
|
79
|
+
return file;
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
this.logError(error);
|
|
83
|
+
this.recordingStateSubject.next(MediaRecordingState.ERROR);
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
get recordingState() {
|
|
88
|
+
return this.recordingStateSubject.value;
|
|
89
|
+
}
|
|
90
|
+
async start() {
|
|
91
|
+
if ([MediaRecordingState.RECORDING, MediaRecordingState.PAUSED].includes(this.recordingStateSubject.value)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
this.recordingSubject.next(undefined);
|
|
95
|
+
// account for requirement on iOS as per this bug report: https://bugs.webkit.org/show_bug.cgi?id=252303
|
|
96
|
+
if (!navigator.mediaDevices) {
|
|
97
|
+
console.warn(`[Stream Chat] Media devices API missing, it's possible your app is not served from a secure context (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts)`);
|
|
98
|
+
const error = new Error('Media recording is not supported');
|
|
99
|
+
this.logError(error);
|
|
100
|
+
this.recordingStateSubject.next(MediaRecordingState.ERROR);
|
|
101
|
+
this.notificationService.addTemporaryNotification(`streamChat.Media recording not supported`);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
106
|
+
this.mediaRecorder = new MediaRecorder(stream, this.config);
|
|
107
|
+
this.mediaRecorder.addEventListener('dataavailable', this.handleDataavailableEvent);
|
|
108
|
+
this.mediaRecorder.addEventListener('error', this.handleErrorEvent);
|
|
109
|
+
this.startTime = new Date().getTime();
|
|
110
|
+
this.mediaRecorder.start();
|
|
111
|
+
this.recordingStateSubject.next(MediaRecordingState.RECORDING);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
this.logError(error);
|
|
115
|
+
void this.stop({ cancel: true });
|
|
116
|
+
this.recordingStateSubject.next(MediaRecordingState.ERROR);
|
|
117
|
+
const isNotAllowed = error.name?.includes('NotAllowedError');
|
|
118
|
+
this.notificationService.addTemporaryNotification(isNotAllowed
|
|
119
|
+
? `streamChat.Please grant permission to use microhpone`
|
|
120
|
+
: `streamChat.Error starting recording`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
pause() {
|
|
124
|
+
if (this.recordingStateSubject.value !== MediaRecordingState.RECORDING)
|
|
125
|
+
return;
|
|
126
|
+
if (this.startTime) {
|
|
127
|
+
this.recordedChunkDurations.push(new Date().getTime() - this.startTime);
|
|
128
|
+
this.startTime = undefined;
|
|
129
|
+
}
|
|
130
|
+
this.mediaRecorder?.pause();
|
|
131
|
+
this.recordingStateSubject.next(MediaRecordingState.PAUSED);
|
|
132
|
+
}
|
|
133
|
+
resume() {
|
|
134
|
+
if (this.recordingStateSubject.value !== MediaRecordingState.PAUSED)
|
|
135
|
+
return;
|
|
136
|
+
this.startTime = new Date().getTime();
|
|
137
|
+
this.mediaRecorder?.resume();
|
|
138
|
+
this.recordingStateSubject.next(MediaRecordingState.RECORDING);
|
|
139
|
+
}
|
|
140
|
+
async stop(options = { cancel: false }) {
|
|
141
|
+
if (this.startTime) {
|
|
142
|
+
this.recordedChunkDurations.push(new Date().getTime() - this.startTime);
|
|
143
|
+
this.startTime = undefined;
|
|
144
|
+
}
|
|
145
|
+
let recording;
|
|
146
|
+
this.mediaRecorder?.stop();
|
|
147
|
+
try {
|
|
148
|
+
if (!options.cancel &&
|
|
149
|
+
this.recordingStateSubject.value !== MediaRecordingState.ERROR) {
|
|
150
|
+
recording = await new Promise((resolve, reject) => {
|
|
151
|
+
this.recording$.subscribe((r) => {
|
|
152
|
+
if (r) {
|
|
153
|
+
resolve(r);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
this.recordingState$.subscribe((s) => {
|
|
157
|
+
if (s === MediaRecordingState.ERROR) {
|
|
158
|
+
reject(new Error(`Recording couldn't be created`));
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
this.notificationService.addTemporaryNotification('streamChat.An error has occurred during recording');
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
this.recordedChunkDurations = [];
|
|
169
|
+
this.startTime = undefined;
|
|
170
|
+
this.mediaRecorder?.removeEventListener('dataavailable', this.handleDataavailableEvent);
|
|
171
|
+
this.mediaRecorder?.removeEventListener('error', this.handleErrorEvent);
|
|
172
|
+
if (this.mediaRecorder?.stream?.active) {
|
|
173
|
+
this.mediaRecorder?.stream?.getTracks().forEach((track) => {
|
|
174
|
+
track.stop();
|
|
175
|
+
this.mediaRecorder?.stream?.removeTrack(track);
|
|
176
|
+
});
|
|
177
|
+
this.mediaRecorder = undefined;
|
|
178
|
+
}
|
|
179
|
+
this.recordingStateSubject.next(MediaRecordingState.STOPPED);
|
|
180
|
+
}
|
|
181
|
+
return recording;
|
|
182
|
+
}
|
|
183
|
+
logError(error) {
|
|
184
|
+
this.chatService.chatClient?.logger('error', error.message, {
|
|
185
|
+
error: error,
|
|
186
|
+
tag: ['MediaRecorder'],
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVkaWEtcmVjb3JkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zdHJlYW0tY2hhdC1hbmd1bGFyL3NyYy9saWIvdm9pY2UtcmVjb3JkZXIvbWVkaWEtcmVjb3JkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBYyxNQUFNLE1BQU0sQ0FBQztBQUNuRCxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLGlCQUFpQixFQUNqQix3QkFBd0IsR0FDekIsTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxlQUFlLE1BQU0sbUJBQW1CLENBQUM7QUFPaEQsTUFBTSxDQUFOLElBQVksbUJBS1g7QUFMRCxXQUFZLG1CQUFtQjtJQUM3Qix3Q0FBaUIsQ0FBQTtJQUNqQiw4Q0FBdUIsQ0FBQTtJQUN2QiwwQ0FBbUIsQ0FBQTtJQUNuQixzQ0FBZSxDQUFBO0FBQ2pCLENBQUMsRUFMVyxtQkFBbUIsS0FBbkIsbUJBQW1CLFFBSzlCO0FBTUQsTUFBTSxPQUFnQixrQkFBa0I7SUFtQnRDLFlBQ1ksbUJBQXdDLEVBQ3hDLFdBQThCLEVBQ2hDLFVBQTZCO1FBRjNCLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBcUI7UUFDeEMsZ0JBQVcsR0FBWCxXQUFXLENBQW1CO1FBQ2hDLGVBQVUsR0FBVixVQUFVLENBQW1CO1FBZDdCLHFCQUFnQixHQUFHLElBQUksZUFBZSxDQUU5QyxTQUFTLENBQUMsQ0FBQztRQUlILDJCQUFzQixHQUFhLEVBQUUsQ0FBQztRQUN4QywwQkFBcUIsR0FBRyxJQUFJLGVBQWUsQ0FDakQsbUJBQW1CLENBQUMsT0FBTyxDQUM1QixDQUFDO1FBNkJGLDJCQUFzQixHQUFHLENBQUMsUUFBZ0IsRUFBRSxFQUFFO1lBQzVDLElBQUksSUFBSSxDQUFDLDRCQUE0QixFQUFFO2dCQUNyQyxPQUFPLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7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LEVBQ2YsSUFBSSxDQUFDLHdCQUF3QixDQUM5QixDQUFDO1lBQ0YsSUFBSSxDQUFDLGFBQWEsRUFBRSxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7WUFDeEUsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUU7Z0JBQ3RDLElBQUksQ0FBQyxhQUFhLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO29CQUN4RCxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7b0JBQ2IsSUFBSSxDQUFDLGFBQWEsRUFBRSxNQUFNLEVBQUUsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNqRCxDQUFDLENBQUMsQ0FBQztnQkFDSCxJQUFJLENBQUMsYUFBYSxHQUFHLFNBQVMsQ0FBQzthQUNoQztZQUVELElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDOUQ7UUFFRCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBSVMsUUFBUSxDQUFDLEtBQVk7UUFDN0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTyxFQUFFO1lBQzFELEtBQUssRUFBRSxLQUFLO1lBQ1osR0FBRyxFQUFFLENBQUMsZUFBZSxDQUFDO1NBQ3ZCLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtcbiAgY3JlYXRlRmlsZUZyb21CbG9icyxcbiAgY3JlYXRlVXJpRnJvbUJsb2IsXG4gIGdldEV4dGVuc2lvbkZyb21NaW1lVHlwZSxcbn0gZnJvbSAnLi4vZmlsZS11dGlscyc7XG5pbXBvcnQgeyBOb3RpZmljYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vbm90aWZpY2F0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ2hhdENsaWVudFNlcnZpY2UgfSBmcm9tICcuLi9jaGF0LWNsaWVudC5zZXJ2aWNlJztcbmltcG9ydCBmaXhXZWJtRHVyYXRpb24gZnJvbSAnZml4LXdlYm0tZHVyYXRpb24nO1xuaW1wb3J0IHsgVHJhbnNjb2RlclNlcnZpY2UgfSBmcm9tICcuL3RyYW5zY29kZXIuc2VydmljZSc7XG5pbXBvcnQgeyBNZWRpYVJlY29yZGluZyB9IGZyb20gJy4uL3R5cGVzJztcblxuZXhwb3J0IHR5cGUgTWVkaWFSZWNvcmRlckNvbmZpZyA9IE9taXQ8TWVkaWFSZWNvcmRlck9wdGlvbnMsICdtaW1lVHlwZSc+ICZcbiAgUmVxdWlyZWQ8UGljazxNZWRpYVJlY29yZGVyT3B0aW9ucywgJ21pbWVUeXBlJz4+O1xuXG5leHBvcnQgZW51bSBNZWRpYVJlY29yZGluZ1N0YXRlIHtcbiAgUEFVU0VEID0gJ3BhdXNlZCcsXG4gIFJFQ09SRElORyA9ICdyZWNvcmRpbmcnLFxuICBTVE9QUEVEID0gJ3N0b3BwZWQnLFxuICBFUlJPUiA9ICdlcnJvcicsXG59XG5cbmV4cG9ydCB0eXBlIE1lZGlhUmVjb3JkaW5nVGl0bGVPcHRpb25zID0ge1xuICBtaW1lVHlwZTogc3RyaW5nO1xufTtcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIE11bHRpbWVkaWFSZWNvcmRlcjxUID0gbnVsbD4ge1xuICBhYnN0cmFjdCBjb25maWc6IE1lZGlhUmVjb3JkZXJDb25maWc7XG4gIGN1c3RvbUdlbmVyYXRlUmVjb3JkaW5nVGl0bGU6XG4gICAgfCAoKG9wdGlvbnM6IE1lZGlhUmVjb3JkaW5nVGl0bGVPcHRpb25zKSA9PiBzdHJpbmcpXG4gICAgfCB1bmRlZmluZWQ7XG4gIHJlY29yZGluZ1N0YXRlJDogT2JzZXJ2YWJsZTxNZWRpYVJlY29yZGluZ1N0YXRlPjtcbiAgcmVjb3JkaW5nJDogT2JzZXJ2YWJsZTwoTWVkaWFSZWNvcmRpbmcgJiBUKSB8IHVuZGVmaW5lZD47XG5cbiAgcHJvdGVjdGVkIHJlY29yZGluZ1N1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFxuICAgIChNZWRpYVJlY29yZGluZyAmIFQpIHwgdW5kZWZpbmVkXG4gID4odW5kZWZpbmVkKTtcblxuICBwcm90ZWN0ZWQgbWVkaWFSZWNvcmRlcjogTWVkaWFSZWNvcmRlciB8IHVuZGVmaW5lZDtcbiAgcHJvdGVjdGVkIHN0YXJ0VGltZTogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICBwcm90ZWN0ZWQgcmVjb3JkZWRDaHVua0R1cmF0aW9uczogbnVtYmVyW10gPSBbXTtcbiAgcHJpdmF0ZSByZWNvcmRpbmdTdGF0ZVN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PE1lZGlhUmVjb3JkaW5nU3RhdGU+KFxuICAgIE1lZGlhUmVjb3JkaW5nU3RhdGUuU1RPUFBFRFxuICApO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBub3RpZmljYXRpb25TZXJ2aWNlOiBOb3RpZmljYXRpb25TZXJ2aWNlLFxuICAgIHByb3RlY3RlZCBjaGF0U2VydmljZTogQ2hhdENsaWVudFNlcnZpY2UsXG4gICAgcHJpdmF0ZSB0cmFuc2NvZGVyOiBUcmFuc2NvZGVyU2VydmljZVxuICApIHtcbiAgICB0aGlzLnJlY29yZGluZyQgPSB0aGlzLnJlY29yZGluZ1N1YmplY3QuYXNPYnNlcnZhYmxlKCk7XG4gICAgdGhpcy5yZWNvcmRpbmdTdGF0ZSQgPSB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIGdldCBkdXJhdGlvbk1zKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLnJlY29yZGVkQ2h1bmtEdXJhdGlvbnMucmVkdWNlKChhY2MsIHZhbCkgPT4gYWNjICsgdmFsLCAwKSArXG4gICAgICAodGhpcy5zdGFydFRpbWUgPyBEYXRlLm5vdygpIC0gdGhpcy5zdGFydFRpbWUgOiAwKVxuICAgICk7XG4gIH1cblxuICBnZXQgbWVkaWFUeXBlKCkge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZy5taW1lVHlwZS5zcGxpdCgnLycpPy5bMF0gfHwgJ3Vua25vd24nO1xuICB9XG5cbiAgZ2V0IGlzUmVjb3JkaW5nKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC52YWx1ZSA9PT0gTWVkaWFSZWNvcmRpbmdTdGF0ZS5SRUNPUkRJTkcgfHxcbiAgICAgIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBNZWRpYVJlY29yZGluZ1N0YXRlLlBBVVNFRFxuICAgICk7XG4gIH1cblxuICBnZW5lcmF0ZVJlY29yZGluZ1RpdGxlID0gKG1pbWVUeXBlOiBzdHJpbmcpID0+IHtcbiAgICBpZiAodGhpcy5jdXN0b21HZW5lcmF0ZVJlY29yZGluZ1RpdGxlKSB7XG4gICAgICByZXR1cm4gdGhpcy5jdXN0b21HZW5lcmF0ZVJlY29yZGluZ1RpdGxlKHsgbWltZVR5cGUgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBgJHtcbiAgICAgICAgdGhpcy5tZWRpYVR5cGVcbiAgICAgIH1fcmVjb3JkaW5nXyR7bmV3IERhdGUoKS50b0lTT1N0cmluZygpfS4ke2dldEV4dGVuc2lvbkZyb21NaW1lVHlwZShcbiAgICAgICAgbWltZVR5cGVcbiAgICAgICl9YDsgLy8gZXh0ZW5zaW9uIG5lZWRlZCBzbyB0aGF0IGRlc2t0b3AgU2FmYXJpIGNhbiBwbGF5IHRoZSBhc3NldFxuICAgIH1cbiAgfTtcblxuICBhc3luYyBtYWtlUmVjb3JkaW5nKGJsb2I6IEJsb2IpIHtcbiAgICBjb25zdCB7IG1pbWVUeXBlIH0gPSB0aGlzLmNvbmZpZztcbiAgICB0cnkge1xuICAgICAgaWYgKG1pbWVUeXBlLmluY2x1ZGVzKCd3ZWJtJykpIHtcbiAgICAgICAgLy8gVGhlIGJyb3dzZXIgZG9lcyBub3QgaW5jbHVkZSBkdXJhdGlvbiBtZXRhZGF0YSB3aXRoIHRoZSByZWNvcmRlZCBibG9iXG4gICAgICAgIGJsb2IgPSBhd2FpdCBmaXhXZWJtRHVyYXRpb24oYmxvYiwgdGhpcy5kdXJhdGlvbk1zLCB7XG4gICAgICAgICAgbG9nZ2VyOiAoKSA9PiBudWxsLCAvLyBwcmV2ZW50cyBwb2xsdXRpbmcgdGhlIGJyb3dzZXIgY29uc29sZVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGJsb2IgPSBhd2FpdCB0aGlzLnRyYW5zY29kZXIudHJhbnNjb2RlKGJsb2IpO1xuXG4gICAgICBpZiAoIWJsb2IpIHJldHVybjtcblxuICAgICAgY29uc3QgZmlsZSA9IGNyZWF0ZUZpbGVGcm9tQmxvYnMoe1xuICAgICAgICBibG9ic0FycmF5OiBbYmxvYl0sXG4gICAgICAgIGZpbGVOYW1lOiB0aGlzLmdlbmVyYXRlUmVjb3JkaW5nVGl0bGUoYmxvYi50eXBlKSxcbiAgICAgICAgbWltZVR5cGU6IGJsb2IudHlwZSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcHJldmlld1VybCA9IGF3YWl0IGNyZWF0ZVVyaUZyb21CbG9iKGZpbGUpO1xuXG4gICAgICBjb25zdCBleHRyYURhdGEgPSB0aGlzLmVucmljaFdpdGhFeHRyYURhdGEoKTtcbiAgICAgIHRoaXMucmVjb3JkaW5nU3ViamVjdC5uZXh0KHtcbiAgICAgICAgcmVjb3JkaW5nOiBmaWxlLFxuICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbk1zIC8gMTAwMCxcbiAgICAgICAgYXNzZXRfdXJsOiBwcmV2aWV3VXJsLFxuICAgICAgICBtaW1lX3R5cGU6IG1pbWVUeXBlLFxuICAgICAgICAuLi5leHRyYURhdGEsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBmaWxlO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmxvZ0Vycm9yKGVycm9yIGFzIEVycm9yKTtcbiAgICAgIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0Lm5leHQoTWVkaWFSZWNvcmRpbmdTdGF0ZS5FUlJPUik7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIGhhbmRsZUVycm9yRXZlbnQgPSAoZTogRXZlbnQpID0+IHtcbiAgICAvKiBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hcmd1bWVudCAqL1xuICAgIHRoaXMubG9nRXJyb3IoKGUgYXMgRXJyb3JFdmVudCkuZXJyb3IpO1xuICAgIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0Lm5leHQoTWVkaWFSZWNvcmRpbmdTdGF0ZS5FUlJPUik7XG4gICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLmFkZFRlbXBvcmFyeU5vdGlmaWNhdGlvbihcbiAgICAgICdzdHJlYW1DaGF0LkFuIGVycm9yIGhhcyBvY2N1cnJlZCBkdXJpbmcgcmVjb3JkaW5nJ1xuICAgICk7XG4gICAgdm9pZCB0aGlzLnN0b3AoeyBjYW5jZWw6IHRydWUgfSk7XG4gIH07XG5cbiAgaGFuZGxlRGF0YWF2YWlsYWJsZUV2ZW50ID0gKGU6IEJsb2JFdmVudCkgPT4ge1xuICAgIGlmICghZS5kYXRhLnNpemUpIHJldHVybjtcbiAgICB2b2lkIHRoaXMubWFrZVJlY29yZGluZyhlLmRhdGEpO1xuICB9O1xuXG4gIGdldCByZWNvcmRpbmdTdGF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QudmFsdWU7XG4gIH1cblxuICBhc3luYyBzdGFydCgpIHtcbiAgICBpZiAoXG4gICAgICBbTWVkaWFSZWNvcmRpbmdTdGF0ZS5SRUNPUkRJTkcsIE1lZGlhUmVjb3JkaW5nU3RhdGUuUEFVU0VEXS5pbmNsdWRlcyhcbiAgICAgICAgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QudmFsdWVcbiAgICAgIClcbiAgICApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnJlY29yZGluZ1N1YmplY3QubmV4dCh1bmRlZmluZWQpO1xuXG4gICAgLy8gYWNjb3VudCBmb3IgcmVxdWlyZW1lbnQgb24gaU9TIGFzIHBlciB0aGlzIGJ1ZyByZXBvcnQ6IGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0yNTIzMDNcbiAgICBpZiAoIW5hdmlnYXRvci5tZWRpYURldmljZXMpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFtTdHJlYW0gQ2hhdF0gTWVkaWEgZGV2aWNlcyBBUEkgbWlzc2luZywgaXQncyBwb3NzaWJsZSB5b3VyIGFwcCBpcyBub3Qgc2VydmVkIGZyb20gYSBzZWN1cmUgY29udGV4dCAoaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvU2VjdXJpdHkvU2VjdXJlX0NvbnRleHRzKWBcbiAgICAgICk7XG4gICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcignTWVkaWEgcmVjb3JkaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICAgIHRoaXMubG9nRXJyb3IoZXJyb3IpO1xuICAgICAgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QubmV4dChNZWRpYVJlY29yZGluZ1N0YXRlLkVSUk9SKTtcbiAgICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5hZGRUZW1wb3JhcnlOb3RpZmljYXRpb24oXG4gICAgICAgIGBzdHJlYW1DaGF0Lk1lZGlhIHJlY29yZGluZyBub3Qgc3VwcG9ydGVkYFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgc3RyZWFtID0gYXdhaXQgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoeyBhdWRpbzogdHJ1ZSB9KTtcbiAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IG5ldyBNZWRpYVJlY29yZGVyKHN0cmVhbSwgdGhpcy5jb25maWcpO1xuXG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgJ2RhdGFhdmFpbGFibGUnLFxuICAgICAgICB0aGlzLmhhbmRsZURhdGFhdmFpbGFibGVFdmVudFxuICAgICAgKTtcbiAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5hZGRFdmVudExpc3RlbmVyKCdlcnJvcicsIHRoaXMuaGFuZGxlRXJyb3JFdmVudCk7XG5cbiAgICAgIHRoaXMuc3RhcnRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhcnQoKTtcblxuICAgICAgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QubmV4dChNZWRpYVJlY29yZGluZ1N0YXRlLlJFQ09SRElORyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMubG9nRXJyb3IoZXJyb3IgYXMgRXJyb3IpO1xuICAgICAgdm9pZCB0aGlzLnN0b3AoeyBjYW5jZWw6IHRydWUgfSk7XG4gICAgICB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC5uZXh0KE1lZGlhUmVjb3JkaW5nU3RhdGUuRVJST1IpO1xuICAgICAgY29uc3QgaXNOb3RBbGxvd2VkID0gKGVycm9yIGFzIEVycm9yKS5uYW1lPy5pbmNsdWRlcygnTm90QWxsb3dlZEVycm9yJyk7XG4gICAgICB0aGlzLm5vdGlmaWNhdGlvblNlcnZpY2UuYWRkVGVtcG9yYXJ5Tm90aWZpY2F0aW9uKFxuICAgICAgICBpc05vdEFsbG93ZWRcbiAgICAgICAgICA/IGBzdHJlYW1DaGF0LlBsZWFzZSBncmFudCBwZXJtaXNzaW9uIHRvIHVzZSBtaWNyb2hwb25lYFxuICAgICAgICAgIDogYHN0cmVhbUNoYXQuRXJyb3Igc3RhcnRpbmcgcmVjb3JkaW5nYFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwYXVzZSgpIHtcbiAgICBpZiAodGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QudmFsdWUgIT09IE1lZGlhUmVjb3JkaW5nU3RhdGUuUkVDT1JESU5HKVxuICAgICAgcmV0dXJuO1xuICAgIGlmICh0aGlzLnN0YXJ0VGltZSkge1xuICAgICAgdGhpcy5yZWNvcmRlZENodW5rRHVyYXRpb25zLnB1c2gobmV3IERhdGUoKS5nZXRUaW1lKCkgLSB0aGlzLnN0YXJ0VGltZSk7XG4gICAgICB0aGlzLnN0YXJ0VGltZSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdGhpcy5tZWRpYVJlY29yZGVyPy5wYXVzZSgpO1xuICAgIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0Lm5leHQoTWVkaWFSZWNvcmRpbmdTdGF0ZS5QQVVTRUQpO1xuICB9XG5cbiAgcmVzdW1lKCkge1xuICAgIGlmICh0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC52YWx1ZSAhPT0gTWVkaWFSZWNvcmRpbmdTdGF0ZS5QQVVTRUQpIHJldHVybjtcbiAgICB0aGlzLnN0YXJ0VGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgIHRoaXMubWVkaWFSZWNvcmRlcj8ucmVzdW1lKCk7XG4gICAgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QubmV4dChNZWRpYVJlY29yZGluZ1N0YXRlLlJFQ09SRElORyk7XG4gIH1cblxuICBhc3luYyBzdG9wKG9wdGlvbnM6IHsgY2FuY2VsOiBib29sZWFuIH0gPSB7IGNhbmNlbDogZmFsc2UgfSkge1xuICAgIGlmICh0aGlzLnN0YXJ0VGltZSkge1xuICAgICAgdGhpcy5yZWNvcmRlZENodW5rRHVyYXRpb25zLnB1c2gobmV3IERhdGUoKS5nZXRUaW1lKCkgLSB0aGlzLnN0YXJ0VGltZSk7XG4gICAgICB0aGlzLnN0YXJ0VGltZSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgbGV0IHJlY29yZGluZyE6IE1lZGlhUmVjb3JkaW5nICYgVDtcbiAgICB0aGlzLm1lZGlhUmVjb3JkZXI/LnN0b3AoKTtcbiAgICB0cnkge1xuICAgICAgaWYgKFxuICAgICAgICAhb3B0aW9ucy5jYW5jZWwgJiZcbiAgICAgICAgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QudmFsdWUgIT09IE1lZGlhUmVjb3JkaW5nU3RhdGUuRVJST1JcbiAgICAgICkge1xuICAgICAgICByZWNvcmRpbmcgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgdGhpcy5yZWNvcmRpbmckLnN1YnNjcmliZSgocikgPT4ge1xuICAgICAgICAgICAgaWYgKHIpIHtcbiAgICAgICAgICAgICAgcmVzb2x2ZShyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aGlzLnJlY29yZGluZ1N0YXRlJC5zdWJzY3JpYmUoKHMpID0+IHtcbiAgICAgICAgICAgIGlmIChzID09PSBNZWRpYVJlY29yZGluZ1N0YXRlLkVSUk9SKSB7XG4gICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYFJlY29yZGluZyBjb3VsZG4ndCBiZSBjcmVhdGVkYCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5hZGRUZW1wb3JhcnlOb3RpZmljYXRpb24oXG4gICAgICAgICdzdHJlYW1DaGF0LkFuIGVycm9yIGhhcyBvY2N1cnJlZCBkdXJpbmcgcmVjb3JkaW5nJ1xuICAgICAgKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5yZWNvcmRlZENodW5rRHVyYXRpb25zID0gW107XG4gICAgICB0aGlzLnN0YXJ0VGltZSA9IHVuZGVmaW5lZDtcblxuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyPy5yZW1vdmVFdmVudExpc3RlbmVyKFxuICAgICAgICAnZGF0YWF2YWlsYWJsZScsXG4gICAgICAgIHRoaXMuaGFuZGxlRGF0YWF2YWlsYWJsZUV2ZW50XG4gICAgICApO1xuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyPy5yZW1vdmVFdmVudExpc3RlbmVyKCdlcnJvcicsIHRoaXMuaGFuZGxlRXJyb3JFdmVudCk7XG4gICAgICBpZiAodGhpcy5tZWRpYVJlY29yZGVyPy5zdHJlYW0/LmFjdGl2ZSkge1xuICAgICAgICB0aGlzLm1lZGlhUmVjb3JkZXI/LnN0cmVhbT8uZ2V0VHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgICAgdGhpcy5tZWRpYVJlY29yZGVyPy5zdHJlYW0/LnJlbW92ZVRyYWNrKHRyYWNrKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMubWVkaWFSZWNvcmRlciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QubmV4dChNZWRpYVJlY29yZGluZ1N0YXRlLlNUT1BQRUQpO1xuICAgIH1cblxuICAgIHJldHVybiByZWNvcmRpbmc7XG4gIH1cblxuICBwcm90ZWN0ZWQgYWJzdHJhY3QgZW5yaWNoV2l0aEV4dHJhRGF0YSgpOiBUO1xuXG4gIHByb3RlY3RlZCBsb2dFcnJvcihlcnJvcjogRXJyb3IpIHtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRDbGllbnQ/LmxvZ2dlcignZXJyb3InLCBlcnJvci5tZXNzYWdlLCB7XG4gICAgICBlcnJvcjogZXJyb3IsXG4gICAgICB0YWc6IFsnTWVkaWFSZWNvcmRlciddLFxuICAgIH0pO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const ENCODING_BIT_RATE = 128; // kbps;
|
|
2
|
+
const COUNT_SAMPLES_PER_ENCODED_BLOCK = 1152;
|
|
3
|
+
const SAMPLE_RATE = 16000;
|
|
4
|
+
const readFileAsArrayBuffer = (blob) => new Promise((resolve, reject) => {
|
|
5
|
+
const blobReader = new FileReader();
|
|
6
|
+
blobReader.onload = () => {
|
|
7
|
+
resolve(blobReader.result);
|
|
8
|
+
};
|
|
9
|
+
blobReader.onerror = () => {
|
|
10
|
+
reject(blobReader.error);
|
|
11
|
+
};
|
|
12
|
+
blobReader.readAsArrayBuffer(blob);
|
|
13
|
+
});
|
|
14
|
+
const toAudioBuffer = async (blob) => {
|
|
15
|
+
const audioCtx = new AudioContext();
|
|
16
|
+
const arrayBuffer = await readFileAsArrayBuffer(blob);
|
|
17
|
+
const decodedData = await audioCtx.decodeAudioData(arrayBuffer);
|
|
18
|
+
if (audioCtx.state !== 'closed')
|
|
19
|
+
await audioCtx.close();
|
|
20
|
+
return decodedData;
|
|
21
|
+
};
|
|
22
|
+
const renderAudio = async (audioBuffer, sampleRate) => {
|
|
23
|
+
const offlineAudioCtx = new OfflineAudioContext(audioBuffer.numberOfChannels, audioBuffer.duration * sampleRate, sampleRate);
|
|
24
|
+
const source = offlineAudioCtx.createBufferSource();
|
|
25
|
+
source.buffer = audioBuffer;
|
|
26
|
+
source.connect(offlineAudioCtx.destination);
|
|
27
|
+
source.start();
|
|
28
|
+
return await offlineAudioCtx.startRendering();
|
|
29
|
+
};
|
|
30
|
+
const float32ArrayToInt16Array = (float32Arr) => {
|
|
31
|
+
const int16Arr = new Int16Array(float32Arr.length);
|
|
32
|
+
for (let i = 0; i < float32Arr.length; i++) {
|
|
33
|
+
const float32Value = float32Arr[i];
|
|
34
|
+
// Clamp the float value between -1 and 1
|
|
35
|
+
const clampedValue = Math.max(-1, Math.min(1, float32Value));
|
|
36
|
+
// Convert the float value to a signed 16-bit integer
|
|
37
|
+
int16Arr[i] = Math.round(clampedValue * 32767);
|
|
38
|
+
}
|
|
39
|
+
return int16Arr;
|
|
40
|
+
};
|
|
41
|
+
const splitDataByChannel = (audioBuffer) => Array.from({ length: audioBuffer.numberOfChannels }, (_, i) => audioBuffer.getChannelData(i)).map(float32ArrayToInt16Array);
|
|
42
|
+
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument */
|
|
43
|
+
export async function encodeWebmToMp3(blob, lameJs) {
|
|
44
|
+
const audioBuffer = await renderAudio(await toAudioBuffer(blob), SAMPLE_RATE);
|
|
45
|
+
const channelCount = audioBuffer.numberOfChannels;
|
|
46
|
+
const dataByChannel = splitDataByChannel(audioBuffer);
|
|
47
|
+
const mp3Encoder = new lameJs.Mp3Encoder(channelCount, SAMPLE_RATE, ENCODING_BIT_RATE);
|
|
48
|
+
const dataBuffer = [];
|
|
49
|
+
let remaining = dataByChannel[0].length;
|
|
50
|
+
for (let i = 0; remaining >= COUNT_SAMPLES_PER_ENCODED_BLOCK; i += COUNT_SAMPLES_PER_ENCODED_BLOCK) {
|
|
51
|
+
const [leftChannelBlock, rightChannelBlock] = dataByChannel.map((channel) => channel.subarray(i, i + COUNT_SAMPLES_PER_ENCODED_BLOCK));
|
|
52
|
+
dataBuffer.push(new Int8Array(mp3Encoder.encodeBuffer(leftChannelBlock, rightChannelBlock)));
|
|
53
|
+
remaining -= COUNT_SAMPLES_PER_ENCODED_BLOCK;
|
|
54
|
+
}
|
|
55
|
+
const lastBlock = mp3Encoder.flush();
|
|
56
|
+
if (lastBlock.length)
|
|
57
|
+
dataBuffer.push(new Int8Array(lastBlock));
|
|
58
|
+
return new Blob(dataBuffer, { type: 'audio/mp3;sbu_type=voice' });
|
|
59
|
+
}
|
|
60
|
+
/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument */
|
|
61
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXAzLXRyYW5zY29kZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zdHJlYW0tY2hhdC1hbmd1bGFyL3NyYy9saWIvdm9pY2UtcmVjb3JkZXIvbXAzLXRyYW5zY29kZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxpQkFBaUIsR0FBRyxHQUFHLENBQUMsQ0FBQyxRQUFRO0FBQ3ZDLE1BQU0sK0JBQStCLEdBQUcsSUFBSSxDQUFDO0FBQzdDLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQztBQUUxQixNQUFNLHFCQUFxQixHQUFHLENBQUMsSUFBVSxFQUF3QixFQUFFLENBQ2pFLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO0lBQzlCLE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxFQUFFLENBQUM7SUFDcEMsVUFBVSxDQUFDLE1BQU0sR0FBRyxHQUFHLEVBQUU7UUFDdkIsT0FBTyxDQUFDLFVBQVUsQ0FBQyxNQUFxQixDQUFDLENBQUM7SUFDNUMsQ0FBQyxDQUFDO0lBRUYsVUFBVSxDQUFDLE9BQU8sR0FBRyxHQUFHLEVBQUU7UUFDeEIsTUFBTSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMzQixDQUFDLENBQUM7SUFFRixVQUFVLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDckMsQ0FBQyxDQUFDLENBQUM7QUFFTCxNQUFNLGFBQWEsR0FBRyxLQUFLLEVBQUUsSUFBVSxFQUFFLEVBQUU7SUFDekMsTUFBTSxRQUFRLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztJQUVwQyxNQUFNLFdBQVcsR0FBRyxNQUFNLHFCQUFxQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RELE1BQU0sV0FBVyxHQUFHLE1BQU0sUUFBUSxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNoRSxJQUFJLFFBQVEsQ0FBQyxLQUFLLEtBQUss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QztRQUNGLFVBQVUsQ0FBQyxJQUFJLENBQ2IsSUFBSSxTQUFTLENBQ1gsVUFBVSxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsRUFBRSxpQkFBaUIsQ0FBQyxDQUM3RCxDQUNGLENBQUM7UUFDRixTQUFTLElBQUksK0JBQStCLENBQUM7S0FDOUM7SUFFRCxNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDckMsSUFBSSxTQUFTLENBQUMsTUFBTTtRQUFFLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUNoRSxPQUFPLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxFQUFFLElBQUksRUFBRSwwQkFBMEIsRUFBRSxDQUFDLENBQUM7QUFDcEUsQ0FBQztBQUNELHFOQUFxTiIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IEVOQ09ESU5HX0JJVF9SQVRFID0gMTI4OyAvLyBrYnBzO1xuY29uc3QgQ09VTlRfU0FNUExFU19QRVJfRU5DT0RFRF9CTE9DSyA9IDExNTI7XG5jb25zdCBTQU1QTEVfUkFURSA9IDE2MDAwO1xuXG5jb25zdCByZWFkRmlsZUFzQXJyYXlCdWZmZXIgPSAoYmxvYjogQmxvYik6IFByb21pc2U8QXJyYXlCdWZmZXI+ID0+XG4gIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCBibG9iUmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcbiAgICBibG9iUmVhZGVyLm9ubG9hZCA9ICgpID0+IHtcbiAgICAgIHJlc29sdmUoYmxvYlJlYWRlci5yZXN1bHQgYXMgQXJyYXlCdWZmZXIpO1xuICAgIH07XG5cbiAgICBibG9iUmVhZGVyLm9uZXJyb3IgPSAoKSA9PiB7XG4gICAgICByZWplY3QoYmxvYlJlYWRlci5lcnJvcik7XG4gICAgfTtcblxuICAgIGJsb2JSZWFkZXIucmVhZEFzQXJyYXlCdWZmZXIoYmxvYik7XG4gIH0pO1xuXG5jb25zdCB0b0F1ZGlvQnVmZmVyID0gYXN5bmMgKGJsb2I6IEJsb2IpID0+IHtcbiAgY29uc3QgYXVkaW9DdHggPSBuZXcgQXVkaW9Db250ZXh0KCk7XG5cbiAgY29uc3QgYXJyYXlCdWZmZXIgPSBhd2FpdCByZWFkRmlsZUFzQXJyYXlCdWZmZXIoYmxvYik7XG4gIGNvbnN0IGRlY29kZWREYXRhID0gYXdhaXQgYXVkaW9DdHguZGVjb2RlQXVkaW9EYXRhKGFycmF5QnVmZmVyKTtcbiAgaWYgKGF1ZGlvQ3R4LnN0YXRlICE9PSAnY2xvc2VkJykgYXdhaXQgYXVkaW9DdHguY2xvc2UoKTtcbiAgcmV0dXJuIGRlY29kZWREYXRhO1xufTtcblxuY29uc3QgcmVuZGVyQXVkaW8gPSBhc3luYyAoYXVkaW9CdWZmZXI6IEF1ZGlvQnVmZmVyLCBzYW1wbGVSYXRlOiBudW1iZXIpID0+IHtcbiAgY29uc3Qgb2ZmbGluZUF1ZGlvQ3R4ID0gbmV3IE9mZmxpbmVBdWRpb0NvbnRleHQoXG4gICAgYXVkaW9CdWZmZXIubnVtYmVyT2ZDaGFubmVscyxcbiAgICBhdWRpb0J1ZmZlci5kdXJhdGlvbiAqIHNhbXBsZVJhdGUsXG4gICAgc2FtcGxlUmF0ZVxuICApO1xuICBjb25zdCBzb3VyY2UgPSBvZmZsaW5lQXVkaW9DdHguY3JlYXRlQnVmZmVyU291cmNlKCk7XG4gIHNvdXJjZS5idWZmZXIgPSBhdWRpb0J1ZmZlcjtcbiAgc291cmNlLmNvbm5lY3Qob2ZmbGluZUF1ZGlvQ3R4LmRlc3RpbmF0aW9uKTtcbiAgc291cmNlLnN0YXJ0KCk7XG5cbiAgcmV0dXJuIGF3YWl0IG9mZmxpbmVBdWRpb0N0eC5zdGFydFJlbmRlcmluZygpO1xufTtcblxuY29uc3QgZmxvYXQzMkFycmF5VG9JbnQxNkFycmF5ID0gKGZsb2F0MzJBcnI6IEZsb2F0MzJBcnJheSkgPT4ge1xuICBjb25zdCBpbnQxNkFyciA9IG5ldyBJbnQxNkFycmF5KGZsb2F0MzJBcnIubGVuZ3RoKTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBmbG9hdDMyQXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgZmxvYXQzMlZhbHVlID0gZmxvYXQzMkFycltpXTtcbiAgICAvLyBDbGFtcCB0aGUgZmxvYXQgdmFsdWUgYmV0d2VlbiAtMSBhbmQgMVxuICAgIGNvbnN0IGNsYW1wZWRWYWx1ZSA9IE1hdGgubWF4KC0xLCBNYXRoLm1pbigxLCBmbG9hdDMyVmFsdWUpKTtcbiAgICAvLyBDb252ZXJ0IHRoZSBmbG9hdCB2YWx1ZSB0byBhIHNpZ25lZCAxNi1iaXQgaW50ZWdlclxuICAgIGludDE2QXJyW2ldID0gTWF0aC5yb3VuZChjbGFtcGVkVmFsdWUgKiAzMjc2Nyk7XG4gIH1cbiAgcmV0dXJuIGludDE2QXJyO1xufTtcblxuY29uc3Qgc3BsaXREYXRhQnlDaGFubmVsID0gKGF1ZGlvQnVmZmVyOiBBdWRpb0J1ZmZlcikgPT5cbiAgQXJyYXkuZnJvbSh7IGxlbmd0aDogYXVkaW9CdWZmZXIubnVtYmVyT2ZDaGFubmVscyB9LCAoXywgaSkgPT5cbiAgICBhdWRpb0J1ZmZlci5nZXRDaGFubmVsRGF0YShpKVxuICApLm1hcChmbG9hdDMyQXJyYXlUb0ludDE2QXJyYXkpO1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55LCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWFzc2lnbm1lbnQsIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtY2FsbCwgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1tZW1iZXItYWNjZXNzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWFyZ3VtZW50ICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZW5jb2RlV2VibVRvTXAzKGJsb2I6IEJsb2IsIGxhbWVKczogYW55KSB7XG4gIGNvbnN0IGF1ZGlvQnVmZmVyID0gYXdhaXQgcmVuZGVyQXVkaW8oYXdhaXQgdG9BdWRpb0J1ZmZlcihibG9iKSwgU0FNUExFX1JBVEUpO1xuICBjb25zdCBjaGFubmVsQ291bnQgPSBhdWRpb0J1ZmZlci5udW1iZXJPZkNoYW5uZWxzO1xuICBjb25zdCBkYXRhQnlDaGFubmVsID0gc3BsaXREYXRhQnlDaGFubmVsKGF1ZGlvQnVmZmVyKTtcbiAgY29uc3QgbXAzRW5jb2RlciA9IG5ldyBsYW1lSnMuTXAzRW5jb2RlcihcbiAgICBjaGFubmVsQ291bnQsXG4gICAgU0FNUExFX1JBVEUsXG4gICAgRU5DT0RJTkdfQklUX1JBVEVcbiAgKTtcblxuICBjb25zdCBkYXRhQnVmZmVyOiBJbnQ4QXJyYXlbXSA9IFtdO1xuICBsZXQgcmVtYWluaW5nID0gZGF0YUJ5Q2hhbm5lbFswXS5sZW5ndGg7XG4gIGZvciAoXG4gICAgbGV0IGkgPSAwO1xuICAgIHJlbWFpbmluZyA+PSBDT1VOVF9TQU1QTEVTX1BFUl9FTkNPREVEX0JMT0NLO1xuICAgIGkgKz0gQ09VTlRfU0FNUExFU19QRVJfRU5DT0RFRF9CTE9DS1xuICApIHtcbiAgICBjb25zdCBbbGVmdENoYW5uZWxCbG9jaywgcmlnaHRDaGFubmVsQmxvY2tdID0gZGF0YUJ5Q2hhbm5lbC5tYXAoKGNoYW5uZWwpID0+XG4gICAgICBjaGFubmVsLnN1YmFycmF5KGksIGkgKyBDT1VOVF9TQU1QTEVTX1BFUl9FTkNPREVEX0JMT0NLKVxuICAgICk7XG4gICAgZGF0YUJ1ZmZlci5wdXNoKFxuICAgICAgbmV3IEludDhBcnJheShcbiAgICAgICAgbXAzRW5jb2Rlci5lbmNvZGVCdWZmZXIobGVmdENoYW5uZWxCbG9jaywgcmlnaHRDaGFubmVsQmxvY2spXG4gICAgICApXG4gICAgKTtcbiAgICByZW1haW5pbmcgLT0gQ09VTlRfU0FNUExFU19QRVJfRU5DT0RFRF9CTE9DSztcbiAgfVxuXG4gIGNvbnN0IGxhc3RCbG9jayA9IG1wM0VuY29kZXIuZmx1c2goKTtcbiAgaWYgKGxhc3RCbG9jay5sZW5ndGgpIGRhdGFCdWZmZXIucHVzaChuZXcgSW50OEFycmF5KGxhc3RCbG9jaykpO1xuICByZXR1cm4gbmV3IEJsb2IoZGF0YUJ1ZmZlciwgeyB0eXBlOiAnYXVkaW8vbXAzO3NidV90eXBlPXZvaWNlJyB9KTtcbn1cbi8qIGVzbGludC1lbmFibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSwgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hc3NpZ25tZW50LCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWNhbGwsIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtbWVtYmVyLWFjY2VzcywgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hcmd1bWVudCAqL1xuIl19
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Injectable, NgModule } from '@angular/core';
|
|
2
|
+
import { readBlobAsArrayBuffer } from '../file-utils';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
const WAV_HEADER_LENGTH_BYTES = 44;
|
|
5
|
+
const BYTES_PER_SAMPLE = 2;
|
|
6
|
+
const RIFF_FILE_MAX_BYTES = 4294967295;
|
|
7
|
+
const HEADER = {
|
|
8
|
+
AUDIO_FORMAT: { offset: 20, value: 1 },
|
|
9
|
+
BITS_PER_SAMPLE: { offset: 34, value: BYTES_PER_SAMPLE * 8 },
|
|
10
|
+
BLOCK_ALIGN: { offset: 32 },
|
|
11
|
+
BYTE_RATE: { offset: 28 },
|
|
12
|
+
CHANNEL_COUNT: { offset: 22 },
|
|
13
|
+
CHUNK_ID: { offset: 0, value: 0x52494646 },
|
|
14
|
+
CHUNK_SIZE: { offset: 4 },
|
|
15
|
+
FILE_FORMAT: { offset: 8, value: 0x57415645 },
|
|
16
|
+
SAMPLE_RATE: { offset: 24 },
|
|
17
|
+
SUBCHUNK1_ID: { offset: 12, value: 0x666d7420 },
|
|
18
|
+
SUBCHUNK1_SIZE: { offset: 16, value: 16 },
|
|
19
|
+
SUBCHUNK2_ID: { offset: 36, value: 0x64617461 },
|
|
20
|
+
SUBCHUNK2_SIZE: { offset: 40 }, // actual audio data size
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The `TranscoderService` is used to transcibe audio recording to a format that's supported by all major browsers. The SDK uses this to create voice messages.
|
|
24
|
+
*
|
|
25
|
+
* If you want to use your own transcoder you can provide a `customTranscoder`.
|
|
26
|
+
*/
|
|
27
|
+
export class TranscoderService {
|
|
28
|
+
constructor() {
|
|
29
|
+
this.config = {
|
|
30
|
+
sampleRate: 16000,
|
|
31
|
+
};
|
|
32
|
+
this.splitDataByChannel = (audioBuffer) => Array.from({ length: audioBuffer.numberOfChannels }, (_, i) => audioBuffer.getChannelData(i));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The default transcoder will leave audio/mp4 files as is, and transcode webm files to wav. If you want to customize this, you can provide your own transcoder using the `customTranscoder` field
|
|
36
|
+
* @param blob
|
|
37
|
+
* @returns the transcoded file
|
|
38
|
+
*/
|
|
39
|
+
async transcode(blob) {
|
|
40
|
+
if (this.customTranscoder) {
|
|
41
|
+
return this.customTranscoder(blob);
|
|
42
|
+
}
|
|
43
|
+
if (blob.type.includes('audio/mp4')) {
|
|
44
|
+
return blob;
|
|
45
|
+
}
|
|
46
|
+
const audioBuffer = await this.renderAudio(await this.toAudioBuffer(blob), this.config.sampleRate);
|
|
47
|
+
const numberOfSamples = audioBuffer.duration * this.config.sampleRate;
|
|
48
|
+
const fileSizeBytes = numberOfSamples * audioBuffer.numberOfChannels * BYTES_PER_SAMPLE +
|
|
49
|
+
WAV_HEADER_LENGTH_BYTES;
|
|
50
|
+
const arrayBuffer = new ArrayBuffer(fileSizeBytes);
|
|
51
|
+
this.writeWavHeader({
|
|
52
|
+
arrayBuffer,
|
|
53
|
+
channelCount: audioBuffer.numberOfChannels,
|
|
54
|
+
sampleRate: this.config.sampleRate,
|
|
55
|
+
});
|
|
56
|
+
this.writeWavAudioData({
|
|
57
|
+
arrayBuffer,
|
|
58
|
+
dataByChannel: this.splitDataByChannel(audioBuffer),
|
|
59
|
+
});
|
|
60
|
+
return new Blob([arrayBuffer], { type: 'audio/wav' });
|
|
61
|
+
}
|
|
62
|
+
async renderAudio(audioBuffer, sampleRate) {
|
|
63
|
+
const offlineAudioCtx = new OfflineAudioContext(audioBuffer.numberOfChannels, audioBuffer.duration * sampleRate, sampleRate);
|
|
64
|
+
const source = offlineAudioCtx.createBufferSource();
|
|
65
|
+
source.buffer = audioBuffer;
|
|
66
|
+
source.connect(offlineAudioCtx.destination);
|
|
67
|
+
source.start();
|
|
68
|
+
return await offlineAudioCtx.startRendering();
|
|
69
|
+
}
|
|
70
|
+
async toAudioBuffer(blob) {
|
|
71
|
+
const audioCtx = new AudioContext();
|
|
72
|
+
const arrayBuffer = await readBlobAsArrayBuffer(blob);
|
|
73
|
+
const decodedData = await audioCtx.decodeAudioData(arrayBuffer);
|
|
74
|
+
if (audioCtx.state !== 'closed')
|
|
75
|
+
await audioCtx.close();
|
|
76
|
+
return decodedData;
|
|
77
|
+
}
|
|
78
|
+
writeWavAudioData({ arrayBuffer, dataByChannel, }) {
|
|
79
|
+
const dataView = new DataView(arrayBuffer);
|
|
80
|
+
const channelCount = dataByChannel.length;
|
|
81
|
+
dataByChannel.forEach((channelData, channelIndex) => {
|
|
82
|
+
let writeOffset = WAV_HEADER_LENGTH_BYTES + channelCount * channelIndex;
|
|
83
|
+
channelData.forEach((float32Value) => {
|
|
84
|
+
dataView.setInt16(writeOffset, float32Value < 0
|
|
85
|
+
? Math.max(-1, float32Value) * 32768
|
|
86
|
+
: Math.min(1, float32Value) * 32767, true);
|
|
87
|
+
writeOffset += channelCount * BYTES_PER_SAMPLE;
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
writeWavHeader({ arrayBuffer, channelCount, sampleRate, }) {
|
|
92
|
+
const byteRate = sampleRate * channelCount * BYTES_PER_SAMPLE; // bytes/sec
|
|
93
|
+
const blockAlign = channelCount * BYTES_PER_SAMPLE;
|
|
94
|
+
const dataView = new DataView(arrayBuffer);
|
|
95
|
+
/*
|
|
96
|
+
* The maximum size of a RIFF file is 4294967295 bytes and since the header takes up 44 bytes there are 4294967251 bytes left for the
|
|
97
|
+
* data chunk.
|
|
98
|
+
*/
|
|
99
|
+
const dataChunkSize = Math.min(dataView.byteLength - WAV_HEADER_LENGTH_BYTES, RIFF_FILE_MAX_BYTES - WAV_HEADER_LENGTH_BYTES);
|
|
100
|
+
dataView.setUint32(HEADER.CHUNK_ID.offset, HEADER.CHUNK_ID.value); // "RIFF"
|
|
101
|
+
dataView.setUint32(HEADER.CHUNK_SIZE.offset, arrayBuffer.byteLength - 8, true); // adjustment for the first two headers - chunk id + file size
|
|
102
|
+
dataView.setUint32(HEADER.FILE_FORMAT.offset, HEADER.FILE_FORMAT.value); // "WAVE"
|
|
103
|
+
dataView.setUint32(HEADER.SUBCHUNK1_ID.offset, HEADER.SUBCHUNK1_ID.value); // "fmt "
|
|
104
|
+
dataView.setUint32(HEADER.SUBCHUNK1_SIZE.offset, HEADER.SUBCHUNK1_SIZE.value, true);
|
|
105
|
+
dataView.setUint16(HEADER.AUDIO_FORMAT.offset, HEADER.AUDIO_FORMAT.value, true);
|
|
106
|
+
dataView.setUint16(HEADER.CHANNEL_COUNT.offset, channelCount, true);
|
|
107
|
+
dataView.setUint32(HEADER.SAMPLE_RATE.offset, sampleRate, true);
|
|
108
|
+
dataView.setUint32(HEADER.BYTE_RATE.offset, byteRate, true);
|
|
109
|
+
dataView.setUint16(HEADER.BLOCK_ALIGN.offset, blockAlign, true);
|
|
110
|
+
dataView.setUint16(HEADER.BITS_PER_SAMPLE.offset, HEADER.BITS_PER_SAMPLE.value, true);
|
|
111
|
+
dataView.setUint32(HEADER.SUBCHUNK2_ID.offset, HEADER.SUBCHUNK2_ID.value); // "data"
|
|
112
|
+
dataView.setUint32(HEADER.SUBCHUNK2_SIZE.offset, dataChunkSize, true);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
TranscoderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: TranscoderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
116
|
+
TranscoderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: TranscoderService, providedIn: NgModule });
|
|
117
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: TranscoderService, decorators: [{
|
|
118
|
+
type: Injectable,
|
|
119
|
+
args: [{ providedIn: NgModule }]
|
|
120
|
+
}], ctorParameters: function () { return []; } });
|
|
121
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNjb2Rlci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc3RyZWFtLWNoYXQtYW5ndWxhci9zcmMvbGliL3ZvaWNlLXJlY29yZGVyL3RyYW5zY29kZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNyRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxlQUFlLENBQUM7O0FBVXRELE1BQU0sdUJBQXVCLEdBQUcsRUFBVyxDQUFDO0FBQzVDLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBVSxDQUFDO0FBQ3BDLE1BQU0sbUJBQW1CLEdBQUcsVUFBbUIsQ0FBQztBQUVoRCxNQUFNLE1BQU0sR0FBRztJQUNiLFlBQVksRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRTtJQUN0QyxlQUFlLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxnQkFBZ0IsR0FBRyxDQUFDLEVBQUU7SUFDNUQsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRTtJQUMzQixTQUFTLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFO0lBQ3pCLGFBQWEsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUU7SUFDN0IsUUFBUSxFQUFFLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFO0lBQzFDLFVBQVUsRUFBRSxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUU7SUFDekIsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFO0lBQzdDLFdBQVcsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUU7SUFDM0IsWUFBWSxFQUFFLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFB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QUFFLElBQUksQ0FBQyxDQUFDO1FBQ3BFLFFBQVEsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2hFLFFBQVEsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzVELFFBQVEsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2hFLFFBQVEsQ0FBQyxTQUFTLENBQ2hCLE1BQU0sQ0FBQyxlQUFlLENBQUMsTUFBTSxFQUM3QixNQUFNLENBQUMsZUFBZSxDQUFDLEtBQUssRUFDNUIsSUFBSSxDQUNMLENBQUM7UUFFRixRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTO1FBQ3BGLFFBQVEsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsYUFBYSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3hFLENBQUM7OzhHQXhJVSxpQkFBaUI7a0hBQWpCLGlCQUFpQixjQURKLFFBQVE7MkZBQ3JCLGlCQUFpQjtrQkFEN0IsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgcmVhZEJsb2JBc0FycmF5QnVmZmVyIH0gZnJvbSAnLi4vZmlsZS11dGlscyc7XG5cbmV4cG9ydCB0eXBlIFRyYW5zY29kZXJDb25maWcgPSB7XG4gIHNhbXBsZVJhdGU6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIFRyYW5zY29kZVBhcmFtcyA9IFRyYW5zY29kZXJDb25maWcgJiB7XG4gIGJsb2I6IEJsb2I7XG59O1xuXG5jb25zdCBXQVZfSEVBREVSX0xFTkdUSF9CWVRFUyA9IDQ0IGFzIGNvbnN0O1xuY29uc3QgQllURVNfUEVSX1NBTVBMRSA9IDIgYXMgY29uc3Q7XG5jb25zdCBSSUZGX0ZJTEVfTUFYX0JZVEVTID0gNDI5NDk2NzI5NSBhcyBjb25zdDtcblxuY29uc3QgSEVBREVSID0ge1xuICBBVURJT19GT1JNQVQ6IHsgb2Zmc2V0OiAyMCwgdmFsdWU6IDEgfSwgLy8gUENNID0gMVxuICBCSVRTX1BFUl9TQU1QTEU6IHsgb2Zmc2V0OiAzNCwgdmFsdWU6IEJZVEVTX1BFUl9TQU1QTEUgKiA4IH0sIC8vIDE2IGJpdHMgZW5jb2RpbmdcbiAgQkxPQ0tfQUxJR046IHsgb2Zmc2V0OiAzMiB9LFxuICBCWVRFX1JBVEU6IHsgb2Zmc2V0OiAyOCB9LFxuICBDSEFOTkVMX0NPVU5UOiB7IG9mZnNldDogMjIgfSwgLy8gMSAtIG1vbm8sIDIgLSBzdGVyZW9cbiAgQ0hVTktfSUQ6IHsgb2Zmc2V0OiAwLCB2YWx1ZTogMHg1MjQ5NDY0NiB9LCAvLyBoZXggcmVwcmVzZW50YXRpb24gb2Ygc3RyaW5nIFwiUklGRlwiIChSZXNvdXJjZSBJbnRlcmNoYW5nZSBGaWxlIEZvcm1hdCkgLSBpZGVudGlmaWVzIHRoZSBmaWxlIHN0cnVjdHVyZSB0aGF0IGRlZmluZXMgYSBjbGFzcyBvZiBtb3JlIHNwZWNpZmljIGZpbGUgZm9ybWF0cywgZS5nLiBXQVZFXG4gIENIVU5LX1NJWkU6IHsgb2Zmc2V0OiA0IH0sXG4gIEZJTEVfRk9STUFUOiB7IG9mZnNldDogOCwgdmFsdWU6IDB4NTc0MTU2NDUgfSwgLy8gaGV4IHJlcHJlc2VudGF0aW9uIG9mIHN0cmluZyBcIldBVkVcIlxuICBTQU1QTEVfUkFURTogeyBvZmZzZXQ6IDI0IH0sXG4gIFNVQkNIVU5LMV9JRDogeyBvZmZzZXQ6IDEyLCB2YWx1ZTogMHg2NjZkNzQyMCB9LCAvLyBoZXggcmVwcmVzZW50YXRpb24gb2Ygc3RyaW5nIFwiZm10IFwiIC0gaWRlbnRpZmllcyB0aGUgc3RhcnQgb2YgXCJmb3JtYXRcIiBzZWN0aW9uIG9mIHRoZSBoZWFkZXJcbiAgU1VCQ0hVTksxX1NJWkU6IHsgb2Zmc2V0OiAxNiwgdmFsdWU6IDE2IH0sIC8vIFN1YmNodW5rMSBTaXplIHdpdGhvdXQgU1VCQ0hVTksxX0lEIGFuZCBTVUJDSFVOSzFfU0laRSBmaWVsZHNcbiAgU1VCQ0hVTksyX0lEOiB7IG9mZnNldDogMzYsIHZhbHVlOiAweDY0NjE3NDYxIH0sIC8vIGhleCByZXByZXNlbnRhdGlvbiBvZiBzdHJpbmcgXCJkYXRhXCIgLSBpZGVudGlmaWVzIHRoZSBzdGFydCBvZiBhY3R1YWwgYXVkaW8gZGF0YSBzZWN0aW9uXG4gIFNVQkNIVU5LMl9TSVpFOiB7IG9mZnNldDogNDAgfSwgLy8gYWN0dWFsIGF1ZGlvIGRhdGEgc2l6ZVxufSBhcyBjb25zdDtcblxudHlwZSBXcml0ZVdhdmVIZWFkZXJQYXJhbXMgPSB7XG4gIGFycmF5QnVmZmVyOiBBcnJheUJ1ZmZlcjtcbiAgLy8gMSAtIG1vbm8sIDIgLSBzdGVyZW9cbiAgY2hhbm5lbENvdW50OiBudW1iZXI7XG4gIC8vIE51bWJlciBvZiBzYW1wbGVzIHBlciBzZWNvbmQsIGUuZy4gNDQxMDBIelxuICBzYW1wbGVSYXRlOiBudW1iZXI7XG59O1xuXG50eXBlIFdyaXRlQXVkaW9EYXRhUGFyYW1zID0ge1xuICBhcnJheUJ1ZmZlcjogQXJyYXlCdWZmZXI7XG4gIGRhdGFCeUNoYW5uZWw6IEZsb2F0MzJBcnJheVtdO1xufTtcblxuLyoqXG4gKiBUaGUgYFRyYW5zY29kZXJTZXJ2aWNlYCBpcyB1c2VkIHRvIHRyYW5zY2liZSBhdWRpbyByZWNvcmRpbmcgdG8gYSBmb3JtYXQgdGhhdCdzIHN1cHBvcnRlZCBieSBhbGwgbWFqb3IgYnJvd3NlcnMuIFRoZSBTREsgdXNlcyB0aGlzIHRvIGNyZWF0ZSB2b2ljZSBtZXNzYWdlcy5cbiAqXG4gKiBJZiB5b3Ugd2FudCB0byB1c2UgeW91ciBvd24gdHJhbnNjb2RlciB5b3UgY2FuIHByb3ZpZGUgYSBgY3VzdG9tVHJhbnNjb2RlcmAuXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogTmdNb2R1bGUgfSlcbmV4cG9ydCBjbGFzcyBUcmFuc2NvZGVyU2VydmljZSB7XG4gIGNvbmZpZzogVHJhbnNjb2RlckNvbmZpZyA9IHtcbiAgICBzYW1wbGVSYXRlOiAxNjAwMCxcbiAgfTtcbiAgY3VzdG9tVHJhbnNjb2Rlcj86IChibG9iOiBCbG9iKSA9PiBCbG9iIHwgUHJvbWlzZTxCbG9iPjtcbiAgY29uc3RydWN0b3IoKSB7fVxuXG4gIC8qKlxuICAgKiBUaGUgZGVmYXVsdCB0cmFuc2NvZGVyIHdpbGwgbGVhdmUgYXVkaW8vbXA0IGZpbGVzIGFzIGlzLCBhbmQgdHJhbnNjb2RlIHdlYm0gZmlsZXMgdG8gd2F2LiBJZiB5b3Ugd2FudCB0byBjdXN0b21pemUgdGhpcywgeW91IGNhbiBwcm92aWRlIHlvdXIgb3duIHRyYW5zY29kZXIgdXNpbmcgdGhlIGBjdXN0b21UcmFuc2NvZGVyYCBmaWVsZFxuICAgKiBAcGFyYW0gYmxvYlxuICAgKiBAcmV0dXJucyB0aGUgdHJhbnNjb2RlZCBmaWxlXG4gICAqL1xuICBhc3luYyB0cmFuc2NvZGUoYmxvYjogQmxvYikge1xuICAgIGlmICh0aGlzLmN1c3RvbVRyYW5zY29kZXIpIHtcbiAgICAgIHJldHVybiB0aGlzLmN1c3RvbVRyYW5zY29kZXIoYmxvYik7XG4gICAgfVxuICAgIGlmIChibG9iLnR5cGUuaW5jbHVkZXMoJ2F1ZGlvL21wNCcpKSB7XG4gICAgICByZXR1cm4gYmxvYjtcbiAgICB9XG4gICAgY29uc3QgYXVkaW9CdWZmZXIgPSBhd2FpdCB0aGlzLnJlbmRlckF1ZGlvKFxuICAgICAgYXdhaXQgdGhpcy50b0F1ZGlvQnVmZmVyKGJsb2IpLFxuICAgICAgdGhpcy5jb25maWcuc2FtcGxlUmF0ZVxuICAgICk7XG4gICAgY29uc3QgbnVtYmVyT2ZTYW1wbGVzID0gYXVkaW9CdWZmZXIuZHVyYXRpb24gKiB0aGlzLmNvbmZpZy5zYW1wbGVSYXRlO1xuICAgIGNvbnN0IGZpbGVTaXplQnl0ZXMgPVxuICAgICAgbnVtYmVyT2ZTYW1wbGVzICogYXVkaW9CdWZmZXIubnVtYmVyT2ZDaGFubmVscyAqIEJZVEVTX1BFUl9TQU1QTEUgK1xuICAgICAgV0FWX0hFQURFUl9MRU5HVEhfQllURVM7XG5cbiAgICBjb25zdCBhcnJheUJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcihmaWxlU2l6ZUJ5dGVzKTtcbiAgICB0aGlzLndyaXRlV2F2SGVhZGVyKHtcbiAgICAgIGFycmF5QnVmZmVyLFxuICAgICAgY2hhbm5lbENvdW50OiBhdWRpb0J1ZmZlci5udW1iZXJPZkNoYW5uZWxzLFxuICAgICAgc2FtcGxlUmF0ZTogdGhpcy5jb25maWcuc2FtcGxlUmF0ZSxcbiAgICB9KTtcbiAgICB0aGlzLndyaXRlV2F2QXVkaW9EYXRhKHtcbiAgICAgIGFycmF5QnVmZmVyLFxuICAgICAgZGF0YUJ5Q2hhbm5lbDogdGhpcy5zcGxpdERhdGFCeUNoYW5uZWwoYXVkaW9CdWZmZXIpLFxuICAgIH0pO1xuICAgIHJldHVybiBuZXcgQmxvYihbYXJyYXlCdWZmZXJdLCB7IHR5cGU6ICdhdWRpby93YXYnIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHJlbmRlckF1ZGlvKGF1ZGlvQnVmZmVyOiBBdWRpb0J1ZmZlciwgc2FtcGxlUmF0ZTogbnVtYmVyKSB7XG4gICAgY29uc3Qgb2ZmbGluZUF1ZGlvQ3R4ID0gbmV3IE9mZmxpbmVBdWRpb0NvbnRleHQoXG4gICAgICBhdWRpb0J1ZmZlci5udW1iZXJPZkNoYW5uZWxzLFxuICAgICAgYXVkaW9CdWZmZXIuZHVyYXRpb24gKiBzYW1wbGVSYXRlLFxuICAgICAgc2FtcGxlUmF0ZVxuICAgICk7XG4gICAgY29uc3Qgc291cmNlID0gb2ZmbGluZUF1ZGlvQ3R4LmNyZWF0ZUJ1ZmZlclNvdXJjZSgpO1xuICAgIHNvdXJjZS5idWZmZXIgPSBhdWRpb0J1ZmZlcjtcbiAgICBzb3VyY2UuY29ubmVjdChvZmZsaW5lQXVkaW9DdHguZGVzdGluYXRpb24pO1xuICAgIHNvdXJjZS5zdGFydCgpO1xuXG4gICAgcmV0dXJuIGF3YWl0IG9mZmxpbmVBdWRpb0N0eC5zdGFydFJlbmRlcmluZygpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHRvQXVkaW9CdWZmZXIoYmxvYjogQmxvYikge1xuICAgIGNvbnN0IGF1ZGlvQ3R4ID0gbmV3IEF1ZGlvQ29udGV4dCgpO1xuXG4gICAgY29uc3QgYXJyYXlCdWZmZXIgPSBhd2FpdCByZWFkQmxvYkFzQXJyYXlCdWZmZXIoYmxvYik7XG4gICAgY29uc3QgZGVjb2RlZERhdGEgPSBhd2FpdCBhdWRpb0N0eC5kZWNvZGVBdWRpb0RhdGEoYXJyYXlCdWZmZXIpO1xuICAgIGlmIChhdWRpb0N0eC5zdGF0ZSAhPT0gJ2Nsb3NlZCcpIGF3YWl0IGF1ZGlvQ3R4LmNsb3NlKCk7XG4gICAgcmV0dXJuIGRlY29kZWREYXRhO1xuICB9XG5cbiAgcHJvdGVjdGVkIHdyaXRlV2F2QXVkaW9EYXRhKHtcbiAgICBhcnJheUJ1ZmZlcixcbiAgICBkYXRhQnlDaGFubmVsLFxuICB9OiBXcml0ZUF1ZGlvRGF0YVBhcmFtcykge1xuICAgIGNvbnN0IGRhdGFWaWV3ID0gbmV3IERhdGFWaWV3KGFycmF5QnVmZmVyKTtcbiAgICBjb25zdCBjaGFubmVsQ291bnQgPSBkYXRhQnlDaGFubmVsLmxlbmd0aDtcblxuICAgIGRhdGFCeUNoYW5uZWwuZm9yRWFjaCgoY2hhbm5lbERhdGEsIGNoYW5uZWxJbmRleCkgPT4ge1xuICAgICAgbGV0IHdyaXRlT2Zmc2V0ID0gV0FWX0hFQURFUl9MRU5HVEhfQllURVMgKyBjaGFubmVsQ291bnQgKiBjaGFubmVsSW5kZXg7XG5cbiAgICAgIGNoYW5uZWxEYXRhLmZvckVhY2goKGZsb2F0MzJWYWx1ZSkgPT4ge1xuICAgICAgICBkYXRhVmlldy5zZXRJbnQxNihcbiAgICAgICAgICB3cml0ZU9mZnNldCxcbiAgICAgICAgICBmbG9hdDMyVmFsdWUgPCAwXG4gICAgICAgICAgICA/IE1hdGgubWF4KC0xLCBmbG9hdDMyVmFsdWUpICogMzI3NjhcbiAgICAgICAgICAgIDogTWF0aC5taW4oMSwgZmxvYXQzMlZhbHVlKSAqIDMyNzY3LFxuICAgICAgICAgIHRydWVcbiAgICAgICAgKTtcbiAgICAgICAgd3JpdGVPZmZzZXQgKz0gY2hhbm5lbENvdW50ICogQllURVNfUEVSX1NBTVBMRTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHdyaXRlV2F2SGVhZGVyKHtcbiAgICBhcnJheUJ1ZmZlcixcbiAgICBjaGFubmVsQ291bnQsXG4gICAgc2FtcGxlUmF0ZSxcbiAgfTogV3JpdGVXYXZlSGVhZGVyUGFyYW1zKSB7XG4gICAgY29uc3QgYnl0ZVJhdGUgPSBzYW1wbGVSYXRlICogY2hhbm5lbENvdW50ICogQllURVNfUEVSX1NBTVBMRTsgLy8gYnl0ZXMvc2VjXG4gICAgY29uc3QgYmxvY2tBbGlnbiA9IGNoYW5uZWxDb3VudCAqIEJZVEVTX1BFUl9TQU1QTEU7XG5cbiAgICBjb25zdCBkYXRhVmlldyA9IG5ldyBEYXRhVmlldyhhcnJheUJ1ZmZlcik7XG4gICAgLypcbiAgICAgKiBUaGUgbWF4aW11bSBzaXplIG9mIGEgUklGRiBmaWxlIGlzIDQyOTQ5NjcyOTUgYnl0ZXMgYW5kIHNpbmNlIHRoZSBoZWFkZXIgdGFrZXMgdXAgNDQgYnl0ZXMgdGhlcmUgYXJlIDQyOTQ5NjcyNTEgYnl0ZXMgbGVmdCBmb3IgdGhlXG4gICAgICogZGF0YSBjaHVuay5cbiAgICAgKi9cbiAgICBjb25zdCBkYXRhQ2h1bmtTaXplID0gTWF0aC5taW4oXG4gICAgICBkYXRhVmlldy5ieXRlTGVuZ3RoIC0gV0FWX0hFQURFUl9MRU5HVEhfQllURVMsXG4gICAgICBSSUZGX0ZJTEVfTUFYX0JZVEVTIC0gV0FWX0hFQURFUl9MRU5HVEhfQllURVNcbiAgICApO1xuXG4gICAgZGF0YVZpZXcuc2V0VWludDMyKEhFQURFUi5DSFVOS19JRC5vZmZzZXQsIEhFQURFUi5DSFVOS19JRC52YWx1ZSk7IC8vIFwiUklGRlwiXG4gICAgZGF0YVZpZXcuc2V0VWludDMyKFxuICAgICAgSEVBREVSLkNIVU5LX1NJWkUub2Zmc2V0LFxuICAgICAgYXJyYXlCdWZmZXIuYnl0ZUxlbmd0aCAtIDgsXG4gICAgICB0cnVlXG4gICAgKTsgLy8gYWRqdXN0bWVudCBmb3IgdGhlIGZpcnN0IHR3byBoZWFkZXJzIC0gY2h1bmsgaWQgKyBmaWxlIHNpemVcbiAgICBkYXRhVmlldy5zZXRVaW50MzIoSEVBREVSLkZJTEVfRk9STUFULm9mZnNldCwgSEVBREVSLkZJTEVfRk9STUFULnZhbHVlKTsgLy8gXCJXQVZFXCJcblxuICAgIGRhdGFWaWV3LnNldFVpbnQzMihIRUFERVIuU1VCQ0hVTksxX0lELm9mZnNldCwgSEVBREVSLlNVQkNIVU5LMV9JRC52YWx1ZSk7IC8vIFwiZm10IFwiXG4gICAgZGF0YVZpZXcuc2V0VWludDMyKFxuICAgICAgSEVBREVSLlNVQkNIVU5LMV9TSVpFLm9mZnNldCxcbiAgICAgIEhFQURFUi5TVUJDSFVOSzFfU0laRS52YWx1ZSxcbiAgICAgIHRydWVcbiAgICApO1xuICAgIGRhdGFWaWV3LnNldFVpbnQxNihcbiAgICAgIEhFQURFUi5BVURJT19GT1JNQVQub2Zmc2V0LFxuICAgICAgSEVBREVSLkFVRElPX0ZPUk1BVC52YWx1ZSxcbiAgICAgIHRydWVcbiAgICApO1xuICAgIGRhdGFWaWV3LnNldFVpbnQxNihIRUFERVIuQ0hBTk5FTF9DT1VOVC5vZmZzZXQsIGNoYW5uZWxDb3VudCwgdHJ1ZSk7XG4gICAgZGF0YVZpZXcuc2V0VWludDMyKEhFQURFUi5TQU1QTEVfUkFURS5vZmZzZXQsIHNhbXBsZVJhdGUsIHRydWUpO1xuICAgIGRhdGFWaWV3LnNldFVpbnQzMihIRUFERVIuQllURV9SQVRFLm9mZnNldCwgYnl0ZVJhdGUsIHRydWUpO1xuICAgIGRhdGFWaWV3LnNldFVpbnQxNihIRUFERVIuQkxPQ0tfQUxJR04ub2Zmc2V0LCBibG9ja0FsaWduLCB0cnVlKTtcbiAgICBkYXRhVmlldy5zZXRVaW50MTYoXG4gICAgICBIRUFERVIuQklUU19QRVJfU0FNUExFLm9mZnNldCxcbiAgICAgIEhFQURFUi5CSVRTX1BFUl9TQU1QTEUudmFsdWUsXG4gICAgICB0cnVlXG4gICAgKTtcblxuICAgIGRhdGFWaWV3LnNldFVpbnQzMihIRUFERVIuU1VCQ0hVTksyX0lELm9mZnNldCwgSEVBREVSLlNVQkNIVU5LMl9JRC52YWx1ZSk7IC8vIFwiZGF0YVwiXG4gICAgZGF0YVZpZXcuc2V0VWludDMyKEhFQURFUi5TVUJDSFVOSzJfU0laRS5vZmZzZXQsIGRhdGFDaHVua1NpemUsIHRydWUpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNwbGl0RGF0YUJ5Q2hhbm5lbCA9IChhdWRpb0J1ZmZlcjogQXVkaW9CdWZmZXIpID0+XG4gICAgQXJyYXkuZnJvbSh7IGxlbmd0aDogYXVkaW9CdWZmZXIubnVtYmVyT2ZDaGFubmVscyB9LCAoXywgaSkgPT5cbiAgICAgIGF1ZGlvQnVmZmVyLmdldENoYW5uZWxEYXRhKGkpXG4gICAgKTtcbn1cbiJdfQ==
|
package/esm2020/lib/voice-recorder/voice-recorder-wavebar/voice-recorder-wavebar.component.mjs
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Component } from '@angular/core';
|
|
2
|
+
import { formatDuration } from '../../format-duration';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "../amplitude-recorder.service";
|
|
5
|
+
import * as i2 from "../audio-recorder.service";
|
|
6
|
+
import * as i3 from "@angular/common";
|
|
7
|
+
/**
|
|
8
|
+
* The `VoiceRecorderWavebarComponent` displays the amplitudes of the recording while the recoding is in progress
|
|
9
|
+
*/
|
|
10
|
+
export class VoiceRecorderWavebarComponent {
|
|
11
|
+
constructor(amplitudeRecorder, audioRecorder) {
|
|
12
|
+
this.amplitudeRecorder = amplitudeRecorder;
|
|
13
|
+
this.audioRecorder = audioRecorder;
|
|
14
|
+
this.isLongerThanOneHour = false;
|
|
15
|
+
this.amplitudes$ = this.amplitudeRecorder.amplitudes$;
|
|
16
|
+
this.formattedDuration = formatDuration(this.audioRecorder.durationMs / 1000);
|
|
17
|
+
this.durationComputeInterval = setInterval(() => {
|
|
18
|
+
this.isLongerThanOneHour = this.audioRecorder.durationMs / 1000 > 3600;
|
|
19
|
+
this.formattedDuration = formatDuration(this.audioRecorder.durationMs / 1000);
|
|
20
|
+
}, 1000);
|
|
21
|
+
}
|
|
22
|
+
trackByIndex(i) {
|
|
23
|
+
return i;
|
|
24
|
+
}
|
|
25
|
+
ngOnDestroy() {
|
|
26
|
+
clearInterval(this.durationComputeInterval);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
VoiceRecorderWavebarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: VoiceRecorderWavebarComponent, deps: [{ token: i1.AmplitudeRecorderService }, { token: i2.AudioRecorderService }], target: i0.ɵɵFactoryTarget.Component });
|
|
30
|
+
VoiceRecorderWavebarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: VoiceRecorderWavebarComponent, selector: "stream-voice-recorder-wavebar", ngImport: i0, template: "<div\n class=\"str-chat__recording-timer\"\n [class.str-chat__recording-timer--hours]=\"isLongerThanOneHour\"\n>\n {{ formattedDuration }}\n</div>\n<div class=\"str-chat__waveform-box-container\">\n <div class=\"str-chat__audio_recorder__waveform-box\">\n <div\n *ngFor=\"let amplitude of amplitudes$ | async; trackBy: trackByIndex\"\n class=\"str-chat__wave-progress-bar__amplitude-bar\"\n [style.--str-chat__wave-progress-bar__amplitude-bar-height]=\"\n (amplitude ?? 0) * 100 + '%'\n \"\n ></div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] });
|
|
31
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: VoiceRecorderWavebarComponent, decorators: [{
|
|
32
|
+
type: Component,
|
|
33
|
+
args: [{ selector: 'stream-voice-recorder-wavebar', template: "<div\n class=\"str-chat__recording-timer\"\n [class.str-chat__recording-timer--hours]=\"isLongerThanOneHour\"\n>\n {{ formattedDuration }}\n</div>\n<div class=\"str-chat__waveform-box-container\">\n <div class=\"str-chat__audio_recorder__waveform-box\">\n <div\n *ngFor=\"let amplitude of amplitudes$ | async; trackBy: trackByIndex\"\n class=\"str-chat__wave-progress-bar__amplitude-bar\"\n [style.--str-chat__wave-progress-bar__amplitude-bar-height]=\"\n (amplitude ?? 0) * 100 + '%'\n \"\n ></div>\n </div>\n</div>\n" }]
|
|
34
|
+
}], ctorParameters: function () { return [{ type: i1.AmplitudeRecorderService }, { type: i2.AudioRecorderService }]; } });
|
|
35
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidm9pY2UtcmVjb3JkZXItd2F2ZWJhci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zdHJlYW0tY2hhdC1hbmd1bGFyL3NyYy9saWIvdm9pY2UtcmVjb3JkZXIvdm9pY2UtcmVjb3JkZXItd2F2ZWJhci92b2ljZS1yZWNvcmRlci13YXZlYmFyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0cmVhbS1jaGF0LWFuZ3VsYXIvc3JjL2xpYi92b2ljZS1yZWNvcmRlci92b2ljZS1yZWNvcmRlci13YXZlYmFyL3ZvaWNlLXJlY29yZGVyLXdhdmViYXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBYSxNQUFNLGVBQWUsQ0FBQztBQUlyRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7Ozs7O0FBRXZEOztHQUVHO0FBTUgsTUFBTSxPQUFPLDZCQUE2QjtJQU14QyxZQUNVLGlCQUEyQyxFQUMzQyxhQUFtQztRQURuQyxzQkFBaUIsR0FBakIsaUJBQWlCLENBQTBCO1FBQzNDLGtCQUFhLEdBQWIsYUFBYSxDQUFzQjtRQUo3Qyx3QkFBbUIsR0FBRyxLQUFLLENBQUM7UUFNMUIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDO1FBQ3RELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxjQUFjLENBQ3JDLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxHQUFHLElBQUksQ0FDckMsQ0FBQztRQUNGLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFO1lBQzlDLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO1lBQ3ZFLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxjQUFjLENBQ3JDLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxHQUFHLElBQUksQ0FDckMsQ0FBQztRQUNKLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFRCxZQUFZLENBQUMsQ0FBUztRQUNwQixPQUFPLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFRCxXQUFXO1FBQ1QsYUFBYSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO0lBQzlDLENBQUM7OzBIQTVCVSw2QkFBNkI7OEdBQTdCLDZCQUE2QixxRUNkMUMsOGlCQWlCQTsyRkRIYSw2QkFBNkI7a0JBTHpDLFNBQVM7K0JBQ0UsK0JBQStCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkRlc3Ryb3kgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFtcGxpdHVkZVJlY29yZGVyU2VydmljZSB9IGZyb20gJy4uL2FtcGxpdHVkZS1yZWNvcmRlci5zZXJ2aWNlJztcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEF1ZGlvUmVjb3JkZXJTZXJ2aWNlIH0gZnJvbSAnLi4vYXVkaW8tcmVjb3JkZXIuc2VydmljZSc7XG5pbXBvcnQgeyBmb3JtYXREdXJhdGlvbiB9IGZyb20gJy4uLy4uL2Zvcm1hdC1kdXJhdGlvbic7XG5cbi8qKlxuICogVGhlIGBWb2ljZVJlY29yZGVyV2F2ZWJhckNvbXBvbmVudGAgZGlzcGxheXMgdGhlIGFtcGxpdHVkZXMgb2YgdGhlIHJlY29yZGluZyB3aGlsZSB0aGUgcmVjb2RpbmcgaXMgaW4gcHJvZ3Jlc3NcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnc3RyZWFtLXZvaWNlLXJlY29yZGVyLXdhdmViYXInLFxuICB0ZW1wbGF0ZVVybDogJy4vdm9pY2UtcmVjb3JkZXItd2F2ZWJhci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlczogW10sXG59KVxuZXhwb3J0IGNsYXNzIFZvaWNlUmVjb3JkZXJXYXZlYmFyQ29tcG9uZW50IGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgYW1wbGl0dWRlcyQ6IE9ic2VydmFibGU8bnVtYmVyW10+O1xuICBmb3JtYXR0ZWREdXJhdGlvbjogc3RyaW5nO1xuICBkdXJhdGlvbkNvbXB1dGVJbnRlcnZhbDogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0SW50ZXJ2YWw+O1xuICBpc0xvbmdlclRoYW5PbmVIb3VyID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBhbXBsaXR1ZGVSZWNvcmRlcjogQW1wbGl0dWRlUmVjb3JkZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgYXVkaW9SZWNvcmRlcjogQXVkaW9SZWNvcmRlclNlcnZpY2VcbiAgKSB7XG4gICAgdGhpcy5hbXBsaXR1ZGVzJCA9IHRoaXMuYW1wbGl0dWRlUmVjb3JkZXIuYW1wbGl0dWRlcyQ7XG4gICAgdGhpcy5mb3JtYXR0ZWREdXJhdGlvbiA9IGZvcm1hdER1cmF0aW9uKFxuICAgICAgdGhpcy5hdWRpb1JlY29yZGVyLmR1cmF0aW9uTXMgLyAxMDAwXG4gICAgKTtcbiAgICB0aGlzLmR1cmF0aW9uQ29tcHV0ZUludGVydmFsID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgdGhpcy5pc0xvbmdlclRoYW5PbmVIb3VyID0gdGhpcy5hdWRpb1JlY29yZGVyLmR1cmF0aW9uTXMgLyAxMDAwID4gMzYwMDtcbiAgICAgIHRoaXMuZm9ybWF0dGVkRHVyYXRpb24gPSBmb3JtYXREdXJhdGlvbihcbiAgICAgICAgdGhpcy5hdWRpb1JlY29yZGVyLmR1cmF0aW9uTXMgLyAxMDAwXG4gICAgICApO1xuICAgIH0sIDEwMDApO1xuICB9XG5cbiAgdHJhY2tCeUluZGV4KGk6IG51bWJlcikge1xuICAgIHJldHVybiBpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgY2xlYXJJbnRlcnZhbCh0aGlzLmR1cmF0aW9uQ29tcHV0ZUludGVydmFsKTtcbiAgfVxufVxuIiwiPGRpdlxuICBjbGFzcz1cInN0ci1jaGF0X19yZWNvcmRpbmctdGltZXJcIlxuICBbY2xhc3Muc3RyLWNoYXRfX3JlY29yZGluZy10aW1lci0taG91cnNdPVwiaXNMb25nZXJUaGFuT25lSG91clwiXG4+XG4gIHt7IGZvcm1hdHRlZER1cmF0aW9uIH19XG48L2Rpdj5cbjxkaXYgY2xhc3M9XCJzdHItY2hhdF9fd2F2ZWZvcm0tYm94LWNvbnRhaW5lclwiPlxuICA8ZGl2IGNsYXNzPVwic3RyLWNoYXRfX2F1ZGlvX3JlY29yZGVyX193YXZlZm9ybS1ib3hcIj5cbiAgICA8ZGl2XG4gICAgICAqbmdGb3I9XCJsZXQgYW1wbGl0dWRlIG9mIGFtcGxpdHVkZXMkIHwgYXN5bmM7IHRyYWNrQnk6IHRyYWNrQnlJbmRleFwiXG4gICAgICBjbGFzcz1cInN0ci1jaGF0X193YXZlLXByb2dyZXNzLWJhcl9fYW1wbGl0dWRlLWJhclwiXG4gICAgICBbc3R5bGUuLS1zdHItY2hhdF9fd2F2ZS1wcm9ncmVzcy1iYXJfX2FtcGxpdHVkZS1iYXItaGVpZ2h0XT1cIlxuICAgICAgICAoYW1wbGl0dWRlID8/IDApICogMTAwICsgJyUnXG4gICAgICBcIlxuICAgID48L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Component, Input, } from '@angular/core';
|
|
2
|
+
import { MediaRecordingState } from './media-recorder';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "./audio-recorder.service";
|
|
5
|
+
import * as i2 from "@angular/common";
|
|
6
|
+
import * as i3 from "../voice-recording/voice-recording.component";
|
|
7
|
+
import * as i4 from "../icon/icon-placeholder/icon-placeholder.component";
|
|
8
|
+
import * as i5 from "../icon/loading-indicator/loading-indicator.component";
|
|
9
|
+
import * as i6 from "./voice-recorder-wavebar/voice-recorder-wavebar.component";
|
|
10
|
+
/**
|
|
11
|
+
* The `VoiceRecorderComponent` makes it possible to record audio, and then upload it as a voice recording attachment
|
|
12
|
+
*/
|
|
13
|
+
export class VoiceRecorderComponent {
|
|
14
|
+
constructor(recorder) {
|
|
15
|
+
this.recorder = recorder;
|
|
16
|
+
this.recordState = MediaRecordingState.STOPPED;
|
|
17
|
+
this.isLoading = false;
|
|
18
|
+
this.MediaRecordingState = MediaRecordingState;
|
|
19
|
+
this.subscriptions = [];
|
|
20
|
+
}
|
|
21
|
+
ngOnInit() {
|
|
22
|
+
this.subscriptions.push(this.recorder.recordingState$.subscribe((s) => {
|
|
23
|
+
this.recordState = s;
|
|
24
|
+
if (this.recordState === MediaRecordingState.ERROR) {
|
|
25
|
+
this.voiceRecorderService?.isRecorderVisible$.next(false);
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
ngOnChanges(changes) {
|
|
30
|
+
if (changes.voiceRecorderService && this.voiceRecorderService) {
|
|
31
|
+
this.isVisibleSubscription =
|
|
32
|
+
this.voiceRecorderService.isRecorderVisible$.subscribe((isVisible) => {
|
|
33
|
+
if (!isVisible) {
|
|
34
|
+
this.recording = undefined;
|
|
35
|
+
this.isLoading = false;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
this.isVisibleSubscription?.unsubscribe();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
ngOnDestroy() {
|
|
44
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
45
|
+
}
|
|
46
|
+
cancel() {
|
|
47
|
+
if (this.recording) {
|
|
48
|
+
this.recording = undefined;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
void this.recorder.stop({ cancel: true });
|
|
52
|
+
}
|
|
53
|
+
this.voiceRecorderService?.isRecorderVisible$.next(false);
|
|
54
|
+
}
|
|
55
|
+
async stop() {
|
|
56
|
+
this.recording = await this.recorder.stop();
|
|
57
|
+
}
|
|
58
|
+
pause() {
|
|
59
|
+
this.recorder.pause();
|
|
60
|
+
}
|
|
61
|
+
resume() {
|
|
62
|
+
this.recorder.resume();
|
|
63
|
+
}
|
|
64
|
+
uploadRecording() {
|
|
65
|
+
if (!this.recording) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.isLoading = true;
|
|
69
|
+
this.voiceRecorderService?.recording$.next(this.recording);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
VoiceRecorderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: VoiceRecorderComponent, deps: [{ token: i1.AudioRecorderService }], target: i0.ɵɵFactoryTarget.Component });
|
|
73
|
+
VoiceRecorderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: VoiceRecorderComponent, selector: "stream-voice-recorder", inputs: { voiceRecorderService: "voiceRecorderService" }, providers: [], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"str-chat__audio_recorder-container\"\n *ngIf=\"voiceRecorderService?.isRecorderVisible$ | async\"\n>\n <div class=\"str-chat__audio_recorder\" data-testid=\"audio-recorder\">\n <button\n class=\"str-chat__audio_recorder__cancel-button\"\n data-testid=\"cancel-recording-audio-button\"\n [disabled]=\"isLoading\"\n (click)=\"cancel()\"\n (keyup.enter)=\"cancel()\"\n >\n <stream-icon-placeholder icon=\"bin\"></stream-icon-placeholder>\n </button>\n <stream-voice-recorder-wavebar\n *ngIf=\"\n (recordState === MediaRecordingState.RECORDING ||\n recordState === MediaRecordingState.PAUSED) &&\n !recording\n \"\n ></stream-voice-recorder-wavebar>\n <!-- eslint-disable @angular-eslint/template/no-any -->\n <stream-voice-recording\n [attachment]=\"$any(recording)\"\n *ngIf=\"!!recording\"\n ></stream-voice-recording>\n <!-- eslint-enable @angular-eslint/template/no-any -->\n <button\n *ngIf=\"recordState === MediaRecordingState.PAUSED && !recording\"\n class=\"str-chat__audio_recorder__resume-recording-button\"\n (click)=\"resume()\"\n (keyup.enter)=\"resume()\"\n >\n <stream-icon-placeholder icon=\"mic\"></stream-icon-placeholder>\n </button>\n <button\n *ngIf=\"recordState === MediaRecordingState.RECORDING && !recording\"\n class=\"str-chat__audio_recorder__pause-recording-button\"\n data-testid=\"pause-recording-audio-button\"\n (click)=\"pause()\"\n (keyup.enter)=\"pause()\"\n >\n <stream-icon-placeholder icon=\"pause\"></stream-icon-placeholder>\n </button>\n <ng-container\n *ngIf=\"recordState === MediaRecordingState.STOPPED; else stopButton\"\n >\n <button\n class=\"str-chat__audio_recorder__complete-button\"\n data-testid=\"audio-recorder-complete-button\"\n [disabled]=\"!recording\"\n (click)=\"uploadRecording()\"\n (keyup.enter)=\"uploadRecording()\"\n >\n <stream-loading-indicator\n *ngIf=\"isLoading; else sendIcon\"\n ></stream-loading-indicator>\n <ng-template #sendIcon>\n <stream-icon-placeholder icon=\"send\"></stream-icon-placeholder>\n </ng-template>\n </button>\n </ng-container>\n <ng-template #stopButton>\n <button\n class=\"str-chat__audio_recorder__stop-button\"\n data-testid=\"audio-recorder-stop-button\"\n [disabled]=\"recordState === MediaRecordingState.STOPPED\"\n (click)=\"stop()\"\n (keyup.enter)=\"stop()\"\n >\n <stream-icon-placeholder icon=\"delivered\"></stream-icon-placeholder>\n </button>\n </ng-template>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.VoiceRecordingComponent, selector: "stream-voice-recording", inputs: ["attachment"] }, { kind: "component", type: i4.IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: i5.LoadingIndicatorComponent, selector: "stream-loading-indicator" }, { kind: "component", type: i6.VoiceRecorderWavebarComponent, selector: "stream-voice-recorder-wavebar" }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] });
|
|
74
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: VoiceRecorderComponent, decorators: [{
|
|
75
|
+
type: Component,
|
|
76
|
+
args: [{ selector: 'stream-voice-recorder', providers: [], template: "<div\n class=\"str-chat__audio_recorder-container\"\n *ngIf=\"voiceRecorderService?.isRecorderVisible$ | async\"\n>\n <div class=\"str-chat__audio_recorder\" data-testid=\"audio-recorder\">\n <button\n class=\"str-chat__audio_recorder__cancel-button\"\n data-testid=\"cancel-recording-audio-button\"\n [disabled]=\"isLoading\"\n (click)=\"cancel()\"\n (keyup.enter)=\"cancel()\"\n >\n <stream-icon-placeholder icon=\"bin\"></stream-icon-placeholder>\n </button>\n <stream-voice-recorder-wavebar\n *ngIf=\"\n (recordState === MediaRecordingState.RECORDING ||\n recordState === MediaRecordingState.PAUSED) &&\n !recording\n \"\n ></stream-voice-recorder-wavebar>\n <!-- eslint-disable @angular-eslint/template/no-any -->\n <stream-voice-recording\n [attachment]=\"$any(recording)\"\n *ngIf=\"!!recording\"\n ></stream-voice-recording>\n <!-- eslint-enable @angular-eslint/template/no-any -->\n <button\n *ngIf=\"recordState === MediaRecordingState.PAUSED && !recording\"\n class=\"str-chat__audio_recorder__resume-recording-button\"\n (click)=\"resume()\"\n (keyup.enter)=\"resume()\"\n >\n <stream-icon-placeholder icon=\"mic\"></stream-icon-placeholder>\n </button>\n <button\n *ngIf=\"recordState === MediaRecordingState.RECORDING && !recording\"\n class=\"str-chat__audio_recorder__pause-recording-button\"\n data-testid=\"pause-recording-audio-button\"\n (click)=\"pause()\"\n (keyup.enter)=\"pause()\"\n >\n <stream-icon-placeholder icon=\"pause\"></stream-icon-placeholder>\n </button>\n <ng-container\n *ngIf=\"recordState === MediaRecordingState.STOPPED; else stopButton\"\n >\n <button\n class=\"str-chat__audio_recorder__complete-button\"\n data-testid=\"audio-recorder-complete-button\"\n [disabled]=\"!recording\"\n (click)=\"uploadRecording()\"\n (keyup.enter)=\"uploadRecording()\"\n >\n <stream-loading-indicator\n *ngIf=\"isLoading; else sendIcon\"\n ></stream-loading-indicator>\n <ng-template #sendIcon>\n <stream-icon-placeholder icon=\"send\"></stream-icon-placeholder>\n </ng-template>\n </button>\n </ng-container>\n <ng-template #stopButton>\n <button\n class=\"str-chat__audio_recorder__stop-button\"\n data-testid=\"audio-recorder-stop-button\"\n [disabled]=\"recordState === MediaRecordingState.STOPPED\"\n (click)=\"stop()\"\n (keyup.enter)=\"stop()\"\n >\n <stream-icon-placeholder icon=\"delivered\"></stream-icon-placeholder>\n </button>\n </ng-template>\n </div>\n</div>\n" }]
|
|
77
|
+
}], ctorParameters: function () { return [{ type: i1.AudioRecorderService }]; }, propDecorators: { voiceRecorderService: [{
|
|
78
|
+
type: Input
|
|
79
|
+
}] } });
|
|
80
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidm9pY2UtcmVjb3JkZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc3RyZWFtLWNoYXQtYW5ndWxhci9zcmMvbGliL3ZvaWNlLXJlY29yZGVyL3ZvaWNlLXJlY29yZGVyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0cmVhbS1jaGF0LWFuZ3VsYXIvc3JjL2xpYi92b2ljZS1yZWNvcmRlci92b2ljZS1yZWNvcmRlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULEtBQUssR0FLTixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQzs7Ozs7Ozs7QUFLdkQ7O0dBRUc7QUFPSCxNQUFNLE9BQU8sc0JBQXNCO0lBU2pDLFlBQTRCLFFBQThCO1FBQTlCLGFBQVEsR0FBUixRQUFRLENBQXNCO1FBUDFELGdCQUFXLEdBQXdCLG1CQUFtQixDQUFDLE9BQU8sQ0FBQztRQUMvRCxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBRVQsd0JBQW1CLEdBQUcsbUJBQW1CLENBQUM7UUFDM0Msa0JBQWEsR0FBbUIsRUFBRSxDQUFDO0lBR2tCLENBQUM7SUFFOUQsUUFBUTtRQUNOLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUNyQixJQUFJLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUM1QyxJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQztZQUNyQixJQUFJLElBQUksQ0FBQyxXQUFXLEtBQUssbUJBQW1CLENBQUMsS0FBSyxFQUFFO2dCQUNsRCxJQUFJLENBQUMsb0JBQW9CLEVBQUUsa0JBQWtCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQzNEO1FBQ0gsQ0FBQyxDQUFDLENBQ0gsQ0FBQztJQUNKLENBQUM7SUFFRCxXQUFXLENBQUMsT0FBc0I7UUFDaEMsSUFBSSxPQUFPLENBQUMsb0JBQW9CLElBQUksSUFBSSxDQUFDLG9CQUFvQixFQUFFO1lBQzdELElBQUksQ0FBQyxxQkFBcUI7Z0JBQ3hCLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsQ0FBQyxTQUFTLEVBQUUsRUFBRTtvQkFDbkUsSUFBSSxDQUFDLFNBQVMsRUFBRTt3QkFDZCxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQzt3QkFDM0IsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7cUJBQ3hCO2dCQUNILENBQUMsQ0FBQyxDQUFDO1NBQ047YUFBTTtZQUNMLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxXQUFXLEVBQUUsQ0FBQztTQUMzQztJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFFRCxNQUFNO1FBQ0osSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQ2xCLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1NBQzVCO2FBQU07WUFDTCxLQUFLLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7U0FDM0M7UUFDRCxJQUFJLENBQUMsb0JBQW9CLEVBQUUsa0JBQWtCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFRCxLQUFLLENBQUMsSUFBSTtRQUNSLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzlDLENBQUM7SUFFRCxLQUFLO1FBQ0gsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUN4QixDQUFDO0lBRUQsTUFBTTtRQUNKLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDekIsQ0FBQztJQUVELGVBQWU7UUFDYixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNuQixPQUFPO1NBQ1I7UUFDRCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixJQUFJLENBQUMsb0JBQW9CLEVBQUUsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDN0QsQ0FBQzs7bUhBbkVVLHNCQUFzQjt1R0FBdEIsc0JBQXNCLDBHQUZ0QixFQUFFLCtDQ3JCZixrc0ZBMkVBOzJGRHBEYSxzQkFBc0I7a0JBTmxDLFNBQVM7K0JBQ0UsdUJBQXVCLGFBR3RCLEVBQUU7MkdBR0osb0JBQW9CO3NCQUE1QixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgU2ltcGxlQ2hhbmdlcyxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBdWRpb1JlY29yZGVyU2VydmljZSB9IGZyb20gJy4vYXVkaW8tcmVjb3JkZXIuc2VydmljZSc7XG5pbXBvcnQgeyBNZWRpYVJlY29yZGluZ1N0YXRlIH0gZnJvbSAnLi9tZWRpYS1yZWNvcmRlcic7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEF1ZGlvUmVjb3JkaW5nIH0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHsgVm9pY2VSZWNvcmRlclNlcnZpY2UgfSBmcm9tICcuLi9tZXNzYWdlLWlucHV0L3ZvaWNlLXJlY29yZGVyLnNlcnZpY2UnO1xuXG4vKipcbiAqIFRoZSBgVm9pY2VSZWNvcmRlckNvbXBvbmVudGAgbWFrZXMgaXQgcG9zc2libGUgdG8gcmVjb3JkIGF1ZGlvLCBhbmQgdGhlbiB1cGxvYWQgaXQgYXMgYSB2b2ljZSByZWNvcmRpbmcgYXR0YWNobWVudFxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzdHJlYW0tdm9pY2UtcmVjb3JkZXInLFxuICB0ZW1wbGF0ZVVybDogJy4vdm9pY2UtcmVjb3JkZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZXM6IFtdLFxuICBwcm92aWRlcnM6IFtdLFxufSlcbmV4cG9ydCBjbGFzcyBWb2ljZVJlY29yZGVyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIE9uQ2hhbmdlcyB7XG4gIEBJbnB1dCgpIHZvaWNlUmVjb3JkZXJTZXJ2aWNlPzogVm9pY2VSZWNvcmRlclNlcnZpY2U7XG4gIHJlY29yZFN0YXRlOiBNZWRpYVJlY29yZGluZ1N0YXRlID0gTWVkaWFSZWNvcmRpbmdTdGF0ZS5TVE9QUEVEO1xuICBpc0xvYWRpbmcgPSBmYWxzZTtcbiAgcmVjb3JkaW5nPzogQXVkaW9SZWNvcmRpbmc7XG4gIHJlYWRvbmx5IE1lZGlhUmVjb3JkaW5nU3RhdGUgPSBNZWRpYVJlY29yZGluZ1N0YXRlO1xuICBwcml2YXRlIHN1YnNjcmlwdGlvbnM6IFN1YnNjcmlwdGlvbltdID0gW107XG4gIHByaXZhdGUgaXNWaXNpYmxlU3Vic2NyaXB0aW9uPzogU3Vic2NyaXB0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSByZWNvcmRlcjogQXVkaW9SZWNvcmRlclNlcnZpY2UpIHt9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLnJlY29yZGVyLnJlY29yZGluZ1N0YXRlJC5zdWJzY3JpYmUoKHMpID0+IHtcbiAgICAgICAgdGhpcy5yZWNvcmRTdGF0ZSA9IHM7XG4gICAgICAgIGlmICh0aGlzLnJlY29yZFN0YXRlID09PSBNZWRpYVJlY29yZGluZ1N0YXRlLkVSUk9SKSB7XG4gICAgICAgICAgdGhpcy52b2ljZVJlY29yZGVyU2VydmljZT8uaXNSZWNvcmRlclZpc2libGUkLm5leHQoZmFsc2UpO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXMudm9pY2VSZWNvcmRlclNlcnZpY2UgJiYgdGhpcy52b2ljZVJlY29yZGVyU2VydmljZSkge1xuICAgICAgdGhpcy5pc1Zpc2libGVTdWJzY3JpcHRpb24gPVxuICAgICAgICB0aGlzLnZvaWNlUmVjb3JkZXJTZXJ2aWNlLmlzUmVjb3JkZXJWaXNpYmxlJC5zdWJzY3JpYmUoKGlzVmlzaWJsZSkgPT4ge1xuICAgICAgICAgIGlmICghaXNWaXNpYmxlKSB7XG4gICAgICAgICAgICB0aGlzLnJlY29yZGluZyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMuaXNMb2FkaW5nID0gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5pc1Zpc2libGVTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLmZvckVhY2goKHMpID0+IHMudW5zdWJzY3JpYmUoKSk7XG4gIH1cblxuICBjYW5jZWwoKSB7XG4gICAgaWYgKHRoaXMucmVjb3JkaW5nKSB7XG4gICAgICB0aGlzLnJlY29yZGluZyA9IHVuZGVmaW5lZDtcbiAgICB9IGVsc2Uge1xuICAgICAgdm9pZCB0aGlzLnJlY29yZGVyLnN0b3AoeyBjYW5jZWw6IHRydWUgfSk7XG4gICAgfVxuICAgIHRoaXMudm9pY2VSZWNvcmRlclNlcnZpY2U/LmlzUmVjb3JkZXJWaXNpYmxlJC5uZXh0KGZhbHNlKTtcbiAgfVxuXG4gIGFzeW5jIHN0b3AoKSB7XG4gICAgdGhpcy5yZWNvcmRpbmcgPSBhd2FpdCB0aGlzLnJlY29yZGVyLnN0b3AoKTtcbiAgfVxuXG4gIHBhdXNlKCkge1xuICAgIHRoaXMucmVjb3JkZXIucGF1c2UoKTtcbiAgfVxuXG4gIHJlc3VtZSgpIHtcbiAgICB0aGlzLnJlY29yZGVyLnJlc3VtZSgpO1xuICB9XG5cbiAgdXBsb2FkUmVjb3JkaW5nKCkge1xuICAgIGlmICghdGhpcy5yZWNvcmRpbmcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5pc0xvYWRpbmcgPSB0cnVlO1xuICAgIHRoaXMudm9pY2VSZWNvcmRlclNlcnZpY2U/LnJlY29yZGluZyQubmV4dCh0aGlzLnJlY29yZGluZyk7XG4gIH1cbn1cbiIsIjxkaXZcbiAgY2xhc3M9XCJzdHItY2hhdF9fYXVkaW9fcmVjb3JkZXItY29udGFpbmVyXCJcbiAgKm5nSWY9XCJ2b2ljZVJlY29yZGVyU2VydmljZT8uaXNSZWNvcmRlclZpc2libGUkIHwgYXN5bmNcIlxuPlxuICA8ZGl2IGNsYXNzPVwic3RyLWNoYXRfX2F1ZGlvX3JlY29yZGVyXCIgZGF0YS10ZXN0aWQ9XCJhdWRpby1yZWNvcmRlclwiPlxuICAgIDxidXR0b25cbiAgICAgIGNsYXNzPVwic3RyLWNoYXRfX2F1ZGlvX3JlY29yZGVyX19jYW5jZWwtYnV0dG9uXCJcbiAgICAgIGRhdGEtdGVzdGlkPVwiY2FuY2VsLXJlY29yZGluZy1hdWRpby1idXR0b25cIlxuICAgICAgW2Rpc2FibGVkXT1cImlzTG9hZGluZ1wiXG4gICAgICAoY2xpY2spPVwiY2FuY2VsKClcIlxuICAgICAgKGtleXVwLmVudGVyKT1cImNhbmNlbCgpXCJcbiAgICA+XG4gICAgICA8c3RyZWFtLWljb24tcGxhY2Vob2xkZXIgaWNvbj1cImJpblwiPjwvc3RyZWFtLWljb24tcGxhY2Vob2xkZXI+XG4gICAgPC9idXR0b24+XG4gICAgPHN0cmVhbS12b2ljZS1yZWNvcmRlci13YXZlYmFyXG4gICAgICAqbmdJZj1cIlxuICAgICAgICAocmVjb3JkU3RhdGUgPT09IE1lZGlhUmVjb3JkaW5nU3RhdGUuUkVDT1JESU5HIHx8XG4gICAgICAgICAgcmVjb3JkU3RhdGUgPT09IE1lZGlhUmVjb3JkaW5nU3RhdGUuUEFVU0VEKSAmJlxuICAgICAgICAhcmVjb3JkaW5nXG4gICAgICBcIlxuICAgID48L3N0cmVhbS12b2ljZS1yZWNvcmRlci13YXZlYmFyPlxuICAgIDwhLS0gZXNsaW50LWRpc2FibGUgQGFuZ3VsYXItZXNsaW50L3RlbXBsYXRlL25vLWFueSAtLT5cbiAgICA8c3RyZWFtLXZvaWNlLXJlY29yZGluZ1xuICAgICAgW2F0dGFjaG1lbnRdPVwiJGFueShyZWNvcmRpbmcpXCJcbiAgICAgICpuZ0lmPVwiISFyZWNvcmRpbmdcIlxuICAgID48L3N0cmVhbS12b2ljZS1yZWNvcmRpbmc+XG4gICAgPCEtLSBlc2xpbnQtZW5hYmxlIEBhbmd1bGFyLWVzbGludC90ZW1wbGF0ZS9uby1hbnkgLS0+XG4gICAgPGJ1dHRvblxuICAgICAgKm5nSWY9XCJyZWNvcmRTdGF0ZSA9PT0gTWVkaWFSZWNvcmRpbmdTdGF0ZS5QQVVTRUQgJiYgIXJlY29yZGluZ1wiXG4gICAgICBjbGFzcz1cInN0ci1jaGF0X19hdWRpb19yZWNvcmRlcl9fcmVzdW1lLXJlY29yZGluZy1idXR0b25cIlxuICAgICAgKGNsaWNrKT1cInJlc3VtZSgpXCJcbiAgICAgIChrZXl1cC5lbnRlcik9XCJyZXN1bWUoKVwiXG4gICAgPlxuICAgICAgPHN0cmVhbS1pY29uLXBsYWNlaG9sZGVyIGljb249XCJtaWNcIj48L3N0cmVhbS1pY29uLXBsYWNlaG9sZGVyPlxuICAgIDwvYnV0dG9uPlxuICAgIDxidXR0b25cbiAgICAgICpuZ0lmPVwicmVjb3JkU3RhdGUgPT09IE1lZGlhUmVjb3JkaW5nU3RhdGUuUkVDT1JESU5HICYmICFyZWNvcmRpbmdcIlxuICAgICAgY2xhc3M9XCJzdHItY2hhdF9fYXVkaW9fcmVjb3JkZXJfX3BhdXNlLXJlY29yZGluZy1idXR0b25cIlxuICAgICAgZGF0YS10ZXN0aWQ9XCJwYXVzZS1yZWNvcmRpbmctYXVkaW8tYnV0dG9uXCJcbiAgICAgIChjbGljayk9XCJwYXVzZSgpXCJcbiAgICAgIChrZXl1cC5lbnRlcik9XCJwYXVzZSgpXCJcbiAgICA+XG4gICAgICA8c3RyZWFtLWljb24tcGxhY2Vob2xkZXIgaWNvbj1cInBhdXNlXCI+PC9zdHJlYW0taWNvbi1wbGFjZWhvbGRlcj5cbiAgICA8L2J1dHRvbj5cbiAgICA8bmctY29udGFpbmVyXG4gICAgICAqbmdJZj1cInJlY29yZFN0YXRlID09PSBNZWRpYVJlY29yZGluZ1N0YXRlLlNUT1BQRUQ7IGVsc2Ugc3RvcEJ1dHRvblwiXG4gICAgPlxuICAgICAgPGJ1dHRvblxuICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19hdWRpb19yZWNvcmRlcl9fY29tcGxldGUtYnV0dG9uXCJcbiAgICAgICAgZGF0YS10ZXN0aWQ9XCJhdWRpby1yZWNvcmRlci1jb21wbGV0ZS1idXR0b25cIlxuICAgICAgICBbZGlzYWJsZWRdPVwiIXJlY29yZGluZ1wiXG4gICAgICAgIChjbGljayk9XCJ1cGxvYWRSZWNvcmRpbmcoKVwiXG4gICAgICAgIChrZXl1cC5lbnRlcik9XCJ1cGxvYWRSZWNvcmRpbmcoKVwiXG4gICAgICA+XG4gICAgICAgIDxzdHJlYW0tbG9hZGluZy1pbmRpY2F0b3JcbiAgICAgICAgICAqbmdJZj1cImlzTG9hZGluZzsgZWxzZSBzZW5kSWNvblwiXG4gICAgICAgID48L3N0cmVhbS1sb2FkaW5nLWluZGljYXRvcj5cbiAgICAgICAgPG5nLXRlbXBsYXRlICNzZW5kSWNvbj5cbiAgICAgICAgICA8c3RyZWFtLWljb24tcGxhY2Vob2xkZXIgaWNvbj1cInNlbmRcIj48L3N0cmVhbS1pY29uLXBsYWNlaG9sZGVyPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLXRlbXBsYXRlICNzdG9wQnV0dG9uPlxuICAgICAgPGJ1dHRvblxuICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19hdWRpb19yZWNvcmRlcl9fc3RvcC1idXR0b25cIlxuICAgICAgICBkYXRhLXRlc3RpZD1cImF1ZGlvLXJlY29yZGVyLXN0b3AtYnV0dG9uXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cInJlY29yZFN0YXRlID09PSBNZWRpYVJlY29yZGluZ1N0YXRlLlNUT1BQRURcIlxuICAgICAgICAoY2xpY2spPVwic3RvcCgpXCJcbiAgICAgICAgKGtleXVwLmVudGVyKT1cInN0b3AoKVwiXG4gICAgICA+XG4gICAgICAgIDxzdHJlYW0taWNvbi1wbGFjZWhvbGRlciBpY29uPVwiZGVsaXZlcmVkXCI+PC9zdHJlYW0taWNvbi1wbGFjZWhvbGRlcj5cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvbmctdGVtcGxhdGU+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=
|