Skip to main content

Activity Recording

Once camera and subject calibration are complete, you're ready to record movement activities. Once processing is done, you can retrieve raw data like joint angles, marker data, or videos.

Note: Camera positions must remain fixed after calibration. If you need to reposition cameras, you'll need to recalibrate.

Before You Record​

An account has a plan, and a plan has a limit. usage says whether recording is allowed right now, and why it isn't when it isn't — check it before you offer the button rather than letting the recording fail.

let usage = try await client.usage()
guard usage.recordingAllowed else {
print("Recording blocked: \(usage.reason.map(String.init(describing:)) ?? "no active plan")")
return
}

reason is one of noActivePlan, periodExpired, limitReached or paymentFailed, and is empty while recording is allowed.

The rest describes the plan itself, for a usage bar or a renewal notice:

activitiesUsed / activitiesMaxActivities recorded and allowed this period
periodEndWhen the current period ends
planNameThe plan's name
isFreeTrialWhether this is a free trial
resetPeriodmonthly or annually
willAutoRenewWhether the subscription renews itself

Every one of them is empty when there's no active plan. activitiesMax empty while a plan is active means something different: no limit at all.

Recording​

Start Recording​

Pass any descriptive string as the activity name — use something that helps identify the attempt later (e.g. cmj, squat, cut).

let activity = try await client.startRecording(activityNamed: "cmj", in: session)

Record and Auto-Launch Advanced Analysis​

To have advanced analysis launch automatically once processing completes, pass an activity type when starting the recording. This skips the manual startAnalysis call described in Activity Analysis.

let activity = try await client.startRecording(
activityNamed: "cmj",
in: session,
config: ActivityConfig(activityType: .counterMovementJump)
)

When processing completes, the activity status transitions to .analyzing instead of .ready. See Checking Processing Status below for how to handle this state.

During Recording​

  • The subject performs the movement
  • Ensure the subject remains within the field of view of at least two cameras
  • See the documentation for activity-specific recommendations

Stop Recording​

try await client.stopRecording(session)

Checking Processing Status​

After stopping, videos are uploaded and processed automatically. Processing may take some time (2-5 minutes), so you can check the status periodically.

let status = try await client.activityStatus(for: activity)

switch status {
case .uploading(let uploaded, let total):
print("Uploading: \(uploaded)/\(total) videos")
case .processing:
print("Processing video...")
case .ready:
print("Ready for analysis!")
case .analyzing(let task):
// Analysis was triggered automatically — pass task to analysisStatus
print("Analysis in progress: \(task.id)")
case .failed:
print("Processing failed")
}

Retrieving motion data​

Once the activity status is ready, you can retrieve the motion data, including joint kinematics, marker trajectories and videos.

If a built-in analysis module is available for your activity, you can also retrieve analysis results (e.g., metrics and reports) — either by launching analysis manually, or if you passed an activity type at recording time, analysis may already be in progress. See Activity Analysis for details.

// Download kinematics (MOT format) and marker trajectories (TRC format)
let resultData = await client.motionData(
ofType: [.kinematics(.mot), .markers(.trc)],
for: activity
)

for result in resultData {
switch result.type {
case .kinematics(.mot):
// result.data contains the kinematics file in OpenSim MOT format
print("Kinematics MOT: \(result.data.count) bytes")
case .markers(.trc):
// result.data contains the marker trajectories in TRC format
print("Markers TRC: \(result.data.count) bytes")
default:
break
}
}

// Download raw videos
let videos = await client.videos(for: activity, version: .raw)
print("Downloaded \(videos.count) video(s)")

Tips​

  • Clothing: Wear fitted clothing with good contrast to improve accuracy
  • Background: Use a plain, uncluttered background for better results.
  • Duration: Record only what you need — typically 5-30 seconds — to ensure fast upload and processing

See our Best Practices Guide for more details.

Troubleshooting​

Trial trimmed too short or failed:

  • Camera fields of view may not overlap sufficiently—reposition cameras so at least two capture the subject throughout the activity
  • If the subject is visible for less than 2 seconds, the trial may fail

Inaccurate kinematics:

  • Segment occlusion: Each body segment must be visible by at least 2 cameras at all times — reposition and recalibrate if needed
  • Camera angles too similar: Aim for 40-90° separation between cameras
  • Subject too far from cameras: Move the subject closer if possible
  • Poor contrast: Improve clothing and background contrast, especially at the feet
  • Camera sync issues: Have the subject perform a sync punch at the start of the trial
  • Bad camera calibration: Recalibrate the cameras if necessary.

See our Troubleshooting and Activity-Specific Recommendations guides for more help.

Next Steps​

When the activity is ready — or already analyzing — proceed to Activity Analysis.

If you have another subject to capture with the same camera setup, see Recording Multiple Subjects instead of repeating camera calibration.