๐Ÿ“š SDK Libraries

Complete guide to using the JavaScript/TypeScript SDK for the rPPG API.

๐Ÿ“š SDK Libraries

Complete guide to using the JavaScript/TypeScript SDK for the rPPG API.

Installation

npm install rppg-api-client
yarn add rppg-api-client
pnpm add rppg-api-client

Initialization

Basic Setup

import { RPPGClient } from 'rppg-api-client';

const client = new RPPGClient({
  apiKey: 'your-api-key',
  baseUrl: 'https://api.yourdomain.com/api'
});

With TypeScript

import { RPPGClient, type RPPGClientConfig, type VitalsData } from 'rppg-api-client';

const config: RPPGClientConfig = {
  apiKey: process.env.RPPG_API_KEY!,
  baseUrl: 'https://api.yourdomain.com/api',
  timeout: 60000,
  maxRetries: 3
};

const client = new RPPGClient(config);

Configuration Options

interface RPPGClientConfig {
  apiKey: string;           // Required: Your API key
  baseUrl: string;          // Required: API base URL
  timeout?: number;         // Optional: Request timeout in ms (default: 30000)
  maxRetries?: number;      // Optional: Max retry attempts (default: 3)
  retryDelay?: number;      // Optional: Initial retry delay in ms (default: 1000)
}

Core Methods

1. analyzeVideo()

The simplest way to analyze a video - handles session creation, upload, and polling automatically.

const vitals = await client.analyzeVideo(videoFile, {
  pollingInterval: 3000,  // Check every 3 seconds
  maxPollingTime: 120000  // Give up after 2 minutes
});

console.log('Heart Rate:', vitals.heart_rate);

Parameters:

  • videoFile (File | Blob): Video file to analyze
  • options (optional):
    • pollingInterval (number): Time between polls in ms (default: 3000)
    • maxPollingTime (number): Maximum polling duration in ms (default: 180000)

Returns: Promise<VitalsData>

Throws:

  • ValidationError: Invalid file size or format
  • ServerError: Processing failed
  • TimeoutError: Exceeded max polling time

2. createSession()

Create a new analysis session.

const session = await client.createSession();
console.log('Session ID:', session.session_id);
console.log('Created at:', session.created_at);

Returns: Promise<SessionData>

interface SessionData {
  session_id: string;
  created_at: string;
  owner: string;
}

3. uploadVideo()

Upload a video to an existing session.

const uploadResponse = await client.uploadVideo(sessionId, videoFile);
console.log('Status:', uploadResponse.status); // "processing"

Parameters:

  • sessionId (string): Session ID from createSession()
  • videoFile (File | Blob): Video to upload

Returns: Promise<UploadResponse>

interface UploadResponse {
  session_id: string;
  status: 'processing' | 'completed' | 'failed';
  message?: string;
}

4. getVitals()

Get current vitals for a session (single check, no polling).

const vitalsResponse = await client.getVitals(sessionId);

if (vitalsResponse.status === 'completed') {
  console.log('Heart Rate:', vitalsResponse.vitals.heart_rate);
} else if (vitalsResponse.status === 'processing') {
  console.log('Still processing...');
}

Returns: Promise<VitalsResponse>

interface VitalsResponse {
  status: 'pending' | 'processing' | 'completed' | 'failed';
  vitals?: VitalsData;
  error?: string;
}

5. waitForVitals()

Poll for vitals until processing completes.

const vitals = await client.waitForVitals(sessionId, {
  pollingInterval: 2000,
  maxPollingTime: 120000,
  onProgress: (attempt) => {
    console.log(`Polling attempt ${attempt}...`);
  }
});

Parameters:

  • sessionId (string): Session ID
  • options (optional):
    • pollingInterval (number): Time between polls (default: 3000ms)
    • maxPollingTime (number): Max wait time (default: 180000ms)
    • onProgress (function): Callback on each poll attempt

Returns: Promise<VitalsData>

Data Types

VitalsData

interface VitalsData {
  session_id: string;
  heart_rate: number;           // beats per minute
  respiratory_rate: number;     // breaths per minute
  hrv: number | null;           // heart rate variability
  blood_pressure: string | null; // systolic/diastolic
  confidence: number | null;    // 0-1 confidence score
  timestamp: string;            // ISO 8601 timestamp
  processing_time_ms: number;   // processing duration
}

Error Types

The SDK provides specific error classes:

import {
  RPPGError,
  AuthenticationError,
  ValidationError,
  RateLimitError,
  NotFoundError,
  ServerError,
  NetworkError
} from 'rppg-api-client';

try {
  await client.analyzeVideo(file);
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key');
  } else if (error instanceof ValidationError) {
    console.error('Invalid video file:', error.message);
  } else if (error instanceof RateLimitError) {
    console.error('Rate limit exceeded:', error.retryAfter);
  } else if (error instanceof NetworkError) {
    console.error('Network issue:', error.message);
  }
}

Advanced Usage

Manual Session Management

For more control over the process:

// Step 1: Create session
const session = await client.createSession();
const sessionId = session.session_id;

// Step 2: Upload video
await client.uploadVideo(sessionId, videoFile);

// Step 3: Poll for results
const vitals = await client.waitForVitals(sessionId, {
  onProgress: (attempt) => {
    updateUI(`Processing... (attempt ${attempt})`);
  }
});

// Step 4: Use results
displayVitals(vitals);

Custom Retry Logic

const client = new RPPGClient({
  apiKey: 'your-key',
  baseUrl: 'https://api.yourdomain.com/api',
  maxRetries: 5,        // Retry up to 5 times
  retryDelay: 2000,     // Start with 2 second delay
  timeout: 60000        // 60 second timeout per request
});

Progress Tracking

let progress = 0;
const totalSteps = 100;

const vitals = await client.analyzeVideo(videoFile, {
  pollingInterval: 3000,
  onProgress: (attempt) => {
    progress = Math.min(progress + 10, 90);
    updateProgressBar(progress);
  }
});

updateProgressBar(100); // Complete

Batch Processing

async function processBatch(videoFiles) {
  const results = await Promise.allSettled(
    videoFiles.map(file => client.analyzeVideo(file))
  );
  
  const successful = results.filter(r => r.status === 'fulfilled');
  const failed = results.filter(r => r.status === 'rejected');
  
  console.log(`Processed: ${successful.length}/${videoFiles.length}`);
  return successful.map(r => r.value);
}

Timeout Handling

try {
  const vitals = await client.analyzeVideo(videoFile, {
    maxPollingTime: 60000 // 1 minute max
  });
} catch (error) {
  if (error.message.includes('timeout')) {
    console.error('Processing took too long');
    // Retry with longer video or different settings
  }
}

Browser Usage

With React

import { RPPGClient } from 'rppg-api-client';
import { useState } from 'react';

function VideoAnalyzer() {
  const [vitals, setVitals] = useState(null);
  const [loading, setLoading] = useState(false);
  
  const client = new RPPGClient({
    apiKey: 'your-key',
    baseUrl: '/api' // Proxy through your backend
  });
  
  const handleFileUpload = async (file) => {
    setLoading(true);
    try {
      const results = await client.analyzeVideo(file);
      setVitals(results);
    } catch (error) {
      console.error('Analysis failed:', error);
    } finally {
      setLoading(false);
    }
  };
  
  return (
    <div>
      <input type="file" onChange={(e) => handleFileUpload(e.target.files[0])} />
      {loading && <p>Processing...</p>}
      {vitals && <p>Heart Rate: {vitals.heart_rate} bpm</p>}
    </div>
  );
}

With Vue

<template>
  <div>
    <input type="file" @change="handleUpload" />
    <div v-if="loading">Processing...</div>
    <div v-if="vitals">
      Heart Rate: {{ vitals.heart_rate }} bpm
    </div>
  </div>
</template>

<script>
import { RPPGClient } from 'rppg-api-client';

export default {
  data() {
    return {
      vitals: null,
      loading: false,
      client: new RPPGClient({
        apiKey: 'your-key',
        baseUrl: '/api'
      })
    };
  },
  methods: {
    async handleUpload(event) {
      const file = event.target.files[0];
      this.loading = true;
      
      try {
        this.vitals = await this.client.analyzeVideo(file);
      } catch (error) {
        console.error(error);
      } finally {
        this.loading = false;
      }
    }
  }
};
</script>

Node.js Usage

Express Server

const express = require('express');
const { RPPGClient } = require('rppg-api-client');
const multer = require('multer');

const app = express();
const upload = multer({ dest: 'uploads/' });

const client = new RPPGClient({
  apiKey: process.env.RPPG_API_KEY,
  baseUrl: 'https://api.yourdomain.com/api'
});

app.post('/analyze', upload.single('video'), async (req, res) => {
  try {
    const vitals = await client.analyzeVideo(req.file);
    res.json({ success: true, data: vitals });
  } catch (error) {
    res.status(500).json({ success: false, error: error.message });
  }
});

app.listen(3000);

Next Steps

Have questions? Contact us at support@circadify.com