Skip to main content

Migrating from WebGazer

Parameter and data field names match WebGazer's wherever the concept is the same, so most of a migration is search and replace.

The mapping

WebGazersaccade.js
@jspsych/extension-webgazer@saccadejs/extension
jsPsychExtensionWebgazerjsPsychExtensionSaccade
jsPsych.extensions.webgazerjsPsych.extensions.saccade
@jspsych/plugin-webgazer-init-camera@saccadejs/plugin-preview
jsPsychWebgazerInitCamerajsPsychSaccadePreview
@jspsych/plugin-webgazer-calibrate@saccadejs/plugin-calibrate
jsPsychWebgazerCalibratejsPsychSaccadeCalibrate
@jspsych/plugin-webgazer-validate@saccadejs/plugin-validate
jsPsychWebgazerValidatejsPsychSaccadeValidate
the webgazer.js script tagthe @saccadejs/core script tag
webgazer_datasaccade_data
webgazer_targetssaccade_targets
sampling_interval(removed: one sample per camera frame, no resampling)
startMouseCalibration()(removed: use calibration_mode: "click")
showFaceOverlay(), showFaceFeedbackBox()(removed: the preview plugin shows the eye crop instead)
stop()pause(), or getTracker().stop()

Everything else on the extension keeps its WebGazer name and meaning: start(), pause(), resume(), isInitialized(), faceDetected(), showVideo(), hideVideo(), showPredictions(), hidePredictions(), resetCalibration(), calibratePoint(), getCurrentPrediction(), onGazeUpdate().

Plugin parameters carry over too: instructions, button_text, calibration_points, calibration_mode, repetitions_per_point, randomize_calibration_order, time_to_saccade, time_per_point, validation_points, validation_point_coordinates, roi_radius, randomize_validation_order, validation_duration, point_size, show_validation_data. Validation data keeps raw_gaze, percent_in_roi, average_offset, validation_points and samples_per_sec.

Then add one trial with no WebGazer equivalent:

timeline.push({ type: jsPsychSaccadeTimeSync });   // after preview, before calibration

The real differences

  • Calibration is fitted once, not trained incrementally. No gaze estimate exists until the fit runs. If you call calibratePoint() yourself, you must then call fitCalibration(); saccade-calibrate does it for you.
  • No mouse-movement calibration. WebGazer can keep learning from the cursor throughout an experiment, which makes early and late trials incomparable. saccade.js does not.
  • A face is required for a sample. WebGazer predicts continuously. saccade.js emits a row only for frames in which a face was found, so gaps in saccade_data are meaningful.
  • A 20 MB model download on a participant's first visit, cached afterwards. See Hosting the assets.
  • Corrected timestamps. WebGazer's t comes from when JavaScript received the frame. saccade.js uses the camera's own capture stamp with the measured display and camera lag subtracted. See Timing and synchrony.

New things worth knowing about

NameWhat it is
tta (extension, default 5)Frames averaged per estimate. Set 1 for gaze-contingent designs.
assets (extension)Model and runtime URLs, for self-hosting.
tracker (extension)Pass a pre-built SaccadeTracker instead of letting the extension construct one. Replaces WebGazer's webgazer parameter.
saccade_timing (trial data)What timing correction was applied, and how healthy the camera was.
median_error_px, median_error_viewport (validation data)Headline accuracy numbers.
calibration_points_px (calibration data)The points shown, in pixels. The calibration_points parameter stays in percent.
fitCalibration(), getCalibrationPoints(), getBackend(), getTracker()Extension methods with no WebGazer equivalent.
getTimingOffset(), setTimingOffset(), getLastLoopback()The timing correction, exposed.

Analysis code that hit-tests samples against target rectangles needs nothing beyond the field rename.