Package Exports
- @cariva/asr-sdk-node
Readme
@cariva/asr-sdk-node
Professional medical transcription SDK for Node.js server applications
Overview
A professional Node.js SDK for medical speech recognition in server environments. Purpose-built for healthcare workflows with specialized medical vocabulary, file system integration, and secure processing.
Features
- Medical-First Design - SOAP notes, clinical records, and nursing documentation
- Server-Side Processing - File system integration with batch processing capabilities
- High Performance - Optimized audio compression and server-side processing
- Universal Audio Support - All major audio formats with automatic optimization
- Production Ready - Built for scalable server environments and enterprise workflows
- TypeScript Ready - Full type safety and comprehensive error handling
Installation
Package Manager
# 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 processing)
🚀 Quick Start
Basic Usage
import { ASR, type AsrResponseMap } from '@cariva/asr-sdk-node';
// Initialize with your credentials
const asr = new ASR({
key: process.env.CARIVA_API_KEY!, // Use environment variables
secret: process.env.CARIVA_API_SECRET!,
mode: 'doc-ipd-soap',
lang: 'en',
specialty: 'gen-practitioner', // Default specialty
});
// Process audio file from file system
const processAudioFile = async (audioPath: string) => {
try {
// Process with comprehensive callbacks
const result = await asr.process(audioPath, {
onProcessing: step => {
console.log(`Processing: ${step}`);
// Steps: "Creating transcription task..." -> "Uploading audio file..." -> "Processing audio..."
},
});
// Type-safe access to structured medical data
console.log('Medical data:', result);
return result;
} catch (error) {
console.error('ASR error:', error);
throw error;
}
};
// Example usage
await processAudioFile('./consultation-recording.wav');
Batch Processing
import fs from 'fs';
import path from 'path';
const processBatch = async (audioDir: string) => {
const audioFiles = fs
.readdirSync(audioDir)
.filter(file => /\.(mp3|wav)$/i.test(file))
.map(file => path.join(audioDir, file));
const results = [];
for (const filePath of audioFiles) {
console.log(`Processing: ${path.basename(filePath)}`);
try {
const result = await asr.process(filePath);
results.push({ file: filePath, result });
} catch (error) {
console.error(`Failed to process ${filePath}:`, error.message);
}
}
return results;
};
Server Integration
import express from 'express';
import multer from 'multer';
import { ASR } from '@cariva/asr-sdk-node';
const app = express();
const upload = multer({ dest: 'uploads/' });
// Initialize ASR for different specialties
const asrInstances = {
cardiology: new ASR({
key: process.env.CARIVA_API_KEY!,
secret: process.env.CARIVA_API_SECRET!,
mode: 'doc-ipd-soap',
specialty: 'med-cardio',
}),
general: new ASR({
key: process.env.CARIVA_API_KEY!,
secret: process.env.CARIVA_API_SECRET!,
mode: 'doc-ipd-soap',
specialty: 'gen-practitioner',
}),
};
app.post('/transcribe/:specialty', upload.single('audio'), async (req, res) => {
try {
const { specialty } = req.params;
const asr = asrInstances[specialty] || asrInstances.general;
const result = await asr.process(req.file.path);
res.json({ success: true, data: result });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
});
Medical Modes
The SDK provides specialized transcription modes optimized for different healthcare workflows:
📋 SOAP Notes (doc-ipd-soap)
Best for: Physician documentation, clinical assessments
const result: {
fastTranscription: string; // Raw speech-to-text transcription
subjective?: string; // Patient's reported symptoms and history
objective?: string; // Clinical findings and observations
assessment?: string; // Medical diagnosis and impressions
plan?: string; // Treatment plan and follow-up
} = await asr.process('./consultation.wav');
Use cases: Hospital rounds, consultation notes, diagnostic evaluations
🏥 OPD Clinical Record (doc-opd-clinicalrecord)
Best for: Outpatient consultations, comprehensive examinations
const result: {
chiefComplaint: string;
diagnosis: string;
familyHistory: string;
fastTranscription: string;
pastMedicalHistory: string;
physicalExamination: {
generalAppearance: string;
heent: string;
cardiovascular: string;
respiratory: string;
gastrointestinal: string;
neurological: string;
other: string;
vitalSign: string;
};
plan: string;
presentIllness: string;
rawNote: string;
treatment: string;
investigation: string;
} = await asr.process('./opd-consultation.wav');
Use cases: Outpatient visits, specialist consultations, routine check-ups
👩⚕️ Nursing Notes - Start of Shift (nur-opd-nursenote-start)
Best for: Beginning of shift assessments, patient handoffs
const result: {
focus: string;
assessment: string;
intervention: string;
fastTranscription: string;
rawNote: string;
vitalSigns: {
heartRate: string;
respiratoryRate: string;
bloodPressure: string;
bodyTemperature: string;
oxygenSaturation: string;
};
} = await asr.process('./nurse-start-shift.wav');
Use cases: Shift handoffs, initial patient assessments, care planning
👩⚕️ Nursing Notes - End of Shift (nur-opd-nursenote-end)
Best for: End of shift summaries, patient status updates
const result: {
evaluation: string;
fastTranscription: string;
rawNote: string;
vitalSigns: string;
} = await asr.process('./nurse-end-shift.wav');
Use cases: Shift summaries, patient status reports, care continuity
Medical Specialties
Improve transcription accuracy by up to 35% with specialty-specific medical vocabulary:
const cardiologyASR = new ASR({
key: process.env.CARIVA_API_KEY!,
secret: process.env.CARIVA_API_SECRET!,
mode: 'doc-ipd-soap',
specialty: 'med-cardio', // Optimized for cardiology terminology
});
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 |
Cardiovascular & Respiratory
Specialty | Code | Best For |
---|---|---|
Cardiology | med-cardio |
Cardiac procedures, heart conditions |
Pulmonology | med-pulmonary |
Respiratory conditions, lung function |
Gastroenterology & Specialties
Specialty | Code | Best For |
---|---|---|
Gastroenterology | med-gastro |
GI procedures, digestive disorders |
Neurology | med-neuro |
Neurological assessments, brain conditions |
Nephrology | med-nephro |
Kidney conditions, dialysis |
Oncology | med-onco |
Cancer treatment, oncology consultations |
Surgical & Other Specialties
Specialty | Code | Best For |
---|---|---|
General Surgery | surgery |
Surgical procedures, operative notes |
Orthopedic | orthopedic |
Bone, joint, and muscle conditions |
Dermatology | med-skin |
Skin conditions, dermatological procedures |
Ophthalmology | ophthalmology |
Eye conditions, vision care |
Otolaryngology | otolaryngology |
ENT procedures, hearing, speech |
Obstetrics & Gynecology | ob-gyn |
Women's health, pregnancy, childbirth |
💡 Pro Tip: Choose the most specific specialty for your use case to maximize transcription accuracy.
📖 API Reference
Constructor Options
interface ASRConfig {
key: string; // Required: Your Cariva API key
secret: string; // Required: Your Cariva API secret
mode: Mode; // Required: Transcription mode
lang?: string; // Optional: Language (default: 'en')
specialty?: MedicalSpecialty; // Optional: Medical specialty (default: 'gen-practitioner')
timeout?: number; // Optional: Request timeout in ms (default: 300000)
}
// Usage
const asr = new ASR({
key: process.env.CARIVA_API_KEY!,
secret: process.env.CARIVA_API_SECRET!,
mode: 'doc-ipd-soap',
lang: 'en',
specialty: 'med-cardio',
timeout: 300000, // 5 minutes
});
Process Method
async process(
filePath: string, // Path to audio file
options?: {
onProcessing?: (step: string) => void; // Processing callback
}
): Promise<AsrResponseMap[Mode]['data']>
Processing Options
interface ProcessOptions {
onProcessing?: (step: string) => void; // Optional: Processing step callback
}
// Processing steps you'll receive:
// - "Creating transcription task..."
// - "Uploading audio file..."
// - "Processing audio..."
Response Types
// Fully typed responses based on selected mode
type AsrResponseMap = {
'doc-ipd-soap': {
data: {
fastTranscription: string;
subjective?: string;
objective?: string;
assessment?: string;
plan?: string;
};
};
'doc-opd-clinicalrecord': {
data: {
chiefComplaint: string;
diagnosis: string;
familyHistory: string;
fastTranscription: string;
pastMedicalHistory: string;
physicalExamination: {
generalAppearance: string;
heent: string;
cardiovascular: string;
respiratory: string;
gastrointestinal: string;
neurological: string;
other: string;
vitalSign: string;
};
plan: string;
presentIllness: string;
rawNote: string;
treatment: string;
investigation: string;
};
};
// ... other modes
};
Instance Methods
// Main processing method
async process(file: string | File | Blob, options?: NodeProcessOptions): Promise<AsrResponseMap[Mode]['data']>
// Cancel ongoing transcription
async cancelASRTask(): Promise<void>
// Rate transcription quality (1-5 scale with optional comment)
async rateASRTask(score: number, comment?: string): Promise<void>
// Initialize ASR instance
async create(): Promise<this>
// Clear task state
clearTask(): void
// Getters for current state
readonly taskId: string // Current task ID (empty until processing starts)
readonly status: string // Current processing status
readonly isProcessing: boolean // Whether currently processing
Audio Support
Supported Formats
- Audio: WAV, MP3, MP4, M4A, OGG, AAC, FLAC
- File System: Direct file path processing
- Compression: Server-side optimization using node-lame
File Constraints
- Server-side audio compression reduces file size automatically
- Real-time progress tracking during upload
Audio Processing
// The SDK automatically handles:
// - Format validation
// - Audio compression (MP3 encoding)
// - Duration detection
// - Progress tracking
const result = await asr.process('./consultation.wav', {
onProcessing: step => {
console.log(`Processing: ${step}`);
// Steps: "Creating transcription task..." -> "Uploading audio file..." -> "Processing audio..."
},
});
Server Features
File System Integration
import fs from 'fs';
import path from 'path';
// Process multiple files
const audioDir = './recordings/';
const files = fs
.readdirSync(audioDir)
.filter(file => file.endsWith('.mp3') || file.endsWith('.wav') || file.endsWith('.m4a'));
for (const file of files) {
const filePath = path.join(audioDir, file);
console.log(`Processing: ${file}`);
try {
const result = await asr.process(filePath, {
onProcessing: step => console.log(`${file}: ${step}`),
});
// Save results
const outputPath = path.join('./results/', `${path.parse(file).name}.json`);
fs.writeFileSync(outputPath, JSON.stringify(result, null, 2));
} catch (error) {
console.error(`Failed to process ${file}:`, error.message);
}
}
File Metadata
import fs from 'fs';
// Get file information before processing
const audioPath = './consultation.wav';
const stats = fs.statSync(audioPath);
console.log(`File size: ${(stats.size / 1024 / 1024).toFixed(2)} MB`);
console.log(`Processing: ${audioPath}`);
const result = await asr.process(audioPath);
Usage Examples
ES Modules
import { ASR } from '@cariva/asr-sdk-node';
const asr = new ASR({
key: process.env.CARIVA_API_KEY!,
secret: process.env.CARIVA_API_SECRET!,
mode: 'doc-ipd-soap',
specialty: 'med-cardio',
});
CommonJS
const { ASR } = require('@cariva/asr-sdk-node');
const asr = new ASR({
key: process.env.CARIVA_API_KEY,
secret: process.env.CARIVA_API_SECRET,
mode: 'doc-ipd-soap',
specialty: 'gen-practitioner',
});
TypeScript
import { ASR, type AsrResponseMap } from '@cariva/asr-sdk-node';
const asr = new ASR({
key: process.env.CARIVA_API_KEY!,
secret: process.env.CARIVA_API_SECRET!,
mode: 'doc-ipd-soap',
specialty: 'med-cardio',
});
// Fully typed result
const result: AsrResponseMap['doc-ipd-soap']['data'] = await asr.process('./audio.wav');
Progress Tracking
Monitor the transcription process with detailed callbacks:
const result = await asr.process('./consultation.wav', {
onProcessing: step => {
// Processing steps
console.log(`Step: ${step}`);
// Possible steps:
// - "Creating transcription task..."
// - "Uploading audio file..."
// - "Processing audio..."
},
});
Error Handling
import { AsrError } from '@cariva/asr-sdk-node';
try {
const result = await asr.process('./audio.wav');
} catch (error) {
if (error instanceof AsrError) {
console.error(`ASR Error [${error.code}]:`, error.message);
console.error('Status:', error.status);
console.error('Details:', error.details);
// Handle specific error types
switch (error.code) {
case 'NETWORK_ERROR':
console.error('Check your internet connection');
break;
default:
console.error('Unexpected ASR error occurred');
}
} else {
console.error('Unexpected error:', error);
}
}
Common Error Codes
CREATE_TASK_FAILED
- Failed to create transcription taskUPLOAD_FAILED
- Audio upload failedUPLOAD_ABORTED
- Upload was cancelled or abortedTRANSCRIPTION_FAILED
- Audio processing failedGET_STATUS_FAILED
- Failed to retrieve task statusPROCESS_FAILED
- General processing failureNO_RESULT_DATA
- No transcription data availableRATING_FAILED
- Failed to submit ratingNO_TASK_ID
- No task ID available for operationNO_API_CLIENT
- API client not initializedNO_UPLOAD_METHOD
- No upload method availableNETWORK_ERROR
- Connection or network issuesCONSENT_REQUIRED
- Your account has not accepted the latest Terms and Conditions and/or Privacy Policy. Please log in at http://space.cariva.co.th to review and accept them to continue.INVALID_FILE_TYPE
- Unsupported audio formatENOENT
- File not foundVALIDATION_ERROR
- Invalid input parametersPROCESSING_ERROR
- Audio processing errorINVALID_SCORE
- Invalid rating score (must be 1-5)
Cancellation
Cancel long-running transcription tasks:
// Start transcription
const transcriptionPromise = asr.process('./long-audio.wav');
// Cancel after 5 minutes using instance method
const timeoutId = setTimeout(
async () => {
await asr.cancelASRTask();
console.log('Transcription cancelled due to timeout');
},
5 * 60 * 1000
);
try {
const result = await transcriptionPromise;
clearTimeout(timeoutId);
console.log('Transcription completed:', result);
} catch (error) {
clearTimeout(timeoutId);
console.error('Transcription failed or was cancelled:', error.message);
}
Rating Transcriptions
Rate transcription quality to help improve the service:
// Rate transcription quality (1-5 scale)
await asr.rateASRTask(5, 'Excellent medical transcription accuracy!');
// Rate with just a score
await asr.rateASRTask(4);
// Rate with detailed feedback
await asr.rateASRTask(3, 'Good overall, but missed some medical terminology');
Rating Guidelines
- 5 Stars: Perfect transcription, no errors
- 4 Stars: Minor errors, easily corrected
- 3 Stars: Some errors, but mostly accurate
- 2 Stars: Multiple errors, needs significant correction
- 1 Star: Poor quality, major errors throughout
Complete Example
Medical Transcription Service
import { ASR } from '@cariva/asr-sdk-node';
import fs from 'fs/promises';
import path from 'path';
class MedicalTranscriptionService {
private asrInstances: Record<string, ASR> = {};
constructor() {
// Initialize different ASR instances for different specialties
this.asrInstances = {
cardiology: new ASR({
key: process.env.CARIVA_API_KEY!,
secret: process.env.CARIVA_API_SECRET!,
mode: 'doc-ipd-soap',
specialty: 'med-cardio',
}),
pulmonology: new ASR({
key: process.env.CARIVA_API_KEY!,
secret: process.env.CARIVA_API_SECRET!,
mode: 'doc-ipd-soap',
specialty: 'med-pulmonary',
}),
general: new ASR({
key: process.env.CARIVA_API_KEY!,
secret: process.env.CARIVA_API_SECRET!,
mode: 'doc-ipd-soap',
specialty: 'gen-practitioner',
}),
};
}
async processConsultation(audioPath: string, specialty: string = 'general') {
const asr = this.asrInstances[specialty] || this.asrInstances.general;
console.log(`Processing consultation audio: ${path.basename(audioPath)}`);
console.log(`Using specialty: ${specialty}`);
const result = await asr.process(audioPath, {
onProcessing: step => {
console.log(`📋 ${step}`);
},
});
// Generate comprehensive report
const report = {
timestamp: new Date().toISOString(),
audioFile: path.basename(audioPath),
specialty: specialty,
transcription: result,
};
// Save to file
const reportPath = `./reports/${path.parse(audioPath).name}-${specialty}-report.json`;
await fs.writeFile(reportPath, JSON.stringify(report, null, 2));
console.log(`✅ Report saved: ${reportPath}`);
return report;
}
async processBatch(audioDir: string, specialty: string = 'general') {
const files = await fs.readdir(audioDir);
const audioFiles = files.filter(file => /\.(wav|mp3|m4a)$/i.test(file));
console.log(`📁 Found ${audioFiles.length} audio files to process`);
const results = [];
for (const file of audioFiles) {
const filePath = path.join(audioDir, file);
try {
const result = await this.processConsultation(filePath, specialty);
results.push(result);
} catch (error) {
console.error(`❌ Failed to process ${file}:`, error.message);
}
}
return results;
}
}
// Usage
const service = new MedicalTranscriptionService();
// Process single file
await service.processConsultation('./recordings/cardiology-consult.wav', 'cardiology');
// Process batch
await service.processBatch('./recordings/', 'general');
Express.js API Server
import express from 'express';
import multer from 'multer';
import { ASR } from '@cariva/asr-sdk-node';
const app = express();
const upload = multer({ dest: 'uploads/' });
// Configure ASR instances for different specialties
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' }),
};
app.post('/api/transcribe/:specialty?', upload.single('audio'), async (req, res) => {
try {
const specialty = req.params.specialty || 'general';
const asr = asrInstances[specialty] || asrInstances.general;
if (!req.file) {
return res.status(400).json({
success: false,
error: 'No audio file provided',
});
}
console.log(`Processing ${req.file.originalname} with ${specialty} specialty`);
const result = await asr.process(req.file.path, {
onProcessing: step => {
console.log(`[${req.file.originalname}] ${step}`);
},
});
// Clean up uploaded file
await fs.unlink(req.file.path);
res.json({
success: true,
data: {
filename: req.file.originalname,
specialty: specialty,
transcription: result,
processedAt: new Date().toISOString(),
},
});
} catch (error) {
console.error('Transcription error:', error);
res.status(500).json({
success: false,
error: error.message,
});
}
});
app.listen(3000, () => {
console.log('🎙️ Medical transcription API server running on port 3000');
});
Node.js Compatibility
Node.js Version | Support Status | Notes |
---|---|---|
20.x | ✅ Full Support | Recommended LTS (minimum) |
21.x | ✅ Full Support | Current release |
22.x | ✅ Full Support | Latest release |
18.x | ❌ Not Supported | Upgrade to Node 20+ required |
16.x | ❌ Not Supported | End of life, upgrade required |
Requirements
Runtime Requirements
- Node.js: 20+ (ES2020+ support with modules)
- File System: For handling file uploads and processing
- Network: For API requests to Cariva services
- Memory: Sufficient RAM for audio file processing
Development Requirements
- TypeScript: 4.9+ (for type checking)
- Build Tools: Compatible with ES modules and CommonJS
Production Requirements
- Process Management: PM2, Docker, or similar for production deployment
- Error Monitoring: Recommended for production applications
- Log Management: Structured logging for troubleshooting
💡 Examples
Additional examples and integrations:
- Express.js Integration - Complete REST API server
- Microservice Architecture - Docker containerized service
- Batch Processing Scripts - Command-line batch processors
- Database Integration - Store results in MongoDB/PostgreSQL
- Queue Processing - Redis/Bull queue integration
Related Packages
Package | Purpose |
---|---|
@cariva/asr-sdk-browser | Browser client-side processing |
🆘 Support
For technical support and inquiries, please visit our Contact Page.
Contributing
We welcome contributions! When reporting issues, please include:
- Node.js version and OS
- File size and type
- Error messages and stack traces
- 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.