@lookit/record 4.0.0 → 4.1.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/README.md +125 -6
- package/dist/index.browser.js +70 -12
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.min.js +16 -16
- package/dist/index.browser.min.js.map +1 -1
- package/dist/index.cjs +69 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +104 -9
- package/dist/index.js +69 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/consentVideo.spec.ts +0 -1
- package/src/consentVideo.ts +5 -1
- package/src/index.spec.ts +387 -12
- package/src/recorder.spec.ts +50 -6
- package/src/recorder.ts +9 -1
- package/src/start.ts +7 -1
- package/src/stop.ts +41 -7
- package/src/trial.ts +97 -11
package/dist/index.d.ts
CHANGED
|
@@ -132,6 +132,11 @@ declare const info$3: {
|
|
|
132
132
|
readonly default: false;
|
|
133
133
|
};
|
|
134
134
|
};
|
|
135
|
+
readonly data: {
|
|
136
|
+
readonly chs_type: {
|
|
137
|
+
readonly type: ParameterType.STRING;
|
|
138
|
+
};
|
|
139
|
+
};
|
|
135
140
|
};
|
|
136
141
|
type Info$3 = typeof info$3;
|
|
137
142
|
/** The video consent plugin. */
|
|
@@ -269,6 +274,11 @@ declare class VideoConsentPlugin implements JsPsychPlugin<Info$3> {
|
|
|
269
274
|
readonly default: false;
|
|
270
275
|
};
|
|
271
276
|
};
|
|
277
|
+
readonly data: {
|
|
278
|
+
readonly chs_type: {
|
|
279
|
+
readonly type: ParameterType.STRING;
|
|
280
|
+
};
|
|
281
|
+
};
|
|
272
282
|
};
|
|
273
283
|
private readonly recorder;
|
|
274
284
|
private readonly video_container_id;
|
|
@@ -393,7 +403,9 @@ declare class VideoConsentPlugin implements JsPsychPlugin<Info$3> {
|
|
|
393
403
|
|
|
394
404
|
declare const info$2: {
|
|
395
405
|
readonly name: "start-record-plugin";
|
|
406
|
+
readonly version: string;
|
|
396
407
|
readonly parameters: {};
|
|
408
|
+
readonly data: {};
|
|
397
409
|
};
|
|
398
410
|
type Info$2 = typeof info$2;
|
|
399
411
|
/** Start recording. Used by researchers who want to record across trials. */
|
|
@@ -401,7 +413,9 @@ declare class StartRecordPlugin implements JsPsychPlugin<Info$2> {
|
|
|
401
413
|
private jsPsych;
|
|
402
414
|
static readonly info: {
|
|
403
415
|
readonly name: "start-record-plugin";
|
|
416
|
+
readonly version: string;
|
|
404
417
|
readonly parameters: {};
|
|
418
|
+
readonly data: {};
|
|
405
419
|
};
|
|
406
420
|
private recorder;
|
|
407
421
|
/**
|
|
@@ -416,12 +430,32 @@ declare class StartRecordPlugin implements JsPsychPlugin<Info$2> {
|
|
|
416
430
|
|
|
417
431
|
declare const info$1: {
|
|
418
432
|
readonly name: "stop-record-plugin";
|
|
433
|
+
readonly version: string;
|
|
419
434
|
readonly parameters: {
|
|
435
|
+
/**
|
|
436
|
+
* This string can contain HTML markup. Any content provided will be
|
|
437
|
+
* displayed while the recording is uploading. If null (the default), then
|
|
438
|
+
* the default 'uploading video, please wait' (or appropriate translation
|
|
439
|
+
* based on 'locale') will be displayed. Use a blank string for no
|
|
440
|
+
* message/content.
|
|
441
|
+
*/
|
|
442
|
+
readonly wait_for_upload_message: {
|
|
443
|
+
readonly type: ParameterType.HTML_STRING;
|
|
444
|
+
readonly default: string | null;
|
|
445
|
+
};
|
|
446
|
+
/**
|
|
447
|
+
* Locale code used for translating the default 'uploading video, please
|
|
448
|
+
* wait' message. This code must be present in the translation files. If the
|
|
449
|
+
* code is not found then English will be used. If the
|
|
450
|
+
* 'wait_for_upload_message' parameter is specified then this value is
|
|
451
|
+
* ignored.
|
|
452
|
+
*/
|
|
420
453
|
readonly locale: {
|
|
421
454
|
readonly type: ParameterType.STRING;
|
|
422
455
|
readonly default: "en-us";
|
|
423
456
|
};
|
|
424
457
|
};
|
|
458
|
+
readonly data: {};
|
|
425
459
|
};
|
|
426
460
|
type Info$1 = typeof info$1;
|
|
427
461
|
/** Stop recording. Used by researchers who want to record across trials. */
|
|
@@ -429,12 +463,32 @@ declare class StopRecordPlugin implements JsPsychPlugin<Info$1> {
|
|
|
429
463
|
private jsPsych;
|
|
430
464
|
static readonly info: {
|
|
431
465
|
readonly name: "stop-record-plugin";
|
|
466
|
+
readonly version: string;
|
|
432
467
|
readonly parameters: {
|
|
468
|
+
/**
|
|
469
|
+
* This string can contain HTML markup. Any content provided will be
|
|
470
|
+
* displayed while the recording is uploading. If null (the default), then
|
|
471
|
+
* the default 'uploading video, please wait' (or appropriate translation
|
|
472
|
+
* based on 'locale') will be displayed. Use a blank string for no
|
|
473
|
+
* message/content.
|
|
474
|
+
*/
|
|
475
|
+
readonly wait_for_upload_message: {
|
|
476
|
+
readonly type: ParameterType.HTML_STRING;
|
|
477
|
+
readonly default: string | null;
|
|
478
|
+
};
|
|
479
|
+
/**
|
|
480
|
+
* Locale code used for translating the default 'uploading video, please
|
|
481
|
+
* wait' message. This code must be present in the translation files. If the
|
|
482
|
+
* code is not found then English will be used. If the
|
|
483
|
+
* 'wait_for_upload_message' parameter is specified then this value is
|
|
484
|
+
* ignored.
|
|
485
|
+
*/
|
|
433
486
|
readonly locale: {
|
|
434
487
|
readonly type: ParameterType.STRING;
|
|
435
488
|
readonly default: "en-us";
|
|
436
489
|
};
|
|
437
490
|
};
|
|
491
|
+
readonly data: {};
|
|
438
492
|
};
|
|
439
493
|
private recorder;
|
|
440
494
|
/**
|
|
@@ -454,12 +508,39 @@ declare class StopRecordPlugin implements JsPsychPlugin<Info$1> {
|
|
|
454
508
|
trial(display_element: HTMLElement, trial: TrialType<Info$1>): void;
|
|
455
509
|
}
|
|
456
510
|
|
|
457
|
-
|
|
511
|
+
interface Parameters {
|
|
512
|
+
/**
|
|
513
|
+
* Content that should be displayed while the recording is uploading. If null
|
|
514
|
+
* (the default), then the default 'uploading video, please wait...' (or
|
|
515
|
+
* appropriate translation based on 'locale') will be displayed. Use a blank
|
|
516
|
+
* string for no message/content. Otherwise this parameter can be set to a
|
|
517
|
+
* custom string and can contain HTML markup. If you want to embed
|
|
518
|
+
* images/video/audio in this HTML string, be sure to preload the media files
|
|
519
|
+
* with the `preload` plugin and manual preloading. Use a blank string (`""`)
|
|
520
|
+
* for no message/content.
|
|
521
|
+
*
|
|
522
|
+
* @default null
|
|
523
|
+
*/
|
|
524
|
+
wait_for_upload_message?: null | string;
|
|
525
|
+
/**
|
|
526
|
+
* Locale code used for translating the default 'uploading video, please
|
|
527
|
+
* wait...' message. This code must be present in the translation files. If
|
|
528
|
+
* the code is not found then English will be used. If the
|
|
529
|
+
* 'wait_for_upload_message' parameter is specified then this value
|
|
530
|
+
* isignored.
|
|
531
|
+
*
|
|
532
|
+
* @default "en-us"
|
|
533
|
+
*/
|
|
534
|
+
locale?: string;
|
|
535
|
+
}
|
|
536
|
+
/** This extension allows researchers to record webcam audio/video during trials. */
|
|
458
537
|
declare class TrialRecordExtension implements JsPsychExtension {
|
|
459
538
|
private jsPsych;
|
|
460
539
|
static readonly info: JsPsychExtensionInfo;
|
|
461
540
|
private recorder?;
|
|
462
541
|
private pluginName;
|
|
542
|
+
private uploadMsg;
|
|
543
|
+
private locale;
|
|
463
544
|
/**
|
|
464
545
|
* Video recording extension.
|
|
465
546
|
*
|
|
@@ -467,20 +548,34 @@ declare class TrialRecordExtension implements JsPsychExtension {
|
|
|
467
548
|
*/
|
|
468
549
|
constructor(jsPsych: JsPsych);
|
|
469
550
|
/**
|
|
470
|
-
*
|
|
551
|
+
* Runs on the initialize step for extensions, called when an instance of
|
|
471
552
|
* jsPsych is first initialized through initJsPsych().
|
|
553
|
+
*
|
|
554
|
+
* @param params - Parameters object
|
|
555
|
+
* @param params.wait_for_upload_message - Message to display while waiting
|
|
556
|
+
* for upload. String or null (default)
|
|
557
|
+
* @param params.locale - Message to display while waiting for upload. String
|
|
558
|
+
* or null (default).
|
|
559
|
+
*/
|
|
560
|
+
initialize(params?: Parameters): Promise<void>;
|
|
561
|
+
/**
|
|
562
|
+
* Runs at the start of a trial.
|
|
563
|
+
*
|
|
564
|
+
* @param startParams - Parameters object
|
|
565
|
+
* @param startParams.wait_for_upload_message - Message to display while
|
|
566
|
+
* waiting for upload. String or null (default). If given, this will
|
|
567
|
+
* overwrite the value used during initialization.
|
|
472
568
|
*/
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
on_start(): void;
|
|
476
|
-
/** Ran when the trial has loaded. */
|
|
569
|
+
on_start(startParams?: Parameters): void;
|
|
570
|
+
/** Runs when the trial has loaded. */
|
|
477
571
|
on_load(): void;
|
|
478
572
|
/**
|
|
479
|
-
*
|
|
573
|
+
* Runs when trial has finished.
|
|
480
574
|
*
|
|
481
|
-
* @returns
|
|
575
|
+
* @returns Any data from the trial extension that should be added to the rest
|
|
576
|
+
* of the trial data.
|
|
482
577
|
*/
|
|
483
|
-
on_finish(): {}
|
|
578
|
+
on_finish(): Promise<{}>;
|
|
484
579
|
/**
|
|
485
580
|
* Gets the plugin name for the trial that is being extended. This is same as
|
|
486
581
|
* the "trial_type" value that is stored in the data for this trial.
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import Handlebars from 'handlebars';
|
|
|
6
6
|
|
|
7
7
|
var _package = {
|
|
8
8
|
name: "@lookit/record",
|
|
9
|
-
version: "4.
|
|
9
|
+
version: "4.1.0",
|
|
10
10
|
description: "Recording extensions and plugins for CHS studies.",
|
|
11
11
|
homepage: "https://github.com/lookit/lookit-jspsych#readme",
|
|
12
12
|
bugs: {
|
|
@@ -287,6 +287,7 @@ class Recorder {
|
|
|
287
287
|
} else {
|
|
288
288
|
await this.s3.completeUpload();
|
|
289
289
|
}
|
|
290
|
+
this.reset();
|
|
290
291
|
resolve();
|
|
291
292
|
};
|
|
292
293
|
}
|
|
@@ -381,6 +382,11 @@ const info$3 = {
|
|
|
381
382
|
prompt_only_adults: { type: ParameterType.BOOL, default: false },
|
|
382
383
|
consent_statement_text: { type: ParameterType.STRING, default: "" },
|
|
383
384
|
omit_injury_phrase: { type: ParameterType.BOOL, default: false }
|
|
385
|
+
},
|
|
386
|
+
data: {
|
|
387
|
+
chs_type: {
|
|
388
|
+
type: ParameterType.STRING
|
|
389
|
+
}
|
|
384
390
|
}
|
|
385
391
|
};
|
|
386
392
|
const _VideoConsentPlugin = class {
|
|
@@ -509,7 +515,6 @@ const _VideoConsentPlugin = class {
|
|
|
509
515
|
stop.disabled = true;
|
|
510
516
|
this.addMessage(display, this.uploadingMsg);
|
|
511
517
|
await this.recorder.stop(true);
|
|
512
|
-
this.recorder.reset();
|
|
513
518
|
this.recordFeed(display);
|
|
514
519
|
this.getImg(display, "record-icon").style.visibility = "hidden";
|
|
515
520
|
this.addMessage(display, this.notRecordingMsg);
|
|
@@ -534,7 +539,12 @@ const _VideoConsentPlugin = class {
|
|
|
534
539
|
let VideoConsentPlugin = _VideoConsentPlugin;
|
|
535
540
|
VideoConsentPlugin.info = info$3;
|
|
536
541
|
|
|
537
|
-
const info$2 = {
|
|
542
|
+
const info$2 = {
|
|
543
|
+
name: "start-record-plugin",
|
|
544
|
+
version: _package.version,
|
|
545
|
+
parameters: {},
|
|
546
|
+
data: {}
|
|
547
|
+
};
|
|
538
548
|
const _StartRecordPlugin = class {
|
|
539
549
|
constructor(jsPsych) {
|
|
540
550
|
this.jsPsych = jsPsych;
|
|
@@ -556,9 +566,18 @@ StartRecordPlugin.info = info$2;
|
|
|
556
566
|
|
|
557
567
|
const info$1 = {
|
|
558
568
|
name: "stop-record-plugin",
|
|
569
|
+
version: _package.version,
|
|
559
570
|
parameters: {
|
|
560
|
-
|
|
561
|
-
|
|
571
|
+
wait_for_upload_message: {
|
|
572
|
+
type: ParameterType.HTML_STRING,
|
|
573
|
+
default: null
|
|
574
|
+
},
|
|
575
|
+
locale: {
|
|
576
|
+
type: ParameterType.STRING,
|
|
577
|
+
default: "en-us"
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
data: {}
|
|
562
581
|
};
|
|
563
582
|
class StopRecordPlugin {
|
|
564
583
|
constructor(jsPsych) {
|
|
@@ -570,11 +589,17 @@ class StopRecordPlugin {
|
|
|
570
589
|
}
|
|
571
590
|
}
|
|
572
591
|
trial(display_element, trial) {
|
|
573
|
-
|
|
592
|
+
if (trial.wait_for_upload_message == null) {
|
|
593
|
+
display_element.innerHTML = chsTemplates.uploadingVideo(trial);
|
|
594
|
+
} else {
|
|
595
|
+
display_element.innerHTML = trial.wait_for_upload_message;
|
|
596
|
+
}
|
|
574
597
|
this.recorder.stop().then(() => {
|
|
575
598
|
window.chs.sessionRecorder = null;
|
|
576
599
|
display_element.innerHTML = "";
|
|
577
600
|
this.jsPsych.finishTrial();
|
|
601
|
+
}).catch((err) => {
|
|
602
|
+
console.error("StopRecordPlugin: recorder stop/upload failed.", err);
|
|
578
603
|
});
|
|
579
604
|
}
|
|
580
605
|
}
|
|
@@ -583,19 +608,50 @@ StopRecordPlugin.info = info$1;
|
|
|
583
608
|
class TrialRecordExtension {
|
|
584
609
|
constructor(jsPsych) {
|
|
585
610
|
this.jsPsych = jsPsych;
|
|
611
|
+
this.uploadMsg = null;
|
|
612
|
+
this.locale = "en-us";
|
|
586
613
|
autoBind(this);
|
|
587
614
|
}
|
|
588
|
-
async initialize() {
|
|
615
|
+
async initialize(params) {
|
|
616
|
+
await new Promise((resolve) => {
|
|
617
|
+
this.uploadMsg = params?.wait_for_upload_message ? params.wait_for_upload_message : null;
|
|
618
|
+
this.locale = params?.locale ? params.locale : "en-us";
|
|
619
|
+
console.log(this.uploadMsg);
|
|
620
|
+
console.log(this.locale);
|
|
621
|
+
resolve();
|
|
622
|
+
});
|
|
589
623
|
}
|
|
590
|
-
on_start() {
|
|
624
|
+
on_start(startParams) {
|
|
625
|
+
if (startParams?.wait_for_upload_message) {
|
|
626
|
+
this.uploadMsg = startParams.wait_for_upload_message;
|
|
627
|
+
}
|
|
628
|
+
if (startParams?.locale) {
|
|
629
|
+
this.locale = startParams.locale;
|
|
630
|
+
}
|
|
631
|
+
console.log(this.uploadMsg);
|
|
632
|
+
console.log(this.locale);
|
|
591
633
|
this.recorder = new Recorder(this.jsPsych);
|
|
592
634
|
}
|
|
593
635
|
on_load() {
|
|
594
636
|
this.pluginName = this.getCurrentPluginName();
|
|
595
637
|
this.recorder?.start(false, `${this.pluginName}`);
|
|
596
638
|
}
|
|
597
|
-
on_finish() {
|
|
598
|
-
this.
|
|
639
|
+
async on_finish() {
|
|
640
|
+
const displayEl = this.jsPsych.getDisplayElement();
|
|
641
|
+
if (this.uploadMsg == null) {
|
|
642
|
+
displayEl.innerHTML = chsTemplates.uploadingVideo({
|
|
643
|
+
type: this.jsPsych.getCurrentTrial().type,
|
|
644
|
+
locale: this.locale
|
|
645
|
+
});
|
|
646
|
+
} else {
|
|
647
|
+
displayEl.innerHTML = this.uploadMsg;
|
|
648
|
+
}
|
|
649
|
+
try {
|
|
650
|
+
await this.recorder?.stop();
|
|
651
|
+
displayEl.innerHTML = "";
|
|
652
|
+
} catch (err) {
|
|
653
|
+
console.error("TrialRecordExtension: recorder stop/upload failed.", err);
|
|
654
|
+
}
|
|
599
655
|
return {};
|
|
600
656
|
}
|
|
601
657
|
getCurrentPluginName() {
|
|
@@ -604,7 +660,9 @@ class TrialRecordExtension {
|
|
|
604
660
|
}
|
|
605
661
|
}
|
|
606
662
|
TrialRecordExtension.info = {
|
|
607
|
-
name: "chs-trial-record-extension"
|
|
663
|
+
name: "chs-trial-record-extension",
|
|
664
|
+
version: _package.version,
|
|
665
|
+
data: {}
|
|
608
666
|
};
|
|
609
667
|
|
|
610
668
|
var img$6 = "data:image/png;base64,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";
|