diff --git a/.changeset/sixty-ears-tan.md b/.changeset/sixty-ears-tan.md new file mode 100644 index 00000000..0404a468 --- /dev/null +++ b/.changeset/sixty-ears-tan.md @@ -0,0 +1,5 @@ +--- +"jspsych": patch +--- + +add a default `mimeType` of `"video/webm" to `initializeCameraRecorder()` diff --git a/docs/plugins/initialize-camera.md b/docs/plugins/initialize-camera.md index 69ce273d..c236f9fe 100644 --- a/docs/plugins/initialize-camera.md +++ b/docs/plugins/initialize-camera.md @@ -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. 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). -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 diff --git a/docs/reference/jspsych-pluginAPI.md b/docs/reference/jspsych-pluginAPI.md index b7fa6005..35bfcbd0 100644 --- a/docs/reference/jspsych-pluginAPI.md +++ b/docs/reference/jspsych-pluginAPI.md @@ -507,7 +507,9 @@ None. #### 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 diff --git a/examples/extension-record-video.html b/examples/extension-record-video.html index 29cf9ee5..5008fd0e 100644 --- a/examples/extension-record-video.html +++ b/examples/extension-record-video.html @@ -13,7 +13,10 @@ const jsPsych = initJsPsych({ extensions: [ {type: jsPsychExtensionRecordVideo} - ] + ], + on_finish: function() { + jsPsych.data.displayData(); + } }); const initCamera = { diff --git a/packages/jspsych/src/modules/plugin-api/MediaAPI.ts b/packages/jspsych/src/modules/plugin-api/MediaAPI.ts index 6dabb447..9eea34db 100644 --- a/packages/jspsych/src/modules/plugin-api/MediaAPI.ts +++ b/packages/jspsych/src/modules/plugin-api/MediaAPI.ts @@ -284,11 +284,38 @@ export class MediaAPI { private camera_recorder: MediaRecorder = null; initializeCameraRecorder(stream: MediaStream, opts?: MediaRecorderOptions) { + let mimeType = this.getCompatibleMimeType() || "video/webm"; + const recorderOptions: MediaRecorderOptions = { + ...opts, + mimeType + } + this.camera_stream = stream; - const recorder = new MediaRecorder(stream, opts); + const recorder = new MediaRecorder(stream, recorderOptions); 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 { return this.camera_stream; }