From 1f535826a296556252d5c0c8da5cb6aaa8fec656 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Fri, 31 Jan 2025 17:29:37 -0500 Subject: [PATCH 1/3] add default `mimeType` if none is specified --- .changeset/sixty-ears-tan.md | 5 +++++ docs/reference/jspsych-pluginAPI.md | 3 +-- examples/extension-record-video.html | 5 ++++- packages/jspsych/src/modules/plugin-api/MediaAPI.ts | 6 ++++++ 4 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 .changeset/sixty-ears-tan.md 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/reference/jspsych-pluginAPI.md b/docs/reference/jspsych-pluginAPI.md index b7fa6005..81b036ef 100644 --- a/docs/reference/jspsych-pluginAPI.md +++ b/docs/reference/jspsych-pluginAPI.md @@ -507,8 +507,7 @@ 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 `"video/webm"`. #### Example ```javascript 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..de50e0af 100644 --- a/packages/jspsych/src/modules/plugin-api/MediaAPI.ts +++ b/packages/jspsych/src/modules/plugin-api/MediaAPI.ts @@ -284,6 +284,12 @@ export class MediaAPI { private camera_recorder: MediaRecorder = null; initializeCameraRecorder(stream: MediaStream, opts?: MediaRecorderOptions) { + if (!opts) { + opts = { mimeType: "video/webm" }; + } else if (!opts.mimeType) { + opts.mimeType = "video/webm"; + } + this.camera_stream = stream; const recorder = new MediaRecorder(stream, opts); this.camera_recorder = recorder; From d258a29aae8452fc2a42998e0a5aaed8ea51aabc Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Sat, 8 Feb 2025 10:18:36 -0500 Subject: [PATCH 2/3] implement compatible mimetype searching if no mimetype provided --- .../src/modules/plugin-api/MediaAPI.ts | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/jspsych/src/modules/plugin-api/MediaAPI.ts b/packages/jspsych/src/modules/plugin-api/MediaAPI.ts index de50e0af..c019a178 100644 --- a/packages/jspsych/src/modules/plugin-api/MediaAPI.ts +++ b/packages/jspsych/src/modules/plugin-api/MediaAPI.ts @@ -284,17 +284,38 @@ export class MediaAPI { private camera_recorder: MediaRecorder = null; initializeCameraRecorder(stream: MediaStream, opts?: MediaRecorderOptions) { - if (!opts) { - opts = { mimeType: "video/webm" }; - } else if (!opts.mimeType) { - opts.mimeType = "video/webm"; + 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; } From 54a9014cf7764430bafb178bb29148aa1c8e6481 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Wed, 12 Feb 2025 22:29:37 -0500 Subject: [PATCH 3/3] expand docs to clarify common mimetypes --- docs/plugins/initialize-camera.md | 2 +- docs/reference/jspsych-pluginAPI.md | 5 ++++- packages/jspsych/src/modules/plugin-api/MediaAPI.ts | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) 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 81b036ef..35bfcbd0 100644 --- a/docs/reference/jspsych-pluginAPI.md +++ b/docs/reference/jspsych-pluginAPI.md @@ -507,7 +507,10 @@ None. #### Description -Generates a `MediaRecorder` object from provided `MediaStream` and stores this for access via [`getCameraRecorder()`](#getcamerarecorder). By default, `mimeType` is set to `"video/webm"`. +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 ```javascript diff --git a/packages/jspsych/src/modules/plugin-api/MediaAPI.ts b/packages/jspsych/src/modules/plugin-api/MediaAPI.ts index c019a178..9eea34db 100644 --- a/packages/jspsych/src/modules/plugin-api/MediaAPI.ts +++ b/packages/jspsych/src/modules/plugin-api/MediaAPI.ts @@ -303,7 +303,7 @@ export class MediaAPI { "video/webm;codecs=vp9,opus", "video/webm;codecs=vp8,opus", // general - 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"', + "video/mp4;codecs=avc1.42E01E,mp4a.40.2", // safari "video/mp4;codecs=h264,aac", "video/mp4;codecs=hevc,aac",