speechrecorderng 2.24.0 → 2.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/lib/audio/capture/capture.mjs +38 -10
- package/esm2020/lib/audio/io/stream.mjs +41 -1
- package/esm2020/lib/io/stream.mjs +10 -1
- package/esm2020/lib/recorder_component.mjs +5 -1
- package/esm2020/lib/speechrecorder/project/project.mjs +1 -1
- package/esm2020/lib/speechrecorder/session/audiorecorder.mjs +162 -171
- package/esm2020/lib/speechrecorder/session/basicrecorder.mjs +165 -4
- package/esm2020/lib/speechrecorder/session/sessionmanager.mjs +24 -12
- package/esm2020/lib/speechrecorderng.component.mjs +76 -134
- package/esm2020/lib/spr.module.version.mjs +2 -2
- package/fesm2015/speechrecorderng.mjs +585 -401
- package/fesm2015/speechrecorderng.mjs.map +1 -1
- package/fesm2020/speechrecorderng.mjs +581 -401
- package/fesm2020/speechrecorderng.mjs.map +1 -1
- package/lib/audio/io/stream.d.ts +13 -0
- package/lib/io/stream.d.ts +3 -0
- package/lib/recorder_component.d.ts +4 -0
- package/lib/speechrecorder/project/project.d.ts +1 -0
- package/lib/speechrecorder/session/audiorecorder.d.ts +7 -9
- package/lib/speechrecorder/session/basicrecorder.d.ts +40 -2
- package/lib/speechrecorder/session/sessionmanager.d.ts +4 -3
- package/lib/speechrecorderng.component.d.ts +1 -2
- package/lib/spr.module.version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -19,6 +19,7 @@ import * as i1$2 from '@angular/material/dialog';
|
|
|
19
19
|
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
|
20
20
|
import * as i3$2 from '@angular/material/button';
|
|
21
21
|
import { MatButtonModule } from '@angular/material/button';
|
|
22
|
+
import { __decorate, __param } from 'tslib';
|
|
22
23
|
import * as i1$3 from '@angular/material/progress-spinner';
|
|
23
24
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
24
25
|
import * as i8 from '@angular/flex-layout/flex';
|
|
@@ -1047,17 +1048,45 @@ class AudioCapture {
|
|
|
1047
1048
|
this._opened = false;
|
|
1048
1049
|
}
|
|
1049
1050
|
audioBuffer() {
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
for (
|
|
1051
|
+
let frameLen = 0;
|
|
1052
|
+
let ch0Data = this.data[0];
|
|
1053
|
+
for (let ch0Chk of ch0Data) {
|
|
1053
1054
|
frameLen += ch0Chk.length;
|
|
1054
1055
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1056
|
+
let ab;
|
|
1057
|
+
try {
|
|
1058
|
+
ab = this.context.createBuffer(this.channelCount, frameLen, this.context.sampleRate);
|
|
1059
|
+
}
|
|
1060
|
+
catch (err) {
|
|
1061
|
+
if (err instanceof DOMException) {
|
|
1062
|
+
if (err.name === 'NotSupportedError') {
|
|
1063
|
+
if (frameLen == 0) {
|
|
1064
|
+
// Empty buffers are not supported by Chromium
|
|
1065
|
+
// Create dummy buffer with one sample
|
|
1066
|
+
ab = this.context.createBuffer(this.channelCount, 1, this.context.sampleRate);
|
|
1067
|
+
}
|
|
1068
|
+
else {
|
|
1069
|
+
throw err;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
else {
|
|
1073
|
+
throw err;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
else if (err instanceof RangeError) {
|
|
1077
|
+
// Out of memory
|
|
1078
|
+
// TODO What to do ??
|
|
1079
|
+
throw err;
|
|
1080
|
+
}
|
|
1081
|
+
else {
|
|
1082
|
+
throw err;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
for (let ch = 0; ch < this.channelCount; ch++) {
|
|
1086
|
+
let chD = ab.getChannelData(ch);
|
|
1087
|
+
let pos = 0;
|
|
1088
|
+
for (let chChk of this.data[ch]) {
|
|
1089
|
+
let bufLen = chChk.length;
|
|
1061
1090
|
chD.set(chChk, pos);
|
|
1062
1091
|
pos += bufLen;
|
|
1063
1092
|
}
|
|
@@ -5633,98 +5662,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImpor
|
|
|
5633
5662
|
type: Output
|
|
5634
5663
|
}] } });
|
|
5635
5664
|
|
|
5636
|
-
class Float32ArrayChunkerOutStream {
|
|
5637
|
-
constructor(outStream) {
|
|
5638
|
-
this.outStream = outStream;
|
|
5639
|
-
this.bufs = new Array();
|
|
5640
|
-
this._channels = 0;
|
|
5641
|
-
this._chunkSize = 0;
|
|
5642
|
-
this.filled = 0;
|
|
5643
|
-
this.receivedFrames = 0;
|
|
5644
|
-
this.sentFrames = 0;
|
|
5645
|
-
}
|
|
5646
|
-
createBuffers() {
|
|
5647
|
-
this.bufs = new Array(this._channels);
|
|
5648
|
-
for (let ch = 0; ch < this._channels; ch++) {
|
|
5649
|
-
this.bufs[ch] = new Float32Array(this._chunkSize);
|
|
5650
|
-
}
|
|
5651
|
-
}
|
|
5652
|
-
set chunkSize(chunkSize) {
|
|
5653
|
-
this._chunkSize = chunkSize;
|
|
5654
|
-
this.createBuffers();
|
|
5655
|
-
}
|
|
5656
|
-
set channels(channels) {
|
|
5657
|
-
this._channels = channels;
|
|
5658
|
-
this.createBuffers();
|
|
5659
|
-
}
|
|
5660
|
-
write(buffers) {
|
|
5661
|
-
let copied = 0;
|
|
5662
|
-
if (buffers.length > 0) {
|
|
5663
|
-
let buffersLen = buffers[0].length;
|
|
5664
|
-
this.receivedFrames += buffersLen;
|
|
5665
|
-
let avail = buffersLen;
|
|
5666
|
-
// Fill out buffers until all values copied
|
|
5667
|
-
while (avail > 0) {
|
|
5668
|
-
let toFill = this._chunkSize - this.filled;
|
|
5669
|
-
if (toFill > avail) {
|
|
5670
|
-
toFill = avail;
|
|
5671
|
-
}
|
|
5672
|
-
let sliceEnd = copied + toFill;
|
|
5673
|
-
// Firefox on Android sends only the first channel
|
|
5674
|
-
for (let ch = 0; ch < buffersLen; ch++) {
|
|
5675
|
-
if (buffers[ch]) {
|
|
5676
|
-
let cpPrt = buffers[ch].slice(copied, sliceEnd);
|
|
5677
|
-
let buf = this.bufs[ch];
|
|
5678
|
-
buf.set(cpPrt, this.filled);
|
|
5679
|
-
}
|
|
5680
|
-
}
|
|
5681
|
-
copied += toFill;
|
|
5682
|
-
avail -= toFill;
|
|
5683
|
-
this.filled += toFill;
|
|
5684
|
-
if (this.filled == this._chunkSize) {
|
|
5685
|
-
this.outStream.write(this.bufs);
|
|
5686
|
-
this.sentFrames += this.filled;
|
|
5687
|
-
this.filled = 0;
|
|
5688
|
-
}
|
|
5689
|
-
}
|
|
5690
|
-
}
|
|
5691
|
-
return copied;
|
|
5692
|
-
}
|
|
5693
|
-
flush() {
|
|
5694
|
-
if (this.filled > 0) {
|
|
5695
|
-
let restBufs = new Array(this._channels);
|
|
5696
|
-
for (let ch = 0; ch < this._channels; ch++) {
|
|
5697
|
-
restBufs[ch] = this.bufs[ch].slice(0, this.filled);
|
|
5698
|
-
}
|
|
5699
|
-
this.outStream.write(restBufs);
|
|
5700
|
-
this.outStream.flush();
|
|
5701
|
-
this.sentFrames += this.filled;
|
|
5702
|
-
this.filled = 0;
|
|
5703
|
-
}
|
|
5704
|
-
}
|
|
5705
|
-
close() {
|
|
5706
|
-
this.outStream.close();
|
|
5707
|
-
}
|
|
5708
|
-
}
|
|
5709
|
-
|
|
5710
|
-
class SequenceAudioFloat32ChunkerOutStream extends Float32ArrayChunkerOutStream {
|
|
5711
|
-
constructor(outStream, chunkDurationSeconds) {
|
|
5712
|
-
super(outStream);
|
|
5713
|
-
this.chunkDurationSeconds = chunkDurationSeconds;
|
|
5714
|
-
this.sampleRate = null;
|
|
5715
|
-
this.sequenceAudioFloat32OutStream = outStream;
|
|
5716
|
-
}
|
|
5717
|
-
setFormat(channels, sampleRate) {
|
|
5718
|
-
this.channels = channels;
|
|
5719
|
-
this.sampleRate = sampleRate;
|
|
5720
|
-
this.chunkSize = Math.round(sampleRate * this.chunkDurationSeconds);
|
|
5721
|
-
this.sequenceAudioFloat32OutStream.setFormat(channels, sampleRate);
|
|
5722
|
-
}
|
|
5723
|
-
nextStream() {
|
|
5724
|
-
this.sequenceAudioFloat32OutStream.nextStream();
|
|
5725
|
-
}
|
|
5726
|
-
}
|
|
5727
|
-
|
|
5728
5665
|
class SessionFinishedDialog {
|
|
5729
5666
|
constructor(dialogRef, data) {
|
|
5730
5667
|
this.dialogRef = dialogRef;
|
|
@@ -7260,23 +7197,209 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImpor
|
|
|
7260
7197
|
type: Input
|
|
7261
7198
|
}] } });
|
|
7262
7199
|
|
|
7200
|
+
class Float32ArrayChunkerOutStream {
|
|
7201
|
+
constructor(outStream) {
|
|
7202
|
+
this.outStream = outStream;
|
|
7203
|
+
this.bufs = new Array();
|
|
7204
|
+
this._channels = 0;
|
|
7205
|
+
this._chunkSize = 0;
|
|
7206
|
+
this.filled = 0;
|
|
7207
|
+
this.receivedFrames = 0;
|
|
7208
|
+
this.sentFrames = 0;
|
|
7209
|
+
}
|
|
7210
|
+
createBuffers() {
|
|
7211
|
+
this.bufs = new Array(this._channels);
|
|
7212
|
+
for (let ch = 0; ch < this._channels; ch++) {
|
|
7213
|
+
this.bufs[ch] = new Float32Array(this._chunkSize);
|
|
7214
|
+
}
|
|
7215
|
+
}
|
|
7216
|
+
set chunkSize(chunkSize) {
|
|
7217
|
+
this._chunkSize = chunkSize;
|
|
7218
|
+
this.createBuffers();
|
|
7219
|
+
}
|
|
7220
|
+
get chunkSize() {
|
|
7221
|
+
return this._chunkSize;
|
|
7222
|
+
}
|
|
7223
|
+
set channels(channels) {
|
|
7224
|
+
this._channels = channels;
|
|
7225
|
+
this.createBuffers();
|
|
7226
|
+
}
|
|
7227
|
+
get channels() {
|
|
7228
|
+
return this._channels;
|
|
7229
|
+
}
|
|
7230
|
+
available() {
|
|
7231
|
+
return this._chunkSize - this.filled;
|
|
7232
|
+
}
|
|
7233
|
+
write(buffers) {
|
|
7234
|
+
let copied = 0;
|
|
7235
|
+
if (buffers.length > 0) {
|
|
7236
|
+
let buffersLen = buffers[0].length;
|
|
7237
|
+
this.receivedFrames += buffersLen;
|
|
7238
|
+
let avail = buffersLen;
|
|
7239
|
+
// Fill out buffers until all values copied
|
|
7240
|
+
while (avail > 0) {
|
|
7241
|
+
let toFill = this._chunkSize - this.filled;
|
|
7242
|
+
if (toFill > avail) {
|
|
7243
|
+
toFill = avail;
|
|
7244
|
+
}
|
|
7245
|
+
let sliceEnd = copied + toFill;
|
|
7246
|
+
// Firefox on Android sends only the first channel
|
|
7247
|
+
for (let ch = 0; ch < buffersLen; ch++) {
|
|
7248
|
+
if (buffers[ch]) {
|
|
7249
|
+
let cpPrt = buffers[ch].slice(copied, sliceEnd);
|
|
7250
|
+
let buf = this.bufs[ch];
|
|
7251
|
+
buf.set(cpPrt, this.filled);
|
|
7252
|
+
}
|
|
7253
|
+
}
|
|
7254
|
+
copied += toFill;
|
|
7255
|
+
avail -= toFill;
|
|
7256
|
+
this.filled += toFill;
|
|
7257
|
+
if (this.filled == this._chunkSize) {
|
|
7258
|
+
this.outStream.write(this.bufs);
|
|
7259
|
+
this.sentFrames += this.filled;
|
|
7260
|
+
this.filled = 0;
|
|
7261
|
+
}
|
|
7262
|
+
}
|
|
7263
|
+
}
|
|
7264
|
+
return copied;
|
|
7265
|
+
}
|
|
7266
|
+
flush() {
|
|
7267
|
+
if (this.filled > 0) {
|
|
7268
|
+
let restBufs = new Array(this._channels);
|
|
7269
|
+
for (let ch = 0; ch < this._channels; ch++) {
|
|
7270
|
+
restBufs[ch] = this.bufs[ch].slice(0, this.filled);
|
|
7271
|
+
}
|
|
7272
|
+
this.outStream.write(restBufs);
|
|
7273
|
+
this.outStream.flush();
|
|
7274
|
+
this.sentFrames += this.filled;
|
|
7275
|
+
this.filled = 0;
|
|
7276
|
+
}
|
|
7277
|
+
}
|
|
7278
|
+
close() {
|
|
7279
|
+
this.outStream.close();
|
|
7280
|
+
}
|
|
7281
|
+
}
|
|
7282
|
+
|
|
7283
|
+
class SequenceAudioFloat32ChunkerOutStream extends Float32ArrayChunkerOutStream {
|
|
7284
|
+
constructor(outStream, chunkDurationSeconds) {
|
|
7285
|
+
super(outStream);
|
|
7286
|
+
this.chunkDurationSeconds = chunkDurationSeconds;
|
|
7287
|
+
this.sampleRate = null;
|
|
7288
|
+
this.sequenceAudioFloat32OutStream = outStream;
|
|
7289
|
+
}
|
|
7290
|
+
setFormat(channels, sampleRate) {
|
|
7291
|
+
console.debug("SequenceAudioFloat32ChunkerOutStream:setFormat(channels: " + channels + ",sampleRate: " + sampleRate + ")");
|
|
7292
|
+
this.channels = channels;
|
|
7293
|
+
this.sampleRate = sampleRate;
|
|
7294
|
+
this.chunkSize = Math.round(sampleRate * this.chunkDurationSeconds);
|
|
7295
|
+
console.debug("SequenceAudioFloat32ChunkerOutStream: chunkSize: " + this.chunkSize);
|
|
7296
|
+
this.sequenceAudioFloat32OutStream.setFormat(channels, sampleRate);
|
|
7297
|
+
}
|
|
7298
|
+
nextStream() {
|
|
7299
|
+
this.sequenceAudioFloat32OutStream.nextStream();
|
|
7300
|
+
}
|
|
7301
|
+
}
|
|
7302
|
+
/**
|
|
7303
|
+
* Streams a SequenceAudioFloat32OutStream to multiple streams
|
|
7304
|
+
*/
|
|
7305
|
+
class SequenceAudioFloat32OutStreamMultiplier {
|
|
7306
|
+
constructor() {
|
|
7307
|
+
this._sequenceAudioFloat32OutStreams = new Array();
|
|
7308
|
+
}
|
|
7309
|
+
get sequenceAudioFloat32OutStreams() {
|
|
7310
|
+
return this._sequenceAudioFloat32OutStreams;
|
|
7311
|
+
}
|
|
7312
|
+
setFormat(channels, sampleRate) {
|
|
7313
|
+
for (let os of this._sequenceAudioFloat32OutStreams) {
|
|
7314
|
+
os.setFormat(channels, sampleRate);
|
|
7315
|
+
}
|
|
7316
|
+
}
|
|
7317
|
+
nextStream() {
|
|
7318
|
+
for (let os of this._sequenceAudioFloat32OutStreams) {
|
|
7319
|
+
os.nextStream();
|
|
7320
|
+
}
|
|
7321
|
+
}
|
|
7322
|
+
close() {
|
|
7323
|
+
for (let os of this._sequenceAudioFloat32OutStreams) {
|
|
7324
|
+
os.close();
|
|
7325
|
+
}
|
|
7326
|
+
}
|
|
7327
|
+
flush() {
|
|
7328
|
+
for (let os of this._sequenceAudioFloat32OutStreams) {
|
|
7329
|
+
os.flush();
|
|
7330
|
+
}
|
|
7331
|
+
}
|
|
7332
|
+
write(buffers) {
|
|
7333
|
+
let toWrite = buffers.length;
|
|
7334
|
+
for (let os of this._sequenceAudioFloat32OutStreams) {
|
|
7335
|
+
os.write(buffers);
|
|
7336
|
+
}
|
|
7337
|
+
return toWrite;
|
|
7338
|
+
}
|
|
7339
|
+
}
|
|
7340
|
+
|
|
7263
7341
|
const FORCE_REQUEST_AUDIO_PERMISSIONS = false;
|
|
7264
7342
|
const RECFILE_API_CTX = 'recfile';
|
|
7265
7343
|
const MAX_RECORDING_TIME_MS = 1000 * 60 * 60 * 60; // 1 hour
|
|
7266
7344
|
const LEVEL_BAR_INTERVALL_SECONDS = 0.1; // 100ms
|
|
7267
|
-
class
|
|
7268
|
-
constructor(
|
|
7345
|
+
class ChunkManager {
|
|
7346
|
+
constructor(chunkAudioBufferReceiver) {
|
|
7347
|
+
this.chunkAudioBufferReceiver = chunkAudioBufferReceiver;
|
|
7348
|
+
this.channels = 0;
|
|
7349
|
+
this.sampleRate = -1;
|
|
7350
|
+
this.chunkIdx = 0;
|
|
7351
|
+
}
|
|
7352
|
+
set recordingFile(value) {
|
|
7353
|
+
this._rf = value;
|
|
7354
|
+
}
|
|
7355
|
+
close() {
|
|
7356
|
+
// Nothing to do
|
|
7357
|
+
}
|
|
7358
|
+
flush() {
|
|
7359
|
+
this.chunkAudioBufferReceiver.postAudioStreamEnd(this.chunkIdx);
|
|
7360
|
+
}
|
|
7361
|
+
nextStream() {
|
|
7362
|
+
// reset chunk counter
|
|
7363
|
+
this.chunkIdx = 0;
|
|
7364
|
+
this.chunkAudioBufferReceiver.postAudioStreamStart();
|
|
7365
|
+
}
|
|
7366
|
+
setFormat(channels, sampleRate) {
|
|
7367
|
+
this.channels = channels;
|
|
7368
|
+
this.sampleRate = sampleRate;
|
|
7369
|
+
}
|
|
7370
|
+
write(buffers) {
|
|
7371
|
+
let aCtx = AudioContextProvider.audioContextInstance();
|
|
7372
|
+
let bChs = buffers.length;
|
|
7373
|
+
let frameLen = 0;
|
|
7374
|
+
if (aCtx && bChs > 0) {
|
|
7375
|
+
frameLen = buffers[0].length;
|
|
7376
|
+
let ad = aCtx.createBuffer(this.channels, frameLen, this.sampleRate);
|
|
7377
|
+
for (let ch = 0; ch < this.channels; ch++) {
|
|
7378
|
+
ad.copyToChannel(buffers[ch], ch);
|
|
7379
|
+
}
|
|
7380
|
+
this.chunkAudioBufferReceiver.postChunkAudioBuffer(ad, this.chunkIdx);
|
|
7381
|
+
this.chunkIdx++;
|
|
7382
|
+
}
|
|
7383
|
+
return frameLen;
|
|
7384
|
+
}
|
|
7385
|
+
}
|
|
7386
|
+
let BasicRecorder = class BasicRecorder {
|
|
7387
|
+
constructor(dialog, sessionService, uploader, config) {
|
|
7269
7388
|
this.dialog = dialog;
|
|
7270
7389
|
this.sessionService = sessionService;
|
|
7390
|
+
this.uploader = uploader;
|
|
7391
|
+
this.config = config;
|
|
7271
7392
|
this.statusMsg = '';
|
|
7272
7393
|
this.statusWaiting = false;
|
|
7273
7394
|
this.readonly = false;
|
|
7395
|
+
this.rfUuid = null;
|
|
7274
7396
|
this.processingRecording = false;
|
|
7275
7397
|
this.ac = null;
|
|
7276
7398
|
this._wakeLock = false;
|
|
7277
7399
|
this._selectedDeviceId = undefined;
|
|
7278
7400
|
this._channelCount = 2;
|
|
7279
7401
|
this._session = null;
|
|
7402
|
+
this.startedDate = null;
|
|
7280
7403
|
this.uploadProgress = 100;
|
|
7281
7404
|
this.uploadStatus = 'ok';
|
|
7282
7405
|
this.audioSignalCollapsed = true;
|
|
@@ -7286,7 +7409,10 @@ class BasicRecorder {
|
|
|
7286
7409
|
this.audioFetchSubscription = null;
|
|
7287
7410
|
this.destroyed = false;
|
|
7288
7411
|
this.navigationDisabled = true;
|
|
7412
|
+
// Default: Do not try to keep the device awake
|
|
7289
7413
|
this.noSleep = null;
|
|
7414
|
+
// Default: Disabled chunked upload
|
|
7415
|
+
this._uploadChunkSizeSeconds = null;
|
|
7290
7416
|
this.userAgent = UserAgentBuilder.userAgent();
|
|
7291
7417
|
console.debug("Detected platform: " + this.userAgent.detectedPlatform);
|
|
7292
7418
|
console.debug("Detected browser: " + this.userAgent.detectedBrowser);
|
|
@@ -7296,6 +7422,16 @@ class BasicRecorder {
|
|
|
7296
7422
|
this.streamLevelMeasure = new StreamLevelMeasure();
|
|
7297
7423
|
this.selCaptureDeviceId = null;
|
|
7298
7424
|
}
|
|
7425
|
+
get uploadChunkSizeSeconds() {
|
|
7426
|
+
return this._uploadChunkSizeSeconds;
|
|
7427
|
+
}
|
|
7428
|
+
set uploadChunkSizeSeconds(value) {
|
|
7429
|
+
let oldValue = this.uploadChunkSizeSeconds;
|
|
7430
|
+
this._uploadChunkSizeSeconds = value;
|
|
7431
|
+
if (value !== oldValue) {
|
|
7432
|
+
this.configureStreamCaptureStream();
|
|
7433
|
+
}
|
|
7434
|
+
}
|
|
7299
7435
|
get wakeLock() {
|
|
7300
7436
|
return this._wakeLock;
|
|
7301
7437
|
}
|
|
@@ -7309,12 +7445,14 @@ class BasicRecorder {
|
|
|
7309
7445
|
}
|
|
7310
7446
|
if (!this.noSleep.isEnabled) {
|
|
7311
7447
|
this.noSleep.enable();
|
|
7448
|
+
console.debug("Enabled wake lock.");
|
|
7312
7449
|
}
|
|
7313
7450
|
}
|
|
7314
7451
|
}
|
|
7315
7452
|
disableWakeLockCond() {
|
|
7316
7453
|
if (this.noSleep && this.noSleep.isEnabled) {
|
|
7317
7454
|
this.noSleep.disable();
|
|
7455
|
+
console.debug("Disabled wake lock.");
|
|
7318
7456
|
}
|
|
7319
7457
|
}
|
|
7320
7458
|
set audioDevices(audioDevices) {
|
|
@@ -7336,6 +7474,27 @@ class BasicRecorder {
|
|
|
7336
7474
|
this.statusAlertType = 'info';
|
|
7337
7475
|
this.statusMsg = 'Ready.';
|
|
7338
7476
|
}
|
|
7477
|
+
configureStreamCaptureStream() {
|
|
7478
|
+
let outStream;
|
|
7479
|
+
if (this.uploadChunkSizeSeconds) {
|
|
7480
|
+
// Multiply the capture stream to...
|
|
7481
|
+
let sasm = new SequenceAudioFloat32OutStreamMultiplier();
|
|
7482
|
+
// ...upload audio data in chunks...
|
|
7483
|
+
let chMng = new ChunkManager(this); // The chunk manager connects the chunked audio stream to this class to upload the chunks
|
|
7484
|
+
let chOsUpload = new SequenceAudioFloat32ChunkerOutStream(chMng, this.uploadChunkSizeSeconds); // The audio stream chunker itself
|
|
7485
|
+
sasm.sequenceAudioFloat32OutStreams.push(chOsUpload);
|
|
7486
|
+
// ...and to measure the level
|
|
7487
|
+
let chOsLvlMeas = new SequenceAudioFloat32ChunkerOutStream(this.streamLevelMeasure, LEVEL_BAR_INTERVALL_SECONDS);
|
|
7488
|
+
sasm.sequenceAudioFloat32OutStreams.push(chOsLvlMeas);
|
|
7489
|
+
outStream = sasm;
|
|
7490
|
+
}
|
|
7491
|
+
else {
|
|
7492
|
+
outStream = new SequenceAudioFloat32ChunkerOutStream(this.streamLevelMeasure, LEVEL_BAR_INTERVALL_SECONDS);
|
|
7493
|
+
}
|
|
7494
|
+
if (this.ac) {
|
|
7495
|
+
this.ac.audioOutStream = outStream;
|
|
7496
|
+
}
|
|
7497
|
+
}
|
|
7339
7498
|
start() {
|
|
7340
7499
|
this.statusAlertType = 'info';
|
|
7341
7500
|
this.statusMsg = 'Starting session...';
|
|
@@ -7542,6 +7701,75 @@ class BasicRecorder {
|
|
|
7542
7701
|
});
|
|
7543
7702
|
}
|
|
7544
7703
|
}
|
|
7704
|
+
startItem() {
|
|
7705
|
+
this.startedDate = null;
|
|
7706
|
+
this.enableWakeLockCond();
|
|
7707
|
+
this.rfUuid = UUID.generate();
|
|
7708
|
+
this.transportActions.startAction.disabled = true;
|
|
7709
|
+
this.transportActions.pauseAction.disabled = true;
|
|
7710
|
+
if (this.readonly) {
|
|
7711
|
+
return;
|
|
7712
|
+
}
|
|
7713
|
+
}
|
|
7714
|
+
started() {
|
|
7715
|
+
if (!this.startedDate) {
|
|
7716
|
+
this.startedDate = new Date();
|
|
7717
|
+
}
|
|
7718
|
+
this.transportActions.startAction.disabled = true;
|
|
7719
|
+
}
|
|
7720
|
+
postRecording(wavFile, recUrl) {
|
|
7721
|
+
let wavBlob = new Blob([wavFile], { type: 'audio/wav' });
|
|
7722
|
+
let ul = new Upload(wavBlob, recUrl);
|
|
7723
|
+
this.uploader.queueUpload(ul);
|
|
7724
|
+
}
|
|
7725
|
+
postAudioStreamStart() {
|
|
7726
|
+
var _a;
|
|
7727
|
+
if (this.rfUuid) {
|
|
7728
|
+
let apiEndPoint = '';
|
|
7729
|
+
if (this.config && this.config.apiEndPoint) {
|
|
7730
|
+
apiEndPoint = this.config.apiEndPoint;
|
|
7731
|
+
}
|
|
7732
|
+
if (apiEndPoint !== '') {
|
|
7733
|
+
apiEndPoint = apiEndPoint + '/';
|
|
7734
|
+
}
|
|
7735
|
+
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
7736
|
+
let recUrl = sessionsUrl + '/' + ((_a = this.session) === null || _a === void 0 ? void 0 : _a.sessionId) + '/' + RECFILE_API_CTX + '/' + this.rfUuid + '/prepareChunksRequest';
|
|
7737
|
+
let fd = new FormData();
|
|
7738
|
+
// Note: At least one parameter must be set
|
|
7739
|
+
fd.set('uuid', this.rfUuid);
|
|
7740
|
+
if (!this.startedDate) {
|
|
7741
|
+
this.startedDate = new Date();
|
|
7742
|
+
}
|
|
7743
|
+
fd.set('startedDate', this.startedDate.toJSON());
|
|
7744
|
+
let ul = new Upload(fd, recUrl);
|
|
7745
|
+
this.uploader.queueUpload(ul);
|
|
7746
|
+
}
|
|
7747
|
+
else {
|
|
7748
|
+
console.error("Recording file UUID not set!");
|
|
7749
|
+
}
|
|
7750
|
+
}
|
|
7751
|
+
postAudioStreamEnd(chunkCount) {
|
|
7752
|
+
var _a;
|
|
7753
|
+
if (this.rfUuid) {
|
|
7754
|
+
let apiEndPoint = '';
|
|
7755
|
+
if (this.config && this.config.apiEndPoint) {
|
|
7756
|
+
apiEndPoint = this.config.apiEndPoint;
|
|
7757
|
+
}
|
|
7758
|
+
if (apiEndPoint !== '') {
|
|
7759
|
+
apiEndPoint = apiEndPoint + '/';
|
|
7760
|
+
}
|
|
7761
|
+
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
7762
|
+
let recUrl = sessionsUrl + '/' + ((_a = this.session) === null || _a === void 0 ? void 0 : _a.sessionId) + '/' + RECFILE_API_CTX + '/' + this.rfUuid + '/concatChunksRequest';
|
|
7763
|
+
let fd = new FormData();
|
|
7764
|
+
fd.set('uuid', this.rfUuid);
|
|
7765
|
+
fd.set('chunkCount', chunkCount.toString());
|
|
7766
|
+
let ul = new Upload(fd, recUrl);
|
|
7767
|
+
this.uploader.queueUpload(ul);
|
|
7768
|
+
}
|
|
7769
|
+
else {
|
|
7770
|
+
console.error("Recording file UUID not set!");
|
|
7771
|
+
}
|
|
7772
|
+
}
|
|
7545
7773
|
closed() {
|
|
7546
7774
|
this.statusAlertType = 'info';
|
|
7547
7775
|
this.statusMsg = 'Session closed.';
|
|
@@ -7558,7 +7786,11 @@ class BasicRecorder {
|
|
|
7558
7786
|
}
|
|
7559
7787
|
});
|
|
7560
7788
|
}
|
|
7561
|
-
}
|
|
7789
|
+
};
|
|
7790
|
+
BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS = 30;
|
|
7791
|
+
BasicRecorder = __decorate([
|
|
7792
|
+
__param(3, Inject(SPEECHRECORDER_CONFIG))
|
|
7793
|
+
], BasicRecorder);
|
|
7562
7794
|
|
|
7563
7795
|
/**
|
|
7564
7796
|
* Created by klausj on 17.06.2017.
|
|
@@ -7872,7 +8104,7 @@ const DEFAULT_PRE_REC_DELAY = 1000;
|
|
|
7872
8104
|
const DEFAULT_POST_REC_DELAY = 500;
|
|
7873
8105
|
class SessionManager extends BasicRecorder {
|
|
7874
8106
|
constructor(changeDetectorRef, renderer, dialog, sessionService, recFileService, uploader, config) {
|
|
7875
|
-
super(dialog, sessionService);
|
|
8107
|
+
super(dialog, sessionService, uploader, config);
|
|
7876
8108
|
this.changeDetectorRef = changeDetectorRef;
|
|
7877
8109
|
this.renderer = renderer;
|
|
7878
8110
|
this.dialog = dialog;
|
|
@@ -7975,7 +8207,7 @@ class SessionManager extends BasicRecorder {
|
|
|
7975
8207
|
if (this.ac) {
|
|
7976
8208
|
this.transportActions.startAction.onAction = () => this.startItem();
|
|
7977
8209
|
this.ac.listener = this;
|
|
7978
|
-
this.
|
|
8210
|
+
this.configureStreamCaptureStream();
|
|
7979
8211
|
// Don't list the devices here. If we do not have audio permissions we only get anonymized devices without labels.
|
|
7980
8212
|
//this.ac.listDevices();
|
|
7981
8213
|
}
|
|
@@ -8121,12 +8353,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8121
8353
|
}
|
|
8122
8354
|
}
|
|
8123
8355
|
startItem() {
|
|
8124
|
-
|
|
8125
|
-
this.transportActions.startAction.disabled = true;
|
|
8126
|
-
this.transportActions.pauseAction.disabled = true;
|
|
8127
|
-
if (this.readonly) {
|
|
8128
|
-
return;
|
|
8129
|
-
}
|
|
8356
|
+
super.startItem();
|
|
8130
8357
|
this.transportActions.fwdAction.disabled = true;
|
|
8131
8358
|
this.transportActions.fwdNextAction.disabled = true;
|
|
8132
8359
|
this.transportActions.bwdAction.disabled = true;
|
|
@@ -8425,8 +8652,8 @@ class SessionManager extends BasicRecorder {
|
|
|
8425
8652
|
}
|
|
8426
8653
|
}
|
|
8427
8654
|
started() {
|
|
8655
|
+
super.started();
|
|
8428
8656
|
this.status = 2 /* PRE_RECORDING */;
|
|
8429
|
-
this.transportActions.startAction.disabled = true;
|
|
8430
8657
|
this.startStopSignalState = 1 /* PRERECORDING */;
|
|
8431
8658
|
if (this._session) {
|
|
8432
8659
|
if (this._session.status === "LOADED") {
|
|
@@ -8595,7 +8822,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8595
8822
|
rf = new SprRecordingFile(sessId, ic, it.recs.length, ad);
|
|
8596
8823
|
it.recs.push(rf);
|
|
8597
8824
|
}
|
|
8598
|
-
if (this.enableUploadRecordings) {
|
|
8825
|
+
if (this.enableUploadRecordings && !this.uploadChunkSizeSeconds) {
|
|
8599
8826
|
// TODO use SpeechRecorderconfig resp. RecfileService
|
|
8600
8827
|
// convert asynchronously to 16-bit integer PCM
|
|
8601
8828
|
// TODO could we avoid conversion to save CPU resources and transfer float PCM directly?
|
|
@@ -8674,6 +8901,25 @@ class SessionManager extends BasicRecorder {
|
|
|
8674
8901
|
}
|
|
8675
8902
|
this.changeDetectorRef.detectChanges();
|
|
8676
8903
|
}
|
|
8904
|
+
postChunkAudioBuffer(audioBuffer, chunkIdx) {
|
|
8905
|
+
var _a;
|
|
8906
|
+
this.processingRecording = true;
|
|
8907
|
+
let ww = new WavWriter();
|
|
8908
|
+
//new REST API URL
|
|
8909
|
+
let apiEndPoint = '';
|
|
8910
|
+
if (this.config && this.config.apiEndPoint) {
|
|
8911
|
+
apiEndPoint = this.config.apiEndPoint;
|
|
8912
|
+
}
|
|
8913
|
+
if (apiEndPoint !== '') {
|
|
8914
|
+
apiEndPoint = apiEndPoint + '/';
|
|
8915
|
+
}
|
|
8916
|
+
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
8917
|
+
let recUrl = sessionsUrl + '/' + ((_a = this.session) === null || _a === void 0 ? void 0 : _a.sessionId) + '/' + RECFILE_API_CTX + '/' + this.promptItem.itemcode + '/' + this.rfUuid + '/' + chunkIdx;
|
|
8918
|
+
ww.writeAsync(audioBuffer, (wavFile) => {
|
|
8919
|
+
this.postRecording(wavFile, recUrl);
|
|
8920
|
+
this.processingRecording = false;
|
|
8921
|
+
});
|
|
8922
|
+
}
|
|
8677
8923
|
postRecording(wavFile, recUrl) {
|
|
8678
8924
|
let wavBlob = new Blob([wavFile], { type: 'audio/wav' });
|
|
8679
8925
|
let ul = new Upload(wavBlob, recUrl);
|
|
@@ -8853,6 +9099,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImpor
|
|
|
8853
9099
|
}] } });
|
|
8854
9100
|
|
|
8855
9101
|
class RecorderComponent {
|
|
9102
|
+
constructor(uploader) {
|
|
9103
|
+
this.uploader = uploader;
|
|
9104
|
+
this.dataSaved = true;
|
|
9105
|
+
}
|
|
8856
9106
|
}
|
|
8857
9107
|
|
|
8858
9108
|
/**
|
|
@@ -8905,7 +9155,7 @@ var Mode;
|
|
|
8905
9155
|
})(Mode || (Mode = {}));
|
|
8906
9156
|
class SpeechrecorderngComponent extends RecorderComponent {
|
|
8907
9157
|
constructor(route, router, changeDetectorRef, sessionsService, projectService, scriptService, recFilesService, uploader) {
|
|
8908
|
-
super();
|
|
9158
|
+
super(uploader);
|
|
8909
9159
|
this.route = route;
|
|
8910
9160
|
this.router = router;
|
|
8911
9161
|
this.changeDetectorRef = changeDetectorRef;
|
|
@@ -8915,7 +9165,6 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
8915
9165
|
this.recFilesService = recFilesService;
|
|
8916
9166
|
this.uploader = uploader;
|
|
8917
9167
|
this._project = null;
|
|
8918
|
-
this.dataSaved = true;
|
|
8919
9168
|
}
|
|
8920
9169
|
ngOnInit() {
|
|
8921
9170
|
try {
|
|
@@ -8958,39 +9207,39 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
8958
9207
|
}
|
|
8959
9208
|
}
|
|
8960
9209
|
fetchSession(sessionId) {
|
|
8961
|
-
//Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'statusMsg: Player initialized.'. Current value: 'statusMsg: Fetching session info...'.
|
|
8962
|
-
// params.subscribe seems not to be asynchronous
|
|
8963
|
-
// this.sm.statusAlertType='info';
|
|
8964
|
-
// this.sm.statusMsg = 'Fetching session info...';
|
|
8965
|
-
// this.sm.statusWaiting=true;
|
|
8966
9210
|
let sessObs = this.sessionsService.sessionObserver(sessionId);
|
|
8967
9211
|
if (sessObs) {
|
|
8968
|
-
sessObs.subscribe(
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
this.project
|
|
9212
|
+
sessObs.subscribe({
|
|
9213
|
+
next: sess => {
|
|
9214
|
+
this.setSession(sess);
|
|
9215
|
+
this.sm.statusAlertType = 'info';
|
|
9216
|
+
this.sm.statusMsg = 'Received session info.';
|
|
9217
|
+
this.sm.statusWaiting = false;
|
|
9218
|
+
if (sess.project) {
|
|
9219
|
+
//console.debug("Session associated project: "+sess.project)
|
|
9220
|
+
this.projectService.projectObservable(sess.project).subscribe({
|
|
9221
|
+
next: (project) => {
|
|
9222
|
+
this.project = project;
|
|
9223
|
+
this.fetchScript(sess);
|
|
9224
|
+
}, error: (reason) => {
|
|
9225
|
+
this.sm.statusMsg = reason;
|
|
9226
|
+
this.sm.statusAlertType = 'error';
|
|
9227
|
+
this.sm.statusWaiting = false;
|
|
9228
|
+
console.error("Error fetching project config: " + reason);
|
|
9229
|
+
}
|
|
9230
|
+
});
|
|
9231
|
+
}
|
|
9232
|
+
else {
|
|
9233
|
+
console.info("Session has no associated project. Using default configuration.");
|
|
8977
9234
|
this.fetchScript(sess);
|
|
8978
|
-
}
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
9235
|
+
}
|
|
9236
|
+
},
|
|
9237
|
+
error: (reason) => {
|
|
9238
|
+
this.sm.statusMsg = reason;
|
|
9239
|
+
this.sm.statusAlertType = 'error';
|
|
9240
|
+
this.sm.statusWaiting = false;
|
|
9241
|
+
console.error("Error fetching session " + reason);
|
|
8984
9242
|
}
|
|
8985
|
-
else {
|
|
8986
|
-
console.info("Session has no associated project. Using default configuration.");
|
|
8987
|
-
this.fetchScript(sess);
|
|
8988
|
-
}
|
|
8989
|
-
}, (reason) => {
|
|
8990
|
-
this.sm.statusMsg = reason;
|
|
8991
|
-
this.sm.statusAlertType = 'error';
|
|
8992
|
-
this.sm.statusWaiting = false;
|
|
8993
|
-
console.error("Error fetching session " + reason);
|
|
8994
9243
|
});
|
|
8995
9244
|
}
|
|
8996
9245
|
}
|
|
@@ -8999,19 +9248,21 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
8999
9248
|
this.sm.statusAlertType = 'info';
|
|
9000
9249
|
this.sm.statusMsg = 'Fetching recording script...';
|
|
9001
9250
|
this.sm.statusWaiting = true;
|
|
9002
|
-
this.scriptService.scriptObservable(sess.script).subscribe(
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
9251
|
+
this.scriptService.scriptObservable(sess.script).subscribe({
|
|
9252
|
+
next: (script) => {
|
|
9253
|
+
this.sm.statusAlertType = 'info';
|
|
9254
|
+
this.sm.statusMsg = 'Received recording script.';
|
|
9255
|
+
this.sm.statusWaiting = false;
|
|
9256
|
+
this.setScript(script);
|
|
9257
|
+
this.sm.session = sess;
|
|
9258
|
+
this.fetchRecordings(sess, this.script);
|
|
9259
|
+
}, error: (reason) => {
|
|
9260
|
+
let errMsg = "Error fetching recording script: " + reason;
|
|
9261
|
+
console.error(errMsg);
|
|
9262
|
+
this.sm.statusMsg = errMsg;
|
|
9263
|
+
this.sm.statusAlertType = 'error';
|
|
9264
|
+
this.sm.statusWaiting = false;
|
|
9265
|
+
}
|
|
9015
9266
|
});
|
|
9016
9267
|
}
|
|
9017
9268
|
else {
|
|
@@ -9028,29 +9279,31 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
9028
9279
|
let prNm = null;
|
|
9029
9280
|
if (this.project) {
|
|
9030
9281
|
let rfsObs = this.recFilesService.recordingFileDescrList(this.project.name, sess.sessionId);
|
|
9031
|
-
rfsObs.subscribe(
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
if (rfs
|
|
9037
|
-
rfs
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9282
|
+
rfsObs.subscribe({
|
|
9283
|
+
next: (rfs) => {
|
|
9284
|
+
this.sm.statusAlertType = 'info';
|
|
9285
|
+
this.sm.statusMsg = 'Received infos of recordings.';
|
|
9286
|
+
this.sm.statusWaiting = false;
|
|
9287
|
+
if (rfs) {
|
|
9288
|
+
if (rfs instanceof Array) {
|
|
9289
|
+
rfs.forEach((rf) => {
|
|
9290
|
+
//console.debug("Already recorded: " + rf+ " "+rf.recording.itemcode);
|
|
9291
|
+
this.sm.addRecordingFileByDescriptor(rf);
|
|
9292
|
+
});
|
|
9293
|
+
}
|
|
9294
|
+
else {
|
|
9295
|
+
console.error('Expected type array for list of already recorded files ');
|
|
9296
|
+
}
|
|
9041
9297
|
}
|
|
9042
9298
|
else {
|
|
9043
|
-
console.
|
|
9299
|
+
//console.debug("Recording file list: " + rfs);
|
|
9044
9300
|
}
|
|
9301
|
+
}, error: (err) => {
|
|
9302
|
+
// we start the session anyway
|
|
9303
|
+
this.startSession();
|
|
9304
|
+
}, complete: () => {
|
|
9305
|
+
this.startSession();
|
|
9045
9306
|
}
|
|
9046
|
-
else {
|
|
9047
|
-
//console.debug("Recording file list: " + rfs);
|
|
9048
|
-
}
|
|
9049
|
-
}, () => {
|
|
9050
|
-
// we start the session anyway
|
|
9051
|
-
this.startSession();
|
|
9052
|
-
}, () => {
|
|
9053
|
-
this.startSession();
|
|
9054
9307
|
});
|
|
9055
9308
|
}
|
|
9056
9309
|
else {
|
|
@@ -9073,36 +9326,10 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
9073
9326
|
return this.dataSaved && !this.sm.isActive();
|
|
9074
9327
|
}
|
|
9075
9328
|
init() {
|
|
9076
|
-
|
|
9077
|
-
//var getUserMediaFnct= n.getUserMedia || n.webkitGetUserMedia ||
|
|
9078
|
-
// n.mozGetUserMedia || n.msGetUserMedia;
|
|
9079
|
-
var w = window;
|
|
9080
|
-
// TODO test onyl !!
|
|
9081
|
-
// let debugFail=true;
|
|
9082
|
-
// AudioContext = w.AudioContext || w.webkitAudioContext;
|
|
9083
|
-
// if (typeof AudioContext !== 'function' || debugFail) {
|
|
9084
|
-
// this.sm.statusAlertType='error';
|
|
9085
|
-
// this.sm.statusMsg = 'ERROR: Browser does not support Web Audio API!';
|
|
9086
|
-
// return false;
|
|
9087
|
-
// } else {
|
|
9088
|
-
// var context = new AudioContext();
|
|
9089
|
-
//
|
|
9090
|
-
// if (typeof navigator.mediaDevices.getUserMedia !== 'function') {
|
|
9091
|
-
// this.sm.statusAlertType='error';
|
|
9092
|
-
// this.sm.statusMsg= 'ERROR: Browser does not support Media streams!';
|
|
9093
|
-
// return false;
|
|
9094
|
-
// } else {
|
|
9095
|
-
//
|
|
9096
|
-
//this.sm = new SessionManager(new SimpleTrafficLight(), this.uploader);
|
|
9097
|
-
//this.sm.init();
|
|
9098
|
-
//this.ap = new AudioPlayer(context,this);
|
|
9099
|
-
//this.sm.listener=this;
|
|
9100
|
-
// }
|
|
9101
|
-
// }
|
|
9329
|
+
//TODO Duplicate code in AudioRecorderComponent
|
|
9102
9330
|
this.uploader.listener = (ue) => {
|
|
9103
9331
|
this.uploadUpdate(ue);
|
|
9104
9332
|
};
|
|
9105
|
-
//TODO Duplicate code in AudioRecorderComponent
|
|
9106
9333
|
window.addEventListener('beforeunload', (e) => {
|
|
9107
9334
|
console.debug("Before page unload event");
|
|
9108
9335
|
if (this.ready()) {
|
|
@@ -9191,6 +9418,13 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
9191
9418
|
chCnt = ProjectUtil.audioChannelCount(project);
|
|
9192
9419
|
console.info("Project requested recording channel count: " + chCnt);
|
|
9193
9420
|
this.sm.autoGainControlConfigs = project.autoGainControlConfigs;
|
|
9421
|
+
if (project.chunkedRecording === true) {
|
|
9422
|
+
console.debug("Enable chunked upload: chunkSize: " + BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS);
|
|
9423
|
+
this.sm.uploadChunkSizeSeconds = BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS;
|
|
9424
|
+
}
|
|
9425
|
+
else {
|
|
9426
|
+
this.sm.uploadChunkSizeSeconds = null;
|
|
9427
|
+
}
|
|
9194
9428
|
}
|
|
9195
9429
|
else {
|
|
9196
9430
|
console.error("Empty project configuration!");
|
|
@@ -9227,50 +9461,7 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
9227
9461
|
pLoader.send();
|
|
9228
9462
|
}
|
|
9229
9463
|
}
|
|
9230
|
-
// loadScript(callback: ()=>any){
|
|
9231
|
-
// var scrLoader = new XMLHttpRequest();
|
|
9232
|
-
// let hn:string =window.location.hostname;
|
|
9233
|
-
// let pn:string =window.location.pathname;
|
|
9234
|
-
// let pr:string =window.location.protocol;
|
|
9235
|
-
// let po:string =window.location.port;
|
|
9236
|
-
//
|
|
9237
|
-
// let sessionId:string=this.session.sessionId;
|
|
9238
|
-
//
|
|
9239
|
-
// let scrUrl:string | null = null;
|
|
9240
|
-
//
|
|
9241
|
-
// if (hn === 'localhost' || this.mode===Mode.DEMO) {
|
|
9242
|
-
// // local debug mode
|
|
9243
|
-
// // FF caches
|
|
9244
|
-
// scrUrl = 'test/' + this.session.script.toString() + '.json?' + new Date().getTime();
|
|
9245
|
-
//
|
|
9246
|
-
// } else {
|
|
9247
|
-
// let scrPath:string = '/wikispeech/session/scripts/servlet';
|
|
9248
|
-
// let scrQu:string = 'sessionId=' + sessionId;
|
|
9249
|
-
// scrUrl = pr + '//' + hn + ':' + po + scrPath;
|
|
9250
|
-
// if (scrQu) {
|
|
9251
|
-
// scrUrl = scrUrl + '?' + scrQu;
|
|
9252
|
-
// }
|
|
9253
|
-
// }
|
|
9254
|
-
//
|
|
9255
|
-
// scrLoader.open("GET",scrUrl , true);
|
|
9256
|
-
// scrLoader.setRequestHeader('Accept','application/json');
|
|
9257
|
-
// scrLoader.responseType = "json";
|
|
9258
|
-
// scrLoader.onload = (e) => {
|
|
9259
|
-
//
|
|
9260
|
-
// this.script = scrLoader.response;
|
|
9261
|
-
//
|
|
9262
|
-
//
|
|
9263
|
-
// this.sm.script = this.script;
|
|
9264
|
-
//
|
|
9265
|
-
// callback();
|
|
9266
|
-
// }
|
|
9267
|
-
// scrLoader.onerror = (e) => {
|
|
9268
|
-
// console.log("Error downloading recording script data ...");
|
|
9269
|
-
// }
|
|
9270
|
-
// scrLoader.send();
|
|
9271
|
-
// }
|
|
9272
9464
|
start() {
|
|
9273
|
-
//this.configure();
|
|
9274
9465
|
}
|
|
9275
9466
|
audioPlayerUpdate(e) {
|
|
9276
9467
|
if (EventType.STARTED === e.type) {
|
|
@@ -10957,13 +11148,12 @@ class Item {
|
|
|
10957
11148
|
}
|
|
10958
11149
|
}
|
|
10959
11150
|
class AudioRecorder extends BasicRecorder {
|
|
10960
|
-
constructor(changeDetectorRef, renderer, route, dialog,
|
|
10961
|
-
super(dialog, sessionService);
|
|
11151
|
+
constructor(changeDetectorRef, renderer, route, dialog, sessionService, recFileService, uploader, config) {
|
|
11152
|
+
super(dialog, sessionService, uploader, config);
|
|
10962
11153
|
this.changeDetectorRef = changeDetectorRef;
|
|
10963
11154
|
this.renderer = renderer;
|
|
10964
11155
|
this.route = route;
|
|
10965
11156
|
this.dialog = dialog;
|
|
10966
|
-
this.projectService = projectService;
|
|
10967
11157
|
this.sessionService = sessionService;
|
|
10968
11158
|
this.recFileService = recFileService;
|
|
10969
11159
|
this.uploader = uploader;
|
|
@@ -10974,7 +11164,6 @@ class AudioRecorder extends BasicRecorder {
|
|
|
10974
11164
|
this.enableDownloadRecordings = false;
|
|
10975
11165
|
this.status = 0 /* BLOCKED */;
|
|
10976
11166
|
this.dataSaved = true;
|
|
10977
|
-
this.startedDate = null;
|
|
10978
11167
|
this.maxRecTimerId = null;
|
|
10979
11168
|
this.maxRecTimerRunning = false;
|
|
10980
11169
|
this._promptIndex = null;
|
|
@@ -11065,7 +11254,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11065
11254
|
if (this.ac) {
|
|
11066
11255
|
this.transportActions.startAction.onAction = () => this.startItem();
|
|
11067
11256
|
this.ac.listener = this;
|
|
11068
|
-
this.
|
|
11257
|
+
this.configureStreamCaptureStream();
|
|
11069
11258
|
// Don't list the devices here. If we do not have audio permissions we only get anonymized devices without labels.
|
|
11070
11259
|
//this.ac.listDevices();
|
|
11071
11260
|
}
|
|
@@ -11092,23 +11281,6 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11092
11281
|
this.uploader.listener = (ue) => {
|
|
11093
11282
|
this.uploadUpdate(ue);
|
|
11094
11283
|
};
|
|
11095
|
-
let wakeLockSupp = ('wakeLock' in navigator);
|
|
11096
|
-
// if(wakeLockSupp) {
|
|
11097
|
-
// let wakeLock = null;
|
|
11098
|
-
// try {
|
|
11099
|
-
// //@ts-ignore
|
|
11100
|
-
// wakeLock = navigator.wakeLock.request('screen');
|
|
11101
|
-
//
|
|
11102
|
-
// //statusElem.textContent = 'Wake Lock is active!';
|
|
11103
|
-
// } catch (err) {
|
|
11104
|
-
// // The Wake Lock request has failed - usually system related, such as battery.
|
|
11105
|
-
// console.error('Wakelock failed'+err)
|
|
11106
|
-
// }
|
|
11107
|
-
// }else{
|
|
11108
|
-
// let noSleep=new NoSleep();
|
|
11109
|
-
// noSleep.enable();
|
|
11110
|
-
//
|
|
11111
|
-
// }
|
|
11112
11284
|
}
|
|
11113
11285
|
onKeyPress(ke) {
|
|
11114
11286
|
if (ke.key == ' ') {
|
|
@@ -11161,36 +11333,36 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11161
11333
|
let prNm = null;
|
|
11162
11334
|
if (this.project) {
|
|
11163
11335
|
let rfsObs = this.recFileService.recordingFileList(this.project.name, sess.sessionId);
|
|
11164
|
-
rfsObs.subscribe((rfs) => {
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
|
|
11168
|
-
|
|
11169
|
-
|
|
11170
|
-
|
|
11171
|
-
|
|
11172
|
-
|
|
11173
|
-
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
|
|
11336
|
+
rfsObs.subscribe({ next: (rfs) => {
|
|
11337
|
+
this.statusAlertType = 'info';
|
|
11338
|
+
this.statusMsg = 'Received infos of recordings.';
|
|
11339
|
+
this.statusWaiting = false;
|
|
11340
|
+
if (rfs) {
|
|
11341
|
+
if (rfs instanceof Array) {
|
|
11342
|
+
rfs.forEach((rf) => {
|
|
11343
|
+
if (rf.startedDate) {
|
|
11344
|
+
rf._startedAsDateObj = new Date(rf.startedDate);
|
|
11345
|
+
}
|
|
11346
|
+
if (rf.date) {
|
|
11347
|
+
rf._dateAsDateObj = new Date(rf.date);
|
|
11348
|
+
}
|
|
11349
|
+
this.recorderCombiPane.push(rf);
|
|
11350
|
+
});
|
|
11351
|
+
}
|
|
11352
|
+
else {
|
|
11353
|
+
console.error('Expected type array for list of already recorded files ');
|
|
11354
|
+
}
|
|
11179
11355
|
}
|
|
11180
11356
|
else {
|
|
11181
|
-
console.
|
|
11357
|
+
//console.debug("Recording file list: " + rfs);
|
|
11182
11358
|
}
|
|
11183
|
-
}
|
|
11184
|
-
|
|
11185
|
-
|
|
11186
|
-
}
|
|
11187
|
-
|
|
11188
|
-
|
|
11189
|
-
|
|
11190
|
-
}, () => {
|
|
11191
|
-
// Normal start
|
|
11192
|
-
this.start();
|
|
11193
|
-
});
|
|
11359
|
+
}, error: (err) => {
|
|
11360
|
+
// Failed fetching existing, but we start the session anyway
|
|
11361
|
+
this.start();
|
|
11362
|
+
}, complete: () => {
|
|
11363
|
+
// Normal start
|
|
11364
|
+
this.start();
|
|
11365
|
+
} });
|
|
11194
11366
|
}
|
|
11195
11367
|
else {
|
|
11196
11368
|
// No project def -> error
|
|
@@ -11212,6 +11384,12 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11212
11384
|
chCnt = ProjectUtil.audioChannelCount(project);
|
|
11213
11385
|
console.info("Project requested recording channel count: " + chCnt);
|
|
11214
11386
|
this.autoGainControlConfigs = project.autoGainControlConfigs;
|
|
11387
|
+
if (project.chunkedRecording === true) {
|
|
11388
|
+
this.uploadChunkSizeSeconds = BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS;
|
|
11389
|
+
}
|
|
11390
|
+
else {
|
|
11391
|
+
this.uploadChunkSizeSeconds = null;
|
|
11392
|
+
}
|
|
11215
11393
|
}
|
|
11216
11394
|
else {
|
|
11217
11395
|
console.error("Empty project configuration!");
|
|
@@ -11311,12 +11489,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11311
11489
|
}
|
|
11312
11490
|
}
|
|
11313
11491
|
startItem() {
|
|
11314
|
-
|
|
11315
|
-
this.transportActions.startAction.disabled = true;
|
|
11316
|
-
this.transportActions.pauseAction.disabled = true;
|
|
11317
|
-
if (this.readonly) {
|
|
11318
|
-
return;
|
|
11319
|
-
}
|
|
11492
|
+
super.startItem();
|
|
11320
11493
|
this.transportActions.fwdAction.disabled = true;
|
|
11321
11494
|
this.transportActions.fwdNextAction.disabled = true;
|
|
11322
11495
|
this.transportActions.bwdAction.disabled = true;
|
|
@@ -11468,8 +11641,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11468
11641
|
}
|
|
11469
11642
|
}
|
|
11470
11643
|
started() {
|
|
11471
|
-
|
|
11472
|
-
this.transportActions.startAction.disabled = true;
|
|
11644
|
+
super.started();
|
|
11473
11645
|
this.statusAlertType = 'info';
|
|
11474
11646
|
this.statusMsg = 'Recording...';
|
|
11475
11647
|
let maxRecordingTimeMs = MAX_RECORDING_TIME_MS;
|
|
@@ -11502,24 +11674,6 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11502
11674
|
this.ac.stop();
|
|
11503
11675
|
}
|
|
11504
11676
|
}
|
|
11505
|
-
// addRecordingFileByDescriptor(rfd:RecordingFileDescriptorImpl){
|
|
11506
|
-
// let prIdx=0;
|
|
11507
|
-
// if(this.items) {
|
|
11508
|
-
// let it = this.items[prIdx];
|
|
11509
|
-
// if (it) {
|
|
11510
|
-
// if (!it.recs) {
|
|
11511
|
-
// it.recs = new Array<SprRecordingFile>();
|
|
11512
|
-
// }
|
|
11513
|
-
//
|
|
11514
|
-
// } else {
|
|
11515
|
-
// //console.debug("WARN: No recording item with code: \"" +rfd.recording.itemcode+ "\" found.");
|
|
11516
|
-
// }
|
|
11517
|
-
// }
|
|
11518
|
-
// }
|
|
11519
|
-
//
|
|
11520
|
-
// addRecordingFileByPromptIndex(promptIndex:number, rf:SprRecordingFile){
|
|
11521
|
-
//
|
|
11522
|
-
// }
|
|
11523
11677
|
stopped() {
|
|
11524
11678
|
this.updateStartActionDisableState();
|
|
11525
11679
|
this.transportActions.stopAction.disabled = true;
|
|
@@ -11534,41 +11688,39 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11534
11688
|
if (this._session) {
|
|
11535
11689
|
sessId = this._session.sessionId;
|
|
11536
11690
|
}
|
|
11537
|
-
|
|
11691
|
+
if (!this.rfUuid) {
|
|
11692
|
+
this.rfUuid = UUID.generate();
|
|
11693
|
+
}
|
|
11694
|
+
let rf = new RecordingFile(this.rfUuid, sessId, ad);
|
|
11538
11695
|
rf._startedAsDateObj = this.startedDate;
|
|
11539
11696
|
if (rf._startedAsDateObj) {
|
|
11540
11697
|
rf.startedDate = rf._startedAsDateObj.toString();
|
|
11541
11698
|
}
|
|
11542
|
-
|
|
11543
|
-
|
|
11544
|
-
|
|
11545
|
-
|
|
11546
|
-
if (
|
|
11547
|
-
apiEndPoint =
|
|
11699
|
+
rf.frames = ad.length;
|
|
11700
|
+
this.displayRecFile = rf;
|
|
11701
|
+
this.recorderCombiPane.push(rf);
|
|
11702
|
+
// Upload if upload enabled and not in chunked upload mode
|
|
11703
|
+
if (this.enableUploadRecordings && !this.uploadChunkSizeSeconds) {
|
|
11704
|
+
let apiEndPoint = '';
|
|
11705
|
+
if (this.config && this.config.apiEndPoint) {
|
|
11706
|
+
apiEndPoint = this.config.apiEndPoint;
|
|
11707
|
+
}
|
|
11708
|
+
if (apiEndPoint !== '') {
|
|
11709
|
+
apiEndPoint = apiEndPoint + '/';
|
|
11710
|
+
}
|
|
11711
|
+
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
11712
|
+
let recUrl = sessionsUrl + '/' + rf.session + '/' + RECFILE_API_CTX + '/' + rf.uuid;
|
|
11713
|
+
// convert asynchronously to 16-bit integer PCM
|
|
11714
|
+
// TODO could we avoid conversion to save CPU resources and transfer float PCM directly?
|
|
11715
|
+
// TODO duplicate conversion for manual download
|
|
11716
|
+
this.processingRecording = true;
|
|
11717
|
+
let ww = new WavWriter();
|
|
11718
|
+
ww.writeAsync(ad, (wavFile) => {
|
|
11719
|
+
this.postRecordingMultipart(wavFile, rf.uuid, rf.session, rf._startedAsDateObj, recUrl);
|
|
11720
|
+
this.processingRecording = false;
|
|
11721
|
+
this.changeDetectorRef.detectChanges();
|
|
11722
|
+
});
|
|
11548
11723
|
}
|
|
11549
|
-
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
11550
|
-
let recUrl = sessionsUrl + '/' + rf.session + '/' + RECFILE_API_CTX + '/' + rf.uuid;
|
|
11551
|
-
//
|
|
11552
|
-
//
|
|
11553
|
-
//
|
|
11554
|
-
// // convert asynchronously to 16-bit integer PCM
|
|
11555
|
-
// // TODO could we avoid conversion to save CPU resources and transfer float PCM directly?
|
|
11556
|
-
// // TODO duplicate conversion for manual download
|
|
11557
|
-
// //console.log("Build wav writer...");
|
|
11558
|
-
this.processingRecording = true;
|
|
11559
|
-
let ww = new WavWriter();
|
|
11560
|
-
ww.writeAsync(ad, (wavFile) => {
|
|
11561
|
-
//this.postRecording(wavFile, recUrl);
|
|
11562
|
-
//rf._dateAsDateObj=new Date();
|
|
11563
|
-
rf.frames = ad.length;
|
|
11564
|
-
this.displayRecFile = rf;
|
|
11565
|
-
//this.recordingListComp.recordingList.push(rf);
|
|
11566
|
-
this.recorderCombiPane.push(rf);
|
|
11567
|
-
this.postRecordingMultipart(wavFile, rf.uuid, rf.session, rf._startedAsDateObj, recUrl);
|
|
11568
|
-
this.processingRecording = false;
|
|
11569
|
-
this.changeDetectorRef.detectChanges();
|
|
11570
|
-
});
|
|
11571
|
-
// }
|
|
11572
11724
|
}
|
|
11573
11725
|
// check complete session
|
|
11574
11726
|
let complete = true;
|
|
@@ -11579,11 +11731,6 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11579
11731
|
this.updateNavigationActions();
|
|
11580
11732
|
this.changeDetectorRef.detectChanges();
|
|
11581
11733
|
}
|
|
11582
|
-
postRecording(wavFile, recUrl) {
|
|
11583
|
-
let wavBlob = new Blob([wavFile], { type: 'audio/wav' });
|
|
11584
|
-
let ul = new Upload(wavBlob, recUrl);
|
|
11585
|
-
this.uploader.queueUpload(ul);
|
|
11586
|
-
}
|
|
11587
11734
|
postRecordingMultipart(wavFile, uuid, sessionId, startedDate, recUrl) {
|
|
11588
11735
|
let wavBlob = new Blob([wavFile], { type: 'audio/wav' });
|
|
11589
11736
|
let fd = new FormData();
|
|
@@ -11600,6 +11747,25 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11600
11747
|
let ul = new Upload(fd, recUrl);
|
|
11601
11748
|
this.uploader.queueUpload(ul);
|
|
11602
11749
|
}
|
|
11750
|
+
postChunkAudioBuffer(audioBuffer, chunkIdx) {
|
|
11751
|
+
var _a;
|
|
11752
|
+
this.processingRecording = true;
|
|
11753
|
+
let ww = new WavWriter();
|
|
11754
|
+
//new REST API URL
|
|
11755
|
+
let apiEndPoint = '';
|
|
11756
|
+
if (this.config && this.config.apiEndPoint) {
|
|
11757
|
+
apiEndPoint = this.config.apiEndPoint;
|
|
11758
|
+
}
|
|
11759
|
+
if (apiEndPoint !== '') {
|
|
11760
|
+
apiEndPoint = apiEndPoint + '/';
|
|
11761
|
+
}
|
|
11762
|
+
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
11763
|
+
let recUrl = sessionsUrl + '/' + ((_a = this.session) === null || _a === void 0 ? void 0 : _a.sessionId) + '/' + RECFILE_API_CTX + '/' + this.rfUuid + '/' + chunkIdx;
|
|
11764
|
+
ww.writeAsync(audioBuffer, (wavFile) => {
|
|
11765
|
+
this.postRecording(wavFile, recUrl);
|
|
11766
|
+
this.processingRecording = false;
|
|
11767
|
+
});
|
|
11768
|
+
}
|
|
11603
11769
|
stop() {
|
|
11604
11770
|
if (this.ac) {
|
|
11605
11771
|
this.ac.close();
|
|
@@ -11627,8 +11793,8 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11627
11793
|
}
|
|
11628
11794
|
}
|
|
11629
11795
|
}
|
|
11630
|
-
AudioRecorder.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: AudioRecorder, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i1$1.ActivatedRoute }, { token: i1$2.MatDialog }, { token:
|
|
11631
|
-
AudioRecorder.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.2", type: AudioRecorder, selector: "app-audiorecorder", inputs: {
|
|
11796
|
+
AudioRecorder.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: AudioRecorder, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i1$1.ActivatedRoute }, { token: i1$2.MatDialog }, { token: SessionService }, { token: RecordingService }, { token: SpeechRecorderUploader }, { token: SPEECHRECORDER_CONFIG }], target: i0.ɵɵFactoryTarget.Component });
|
|
11797
|
+
AudioRecorder.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.2", type: AudioRecorder, selector: "app-audiorecorder", inputs: { projectName: "projectName", dataSaved: "dataSaved" }, host: { listeners: { "window:keypress": "onKeyPress($event)", "window:keydown": "onKeyDown($event)" } }, providers: [SessionService], viewQueries: [{ propertyName: "recorderCombiPane", first: true, predicate: RecorderCombiPane, descendants: true, static: true }, { propertyName: "liveLevelDisplay", first: true, predicate: LevelBar, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
11632
11798
|
<app-warningbar [show]="isTestSession()" warningText="Test recording only!"></app-warningbar>
|
|
11633
11799
|
<app-warningbar [show]="isDefaultAudioTestSession()"
|
|
11634
11800
|
warningText="This test uses default audio device! Regular sessions may require a particular audio device (microphone)!"></app-warningbar>
|
|
@@ -11784,13 +11950,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImpor
|
|
|
11784
11950
|
]
|
|
11785
11951
|
}]
|
|
11786
11952
|
}], ctorParameters: function () {
|
|
11787
|
-
return [{ type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i1$1.ActivatedRoute }, { type: i1$2.MatDialog }, { type:
|
|
11953
|
+
return [{ type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i1$1.ActivatedRoute }, { type: i1$2.MatDialog }, { type: SessionService }, { type: RecordingService }, { type: SpeechRecorderUploader }, { type: SpeechRecorderConfig, decorators: [{
|
|
11788
11954
|
type: Inject,
|
|
11789
11955
|
args: [SPEECHRECORDER_CONFIG]
|
|
11790
11956
|
}] }];
|
|
11791
|
-
}, propDecorators: {
|
|
11792
|
-
type: Input
|
|
11793
|
-
}], projectName: [{
|
|
11957
|
+
}, propDecorators: { projectName: [{
|
|
11794
11958
|
type: Input
|
|
11795
11959
|
}], recorderCombiPane: [{
|
|
11796
11960
|
type: ViewChild,
|
|
@@ -11808,16 +11972,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImpor
|
|
|
11808
11972
|
args: ['window:keydown', ['$event']]
|
|
11809
11973
|
}] } });
|
|
11810
11974
|
class AudioRecorderComponent extends RecorderComponent {
|
|
11811
|
-
constructor(injector, route, router, changeDetectorRef, sessionService, projectService,
|
|
11812
|
-
super();
|
|
11975
|
+
constructor(injector, route, router, changeDetectorRef, sessionService, projectService, uploader) {
|
|
11976
|
+
super(uploader);
|
|
11813
11977
|
this.injector = injector;
|
|
11814
11978
|
this.route = route;
|
|
11815
11979
|
this.router = router;
|
|
11816
11980
|
this.changeDetectorRef = changeDetectorRef;
|
|
11817
11981
|
this.sessionService = sessionService;
|
|
11818
11982
|
this.projectService = projectService;
|
|
11819
|
-
this.
|
|
11820
|
-
this.dataSaved = true;
|
|
11983
|
+
this.uploader = uploader;
|
|
11821
11984
|
}
|
|
11822
11985
|
ngOnInit() {
|
|
11823
11986
|
//super.ngOnInit();
|
|
@@ -11852,6 +12015,9 @@ class AudioRecorderComponent extends RecorderComponent {
|
|
|
11852
12015
|
});
|
|
11853
12016
|
}
|
|
11854
12017
|
ngAfterViewInit() {
|
|
12018
|
+
this.uploader.listener = (ue) => {
|
|
12019
|
+
this.uploadUpdate(ue);
|
|
12020
|
+
};
|
|
11855
12021
|
this.route.queryParams.subscribe((params) => {
|
|
11856
12022
|
if (params['sessionId']) {
|
|
11857
12023
|
this.fetchSession(params['sessionId']);
|
|
@@ -11868,50 +12034,68 @@ class AudioRecorderComponent extends RecorderComponent {
|
|
|
11868
12034
|
//super.ngOnDestroy();
|
|
11869
12035
|
}
|
|
11870
12036
|
fetchSession(sessionId) {
|
|
11871
|
-
//Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'statusMsg: Player initialized.'. Current value: 'statusMsg: Fetching session info...'.
|
|
11872
|
-
// params.subscribe seems not to be asynchronous
|
|
11873
|
-
// this.sm.statusAlertType='info';
|
|
11874
|
-
// this.sm.statusMsg = 'Fetching session info...';
|
|
11875
|
-
// this.sm.statusWaiting=true;
|
|
11876
12037
|
let sessObs = this.sessionService.sessionObserver(sessionId);
|
|
11877
12038
|
if (sessObs) {
|
|
11878
|
-
sessObs.subscribe(
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
|
|
11884
|
-
|
|
11885
|
-
|
|
11886
|
-
|
|
11887
|
-
this.
|
|
11888
|
-
|
|
11889
|
-
|
|
11890
|
-
|
|
11891
|
-
|
|
11892
|
-
|
|
11893
|
-
|
|
11894
|
-
|
|
11895
|
-
|
|
11896
|
-
|
|
11897
|
-
|
|
12039
|
+
sessObs.subscribe({
|
|
12040
|
+
next: (sess) => {
|
|
12041
|
+
this.ar.statusAlertType = 'info';
|
|
12042
|
+
this.ar.statusMsg = 'Received session info.';
|
|
12043
|
+
this.ar.statusWaiting = false;
|
|
12044
|
+
this.session = sess;
|
|
12045
|
+
this.ar.session = sess;
|
|
12046
|
+
if (sess.project) {
|
|
12047
|
+
//console.debug("Session associated project: "+sess.project)
|
|
12048
|
+
this.projectService.projectObservable(sess.project).subscribe({
|
|
12049
|
+
next: (project) => {
|
|
12050
|
+
this.ar.project = project;
|
|
12051
|
+
this.ar.fetchRecordings(sess);
|
|
12052
|
+
}, error: (reason) => {
|
|
12053
|
+
this.ar.statusMsg = reason;
|
|
12054
|
+
this.ar.statusAlertType = 'error';
|
|
12055
|
+
this.ar.statusWaiting = false;
|
|
12056
|
+
console.error("Error fetching project config: " + reason);
|
|
12057
|
+
}
|
|
12058
|
+
});
|
|
12059
|
+
}
|
|
12060
|
+
else {
|
|
12061
|
+
console.info("Session has no associated project. Using default configuration.");
|
|
12062
|
+
}
|
|
12063
|
+
},
|
|
12064
|
+
error: (reason) => {
|
|
12065
|
+
this.ar.statusMsg = reason;
|
|
12066
|
+
this.ar.statusAlertType = 'error';
|
|
12067
|
+
this.ar.statusWaiting = false;
|
|
12068
|
+
console.error("Error fetching session " + reason);
|
|
11898
12069
|
}
|
|
11899
|
-
}, (reason) => {
|
|
11900
|
-
this.ar.statusMsg = reason;
|
|
11901
|
-
this.ar.statusAlertType = 'error';
|
|
11902
|
-
this.ar.statusWaiting = false;
|
|
11903
|
-
console.error("Error fetching session " + reason);
|
|
11904
12070
|
});
|
|
11905
12071
|
}
|
|
11906
12072
|
}
|
|
12073
|
+
uploadUpdate(ue) {
|
|
12074
|
+
let upStatus = ue.status;
|
|
12075
|
+
this.dataSaved = (UploaderStatus.DONE === upStatus);
|
|
12076
|
+
let percentUpl = ue.percentDone();
|
|
12077
|
+
if (UploaderStatus.ERR === upStatus) {
|
|
12078
|
+
this.ar.uploadStatus = 'warn';
|
|
12079
|
+
}
|
|
12080
|
+
else {
|
|
12081
|
+
if (percentUpl < 50) {
|
|
12082
|
+
this.ar.uploadStatus = 'accent';
|
|
12083
|
+
}
|
|
12084
|
+
else {
|
|
12085
|
+
this.ar.uploadStatus = 'success';
|
|
12086
|
+
}
|
|
12087
|
+
this.ar.uploadProgress = percentUpl;
|
|
12088
|
+
}
|
|
12089
|
+
this.changeDetectorRef.detectChanges();
|
|
12090
|
+
}
|
|
11907
12091
|
ready() {
|
|
11908
12092
|
return this.dataSaved && !this.ar.isActive();
|
|
11909
12093
|
}
|
|
11910
12094
|
}
|
|
11911
|
-
AudioRecorderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: AudioRecorderComponent, deps: [{ token: i0.Injector }, { token: i1$1.ActivatedRoute }, { token: i1$1.Router }, { token: i0.ChangeDetectorRef }, { token: SessionService }, { token: ProjectService }, { token:
|
|
12095
|
+
AudioRecorderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: AudioRecorderComponent, deps: [{ token: i0.Injector }, { token: i1$1.ActivatedRoute }, { token: i1$1.Router }, { token: i0.ChangeDetectorRef }, { token: SessionService }, { token: ProjectService }, { token: SpeechRecorderUploader }], target: i0.ɵɵFactoryTarget.Component });
|
|
11912
12096
|
AudioRecorderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.2", type: AudioRecorderComponent, selector: "app-audiorecorder-comp", providers: [SessionService], viewQueries: [{ propertyName: "ar", first: true, predicate: AudioRecorder, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
11913
12097
|
<app-audiorecorder [projectName]="_project?.name" [dataSaved]="dataSaved"></app-audiorecorder>
|
|
11914
|
-
`, isInline: true, styles: [":host{flex:2;display:flex;height:100%;flex-direction:column;min-height:0}\n"], components: [{ type: AudioRecorder, selector: "app-audiorecorder", inputs: ["
|
|
12098
|
+
`, isInline: true, styles: [":host{flex:2;display:flex;height:100%;flex-direction:column;min-height:0}\n"], components: [{ type: AudioRecorder, selector: "app-audiorecorder", inputs: ["projectName", "dataSaved"] }] });
|
|
11915
12099
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImport: i0, type: AudioRecorderComponent, decorators: [{
|
|
11916
12100
|
type: Component,
|
|
11917
12101
|
args: [{
|
|
@@ -11929,7 +12113,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImpor
|
|
|
11929
12113
|
|
|
11930
12114
|
}`]
|
|
11931
12115
|
}]
|
|
11932
|
-
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i1$1.ActivatedRoute }, { type: i1$1.Router }, { type: i0.ChangeDetectorRef }, { type: SessionService }, { type: ProjectService }, { type:
|
|
12116
|
+
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i1$1.ActivatedRoute }, { type: i1$1.Router }, { type: i0.ChangeDetectorRef }, { type: SessionService }, { type: ProjectService }, { type: SpeechRecorderUploader }]; }, propDecorators: { ar: [{
|
|
11933
12117
|
type: ViewChild,
|
|
11934
12118
|
args: [AudioRecorder, { static: true }]
|
|
11935
12119
|
}] } });
|
|
@@ -11978,7 +12162,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.2", ngImpor
|
|
|
11978
12162
|
}]
|
|
11979
12163
|
}] });
|
|
11980
12164
|
|
|
11981
|
-
const VERSION = '2.
|
|
12165
|
+
const VERSION = '2.25.0';
|
|
11982
12166
|
|
|
11983
12167
|
/*
|
|
11984
12168
|
* Public API Surface of speechrecorderng
|