mirror of
https://github.com/jspsych/jsPsych.git
synced 2025-05-10 11:10:54 +00:00
add draft of camera plugin
This commit is contained in:
parent
0a2fe47a2d
commit
e13d504353
1
packages/plugin-initialize-camera/jest.config.cjs
Normal file
1
packages/plugin-initialize-camera/jest.config.cjs
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require("@jspsych/config/jest").makePackageConfig(__dirname);
|
43
packages/plugin-initialize-camera/package.json
Normal file
43
packages/plugin-initialize-camera/package.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "@jspsych/plugin-initialize-camera",
|
||||
"version": "0.0.1",
|
||||
"description": "jsPsych plugin for getting permission to initialize the user's camera",
|
||||
"type": "module",
|
||||
"main": "dist/index.cjs",
|
||||
"exports": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
"typings": "dist/index.d.ts",
|
||||
"unpkg": "dist/index.browser.min.js",
|
||||
"files": [
|
||||
"src",
|
||||
"dist"
|
||||
],
|
||||
"source": "src/index.ts",
|
||||
"scripts": {
|
||||
"test": "jest --passWithNoTests",
|
||||
"test:watch": "npm test -- --watch",
|
||||
"tsc": "tsc",
|
||||
"build": "rollup --config",
|
||||
"build:watch": "npm run build -- --watch"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/jspsych/jsPsych.git",
|
||||
"directory": "packages/plugin-initialize-camera"
|
||||
},
|
||||
"author": "Josh de Leeuw",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/jspsych/jsPsych/issues"
|
||||
},
|
||||
"homepage": "https://www.jspsych.org/latest/plugins/initialize-camera",
|
||||
"peerDependencies": {
|
||||
"jspsych": ">=7.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jspsych/config": "^1.3.0",
|
||||
"@jspsych/test-utils": "^1.1.0"
|
||||
}
|
||||
}
|
3
packages/plugin-initialize-camera/rollup.config.mjs
Normal file
3
packages/plugin-initialize-camera/rollup.config.mjs
Normal file
@ -0,0 +1,3 @@
|
||||
import { makeRollupConfig } from "@jspsych/config/rollup";
|
||||
|
||||
export default makeRollupConfig("jsPsychInitializeCamera");
|
111
packages/plugin-initialize-camera/src/index.ts
Normal file
111
packages/plugin-initialize-camera/src/index.ts
Normal file
@ -0,0 +1,111 @@
|
||||
import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych";
|
||||
|
||||
const info = <const>{
|
||||
name: "initialize-camera",
|
||||
parameters: {
|
||||
/** Function to call */
|
||||
device_select_message: {
|
||||
type: ParameterType.HTML_STRING,
|
||||
default: `<p>Please select the camera you would like to use.</p>`,
|
||||
},
|
||||
/** Is the function call asynchronous? */
|
||||
button_label: {
|
||||
type: ParameterType.STRING,
|
||||
default: "Use this camera",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
type Info = typeof info;
|
||||
|
||||
/**
|
||||
* **initialize-camera**
|
||||
*
|
||||
* jsPsych plugin for getting permission to initialize a camera
|
||||
*
|
||||
* @author Josh de Leeuw
|
||||
* @see {@link https://www.jspsych.org/plugins/jspsych-initialize-camera/ initialize-camera plugin documentation on jspsych.org}
|
||||
*/
|
||||
class InitializeCameraPlugin implements JsPsychPlugin<Info> {
|
||||
static info = info;
|
||||
|
||||
constructor(private jsPsych: JsPsych) {}
|
||||
|
||||
trial(display_element: HTMLElement, trial: TrialType<Info>) {
|
||||
this.run_trial(display_element, trial).then((id) => {
|
||||
this.jsPsych.finishTrial({
|
||||
device_id: id,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async run_trial(display_element: HTMLElement, trial: TrialType<Info>) {
|
||||
await this.askForPermission();
|
||||
|
||||
this.showCameraSelection(display_element, trial);
|
||||
|
||||
this.updateDeviceList(display_element);
|
||||
|
||||
navigator.mediaDevices.ondevicechange = (e) => {
|
||||
this.updateDeviceList(display_element);
|
||||
};
|
||||
|
||||
const mic_id = await this.waitForSelection(display_element);
|
||||
|
||||
const stream = await navigator.mediaDevices.getUserMedia({ video: { deviceId: mic_id } });
|
||||
|
||||
this.jsPsych.pluginAPI.initializeCameraRecorder(stream);
|
||||
|
||||
return mic_id;
|
||||
}
|
||||
|
||||
private async askForPermission() {
|
||||
const stream = await navigator.mediaDevices.getUserMedia({ audio: false, video: true });
|
||||
return stream;
|
||||
}
|
||||
|
||||
private showCameraSelection(display_element, trial: TrialType<Info>) {
|
||||
let html = `
|
||||
${trial.device_select_message}
|
||||
<select name="camera" id="which-camera" style="font-size:14px; font-family: 'Open Sans', 'Arial', sans-serif; padding: 4px;">
|
||||
</select>
|
||||
<p><button class="jspsych-btn" id="btn-select-camera">${trial.button_label}</button></p>`;
|
||||
display_element.innerHTML = html;
|
||||
}
|
||||
|
||||
private waitForSelection(display_element) {
|
||||
return new Promise((resolve) => {
|
||||
display_element.querySelector("#btn-select-camera").addEventListener("click", () => {
|
||||
const camera = display_element.querySelector("#which-camera").value;
|
||||
resolve(camera);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private updateDeviceList(display_element) {
|
||||
navigator.mediaDevices.enumerateDevices().then((devices) => {
|
||||
const mics = devices.filter(
|
||||
(d) =>
|
||||
d.kind === "videoinput" && d.deviceId !== "default" && d.deviceId !== "communications"
|
||||
);
|
||||
|
||||
// remove entries with duplicate groupID
|
||||
const unique_cameras = mics.filter(
|
||||
(mic, index, arr) => arr.findIndex((v) => v.groupId == mic.groupId) == index
|
||||
);
|
||||
|
||||
// reset the list by clearing all current options
|
||||
display_element.querySelector("#which-camera").innerHTML = "";
|
||||
|
||||
unique_cameras.forEach((d) => {
|
||||
let el = document.createElement("option");
|
||||
el.value = d.deviceId;
|
||||
el.innerHTML = d.label;
|
||||
|
||||
display_element.querySelector("#which-camera").appendChild(el);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default InitializeCameraPlugin;
|
7
packages/plugin-initialize-camera/tsconfig.json
Normal file
7
packages/plugin-initialize-camera/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "@jspsych/config/tsconfig.core.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "."
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
Loading…
Reference in New Issue
Block a user