@supadata/media-probe
v0.1.2
Published
Lightweight library for probing remote media assets to get their content type and size
Maintainers
Readme
@supadata/media-probe
Lightweight library for probing remote media assets to get their content type and size efficiently.
Features
- 🚀 Efficient: Uses HTTP Range requests (1 byte) when possible
- 🔄 Smart Fallbacks: Range → HEAD → GET
- 📦 Zero Dependencies: Pure TypeScript, native
fetch - 🎯 Type-Safe: Full TypeScript support
- 🔁 Retry Logic: Built-in exponential backoff
- 🎬 Media Detection: Automatic video/audio detection
- 🛠️ Platform Quirks: Handles TikTok CDN misconfigurations
Installation
npm install @supadata/media-probe
# or
pnpm add @supadata/media-probeQuick Start
import { probeMedia } from '@supadata/media-probe';
const result = await probeMedia('https://example.com/video.mp4');
console.log(result);
// {
// contentType: 'video/mp4',
// size: 1048576,
// supportsRangeRequests: true,
// isVideo: true,
// isAudio: false,
// method: 'range'
// }Usage
Basic Options
const result = await probeMedia('https://example.com/audio.mp3', {
maxRetries: 5,
timeout: 15000,
headers: { 'User-Agent': 'MyApp/1.0' },
});Platform Quirks Mode (TikTok CDN)
Some CDNs return incorrect content-type headers. Enable allowPlatformQuirks to auto-correct:
// TikTok CDN may return 'video/mp4' for MP3 files
const result = await probeMedia(tiktokUrl, {
allowPlatformQuirks: true, // Checks mime_type query parameter
});
// Without quirks: contentType = 'video/mp4' (incorrect)
// With quirks: contentType = 'audio/mpeg' (correct)Error Handling
The library provides specific error types for different failure scenarios:
import {
probeMedia,
NotFoundError,
ForbiddenError,
UnauthorizedError,
ClientError,
ServerError,
TimeoutError,
} from '@supadata/media-probe';
try {
const result = await probeMedia(url);
console.log('Media found:', result);
} catch (error) {
// Handle specific HTTP errors
if (error instanceof NotFoundError) {
console.error('Media does not exist (404)');
} else if (error instanceof ForbiddenError) {
console.error('Access forbidden (403) - check permissions');
} else if (error instanceof UnauthorizedError) {
console.error('Authentication required (401)');
} else if (error instanceof ClientError) {
console.error('Client error (4xx):', error.statusCode);
} else if (error instanceof ServerError) {
console.error('Server error (5xx):', error.statusCode, '- might be temporary');
} else if (error instanceof TimeoutError) {
console.error('Request timed out');
}
}Error Hierarchy:
ProbeError (base)
├── InvalidUrlError
├── NetworkError
│ ├── ClientError (4xx errors - won't be retried)
│ │ ├── NotFoundError (404)
│ │ ├── ForbiddenError (403)
│ │ └── UnauthorizedError (401)
│ └── ServerError (5xx errors - will be retried)
├── TimeoutError (will be retried)
└── MaxRetriesExceededErrorRetry Behavior:
- ✅ Retried: Server errors (5xx), timeouts, network failures
- ❌ Not Retried: Client errors (4xx), invalid URLs
The library intelligently tries all three methods (Range → HEAD → GET) before failing, ensuring maximum compatibility.
Batch Processing
const urls = ['video1.mp4', 'audio1.mp3', 'video2.webm'];
const results = await Promise.all(urls.map(url => probeMedia(url)));Utility Functions
import { isVideoContent, isAudioContent, normalizeContentType } from '@supadata/media-probe';
isVideoContent('video/mp4', 'file.mp4'); // true
isAudioContent(null, 'file.mp3'); // true (detected from extension)
normalizeContentType('video/mp4; codecs="avc1"'); // 'video/mp4'API
probeMedia(url, options?)
Returns Promise<ProbeResult>
Options:
interface ProbeOptions {
maxRetries?: number; // Default: 3
timeout?: number; // Default: 10000ms
headers?: Record<string, string>;
followRedirects?: boolean; // Default: true
allowPlatformQuirks?: boolean; // Default: false
fetch?: typeof fetch; // Custom fetch implementation
}Result:
interface ProbeResult {
contentType: string | null;
size: number | null;
supportsRangeRequests: boolean;
isVideo: boolean;
isAudio: boolean;
method: 'range' | 'head' | 'get';
}Supported Formats
Video: MP4, WebM, MOV, AVI, MKV, OGV, MPEG, FLV, 3GP, WMV
Audio: MP3, M4A, WAV, OGG, FLAC, AAC, Opus
Real-World Examples
Check Streaming Support
const result = await probeMedia(videoUrl);
if (result.supportsRangeRequests) {
console.log('Video supports streaming/seeking');
}Estimate Download Time
const result = await probeMedia(url);
const sizeInMB = result.size / (1024 * 1024);
const timeInSeconds = (sizeInMB * 8) / bandwidthMbps;Format Detection
const result = await probeMedia(url);
if (result.isVideo) {
await processVideo(url);
} else if (result.isAudio) {
await processAudio(url);
}Requirements
- Node.js 18.0.0 or higher (native
fetchsupport)
Development
# Install dependencies
pnpm install
# Run tests
pnpm test
# Type check
pnpm type-check
# Build
pnpm buildLicense
MIT
