npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cariva/asr-sdk-node

v1.6.0

Published

Node.js SDK for Cariva ASR

Readme

@cariva/asr-sdk-node

npm version License Downloads Bundle Size TypeScript Node.js

Professional medical transcription SDK for Node.js server applications

🚀 Quick Start📖 API Reference💡 Examples🆘 Support

Overview

A professional Node.js SDK for medical speech recognition in server environments. Purpose-built for healthcare workflows with specialized medical vocabulary, server-side audio compression, and secure API communication.

Features

  • Medical-First Design — SOAP notes, clinical records, and nursing documentation
  • Server-Side Audio Processing — Automatic MP3 compression via node-lame
  • Dual Authentication — API key+secret (HMAC) or access token (Bearer)
  • Universal Audio Support — WAV, MP3, MP4, M4A, OGG, AAC, FLAC with automatic optimization
  • Custom Payload Extension — Pass arbitrary fields to the API via taskPayload
  • TypeScript Ready — Full type safety and comprehensive error handling

Installation

# npm
npm install @cariva/asr-sdk-node

# yarn
yarn add @cariva/asr-sdk-node

# pnpm
pnpm add @cariva/asr-sdk-node

# bun
bun add @cariva/asr-sdk-node

Requirements

  • Node.js: >= 20.0.0
  • FFmpeg: Optional (for advanced audio format support)

🚀 Quick Start

Authentication

The SDK supports two mutually exclusive authentication methods:

import { ASR } from '@cariva/asr-sdk-node';

// Option A: API Key + Secret (HMAC)
const asr = new ASR({
  key: process.env.CARIVA_API_KEY!,
  secret: process.env.CARIVA_API_SECRET!,
  mode: 'doc-ipd-soap',
});

// Option B: Access Token (Bearer)
const asr = new ASR({
  accessToken: process.env.CARIVA_ACCESS_TOKEN!,
  mode: 'doc-ipd-soap',
});

Basic Usage

The process() method accepts a File or Blob. Load audio from disk using fs/promises:

import { ASR } from '@cariva/asr-sdk-node';
import { readFile } from 'fs/promises';

const asr = new ASR({
  key: process.env.CARIVA_API_KEY!,
  secret: process.env.CARIVA_API_SECRET!,
  mode: 'doc-ipd-soap',
  specialty: 'gen-practitioner',
});

const buffer = await readFile('./consultation.wav');
const file = new File([buffer], 'consultation.wav', { type: 'audio/wav' });

const result = await asr.process(file, {
  onProcessing: step => console.log(`Processing: ${step}`),
  // Steps: "Creating transcription task..." → "Uploading audio file..." → "Processing audio..."
});

console.log(result.data?.fastTranscription);
console.log(result.data?.subjective);

Batch Processing

import { ASR, ASRError } from '@cariva/asr-sdk-node';
import { readdir, readFile } from 'fs/promises';
import path from 'path';

const asr = new ASR({
  key: process.env.CARIVA_API_KEY!,
  secret: process.env.CARIVA_API_SECRET!,
  mode: 'doc-ipd-soap',
});

const audioDir = './recordings/';
const files = (await readdir(audioDir)).filter(f => /\.(wav|mp3|m4a)$/i.test(f));

for (const fileName of files) {
  try {
    const buffer = await readFile(path.join(audioDir, fileName));
    const file = new File([buffer], fileName, { type: 'audio/mpeg' });

    const result = await asr.process(file, {
      onProcessing: step => console.log(`[${fileName}] ${step}`),
    });

    console.log(`✅ ${fileName}:`, result.data?.fastTranscription);
  } catch (error) {
    console.error(`❌ ${fileName}:`, (error as Error).message);
  }
}

Server Integration

import express from 'express';
import multer from 'multer';
import { ASR } from '@cariva/asr-sdk-node';

const app = express();
const upload = multer({ storage: multer.memoryStorage() });

const asr = new ASR({
  key: process.env.CARIVA_API_KEY!,
  secret: process.env.CARIVA_API_SECRET!,
  mode: 'doc-ipd-soap',
  specialty: 'med-cardio',
});

app.post('/transcribe', upload.single('audio'), async (req, res) => {
  if (!req.file) return res.status(400).json({ error: 'No audio file provided' });

  const blob = new Blob([req.file.buffer], { type: req.file.mimetype });
  const result = await asr.process(blob);

  res.json({ success: true, data: result.data });
});

Medical Modes

Best for: Physician documentation, inpatient notes, clinical assessments

const asr = new ASR({ /* config */ mode: 'doc-ipd-soap' });
const result = await asr.process(file);

interface SoapData {
  fastTranscription: string; // raw speech-to-text
  subjective?: string; // patient symptoms and history
  objective?: string; // clinical findings
  assessment?: string; // diagnosis and impressions
  plan?: string; // treatment and follow-up
}

Alias: 'soap'

Best for: Outpatient consultations, comprehensive examinations

interface OpdClinicalRecordData {
  fastTranscription: string;
  chiefComplaint: string;
  presentIllness: string;
  pastMedicalHistory: string;
  familyHistory: string;
  personalHistory?: string;
  currentMedication?: string;
  physicalExamination: {
    generalAppearance: string;
    heent: string;
    cardiovascular: string;
    respiratory: string;
    gastrointestinal: string;
    neurological: string;
    other: string;
    vitalSign: string;
  };
  diagnosis: string;
  investigation: string;
  treatment: string;
  plan: string;
  recommendation?: string;
  rawNote: string;
}

Alias: 'medclerk'

Both nur-opd-nursenote-* and nur-opd-nursenote-faie-* map to the same API endpoint and return the same data.

Start of shiftnur-opd-nursenote-start / nur-opd-nursenote-faie-start

interface NurseNoteStartData {
  fastTranscription: string;
  rawNote: string;
  focus: string;
  assessment: string;
  intervention: string;
  vitalSigns: {
    heartRate: string;
    respiratoryRate: string;
    bloodPressure: string;
    bodyTemperature: string;
    oxygenSaturation: string;
  };
}

End of shiftnur-opd-nursenote-end / nur-opd-nursenote-faie-end

interface NurseNoteEndData {
  fastTranscription: string;
  rawNote: string;
  evaluation: string;
  vitalSigns: {
    heartRate: string;
    respiratoryRate: string;
    bloodPressure: string;
    bodyTemperature: string;
    oxygenSaturation: string;
  };
}

Start of shiftnur-opd-nursenote-adpie-start

interface NurseNoteAdpieStartData {
  fastTranscription: string;
  rawNote: string;
  assessment: {
    objective: string;
    subjective: string;
  };
  diagnosis: string;
  planning: string;
  intervention: string;
}

End of shiftnur-opd-nursenote-adpie-end

interface NurseNoteAdpieEndData {
  fastTranscription: string;
  rawNote: string;
  evaluation: string;
}

Medical Specialties

Improve transcription accuracy with specialty-specific vocabulary:

Primary Care & General Medicine

| Specialty | Code | Best For | | ------------------------ | ------------------ | ------------------------------------ | | General Practitioner | gen-practitioner | Family medicine, routine checkups | | General Medicine | gen-med | Internal medicine, hospitalist notes | | Emergency Medicine | emergency | Trauma, urgent care, triage | | General Pediatrics | gen-ped | Children's healthcare |

Medical Specialties

| Specialty | Code | Best For | | --------------------------- | ---------------- | ----------------------------------------- | | Cardiology | med-cardio | Cardiac procedures, heart conditions | | Pulmonology | med-pulmonary | Respiratory conditions, lung function | | Gastroenterology | med-gastro | GI procedures, digestive disorders | | Neurology | med-neuro | Neurological assessments | | Nephrology | med-nephro | Kidney conditions, dialysis | | Oncology | med-onco | Cancer treatment, oncology consultations | | Endocrinology | med-endo | Diabetes, hormonal disorders | | Allergy & Immunology | med-allergy | Allergic reactions, immunotherapy | | Dermatology | med-skin | Skin conditions | | Ophthalmology | ophthalmology | Eye conditions | | Otolaryngology | otolaryngology | ENT procedures | | Obstetrics & Gynecology | ob-gyn | Women's health, pregnancy | | General Surgery | surgery | Surgical procedures, operative notes | | Orthopedic | orthopedic | Bone, joint, and muscle conditions | | Other | other | Uncommon specialties or mixed terminology |

📖 API Reference

ASRConfig

| Field | Type | Required | Default | Description | | --------------- | ------------------------- | --------------------- | ------------------------------ | ----------------------------------------------------------------------------- | | key | string | ✓ (or accessToken) | — | API key for HMAC authentication | | secret | string | ✓ (or accessToken) | — | API secret for HMAC authentication | | accessToken | string | ✓ (or key+secret) | — | Bearer token authentication | | mode | Mode | ✓ | — | Transcription mode | | lang | string | — | 'en' | Language hint | | specialty | string | — | 'gen-practitioner' | Medical specialty code | | newLineString | string | — | undefined | Replace newlines in output | | prefix | string | — | undefined | Text prefix for the result | | suggestion | boolean | — | undefined | Enable suggestion mode | | timeout | number | — | 300000 | Request timeout in ms | | baseUrl | string | — | CARIVA_BASE_URL (build-time) | Override API base URL; runtime value takes precedence over build-time env var | | taskPayload | Record<string, unknown> | — | undefined | Extra fields merged into every create-task request |

Provide either (key + secret) or accessToken — not both.

NodeProcessOptions

| Field | Type | Description | | --------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------- | | lang | string | Override language for this call | | specialty | string | Override specialty for this call | | newLineString | string | Override newline replacement for this call | | prefix | string | Override prefix for this call | | suggestion | boolean | Override suggestion mode for this call | | taskPayload | Record<string, unknown> | Extra fields for this call (merged with config-level, call wins on conflict) | | onProgress | (p: { percentage: number, loaded: number, total: number }) => void | Upload progress callback | | onProcessing | (step: string) => void | Processing step callback |

Instance Methods

| Method | Signature | Description | | --------------- | ----------------------------------------------------------------------------------- | --------------------------------------------- | | process | (file: File \| Blob, options?: NodeProcessOptions) => Promise<TaskStatusResponse> | Transcribe an audio file | | cancelASRTask | () => Promise<void> | Cancel the current task | | rateASRTask | (score: number, comment?: string, categories?: string[]) => Promise<void> | Rate quality (score: 1–5) | | create | () => Promise<this> | Reset instance for a new task | | cleanup | () => Promise<void> | Release resources and cancel the current task |

Getters

| Getter | Type | Description | | -------------- | --------- | ----------------------------------------------- | | taskId | string | Current task ID (empty until processing starts) | | status | string | Current task status | | isProcessing | boolean | Whether the instance is currently processing |

TaskStatusResponse

interface TaskStatusResponse {
  taskId: string;
  status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'CANCELLED';
  data?: {
    fastTranscription?: string;
    [key: string]: any; // mode-specific fields (subjective, objective, focus, etc.)
  };
  error?: string;
  progress?: number;
  createdAt?: string;
  updatedAt?: string;
  completedAt?: string;
}

Exported Types

import {
  ASR,
  type ASRConfig,
  type NodeProcessOptions,
  type ProcessingCallbacks,
  type Mode,
  type UploadProgress,
  type TaskStatusResponse,
  ASRError,
  ASRValidationError,
  ASRProcessingError,
} from '@cariva/asr-sdk-node';

Custom Task Payload (taskPayload)

Pass arbitrary extra fields to the create-task API request. The SDK forwards them as-is without validation or transformation.

// Config-level: applied to every process() call
const asr = new ASR({
  accessToken: process.env.CARIVA_ACCESS_TOKEN!,
  mode: 'doc-ipd-soap',
  taskPayload: {
    patientId: 'P-001',
    wardCode: 'WARD-A',
  },
});

// Per-call: merged with config-level (call wins on conflict)
const result = await asr.process(file, {
  taskPayload: { encounterId: 'ENC-2026-XYZ' },
  // Final body includes: patientId, wardCode (config) + encounterId (call)
});

SDK-controlled fields (mode, sdkVersion, voiceDuration, etc.) always take precedence over any key in taskPayload.

Progress Tracking

const result = await asr.process(file, {
  onProgress: ({ percentage, loaded, total }) => {
    console.log(`Upload: ${percentage}% (${loaded}/${total} bytes)`);
  },
  onProcessing: step => {
    // "Creating transcription task..."
    // "Uploading audio file..."
    // "Processing audio..."
    console.log(step);
  },
});

Error Handling

import { ASRError, ASRValidationError, ASRProcessingError } from '@cariva/asr-sdk-node';

try {
  const result = await asr.process(file);
} catch (error) {
  if (error instanceof ASRValidationError) {
    // Invalid configuration or input (e.g. missing credentials, invalid file type)
    console.error('Validation error:', error.message);
  } else if (error instanceof ASRProcessingError) {
    // Audio processing pipeline failure
    console.error('Processing error:', error.message);
  } else if (error instanceof ASRError) {
    // API or network error
    console.error(`[${error.code}] ${error.message}`);
  }
}

Error Classes

| Class | Code | When thrown | | -------------------- | ------------------- | ---------------------------------- | | ASRValidationError | VALIDATION_ERROR | Invalid config or input parameters | | ASRProcessingError | PROCESSING_ERROR | Audio processing pipeline failure | | ASRError | (see table below) | API, network, and runtime errors |

ASRError Codes

| Code | Description | | ---------------------- | -------------------------------------------------------------------------------------------------- | | CREATE_TASK_FAILED | Failed to create transcription task | | UPLOAD_FAILED | Audio upload to signed URL failed | | UPLOAD_ABORTED | Upload was cancelled | | TRANSCRIPTION_FAILED | Audio processing failed on the server | | GET_STATUS_FAILED | Failed to retrieve task status | | PROCESS_FAILED | General processing failure | | PROCESSING_TIMED_OUT | Processing exceeded the configured timeout | | NO_RESULT_DATA | Task completed but returned no data | | RATING_FAILED | Failed to submit rating | | NO_TASK_ID | No task ID available for the operation | | NO_API_CLIENT | API client not initialized | | NO_UPLOAD_METHOD | No upload method available in the runtime | | NETWORK_ERROR | Network or connection failure during upload | | CONSENT_REQUIRED | Account must accept Terms & Conditions — log in at space.cariva.co.th | | INVALID_SCORE | Rating score must be between 1 and 5 |

Cancellation

const transcriptionPromise = asr.process(file);

// Cancel after 5 minutes
const timeoutId = setTimeout(
  async () => {
    await asr.cancelASRTask();
    console.log('Cancelled due to timeout');
  },
  5 * 60 * 1000
);

try {
  const result = await transcriptionPromise;
  clearTimeout(timeoutId);
} catch (error) {
  clearTimeout(timeoutId);
  console.error('Failed or cancelled:', (error as Error).message);
}

Rating Transcriptions

// Rate after process() completes (score: 1–5)
await asr.rateASRTask(5, 'Excellent medical transcription accuracy!');

// With categories
await asr.rateASRTask(4, 'Good overall', ['medical-terminology', 'accuracy']);

// Score only
await asr.rateASRTask(3);

| Stars | Meaning | | ---------- | --------------------------------------------- | | ⭐⭐⭐⭐⭐ | Perfect — no errors | | ⭐⭐⭐⭐ | Minor errors, easily corrected | | ⭐⭐⭐ | Some errors, mostly accurate | | ⭐⭐ | Multiple errors, needs significant correction | | ⭐ | Poor quality, major errors throughout |

💡 Examples

Express.js API Server

import express from 'express';
import multer from 'multer';
import { ASR, ASRError } from '@cariva/asr-sdk-node';

const app = express();
const upload = multer({ storage: multer.memoryStorage() });

const asrConfig = {
  key: process.env.CARIVA_API_KEY!,
  secret: process.env.CARIVA_API_SECRET!,
  mode: 'doc-ipd-soap' as const,
};

const asrInstances = {
  cardiology: new ASR({ ...asrConfig, specialty: 'med-cardio' }),
  pulmonology: new ASR({ ...asrConfig, specialty: 'med-pulmonary' }),
  general: new ASR({ ...asrConfig, specialty: 'gen-practitioner' }),
};

type Specialty = keyof typeof asrInstances;

app.post('/api/transcribe/:specialty?', upload.single('audio'), async (req, res) => {
  const specialty = (req.params.specialty as Specialty) || 'general';
  const asr = asrInstances[specialty] ?? asrInstances.general;

  if (!req.file) {
    return res.status(400).json({ success: false, error: 'No audio file provided' });
  }

  try {
    const blob = new Blob([req.file.buffer], { type: req.file.mimetype });
    const result = await asr.process(blob, {
      onProcessing: step => console.log(`[${req.file!.originalname}] ${step}`),
    });

    res.json({ success: true, taskId: result.taskId, data: result.data });
  } catch (error) {
    if (error instanceof ASRError) {
      res.status(500).json({ success: false, code: error.code, error: error.message });
    } else {
      res.status(500).json({ success: false, error: 'Unexpected error' });
    }
  }
});

app.listen(3000, () => console.log('Medical transcription server running on port 3000'));

CommonJS

const { ASR } = require('@cariva/asr-sdk-node');
const { readFile } = require('fs/promises');

const asr = new ASR({
  key: process.env.CARIVA_API_KEY,
  secret: process.env.CARIVA_API_SECRET,
  mode: 'doc-ipd-soap',
  specialty: 'gen-practitioner',
});

async function transcribe(filePath) {
  const buffer = await readFile(filePath);
  const file = new File([buffer], 'audio.wav', { type: 'audio/wav' });
  return asr.process(file);
}

Node.js Compatibility

| Node.js Version | Support | | ----------------- | -------------------------------------- | | 20.x | ✅ Minimum supported (LTS recommended) | | 22.x | ✅ Full support | | 18.x or older | ❌ Not supported — upgrade required |

Related Packages

| Package | Purpose | | ------------------------------------------------------------------------------------ | ------------------------------ | | @cariva/asr-sdk-browser | Browser client-side processing |

🆘 Support

For technical support and inquiries, please visit our Contact Page.

Contributing

When reporting issues, please include:

  • Node.js version and OS
  • File format and size
  • Error message and stack trace
  • Steps to reproduce

License

This project is licensed under the Apache License 2.0.

Copyright 2025 Cariva

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.