Compare commits

...

16 Commits

Author SHA1 Message Date
Josh de Leeuw
861cd1e646
Merge pull request #3495 from jspsych/camera-recorder-default-mimetype
add default `mimeType` if none is specified
2025-03-07 09:52:24 -05:00
Josh de Leeuw
51aefac75b
Merge pull request #3507 from jspsych/changeset-release/main
Version Packages
2025-02-13 14:22:35 -05:00
jade
54a9014cf7 expand docs to clarify common mimetypes 2025-02-12 22:29:37 -05:00
github-actions[bot]
86c1ff4587 chore(release): version packages 2025-02-12 15:04:02 +00:00
Josh de Leeuw
7dee88ca01
Merge pull request #2991 from bbonf/fix-audio-mimetype
fix for wrong audio mimetype preventing playback in Safari
2025-02-12 10:00:12 -05:00
jade
5ab4cc7a0f add changeset 2025-02-08 11:11:35 -05:00
jade
d258a29aae implement compatible mimetype searching if no mimetype provided 2025-02-08 10:18:36 -05:00
cchang-vassar
ce30fca573 Revert "reorder fields in jsPsych citation file; add citation file for extension-webgazer"
This reverts commit 2feebbf9c4.

Applying changes to point-templates-to-dev branch instead.
2025-02-06 15:20:27 -05:00
cchang-vassar
715092030a Revert "Update new plugin and extension template mentions to point to jspsych-dev"
This reverts commit b243de6735.

Changes to be applied in point-templates-to-dev branch instead.
2025-02-06 15:09:59 -05:00
cchang-vassar
2feebbf9c4 reorder fields in jsPsych citation file; add citation file for extension-webgazer 2025-02-06 14:25:48 -05:00
cchang-vassar
b243de6735 Update new plugin and extension template mentions to point to jspsych-dev 2025-02-06 13:51:39 -05:00
Josh de Leeuw
c4f11e29e2
Merge pull request #3128 from jspsych/docs-add-utils-reference
Document the `utils` module and reference it in the randomization docs
2025-02-04 15:11:02 -05:00
jade
1f535826a2 add default mimeType if none is specified 2025-01-31 17:29:37 -05:00
jade
8834532fc9 add deepCopy warning messages for randomization/sample functions 2025-01-11 11:31:25 -07:00
bjoluc
36e64efbfb Add docs page for the utils module 2023-09-12 21:41:21 +02:00
ben
cc1ca257f5 fix for wrong audio mimetype preventing playback in Safari 2023-03-24 11:43:55 +01:00
16 changed files with 159 additions and 12 deletions

View File

@ -0,0 +1,5 @@
---
"jspsych": patch
---
add a default `mimeType` of `"video/webm" to `initializeCameraRecorder()`

View File

@ -3,7 +3,7 @@
<head> <head>
<script src="https://unpkg.com/jspsych@8.2.1"></script> <script src="https://unpkg.com/jspsych@8.2.1"></script>
<script src="https://unpkg.com/@jspsych/plugin-html-button-response@2.1.0"></script> <script src="https://unpkg.com/@jspsych/plugin-html-button-response@2.1.0"></script>
<script src="https://unpkg.com/@jspsych/plugin-html-audio-response@2.1.0"></script> <script src="https://unpkg.com/@jspsych/plugin-html-audio-response@2.1.1"></script>
<script src="https://unpkg.com/@jspsych/plugin-initialize-microphone@2.1.0"></script> <script src="https://unpkg.com/@jspsych/plugin-initialize-microphone@2.1.0"></script>
<link rel="stylesheet" href="https://unpkg.com/jspsych@8.2.1/css/jspsych.css"> <link rel="stylesheet" href="https://unpkg.com/jspsych@8.2.1/css/jspsych.css">
<style> <style>

View File

@ -3,7 +3,7 @@
<head> <head>
<script src="https://unpkg.com/jspsych@8.2.1"></script> <script src="https://unpkg.com/jspsych@8.2.1"></script>
<script src="https://unpkg.com/@jspsych/plugin-html-button-response@2.1.0"></script> <script src="https://unpkg.com/@jspsych/plugin-html-button-response@2.1.0"></script>
<script src="https://unpkg.com/@jspsych/plugin-html-audio-response@2.1.0"></script> <script src="https://unpkg.com/@jspsych/plugin-html-audio-response@2.1.1"></script>
<script src="https://unpkg.com/@jspsych/plugin-initialize-microphone@2.1.0"></script> <script src="https://unpkg.com/@jspsych/plugin-initialize-microphone@2.1.0"></script>
<link rel="stylesheet" href="https://unpkg.com/jspsych@8.2.1/css/jspsych.css"> <link rel="stylesheet" href="https://unpkg.com/jspsych@8.2.1/css/jspsych.css">
<style> <style>

View File

@ -3,7 +3,7 @@
<head> <head>
<script src="https://unpkg.com/jspsych@8.2.1"></script> <script src="https://unpkg.com/jspsych@8.2.1"></script>
<script src="https://unpkg.com/@jspsych/plugin-html-button-response@2.1.0"></script> <script src="https://unpkg.com/@jspsych/plugin-html-button-response@2.1.0"></script>
<script src="https://unpkg.com/@jspsych/plugin-html-audio-response@2.1.0"></script> <script src="https://unpkg.com/@jspsych/plugin-html-audio-response@2.1.1"></script>
<script src="https://unpkg.com/@jspsych/plugin-audio-button-response@2.1.0"></script> <script src="https://unpkg.com/@jspsych/plugin-audio-button-response@2.1.0"></script>
<script src="https://unpkg.com/@jspsych/plugin-initialize-microphone@2.1.0"></script> <script src="https://unpkg.com/@jspsych/plugin-initialize-microphone@2.1.0"></script>
<link rel="stylesheet" href="https://unpkg.com/jspsych@8.2.1/css/jspsych.css"> <link rel="stylesheet" href="https://unpkg.com/jspsych@8.2.1/css/jspsych.css">

View File

@ -63,7 +63,7 @@ This plugin does not yet support [simulation mode](../overview/simulation.md).
Using the CDN-hosted JavaScript file: Using the CDN-hosted JavaScript file:
```js ```js
<script src="https://unpkg.com/@jspsych/plugin-html-audio-response@2.1.0"></script> <script src="https://unpkg.com/@jspsych/plugin-html-audio-response@2.1.1"></script>
``` ```
Using the JavaScript file downloaded from a GitHub release dist archive: Using the JavaScript file downloaded from a GitHub release dist archive:

View File

@ -22,7 +22,7 @@ button_label | string | 'Use this camera.' | The label for the select button.
include_audio | bool | false | Set to `true` to include an audio track in the recordings. include_audio | bool | false | Set to `true` to include an audio track in the recordings.
width | int | null | Request a specific width for the recording. This is not a guarantee that this width will be used, as it depends on the capabilities of the participant's device. Learn more about `MediaRecorder` constraints [here](https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints#requesting_a_specific_value_for_a_setting). width | int | null | Request a specific width for the recording. This is not a guarantee that this width will be used, as it depends on the capabilities of the participant's device. Learn more about `MediaRecorder` constraints [here](https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints#requesting_a_specific_value_for_a_setting).
height | int | null | Request a specific height for the recording. This is not a guarantee that this height will be used, as it depends on the capabilities of the participant's device. Learn more about `MediaRecorder` constraints [here](https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints#requesting_a_specific_value_for_a_setting). height | int | null | Request a specific height for the recording. This is not a guarantee that this height will be used, as it depends on the capabilities of the participant's device. Learn more about `MediaRecorder` constraints [here](https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API/Constraints#requesting_a_specific_value_for_a_setting).
mime_type | string | null | Set this to use a specific [MIME type](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/mimeType) for the recording. Set the entire type, e.g., `'video/mp4; codecs="avc1.424028, mp4a.40.2"'`. mime_type | string | null | Set this to use a specific [MIME type](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/mimeType) for the recording. Set the entire type, e.g., `'video/mp4; codecs="avc1.424028, mp4a.40.2"'`. When provided with the default value of `null`, jsPsych will search for a compatible container/codec combination, with [common types listed here](../reference/jspsych-pluginAPI.md#initializecamerarecorder). If none are found, jsPsych will default to `'video/webm'` as the MIME type.
## Data Generated ## Data Generated

View File

@ -507,7 +507,9 @@ None.
#### Description #### Description
Generates a `MediaRecorder` object from provided `MediaStream` and stores this for access via [`getCameraRecorder()`](#getcamerarecorder). Generates a `MediaRecorder` object from provided `MediaStream` and stores this for access via [`getCameraRecorder()`](#getcamerarecorder). By default, `mimeType` is set to the first compatible container/codec combination found in a list of common types, or `"video/webm"` if no supported combination is found.
The common container/codec combinations that jsPsych checks for are `"video/webm;codecs=vp9,opus"`, `"video/webm;codecs=vp8,opus"`, `"video/mp4;codecs=avc1.42E01E,mp4a.40.2"`, `"video/mp4;codecs=h264,aac"`, and `"video/mp4;codecs=hevc,aac"`.
#### Example #### Example

View File

@ -89,7 +89,7 @@ output:
full_design = { full_design = {
stimulus: ['a.jpg','b.jpg','b.jpg','a.jpg'], stimulus: ['a.jpg','b.jpg','b.jpg','a.jpg'],
ms_delay: [200, 100, 200, 100] ms_delay: [200, 100, 200, 100]
] }
*/ */
``` ```
@ -182,6 +182,8 @@ This method takes an array of values and generates a new random order of the arr
If the array elements are objects with the same set of properties, then this method can optionally return a single object where each property is a randomized order of the properties defined in the original set of objects. This is useful for randomizing sets of parameters that are used to define a jsPsych block. If the array elements are objects with the same set of properties, then this method can optionally return a single object where each property is a randomized order of the properties defined in the original set of objects. This is useful for randomizing sets of parameters that are used to define a jsPsych block.
This returns a shallow copy of the array, i.e. modifications to arrays/objects within this array will affect the original. If this is not desired, consider taking a [`deepCopy`](./jspsych-utils.md#jspsychutilsdeepcopy).
### Examples ### Examples
#### Shuffle an array, no repeats #### Shuffle an array, no repeats
@ -414,6 +416,8 @@ An array containing the sample.
This method returns a sample drawn at random from a set of values with replacement. The relative probability of drawing each item can be controlled by specifying the `weights`. This method returns a sample drawn at random from a set of values with replacement. The relative probability of drawing each item can be controlled by specifying the `weights`.
This returns a shallow copy of the array, i.e. modifications to arrays/objects within this array will affect the original. If this is not desired, consider taking a [`deepCopy`](./jspsych-utils.md#jspsychutilsdeepcopy).
### Examples ### Examples
#### Sample with equal probability #### Sample with equal probability
@ -455,6 +459,8 @@ An array containing the sample.
This method returns a sample drawn at random from a set of values without replacement. The sample size must be less than or equal to the length of the array. This method returns a sample drawn at random from a set of values without replacement. The sample size must be less than or equal to the length of the array.
This returns a shallow copy of the array, i.e. modifications to arrays/objects within this array will affect the original. If this is not desired, consider taking a [`deepCopy`](./jspsych-utils.md#jspsychutilsdeepcopy).
### Examples ### Examples
#### Sample without replacement #### Sample without replacement
@ -532,6 +538,8 @@ Returns an array with the same elements as the input array in a random order.
A simple method for shuffling the order of an array. A simple method for shuffling the order of an array.
This returns a shallow copy of the array, i.e. modifications to arrays/objects within this array will affect the original. If this is not desired, consider taking a [`deepCopy`](./jspsych-utils.md#jspsychutilsdeepcopy).
### Examples ### Examples
#### Shuffle an array #### Shuffle an array
@ -565,6 +573,8 @@ Returns an array with the same elements as the input array in a random order, wi
Shuffle an array, ensuring that neighboring elements in the array are different. Shuffle an array, ensuring that neighboring elements in the array are different.
This returns a shallow copy of the array, i.e. modifications to arrays/objects within this array will affect the original. If this is not desired, consider taking a [`deepCopy`](./jspsych-utils.md#jspsychutilsdeepcopy).
*Warning: if you provide an array that has very few valid permutations with no neighboring elements, then this method will fail and cause the browser to hang.* *Warning: if you provide an array that has very few valid permutations with no neighboring elements, then this method will fail and cause the browser to hang.*
### Examples ### Examples

View File

@ -0,0 +1,93 @@
# jsPsych.utils
The jsPsych.utils module contains utility functions that might turn out useful at one place or the other.
---
## jsPsych.utils.unique
```javascript
jsPsych.utils.unique(array)
```
### Parameters
| Parameter | Type | Description |
| --------- | ----- | ------------------------------ |
| array | Array | An array of arbitrary elements |
### Return value
An array containing all elements from the input array, but without duplicate elements
### Description
This function takes an array and returns a copy of that array with all duplicate elements removed.
### Example
```javascript
jsPsych.utils.unique(["a", "b", "b", 1, 1, 2]) // returns ["a", "b", 1, 2]
```
---
## jsPsych.utils.deepCopy
```javascript
jsPsych.utils.deepCopy(object);
```
### Parameters
| Parameter | Type | Description |
| --------- | --------------- | ---------------------------- |
| object | Object or Array | An arbitrary object or array |
### Return value
A deep copy of the provided object or array
### Description
This function takes an arbitrary object or array and returns a deep copy of it, i.e. all child objects or arrays are recursively copied too.
### Example
```javascript
var myObject = { nested: ["array", "of", "elements"] };
var deepCopy = jsPsych.utils.deepCopy(myObject);
deepCopy.nested[2] = "thingies";
console.log(myObject.nested[2]) // still logs "elements"
```
---
## jsPsych.utils.deepMerge
```javascript
jsPsych.utils.deepMerge(object1, object2);
```
### Parameters
| Parameter | Type | Description |
| --------- | ------ | --------------- |
| object1 | Object | Object to merge |
| object2 | Object | Object to merge |
### Return value
A deep copy of `object1` with all the (nested) properties from `object2` filled in
### Description
This function takes two objects and recursively merges them into a new object. If both objects define the same (nested) property, the property value from `object2` takes precedence.
### Example
```javascript
var object1 = { a: 1, b: { c: 1, d: 2 } };
var object2 = { b: { c: 2 }, e: 3 };
jsPsych.utils.deepMerge(object1, object2); // returns { a: 1, b: { c: 2, d: 2 }, e: 3 }
```

View File

@ -13,7 +13,10 @@
const jsPsych = initJsPsych({ const jsPsych = initJsPsych({
extensions: [ extensions: [
{type: jsPsychExtensionRecordVideo} {type: jsPsychExtensionRecordVideo}
] ],
on_finish: function() {
jsPsych.data.displayData();
}
}); });
const initCamera = { const initCamera = {

View File

@ -71,6 +71,7 @@ nav:
- 'jsPsych.data': 'reference/jspsych-data.md' - 'jsPsych.data': 'reference/jspsych-data.md'
- 'jsPsych.randomization': 'reference/jspsych-randomization.md' - 'jsPsych.randomization': 'reference/jspsych-randomization.md'
- 'jsPsych.turk': 'reference/jspsych-turk.md' - 'jsPsych.turk': 'reference/jspsych-turk.md'
- 'jsPsych.utils': 'reference/jspsych-utils.md'
- 'jsPsych.pluginAPI': 'reference/jspsych-pluginAPI.md' - 'jsPsych.pluginAPI': 'reference/jspsych-pluginAPI.md'
- Plugins: - Plugins:
- 'List of Plugins': 'plugins/list-of-plugins.md' - 'List of Plugins': 'plugins/list-of-plugins.md'

2
package-lock.json generated
View File

@ -14040,7 +14040,7 @@
}, },
"packages/plugin-html-audio-response": { "packages/plugin-html-audio-response": {
"name": "@jspsych/plugin-html-audio-response", "name": "@jspsych/plugin-html-audio-response",
"version": "2.1.0", "version": "2.1.1",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@jspsych/config": "^3.2.0", "@jspsych/config": "^3.2.0",

View File

@ -284,11 +284,38 @@ export class MediaAPI {
private camera_recorder: MediaRecorder = null; private camera_recorder: MediaRecorder = null;
initializeCameraRecorder(stream: MediaStream, opts?: MediaRecorderOptions) { initializeCameraRecorder(stream: MediaStream, opts?: MediaRecorderOptions) {
let mimeType = this.getCompatibleMimeType() || "video/webm";
const recorderOptions: MediaRecorderOptions = {
...opts,
mimeType
}
this.camera_stream = stream; this.camera_stream = stream;
const recorder = new MediaRecorder(stream, opts); const recorder = new MediaRecorder(stream, recorderOptions);
this.camera_recorder = recorder; this.camera_recorder = recorder;
} }
// mimetype checking code adapted from https://github.com/lookit/lookit-jspsych/blob/develop/packages/record/src/videoConfig.ts#L673-L699
/** returns a compatible mimetype string, or null if none from the array are supported. */
private getCompatibleMimeType(): string {
const types = [
// chrome firefox edge
"video/webm;codecs=vp9,opus",
"video/webm;codecs=vp8,opus",
// general
"video/mp4;codecs=avc1.42E01E,mp4a.40.2",
// safari
"video/mp4;codecs=h264,aac",
"video/mp4;codecs=hevc,aac",
]
for (const mimeType of types) {
if (MediaRecorder.isTypeSupported(mimeType)) {
return mimeType;
}
}
return null;
}
getCameraStream(): MediaStream { getCameraStream(): MediaStream {
return this.camera_stream; return this.camera_stream;
} }

View File

@ -1,5 +1,11 @@
# @jspsych/plugin-html-audio-response # @jspsych/plugin-html-audio-response
## 2.1.1
### Patch Changes
- [#2991](https://github.com/jspsych/jsPsych/pull/2991) [`5ab4cc7a0f8750735b88e87df3bb692f140b3c53`](https://github.com/jspsych/jsPsych/commit/5ab4cc7a0f8750735b88e87df3bb692f140b3c53) Thanks [@bbonf](https://github.com/bbonf)! - uses mimetype of audio recorded for playback instead of defaulting to webm
## 2.1.0 ## 2.1.0
### Minor Changes ### Minor Changes

View File

@ -1,6 +1,6 @@
{ {
"name": "@jspsych/plugin-html-audio-response", "name": "@jspsych/plugin-html-audio-response",
"version": "2.1.0", "version": "2.1.1",
"description": "jsPsych plugin for displaying a stimulus and recording an audio response through the microphone", "description": "jsPsych plugin for displaying a stimulus and recording an audio response through the microphone",
"type": "module", "type": "module",
"main": "dist/index.cjs", "main": "dist/index.cjs",

View File

@ -182,7 +182,7 @@ class HtmlAudioResponsePlugin implements JsPsychPlugin<Info> {
}; };
this.stop_event_handler = () => { this.stop_event_handler = () => {
const data = new Blob(this.recorded_data_chunks, { type: "audio/webm" }); const data = new Blob(this.recorded_data_chunks, { type: this.recorded_data_chunks[0].type });
this.audio_url = URL.createObjectURL(data); this.audio_url = URL.createObjectURL(data);
const reader = new FileReader(); const reader = new FileReader();
reader.addEventListener("load", () => { reader.addEventListener("load", () => {