@lookit/record 4.0.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -356,9 +356,28 @@ To use the CHS trial recording extension, you need to:
356
356
 
357
357
  ### Parameters
358
358
 
359
- This extension does not accept any parameters.
359
+ **`wait_for_upload_message` [`null` or HTML string | `null` ]**
360
360
 
361
- ### Example
361
+ This parameter determines what content should be displayed while the trial
362
+ recording is uploading. If `null` (the default), then the message 'uploading
363
+ video, please wait...' (or appropriate translation based on `locale`) will be
364
+ displayed. Otherwise this parameter can be set to a custom string and can
365
+ contain HTML markup. If you want to embed images/video/audio in this HTML
366
+ string, be sure to preload the media files with the `preload` plugin and
367
+ [manual preloading](https://www.jspsych.org/latest/overview/media-preloading/#manual-preloading).
368
+ Use a blank string (`""`) for no message/content. If a value is provided then
369
+ the `locale` parameter will be ignored.
370
+
371
+ **`max_upload_seconds` [ Integer | 10 ]**
372
+
373
+ Maximum duration (in seconds) to wait for the trial recording to finish
374
+ uploading before continuing with the experiment. If the maximum upload duration
375
+ is reached and the upload has not finished, then the experiment will move on and
376
+ the trial recording upload will continue in the background.
377
+
378
+ ### Examples
379
+
380
+ **Basic usage**
362
381
 
363
382
  To record a single trial, you will have to first load the extension in
364
383
  `initJsPsych`.
@@ -375,7 +394,7 @@ record any trial you design.
375
394
 
376
395
  ```javascript
377
396
  const trialRec = {
378
- // ... Other trial paramters ...
397
+ // ... Other trial parameters ...
379
398
  extensions: [{ type: chsRecord.TrialRecordExtension }],
380
399
  };
381
400
  ```
@@ -386,6 +405,81 @@ Finally, insert the trials into the timeline.
386
405
  jsPsych.run([videoConfig, trialRec]);
387
406
  ```
388
407
 
408
+ **Setting parameters**
409
+
410
+ You can set the trial extension parameters when you load the extension with
411
+ `initJsPsych`.
412
+
413
+ In the example below, the default "uploading video, please wait..." message will
414
+ be displayed in French while a trial recording is uploading at the end of the
415
+ trial.
416
+
417
+ ```javascript
418
+ const jsPsych = initJsPsych({
419
+ extensions: [
420
+ {
421
+ type: chsRecord.TrialRecordExtension,
422
+ params: { locale: "fr" },
423
+ },
424
+ ],
425
+ });
426
+ ```
427
+
428
+ And in this example, the custom message "Please wait!" will be displayed while
429
+ the trial recording is uploading. You can include any HTML-formatted content in
430
+ this string, which means you can display images, videos, animations etc.
431
+
432
+ ```javascript
433
+ const jsPsych = initJsPsych({
434
+ extensions: [
435
+ {
436
+ type: chsRecord.TrialRecordExtension,
437
+ params: { wait_for_upload_message: "<div>Please wait!</div>" },
438
+ },
439
+ ],
440
+ });
441
+ ```
442
+
443
+ You can also set the parameters within individual trials. This will override any
444
+ parameters set during the extension initialization (in `initJsPsych`), which can
445
+ be useful if you want to change the parameter values during the experiment. In
446
+ this example, the `wait_for_upload_message` is set to an empty string, which
447
+ will prevent the default "uploading video, please wait..." message from
448
+ appearing after the trial finishes.
449
+
450
+ ```javascript
451
+ const trialRec = {
452
+ // ... Other trial parameters ...
453
+ extensions: [
454
+ {
455
+ type: chsRecord.TrialRecordExtension,
456
+ params: { wait_for_upload_message: "" },
457
+ },
458
+ ],
459
+ };
460
+ ```
461
+
462
+ By default, the trial recording extension will wait up to 10 seconds for the
463
+ recording to finish uploading before moving on to the next trial. If the upload
464
+ does not finish in that time, it will continue to upload in the background. You
465
+ can adjust this duration with the `max_upload_seconds` parameter. You may want
466
+ to increase or decrease this duration depending on the duration of your recorded
467
+ trials, or you expect that some participants may have slow/unreliable internet
468
+ connections. This example decreases the maximum upload duration from 10 to 5
469
+ seconds:
470
+
471
+ ```javascript
472
+ const trialRec = {
473
+ // ... Other trial parameters ...
474
+ extensions: [
475
+ {
476
+ type: chsRecord.TrialRecordExtension,
477
+ params: { max_upload_seconds: 5 },
478
+ },
479
+ ],
480
+ };
481
+ ```
482
+
389
483
  ## Session Recording
390
484
 
391
485
  You might prefer to record across multiple trials in a study session. This can
@@ -414,8 +508,18 @@ const startRec = { type: chsRecord.StartRecordPlugin };
414
508
 
415
509
  #### Parameters
416
510
 
417
- This plugin does not accept any parameters, other those available in all
418
- plugins.
511
+ **`wait_for_connection_message` [`null` or HTML string | `null` ]**
512
+
513
+ This parameter determines what content should be displayed while the session
514
+ recording is initializing. If `null` (the default), then the message
515
+ 'establishing video connection, please wait' (or appropriate translation based
516
+ on `locale`) will be displayed. Otherwise this parameter can be set to a custom
517
+ string and can contain HTML markup. If you want to embed images/video/audio in
518
+ this HTML string, be sure to preload the media files with the `preload` plugin
519
+ and
520
+ [manual preloading](https://www.jspsych.org/latest/overview/media-preloading/#manual-preloading).
521
+ Use a blank string (`""`) for no message/content. If a value is provided then
522
+ the `locale` parameter will be ignored.
419
523
 
420
524
  ### Stop Recording Plugin
421
525
 
@@ -425,12 +529,44 @@ The plugin to stop session recording is called `chsRecord.StopRecordPlugin`.
425
529
  const stopRec = { type: chsRecord.StopRecordPlugin };
426
530
  ```
427
531
 
532
+ When the trial starts, by default, this plugin will display "uploading video,
533
+ please wait...", or the appropriate translation based on the `locale` parameter.
534
+ This message can be customized using the `wait_for_upload_message` parameter,
535
+ which is the HTML-formatted string to be displayed while the session recording
536
+ is uploading.
537
+
538
+ ```javascript
539
+ const stopRec = {
540
+ type: chsRecord.StopRecordPlugin,
541
+ wait_for_upload_message:
542
+ "<p style='color:red;'>Please wait while we upload your video.</p>",
543
+ };
544
+ ```
545
+
428
546
  #### Parameters
429
547
 
430
- This plugin does not accept any parameters, other those available in all
431
- plugins.
548
+ **`wait_for_upload_message` [`null` or HTML string | `null` ]**
432
549
 
433
- ### Example
550
+ This parameter determines what content should be displayed while the session
551
+ recording is uploading. If `null` (the default), then the message 'uploading
552
+ video, please wait...' (or appropriate translation based on `locale`) will be
553
+ displayed. Otherwise this parameter can be set to a custom string and can
554
+ contain HTML markup. If you want to embed images/video/audio in this HTML
555
+ string, be sure to preload the media files with the `preload` plugin and
556
+ [manual preloading](https://www.jspsych.org/latest/overview/media-preloading/#manual-preloading).
557
+ Use a blank string (`""`) for no message/content. If a value is provided then
558
+ the `locale` parameter will be ignored.
559
+
560
+ **`max_upload_seconds` [ Integer | 10 ]**
561
+
562
+ Maximum duration (in seconds) to wait for the session recording to finish
563
+ uploading before continuing with the experiment. If the maximum upload duration
564
+ is reached and the upload has not finished, then the experiment will move on and
565
+ the session recording upload will continue in the background.
566
+
567
+ ### Examples
568
+
569
+ **Basic usage**
434
570
 
435
571
  First, make sure that you've added a video config trial to your experiment
436
572
  timeline. Then, create your start and stop recording trials:
@@ -476,3 +612,58 @@ jsPsych.run([
476
612
  stopRec,
477
613
  ]);
478
614
  ```
615
+
616
+ **Setting parameters**
617
+
618
+ By default, the start session recording plugin will display "establishing video
619
+ connection, please wait" while establishing the connection to our video storage,
620
+ and the stop session recording plugin will display "uploading video, please
621
+ wait..." while the session recording is uploading. You can set the `locale`
622
+ parameter value to translate these messages to another language. For example,
623
+ the trial below will display the Brazilian Portuguese translation of these
624
+ messages. If the locale string does not match any of the translation codes that
625
+ we support, then the message will be displayed in English.
626
+
627
+ ```javascript
628
+ const startpRec = {
629
+ type: type: chsRecord.StartRecordPlugin,
630
+ locale: "pt-br",
631
+ };
632
+ const stopRec = {
633
+ type: chsRecord.StopRecordPlugin,
634
+ locale: "pt-br",
635
+ };
636
+ ```
637
+
638
+ You can also set custom content to be displayed at the start of the session
639
+ recording, while it is initializing, and/or at the end, when the file is
640
+ uploading. The value must be a string. It can include HTML-formatted content,
641
+ which means that you can embed audio, video, images etc. (be sure to preload any
642
+ media files!).
643
+
644
+ ```javascript
645
+ const startpRec = {
646
+ type: type: chsRecord.StartRecordPlugin,
647
+ wait_for_connection_message: "<p style='color:green;>Please wait...</p>"
648
+ };
649
+ const stopRec = {
650
+ type: chsRecord.StopRecordPlugin,
651
+ wait_for_upload_message: "<p style='color:red;'>Hang on a sec!</p>",
652
+ };
653
+ ```
654
+
655
+ By default, the stop session recording plugin will wait up to 10 seconds for the
656
+ session recording to finish uploading before moving on with the experiment. If
657
+ the upload does not finish in that time, it will continue to upload in the
658
+ background. You can adjust this duration with the `max_upload_seconds`
659
+ parameter. You may want to increase this duration if, for example, your
660
+ experiment creates a very long session recording, or you expect that some
661
+ participants may have slow/unreliable internet connections. This example
662
+ increases the maximum upload duration from 10 to 20 seconds:
663
+
664
+ ```javascript
665
+ const stopRec = {
666
+ type: chsRecord.StopRecordPlugin,
667
+ max_upload_seconds: 20,
668
+ };
669
+ ```
@@ -32,7 +32,7 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
32
32
 
33
33
  var _package = {
34
34
  name: "@lookit/record",
35
- version: "4.0.0",
35
+ version: "5.0.0",
36
36
  description: "Recording extensions and plugins for CHS studies.",
37
37
  homepage: "https://github.com/lookit/lookit-jspsych#readme",
38
38
  bugs: {
@@ -73,8 +73,8 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
73
73
  typescript: "^5.6.2"
74
74
  },
75
75
  peerDependencies: {
76
- "@lookit/data": "^0.2.0",
77
- "@lookit/templates": "^2.1.0",
76
+ "@lookit/data": "^0.3.0",
77
+ "@lookit/templates": "^3.0.0",
78
78
  jspsych: "^8.0.3"
79
79
  }
80
80
  };
@@ -149,6 +149,12 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
149
149
  this.name = "S3UndefinedError";
150
150
  }
151
151
  }
152
+ class NoFileNameError extends Error {
153
+ constructor() {
154
+ super("No filename found for recording.");
155
+ this.name = "NoFileNameError";
156
+ }
157
+ }
152
158
  class StreamActiveOnResetError extends Error {
153
159
  constructor() {
154
160
  super("Won't reset recorder. Stream is still active.");
@@ -173,6 +179,12 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
173
179
  this.name = "ElementNotFoundError";
174
180
  }
175
181
  }
182
+ class TimeoutError extends Error {
183
+ constructor(msg) {
184
+ super(`${msg}`);
185
+ this.name = "TimeoutError";
186
+ }
187
+ }
176
188
 
177
189
  // Gets all non-builtin properties up the prototype chain.
178
190
  const getAllProperties = object => {
@@ -8465,6 +8477,31 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
8465
8477
 
8466
8478
  var img$7 = "data:image/svg+xml,%3c%3fxml version='1.0' encoding='utf-8' %3f%3e%3csvg viewBox='-1 -1 18 18' xmlns='http://www.w3.org/2000/svg'%3e %3ccircle fill='red' stroke='black' stroke-width='0.5' cx='8' cy='8' r='8'%3e%3c/circle%3e%3c/svg%3e";
8467
8479
 
8480
+ const promiseWithTimeout = (promise, promiseId, timeoutMs, onTimeoutCleanup) => {
8481
+ let timeoutHandle;
8482
+ const timeout = new Promise((resolve) => {
8483
+ timeoutHandle = setTimeout(() => {
8484
+ onTimeoutCleanup?.();
8485
+ resolve("timeout");
8486
+ }, timeoutMs);
8487
+ });
8488
+ return Promise.race([promise, timeout]).then(
8489
+ (value) => {
8490
+ if (value == "timeout") {
8491
+ console.log(`Upload for ${promiseId} timed out.`);
8492
+ } else {
8493
+ console.log(`Upload for ${promiseId} completed.`);
8494
+ clearTimeout(timeoutHandle);
8495
+ }
8496
+ return value;
8497
+ },
8498
+ (err) => {
8499
+ clearTimeout(timeoutHandle);
8500
+ throw err;
8501
+ }
8502
+ );
8503
+ };
8504
+
8468
8505
  class Recorder {
8469
8506
  constructor(jsPsych) {
8470
8507
  this.jsPsych = jsPsych;
@@ -8569,13 +8606,73 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
8569
8606
  this.recorder.stop();
8570
8607
  this.stream.getTracks().map((t) => t.stop());
8571
8608
  }
8572
- stop(maintain_container_size = false) {
8609
+ stop({
8610
+ maintain_container_size = false,
8611
+ stop_timeout_ms = null,
8612
+ upload_timeout_ms = 1e4
8613
+ } = {}) {
8614
+ this.preStopCheck();
8573
8615
  this.clearWebcamFeed(maintain_container_size);
8574
8616
  this.stopTracks();
8575
- if (!this.stopPromise) {
8576
- throw new NoStopPromiseError();
8577
- }
8578
- return this.stopPromise;
8617
+ const snapshot = {
8618
+ s3: !this.localDownload ? this.s3 : null,
8619
+ filename: this.filename,
8620
+ localDownload: this.localDownload,
8621
+ url: "null"
8622
+ };
8623
+ const stopped = stop_timeout_ms ? promiseWithTimeout(
8624
+ this.stopPromise,
8625
+ `${snapshot.filename}-stopped`,
8626
+ stop_timeout_ms,
8627
+ this.createTimeoutHandler("stop", snapshot.filename)
8628
+ ) : this.stopPromise;
8629
+ stopped.finally(() => {
8630
+ try {
8631
+ this.reset();
8632
+ } catch (err) {
8633
+ console.error("Error while resetting recorder after stop: ", err);
8634
+ }
8635
+ });
8636
+ const uploadPromise = (async () => {
8637
+ let url;
8638
+ try {
8639
+ url = await stopped;
8640
+ if (url == "timeout") {
8641
+ throw new TimeoutError("Recorder stop timed out.");
8642
+ }
8643
+ } catch (err) {
8644
+ console.warn("Upload failed because recorder stop timed out");
8645
+ throw err;
8646
+ }
8647
+ snapshot.url = url;
8648
+ if (snapshot.localDownload) {
8649
+ try {
8650
+ this.download(snapshot.filename, snapshot.url);
8651
+ await Promise.resolve();
8652
+ } catch (err) {
8653
+ console.error("Local download failed: ", err);
8654
+ throw err;
8655
+ }
8656
+ } else {
8657
+ try {
8658
+ await snapshot.s3.completeUpload();
8659
+ } catch (err) {
8660
+ console.error("Upload failed: ", err);
8661
+ throw err;
8662
+ }
8663
+ }
8664
+ })();
8665
+ const uploaded = upload_timeout_ms ? promiseWithTimeout(
8666
+ uploadPromise,
8667
+ `${snapshot.filename}-uploaded`,
8668
+ upload_timeout_ms,
8669
+ this.createTimeoutHandler("upload", snapshot.filename)
8670
+ ) : uploadPromise;
8671
+ window.chs.pendingUploads.push({
8672
+ promise: uploadPromise,
8673
+ file: snapshot.filename
8674
+ });
8675
+ return { stopped, uploaded };
8579
8676
  }
8580
8677
  initializeCheck() {
8581
8678
  if (!this.recorder) {
@@ -8588,18 +8685,27 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
8588
8685
  throw new StreamDataInitializeError();
8589
8686
  }
8590
8687
  }
8688
+ preStopCheck() {
8689
+ if (!this.recorder) {
8690
+ throw new RecorderInitializeError();
8691
+ }
8692
+ if (!this.stream.active) {
8693
+ throw new StreamInactiveInitializeError();
8694
+ }
8695
+ if (!this.stopPromise) {
8696
+ throw new NoStopPromiseError();
8697
+ }
8698
+ if (!this.filename) {
8699
+ throw new NoFileNameError();
8700
+ }
8701
+ }
8591
8702
  handleStop(resolve) {
8592
- return async () => {
8703
+ return () => {
8593
8704
  if (this.blobs.length === 0) {
8594
8705
  throw new CreateURLError();
8595
8706
  }
8596
8707
  this.url = URL.createObjectURL(new Blob(this.blobs));
8597
- if (this.localDownload) {
8598
- this.download();
8599
- } else {
8600
- await this.s3.completeUpload();
8601
- }
8602
- resolve();
8708
+ resolve(this.url);
8603
8709
  };
8604
8710
  }
8605
8711
  handleDataAvailable(event) {
@@ -8608,11 +8714,11 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
8608
8714
  this.s3.onDataAvailable(event.data);
8609
8715
  }
8610
8716
  }
8611
- download() {
8612
- if (this.filename && this.url) {
8717
+ download(filename, url) {
8718
+ if (filename && url) {
8613
8719
  const link = document.createElement("a");
8614
- link.href = this.url;
8615
- link.download = this.filename;
8720
+ link.href = url;
8721
+ link.download = filename;
8616
8722
  link.click();
8617
8723
  }
8618
8724
  }
@@ -8641,6 +8747,18 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
8641
8747
  const rand_digits = Math.floor(Math.random() * 1e3);
8642
8748
  return `${prefix}_${window.chs.study.id}_${trial_id}_${window.chs.response.id}_${new Date().getTime()}_${rand_digits}.webm`;
8643
8749
  }
8750
+ createTimeoutHandler(eventName, id) {
8751
+ return () => {
8752
+ console.warn(`Recorder ${eventName} timed out: ${id}`);
8753
+ if (!this.stream.active) {
8754
+ try {
8755
+ this.reset();
8756
+ } catch (err) {
8757
+ console.error("Error while resetting recorder after timeout: ", err);
8758
+ }
8759
+ }
8760
+ };
8761
+ }
8644
8762
  }
8645
8763
 
8646
8764
  const info$3 = {
@@ -8693,6 +8811,11 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
8693
8811
  prompt_only_adults: { type: jspsych.ParameterType.BOOL, default: false },
8694
8812
  consent_statement_text: { type: jspsych.ParameterType.STRING, default: "" },
8695
8813
  omit_injury_phrase: { type: jspsych.ParameterType.BOOL, default: false }
8814
+ },
8815
+ data: {
8816
+ chs_type: {
8817
+ type: jspsych.ParameterType.STRING
8818
+ }
8696
8819
  }
8697
8820
  };
8698
8821
  class VideoConsentPlugin {
@@ -8822,8 +8945,10 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
8822
8945
  stop.addEventListener("click", async () => {
8823
8946
  stop.disabled = true;
8824
8947
  this.addMessage(display, this.uploadingMsg);
8825
- await this.recorder.stop(true);
8826
- this.recorder.reset();
8948
+ const { stopped, uploaded } = this.recorder.stop({
8949
+ maintain_container_size: true
8950
+ });
8951
+ await stopped;
8827
8952
  this.recordFeed(display);
8828
8953
  this.getImg(display, "record-icon").style.visibility = "hidden";
8829
8954
  this.addMessage(display, this.notRecordingMsg);
@@ -8846,7 +8971,21 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
8846
8971
  }
8847
8972
  }
8848
8973
 
8849
- const info$2 = { name: "start-record-plugin", parameters: {} };
8974
+ const info$2 = {
8975
+ name: "start-record-plugin",
8976
+ version: _package.version,
8977
+ parameters: {
8978
+ wait_for_connection_message: {
8979
+ type: jspsych.ParameterType.HTML_STRING,
8980
+ default: null
8981
+ },
8982
+ locale: {
8983
+ type: jspsych.ParameterType.STRING,
8984
+ default: "en-us"
8985
+ }
8986
+ },
8987
+ data: {}
8988
+ };
8850
8989
  class StartRecordPlugin {
8851
8990
  constructor(jsPsych) {
8852
8991
  this.jsPsych = jsPsych;
@@ -8859,8 +8998,14 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
8859
8998
  }
8860
8999
  static info = info$2;
8861
9000
  recorder;
8862
- trial() {
8863
- this.recorder.start(false, `${StartRecordPlugin.info.name}-multiframe`).then(() => {
9001
+ async trial(display_element, trial) {
9002
+ if (trial.wait_for_connection_message == null) {
9003
+ display_element.innerHTML = chsTemplates.establishingConnection(trial);
9004
+ } else {
9005
+ display_element.innerHTML = trial.wait_for_connection_message;
9006
+ }
9007
+ await this.recorder.start(false, `${StartRecordPlugin.info.name}-multiframe`).then(() => {
9008
+ display_element.innerHTML = "";
8864
9009
  this.jsPsych.finishTrial();
8865
9010
  });
8866
9011
  }
@@ -8868,9 +9013,22 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
8868
9013
 
8869
9014
  const info$1 = {
8870
9015
  name: "stop-record-plugin",
9016
+ version: _package.version,
8871
9017
  parameters: {
8872
- locale: { type: jspsych.ParameterType.STRING, default: "en-us" }
8873
- }
9018
+ wait_for_upload_message: {
9019
+ type: jspsych.ParameterType.HTML_STRING,
9020
+ default: null
9021
+ },
9022
+ locale: {
9023
+ type: jspsych.ParameterType.STRING,
9024
+ default: "en-us"
9025
+ },
9026
+ max_upload_seconds: {
9027
+ type: jspsych.ParameterType.INT,
9028
+ default: 10
9029
+ }
9030
+ },
9031
+ data: {}
8874
9032
  };
8875
9033
  class StopRecordPlugin {
8876
9034
  constructor(jsPsych) {
@@ -8883,13 +9041,25 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
8883
9041
  }
8884
9042
  static info = info$1;
8885
9043
  recorder;
8886
- trial(display_element, trial) {
8887
- display_element.innerHTML = chsTemplates.uploadingVideo(trial);
8888
- this.recorder.stop().then(() => {
9044
+ async trial(display_element, trial) {
9045
+ if (trial.wait_for_upload_message == null) {
9046
+ display_element.innerHTML = chsTemplates.uploadingVideo(trial);
9047
+ } else {
9048
+ display_element.innerHTML = trial.wait_for_upload_message;
9049
+ }
9050
+ const { stopped, uploaded } = this.recorder.stop({
9051
+ upload_timeout_ms: trial.max_upload_seconds !== null ? trial.max_upload_seconds * 1e3 : null
9052
+ });
9053
+ try {
9054
+ await stopped;
9055
+ await uploaded;
9056
+ } catch (err) {
9057
+ console.error("StopRecordPlugin: recorder stop/upload failed.", err);
9058
+ } finally {
8889
9059
  window.chs.sessionRecorder = null;
8890
9060
  display_element.innerHTML = "";
8891
9061
  this.jsPsych.finishTrial();
8892
- });
9062
+ }
8893
9063
  }
8894
9064
  }
8895
9065
 
@@ -8899,22 +9069,70 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
8899
9069
  autoBind(this);
8900
9070
  }
8901
9071
  static info = {
8902
- name: "chs-trial-record-extension"
9072
+ name: "chs-trial-record-extension",
9073
+ version: _package.version,
9074
+ data: {}
8903
9075
  };
8904
9076
  recorder;
8905
9077
  pluginName;
8906
- async initialize() {
9078
+ uploadMsg = null;
9079
+ locale = "en-us";
9080
+ maxUploadSeconds = void 0;
9081
+ async initialize(params) {
9082
+ await new Promise((resolve) => {
9083
+ this.uploadMsg = params?.wait_for_upload_message ? params.wait_for_upload_message : null;
9084
+ this.locale = params?.locale ? params.locale : "en-us";
9085
+ this.maxUploadSeconds = params?.max_upload_seconds === void 0 ? 10 : params.max_upload_seconds;
9086
+ resolve();
9087
+ });
8907
9088
  }
8908
- on_start() {
9089
+ on_start(startParams) {
9090
+ if (startParams?.wait_for_upload_message) {
9091
+ this.uploadMsg = startParams.wait_for_upload_message;
9092
+ }
9093
+ if (startParams?.locale) {
9094
+ this.locale = startParams.locale;
9095
+ }
9096
+ if (startParams?.max_upload_seconds !== void 0) {
9097
+ this.maxUploadSeconds = startParams?.max_upload_seconds;
9098
+ }
8909
9099
  this.recorder = new Recorder(this.jsPsych);
9100
+ this.pluginName = this.getCurrentPluginName();
9101
+ this.recorder.start(false, `${this.pluginName}`);
8910
9102
  }
8911
9103
  on_load() {
8912
- this.pluginName = this.getCurrentPluginName();
8913
- this.recorder?.start(false, `${this.pluginName}`);
8914
9104
  }
8915
- on_finish() {
8916
- this.recorder?.stop();
8917
- return {};
9105
+ async on_finish() {
9106
+ const displayEl = this.jsPsych.getDisplayElement();
9107
+ if (this.uploadMsg == null) {
9108
+ displayEl.innerHTML = chsTemplates.uploadingVideo({
9109
+ type: this.jsPsych.getCurrentTrial().type,
9110
+ locale: this.locale
9111
+ });
9112
+ } else {
9113
+ displayEl.innerHTML = this.uploadMsg;
9114
+ }
9115
+ if (this.recorder) {
9116
+ const { stopped, uploaded } = this.recorder.stop({
9117
+ upload_timeout_ms: this.maxUploadSeconds !== null ? this.maxUploadSeconds * 1e3 : null
9118
+ });
9119
+ try {
9120
+ await stopped;
9121
+ await uploaded;
9122
+ displayEl.innerHTML = "";
9123
+ return {};
9124
+ } catch (err) {
9125
+ console.error(
9126
+ "TrialRecordExtension: recorder stop/upload failed.",
9127
+ err
9128
+ );
9129
+ displayEl.innerHTML = "";
9130
+ return {};
9131
+ }
9132
+ } else {
9133
+ displayEl.innerHTML = "";
9134
+ return {};
9135
+ }
8918
9136
  }
8919
9137
  getCurrentPluginName() {
8920
9138
  const current_plugin_class = this.jsPsych.getCurrentTrial().type;
@@ -9325,4 +9543,4 @@ var chsRecord = (function (Data, chsTemplates, jspsych) {
9325
9543
  return index;
9326
9544
 
9327
9545
  })(chsData, chsTemplates, jsPsychModule);
9328
- //# sourceMappingURL=https://unpkg.com/@lookit/record@4.0.0/dist/index.browser.js.map
9546
+ //# sourceMappingURL=https://unpkg.com/@lookit/record@5.0.0/dist/index.browser.js.map