@lookit/record 0.0.3

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.
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Audio Worklet Processor class for processing audio input streams. This is
3
+ * used by the Recorder to run a volume check on the microphone input stream.
4
+ * Source:
5
+ * https://www.webrtc-developers.com/how-to-know-if-my-microphone-works/#detect-noise-or-silence
6
+ */
7
+ export default class MicCheckProcessor extends AudioWorkletProcessor {
8
+ private _volume;
9
+ private _micChecked;
10
+ /** Constructor for the mic check processor. */
11
+ constructor();
12
+ /**
13
+ * Process method that implements the audio processing algorithm for the Audio
14
+ * Processor Worklet. "Although the method is not a part of the
15
+ * AudioWorkletProcessor interface, any implementation of
16
+ * AudioWorkletProcessor must provide a process() method." Source:
17
+ * https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletProcessor/process
18
+ * The process method can take the following arguments: inputs, outputs,
19
+ * parameters. Here we are only using inputs.
20
+ *
21
+ * @param inputs - An array of inputs from the audio stream (microphone)
22
+ * connnected to the node. Each item in the inputs array is an array of
23
+ * channels. Each channel is a Float32Array containing 128 samples. For
24
+ * example, inputs[n][m][i] will access n-th input, m-th channel of that
25
+ * input, and i-th sample of that channel.
26
+ * @returns Boolean indicating whether or not the Audio Worklet Node should
27
+ * remain active, even if the User Agent thinks it is safe to shut down. In
28
+ * this case, when the recorder decides that the mic check criteria has been
29
+ * met, it will return false (processor should be shut down), otherwise it
30
+ * will return true (processor should remain active).
31
+ */
32
+ process(inputs: Float32Array[][]): boolean;
33
+ }
@@ -0,0 +1,146 @@
1
+ import { JsPsych } from "jspsych";
2
+ import { CSSWidthHeight } from "./types";
3
+ /** Recorder handles the state of recording and data storage. */
4
+ export default class Recorder {
5
+ private jsPsych;
6
+ private url?;
7
+ private _s3?;
8
+ private blobs;
9
+ private localDownload;
10
+ private filename?;
11
+ private stopPromise?;
12
+ private webcam_element_id;
13
+ private streamClone;
14
+ /**
15
+ * Recorder for online experiments.
16
+ *
17
+ * @param jsPsych - Object supplied by jsPsych.
18
+ */
19
+ constructor(jsPsych: JsPsych);
20
+ /**
21
+ * Get recorder from jsPsych plugin API.
22
+ *
23
+ * If camera recorder hasn't been initialized, then return the microphone
24
+ * recorder.
25
+ *
26
+ * @returns MediaRecorder from the plugin API.
27
+ */
28
+ private get recorder();
29
+ /**
30
+ * Get stream from either recorder.
31
+ *
32
+ * @returns MediaStream from the plugin API.
33
+ */
34
+ private get stream();
35
+ /**
36
+ * Get s3 class variable. Throw error if doesn't exist.
37
+ *
38
+ * @returns - S3 object.
39
+ */
40
+ private get s3();
41
+ /** Set s3 class variable. */
42
+ private set s3(value);
43
+ /**
44
+ * Initialize recorder using the jsPsych plugin API. There should always be a
45
+ * stream initialized when the Recorder class is instantiated. This method is
46
+ * just used to re-initialize the stream with a clone when the recorder needs
47
+ * to be reset during a trial.
48
+ *
49
+ * @param stream - Media stream returned from getUserMedia that should be used
50
+ * to set up the jsPsych recorder.
51
+ * @param opts - Media recorder options to use when setting up the recorder.
52
+ */
53
+ initializeRecorder(stream: MediaStream, opts?: MediaRecorderOptions): void;
54
+ /** Reset the recorder to be used again. */
55
+ reset(): void;
56
+ /**
57
+ * Insert a rendered template into an element.
58
+ *
59
+ * @param element - Element to have video inserted into.
60
+ * @param template - Template string
61
+ * @param insertStream - Should the stream be attributed to the webcam
62
+ * element.
63
+ * @returns Webcam element
64
+ */
65
+ private insertVideoFeed;
66
+ /**
67
+ * Insert a video element containing the webcam feed onto the page.
68
+ *
69
+ * @param element - The HTML div element that should serve as the container
70
+ * for the webcam display.
71
+ * @param width - The width of the video element containing the webcam feed,
72
+ * in CSS units (optional). Default is `'100%'`
73
+ * @param height - The height of the video element containing the webcam feed,
74
+ * in CSS units (optional). Default is `'auto'`
75
+ */
76
+ insertWebcamFeed(element: HTMLDivElement, width?: CSSWidthHeight, height?: CSSWidthHeight): void;
77
+ /**
78
+ * Insert video playback feed into supplied element.
79
+ *
80
+ * @param element - The HTML div element that should serve as the container
81
+ * for the webcam display.
82
+ * @param on_ended - Callback function called when playing video ends.
83
+ * @param width - The width of the video element containing the webcam feed,
84
+ * in CSS units (optional). Default is `'100%'`
85
+ * @param height - The height of the video element containing the webcam feed,
86
+ * in CSS units (optional). Default is `'auto'`
87
+ */
88
+ insertPlaybackFeed(element: HTMLDivElement, on_ended: (this: HTMLVideoElement, e: Event) => void, width?: CSSWidthHeight, height?: CSSWidthHeight): void;
89
+ /**
90
+ * Insert a feed to be used for recording into an element.
91
+ *
92
+ * @param element - Element to have record feed inserted into.
93
+ * @param width - The width of the video element containing the webcam feed,
94
+ * in CSS units (optional). Default is `'100%'`
95
+ * @param height - The height of the video element containing the webcam feed,
96
+ * in CSS units (optional). Default is `'auto'`
97
+ */
98
+ insertRecordFeed(element: HTMLDivElement, width?: CSSWidthHeight, height?: CSSWidthHeight): void;
99
+ /**
100
+ * Start recording. Also, adds event listeners for handling data and checks
101
+ * for recorder initialization.
102
+ *
103
+ * @param prefix - Prefix for the video recording file name (string). This is
104
+ * the string that comes before "_<TIMESTAMP>.webm".
105
+ */
106
+ start(prefix: "consent" | "session_video" | "trial_video"): Promise<void>;
107
+ /**
108
+ * Stop all streams/tracks. This stops any in-progress recordings and releases
109
+ * the media devices. This is can be called when recording is not in progress,
110
+ * e.g. To end the camera/mic access when the experiment is displaying the
111
+ * camera feed but not recording (e.g. Video-config).
112
+ */
113
+ stopTracks(): void;
114
+ /**
115
+ * Stop recording and camera/microphone. This will stop accessing all media
116
+ * tracks, clear the webcam feed element (if there is one), and return the
117
+ * stop promise. This should only be called after recording has started.
118
+ *
119
+ * @returns Promise that resolves after the media recorder has stopped and
120
+ * final 'dataavailable' event has occurred, when the "stop" event-related
121
+ * callback function is called.
122
+ */
123
+ stop(): Promise<void>;
124
+ /** Throw Error if there isn't a recorder provided by jsPsych. */
125
+ private initializeCheck;
126
+ /**
127
+ * Handle the recorder's stop event. This is a function that takes the stop
128
+ * promise's 'resolve' as an argument and returns a function that resolves
129
+ * that stop promise. The function that is returned is used as the recorder's
130
+ * "stop" event-related callback function.
131
+ *
132
+ * @param resolve - Promise resolve function.
133
+ * @returns Function that is called on the recorder's "stop" event.
134
+ */
135
+ private handleStop;
136
+ /**
137
+ * Function ran at each time slice and when the recorder stopped.
138
+ *
139
+ * @param event - Event containing blob data.
140
+ */
141
+ private handleDataAvailable;
142
+ /** Download data url used in local development. */
143
+ private download;
144
+ /** Private helper to clear the webcam feed, if there is one. */
145
+ private clearWebcamFeed;
146
+ }
@@ -0,0 +1,24 @@
1
+ import { JsPsych, JsPsychPlugin } from "jspsych";
2
+ declare const info: {
3
+ readonly name: "start-record-plugin";
4
+ readonly parameters: {};
5
+ };
6
+ type Info = typeof info;
7
+ /** Start recording. Used by researchers who want to record across trials. */
8
+ export default class StartRecordPlugin implements JsPsychPlugin<Info> {
9
+ private jsPsych;
10
+ static readonly info: {
11
+ readonly name: "start-record-plugin";
12
+ readonly parameters: {};
13
+ };
14
+ private recorder;
15
+ /**
16
+ * Plugin used to start recording.
17
+ *
18
+ * @param jsPsych - Object provided by jsPsych.
19
+ */
20
+ constructor(jsPsych: JsPsych);
21
+ /** Trial function called by jsPsych. */
22
+ trial(): void;
23
+ }
24
+ export {};
package/dist/stop.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ import { JsPsych, JsPsychPlugin } from "jspsych";
2
+ declare const info: {
3
+ readonly name: "stop-record-plugin";
4
+ readonly parameters: {};
5
+ };
6
+ type Info = typeof info;
7
+ /** Stop recording. Used by researchers who want to record across trials. */
8
+ export default class StopRecordPlugin implements JsPsychPlugin<Info> {
9
+ private jsPsych;
10
+ static readonly info: {
11
+ readonly name: "stop-record-plugin";
12
+ readonly parameters: {};
13
+ };
14
+ private recorder;
15
+ /**
16
+ * Plugin used to stop recording.
17
+ *
18
+ * @param jsPsych - Object provided by jsPsych.
19
+ */
20
+ constructor(jsPsych: JsPsych);
21
+ /**
22
+ * Trial function called by jsPsych.
23
+ *
24
+ * @param display_element - DOM element where jsPsych content is being
25
+ * rendered (set in initJsPsych and automatically made available to a
26
+ * plugin's trial method via jsPsych core).
27
+ */
28
+ trial(display_element: HTMLElement): void;
29
+ }
30
+ export {};
@@ -0,0 +1,28 @@
1
+ import { JsPsych, JsPsychExtension, JsPsychExtensionInfo } from "jspsych";
2
+ /** This extension will allow reasearchers to record trials. */
3
+ export default class TrialRecordExtension implements JsPsychExtension {
4
+ private jsPsych;
5
+ static readonly info: JsPsychExtensionInfo;
6
+ private recorder?;
7
+ /**
8
+ * Video recording extension.
9
+ *
10
+ * @param jsPsych - JsPsych object passed into extensions.
11
+ */
12
+ constructor(jsPsych: JsPsych);
13
+ /**
14
+ * Ran on the initialize step for extensions, called when an instance of
15
+ * jsPsych is first initialized through initJsPsych().
16
+ */
17
+ initialize(): Promise<void>;
18
+ /** Ran at the start of a trial. */
19
+ on_start(): void;
20
+ /** Ran when the trial has loaded. */
21
+ on_load(): void;
22
+ /**
23
+ * Ran when trial has finished.
24
+ *
25
+ * @returns Trial data.
26
+ */
27
+ on_finish(): {};
28
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * A valid CSS height/width value, which can be a number, a string containing a
3
+ * number with units, or 'auto'.
4
+ */
5
+ export type CSSWidthHeight = number | `${number}${"px" | "cm" | "mm" | "em" | "%"}` | "auto";
@@ -0,0 +1,21 @@
1
+ import { PluginInfo, TrialType } from "jspsych";
2
+ /**
3
+ * Pulled from EFP. Function to convert researcher's text to HTML.
4
+ *
5
+ * @param text - Text
6
+ * @returns Formatted string
7
+ */
8
+ export declare const expFormat: (text?: string | string[]) => string;
9
+ /**
10
+ * Get a translation file based on selected language.
11
+ *
12
+ * @param lcl - Locale object with locale
13
+ * @returns Translations from i18next
14
+ */
15
+ export declare const getTranslation: (lcl: Intl.Locale) => Record<string, string>;
16
+ /**
17
+ * Initialize both i18next and Handlebars.
18
+ *
19
+ * @param trial - Yup
20
+ */
21
+ export declare const initI18nAndTemplates: (trial: TrialType<PluginInfo>) => void;
@@ -0,0 +1,296 @@
1
+ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych";
2
+ declare const info: {
3
+ readonly name: "video-config-plugin";
4
+ readonly version: string;
5
+ readonly parameters: {
6
+ readonly troubleshooting_intro: {
7
+ /**
8
+ * Optional string to appear at the start of the "Setup tips and
9
+ * troubleshooting" section.
10
+ */
11
+ readonly type: ParameterType.HTML_STRING;
12
+ readonly default: "";
13
+ readonly pretty_name: "Troubleshooting Intro";
14
+ };
15
+ };
16
+ readonly data: {
17
+ readonly rt: {
18
+ readonly type: ParameterType.INT;
19
+ };
20
+ readonly camId: {
21
+ readonly type: ParameterType.STRING;
22
+ };
23
+ readonly micId: {
24
+ readonly type: ParameterType.STRING;
25
+ };
26
+ };
27
+ };
28
+ type Info = typeof info;
29
+ export type VideoConsentTrialType = TrialType<Info>;
30
+ /**
31
+ * **Video Config**.
32
+ *
33
+ * CHS jsPsych plugin for presenting a video recording configuration plugin, to
34
+ * help participants set up their webcam and microphone before beginning a study
35
+ * that includes video/audio recording. This plugin must be used before any
36
+ * other trials in the experiment can access the camera/mic.
37
+ *
38
+ * @author Becky Gilbert
39
+ * @see {@link https://github.com/lookit/lookit-jspsych/blob/main/packages/video-config/README.md video-config plugin documentation on Github}
40
+ */
41
+ export default class VideoConfigPlugin implements JsPsychPlugin<Info> {
42
+ private jsPsych;
43
+ static info: {
44
+ readonly name: "video-config-plugin";
45
+ readonly version: string;
46
+ readonly parameters: {
47
+ readonly troubleshooting_intro: {
48
+ /**
49
+ * Optional string to appear at the start of the "Setup tips and
50
+ * troubleshooting" section.
51
+ */
52
+ readonly type: ParameterType.HTML_STRING;
53
+ readonly default: "";
54
+ readonly pretty_name: "Troubleshooting Intro";
55
+ };
56
+ };
57
+ readonly data: {
58
+ readonly rt: {
59
+ readonly type: ParameterType.INT;
60
+ };
61
+ readonly camId: {
62
+ readonly type: ParameterType.STRING;
63
+ };
64
+ readonly micId: {
65
+ readonly type: ParameterType.STRING;
66
+ };
67
+ };
68
+ };
69
+ private display_el;
70
+ private start_time;
71
+ private recorder;
72
+ private hasReloaded;
73
+ private response;
74
+ private camId;
75
+ private micId;
76
+ private minVolume;
77
+ private micChecked;
78
+ private processorNode;
79
+ private webcam_container_id;
80
+ private reload_button_id_text;
81
+ private reload_button_id_cam;
82
+ private camera_selection_id;
83
+ private mic_selection_id;
84
+ private next_button_id;
85
+ private error_msg_div_id;
86
+ private step1_id;
87
+ private step2_id;
88
+ private step3_id;
89
+ private step_complete_class;
90
+ private step_complete_text;
91
+ private waiting_for_access_msg;
92
+ private checking_mic_msg;
93
+ private access_problem_msg;
94
+ private setup_problem_msg;
95
+ /**
96
+ * Constructor for video config plugin.
97
+ *
98
+ * @param jsPsych - JsPsych object automatically passed into the constructor.
99
+ */
100
+ constructor(jsPsych: JsPsych);
101
+ /**
102
+ * Trial method called by jsPsych.
103
+ *
104
+ * @param display_element - Element where the jsPsych trial will be displayed.
105
+ * @param trial - Trial object with parameters/values.
106
+ */
107
+ trial(display_element: HTMLElement, trial: VideoConsentTrialType): void;
108
+ /**
109
+ * Add HTML content to the page.
110
+ *
111
+ * @param troubleshooting_intro - Troubleshooting intro parameter from the
112
+ * Trial object.
113
+ */
114
+ private addHtmlContent;
115
+ /** Add event listeners to elements after they've been added to the page. */
116
+ private addEventListeners;
117
+ /**
118
+ * Access media devices, populate device lists, setup the jsPsych
119
+ * camera/stream and Recorder instance, and run the permissions/mic checks.
120
+ * This is run when the trial first loads and anytime the user clicks the
121
+ * reload recorder button.
122
+ *
123
+ * 1. Request permissions.
124
+ * 2. Enumerate devices and populate the device selection elements with options.
125
+ * 3. Initialize the jsPsych recorder with the current/selected devices, and
126
+ * create a new Recorder.
127
+ * 4. Run the stream checks. (If completed successfully, this will clear any
128
+ * error messages and enable the next button).
129
+ */
130
+ private setupRecorder;
131
+ /**
132
+ * Request permission to use the webcam and/or microphone. This can be used
133
+ * with and without specific device selection (and other constraints).
134
+ *
135
+ * @param constraints - Media stream constraints object with 'video' and
136
+ * 'audio' properties, whose values can be boolean or a
137
+ * MediaTrackConstraints object or undefined.
138
+ * @param constraints.video - If false, do not include video. If true, use the
139
+ * default webcam device. If a media track constraints object is passed,
140
+ * then it can contain the properties of all media tracks and video tracks:
141
+ * https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints.
142
+ * @param constraints.audio - If false, do not include audio. If true, use the
143
+ * default mic device. If a media track constraints object is passed, then
144
+ * it can contain the properties of all media tracks and audio tracks:
145
+ * https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints.
146
+ * @returns Camera/microphone stream.
147
+ */
148
+ private requestPermission;
149
+ /**
150
+ * Receives device lists and populates the device selection HTML elements.
151
+ * This is run when the trial loads, and in response to changes to the
152
+ * available devices.
153
+ *
154
+ * @param devices - Object with properties 'cameras' and 'mics', which are
155
+ * arrays containing lists of available devices.
156
+ * @param devices.cameras - Array of MediaDeviceInfo objects for webcam/video
157
+ * input devices.
158
+ * @param devices.mics - Array of MediaDeviceInfo objects for mic/audio input
159
+ * devices.
160
+ */
161
+ private updateDeviceSelection;
162
+ /**
163
+ * Takes the selected device IDs from the camera/mic selection elements, gets
164
+ * the streams for these devices, sets these as the input devices via
165
+ * jsPsych.pluginAPI.initializeCameraRecorder, and creates a new Recorder.
166
+ */
167
+ private setDevices;
168
+ /**
169
+ * Run the stream checks after permissions have been granted and devices have
170
+ * been selected. This is run when the trial first loads, after permissions
171
+ * are granted, and in response to changes to the device selection. It checks
172
+ * for (1) the existence of the required streams, (2) minimum microphone input
173
+ * level (when audio is included), and (3) media permissions (via recorder
174
+ * destroy/reload). This runs the stream checks, updates the info/error
175
+ * messages, enables the next button, and handles errors. This is factored out
176
+ * of the set up process (setupRecorder) because it is also triggered by a
177
+ * change in the cam/mic device selection.
178
+ */
179
+ private runStreamChecks;
180
+ /**
181
+ * If there is a change to the available devices, then we need to: (1) get the
182
+ * updated device lists, and (2) update the select elements with these list
183
+ * elements.
184
+ */
185
+ private onDeviceChange;
186
+ /**
187
+ * Gets the lists of available cameras and mics (via Media Devices
188
+ * 'enumerateDevices'). These lists can be used to populate camera/mic
189
+ * selection elements.
190
+ *
191
+ * @param include_audio - Whether or not to include audio capture (mic)
192
+ * devices. Optional, default is true.
193
+ * @param include_camera - Whether or not to include the webcam (video)
194
+ * devices. Optional, default is true.
195
+ * @returns Object with properties 'cameras' and 'mics', containing lists of
196
+ * available devices.
197
+ */
198
+ private getDeviceLists;
199
+ /**
200
+ * Initialize recorder using the jsPsych plugin API. This must be called
201
+ * before running the stream checks.
202
+ *
203
+ * @param stream - Media stream returned from getUserMedia that should be used
204
+ * to set up the jsPsych recorder.
205
+ * @param opts - Media recorder options to use when setting up the recorder.
206
+ */
207
+ initializeAndCreateRecorder: (stream: MediaStream, opts?: MediaRecorderOptions) => void;
208
+ /**
209
+ * Perform a sound check on the audio input (microphone).
210
+ *
211
+ * @param minVol - Minimum mic activity needed to reach the mic check
212
+ * threshold (optional). Default is `this.minVolume`
213
+ * @returns Promise that resolves when the mic check is complete because the
214
+ * audio stream has reached the required minimum level.
215
+ */
216
+ private checkMic;
217
+ /**
218
+ * Handle the mic level messages that are sent via an AudioWorkletProcessor.
219
+ * This checks the current level against the minimum threshold, and if the
220
+ * threshold is met, sets the micChecked property to true and resolves the
221
+ * checkMic promise.
222
+ *
223
+ * @param currentActivityLevel - Microphone activity level calculated by the
224
+ * processor node.
225
+ * @param minVolume - Minimum microphone activity level needed to pass the
226
+ * microphone check.
227
+ * @param resolve - Resolve callback function for Promise returned by the
228
+ * checkMic method.
229
+ */
230
+ private onMicActivityLevel;
231
+ /**
232
+ * Creates the processor node for the mic check input level processing, and
233
+ * connects the microphone to the processor node.
234
+ *
235
+ * @param audioContext - Audio context that was created in checkMic. This is
236
+ * used to create the processor node.
237
+ * @param microphone - Microphone audio stream source, created in checkMic.
238
+ * The processor node will be connected to this source.
239
+ * @returns Promise that resolves after the processor node has been created,
240
+ * and the microphone audio stream source is connected to the processor node
241
+ * and audio context destination.
242
+ */
243
+ private createConnectProcessor;
244
+ /**
245
+ * Set up the port's on message event handler for the mic check processor
246
+ * node. This adds the event related callback, which calls onMicActivityLevel
247
+ * with the event data.
248
+ *
249
+ * @param minVol - Minimum volume level (RMS amplitude) passed from checkMic.
250
+ * @returns Promise that resolves from inside the onMicActivityLevel callback,
251
+ * when the mic stream input level has reached the threshold.
252
+ */
253
+ private setupPortOnMessage;
254
+ /**
255
+ * Update the instructions for a given step, based on whether or not the check
256
+ * has passed for that step.
257
+ *
258
+ * @param step - Which instructions step to update. 1 = stream access, 2 =
259
+ * reload complete, 3 = mic level check.
260
+ * @param checkPassed - Whether or not the mic check has passed.
261
+ */
262
+ private updateInstructions;
263
+ /**
264
+ * Update the errors/messages div with information for the user about the
265
+ * camera/mic checks.
266
+ *
267
+ * @param errorMsg - Message to display in the error message div. Pass an
268
+ * empty string to clear any existing errors/messages.
269
+ */
270
+ private updateErrors;
271
+ /**
272
+ * Collect trial data and end the trial. JsPsych.finishTrial takes the
273
+ * plugin's trial data as an argument, ends the trial, and moves on to the
274
+ * next trial in the experiment timeline.
275
+ */
276
+ private endTrial;
277
+ /**
278
+ * Destroy the recorder. This is used to stop the streams at the end of the
279
+ * trial, and as part of the reload check to test the user's browser
280
+ * permissions by mimicking the start of a new trial (i.e. stop streams and
281
+ * then create a new Recorder instance).
282
+ */
283
+ private destroyRecorder;
284
+ /** Handle the next button click event. */
285
+ private nextButtonClick;
286
+ /** Handle the reload recorder button click event. */
287
+ private reloadButtonClick;
288
+ /**
289
+ * Toggle the next button disable property.
290
+ *
291
+ * @param enable - Whether to enable (true) or disable (false) the next
292
+ * button.
293
+ */
294
+ private enableNext;
295
+ }
296
+ export {};
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@lookit/record",
3
+ "version": "0.0.3",
4
+ "description": "Recording extensions and plugins for CHS studies.",
5
+ "homepage": "https://github.com/lookit/lookit-jspsych#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/lookit/lookit-jspsych/issues"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/lookit/lookit-jspsych.git"
12
+ },
13
+ "license": "ISC",
14
+ "author": "Christopher J Green <okaycj@mit.edu> (https://github.com/okaycj)",
15
+ "main": "dist/index.js",
16
+ "unpkg": "dist/index.browser.min.js",
17
+ "types": "./dist/index.d.ts",
18
+ "files": [
19
+ "src",
20
+ "dist"
21
+ ],
22
+ "scripts": {
23
+ "build": "rollup --config",
24
+ "buildMicCheck": "npx tsc src/mic_check.ts --target esnext --lib ESNext --types node,audioworklet --skipLibCheck true",
25
+ "dev": "rollup --config rollup.config.dev.mjs --watch",
26
+ "test": "jest --coverage"
27
+ },
28
+ "dependencies": {
29
+ "auto-bind": "^5.0.1"
30
+ },
31
+ "devDependencies": {
32
+ "@jspsych/config": "^2.0.0",
33
+ "@jspsych/test-utils": "^1.2.0",
34
+ "@rollup/plugin-image": "^3.0.3",
35
+ "@rollup/plugin-replace": "^6.0.1",
36
+ "@types/audioworklet": "^0.0.60",
37
+ "@types/js-yaml": "^4.0.9",
38
+ "@types/node-polyglot": "^2.5.0",
39
+ "handlebars": "^4.7.8",
40
+ "i18next": "^23.15.1",
41
+ "i18next-icu": "^2.3.0",
42
+ "js-yaml": "^4.1.0",
43
+ "rollup-plugin-dotenv": "^0.5.1",
44
+ "rollup-plugin-polyfill-node": "^0.13.0",
45
+ "rollup-plugin-string-import": "^1.2.4",
46
+ "typescript": "^5.6.2"
47
+ },
48
+ "peerDependencies": {
49
+ "@lookit/data": "^0.0.3",
50
+ "jspsych": "^8.0.2"
51
+ }
52
+ }