@offload-run/sdk
v0.1.0
Published
Official TypeScript SDK for Offload - A simple SaaS API for long-running tasks
Downloads
120
Maintainers
Readme
@offload-run/sdk
Official TypeScript/JavaScript SDK for Offload - A simple SaaS API for long-running tasks like video thumbnail extraction, image/video compression, and more.
Installation
npm install @offload-run/sdk
# or
pnpm add @offload-run/sdk
# or
yarn add @offload-run/sdkQuick Start
import { OffloadClient } from "@offload-run/sdk";
// Initialize client with your API key
const client = new OffloadClient({
apiKey: process.env.OFFLOAD_API_KEY,
});
// Enqueue a job
const { jobId } = await client.enqueueJob({
type: "compressImage",
params: {
imageUrl: "https://example.com/large-image.jpg",
quality: 80,
maxWidth: 1920,
},
});
// Wait for job to complete
const job = await client.waitForJob(jobId);
console.log("Compressed image:", job.result.compressedUrl);Features
- ✅ Type-safe - Full TypeScript support with automatic type inference based on job type
- ✅ Promise-based - Modern async/await API
- ✅ Webhook support - Built-in webhook verification with HMAC signatures
- ✅ Polling helper -
waitForJob()method for easy job completion waiting - ✅ Simple API - Single
enqueueJob()method for all job types with smart type inference - ✅ Error handling - Clear error messages and types
Usage
Initialize Client
import { OffloadClient } from "@offload-run/sdk";
const client = new OffloadClient({
apiKey: "your-api-key",
baseUrl: "https://app.offload.run/api/v1", // Optional, defaults to production
timeout: 30000, // Optional, request timeout in ms
});Video Thumbnail Extraction
Extract a thumbnail from a video at a specific timestamp or use smart frame selection:
// Smart frame selection (auto-detect best frame)
const { jobId } = await client.enqueueJob({
type: "videoThumbnail",
params: {
videoUrl: "https://example.com/video.mp4",
timestamp: "auto", // Automatically find the most representative frame
quality: 90, // High quality (1-100, default: 85)
format: "jpg",
},
});
// Traditional timestamp-based extraction
const { jobId } = await client.enqueueJob({
type: "videoThumbnail",
params: {
videoUrl: "https://example.com/video.mp4",
timestamp: 5, // 5 seconds into the video
width: 1280,
height: 720,
quality: 85, // Optional quality parameter (default: 85)
format: "jpg",
},
});
// Wait for completion
const job = await client.waitForJob(jobId);
console.log("Thumbnail:", job.result.thumbnailUrl);
console.log("Dimensions:", job.result.width, "x", job.result.height);
console.log("Actual timestamp used:", job.result.actualTimestamp); // Only set when using numeric timestampSmart Frame Selection (timestamp: "auto"):
- Automatically analyzes the first 10 seconds of the video
- Selects the most representative frame
- Ideal for generating meaningful preview images
Quality Parameter:
- Range: 1-100 (default: 85)
- Higher values = better quality but larger file size
- Applies to JPG and WebP formats (PNG is lossless and ignores this)
- Recommended: 75-85 for web, 90-95 for high-quality previews
Image Compression
Compress and optimize images:
const { jobId } = await client.enqueueJob({
type: "compressImage",
params: {
imageUrl: "https://example.com/image.png",
quality: 80,
maxWidth: 1920,
maxHeight: 1080,
format: "webp",
stripMetadata: true,
},
});
const job = await client.waitForJob(jobId);
console.log("Original size:", job.result.originalSize);
console.log("Compressed size:", job.result.compressedSize);
console.log("Compression ratio:", job.result.compressionRatio + "%");
console.log("Download:", job.result.compressedUrl);Video Compression
Compress videos with codec selection:
const { jobId } = await client.enqueueJob({
type: "compressVideo",
params: {
videoUrl: "https://example.com/video.mp4",
quality: "medium", // 'low' | 'medium' | 'high'
maxWidth: 1920,
codec: "h264",
stripAudio: false,
},
});
const job = await client.waitForJob(jobId, {
timeout: 300000, // 5 minutes
pollInterval: 2000, // Poll every 2 seconds
onProgress: (job) => {
console.log("Status:", job.status);
},
});
console.log("Compressed video:", job.result.compressedUrl);Enqueue and Wait (One-liner)
// Enqueue job and wait for completion in one call
const job = await client.enqueueAndWait({
type: "compressImage",
params: {
imageUrl: "https://example.com/image.jpg",
quality: 80,
},
});
console.log("Done!", job.result.compressedUrl);Job Management
// Get job status
const job = await client.getJob(jobId);
console.log("Status:", job.status); // 'pending' | 'processing' | 'completed' | 'failed'
// Cancel a job
await client.cancelJob(jobId);
// Wait with custom options
const job = await client.waitForJob(jobId, {
timeout: 60000, // Max 60 seconds
pollInterval: 1000, // Check every second
onProgress: (job) => {
console.log(`Job ${job.id} is ${job.status}`);
},
});Webhooks
Instead of polling, configure webhooks to be notified when jobs complete:
Setting up Webhooks
// When creating a job, specify webhook URL
const { jobId } = await client.enqueueJob({
type: "compressImage",
params: {
imageUrl: "https://example.com/image.jpg",
quality: 80,
},
webhookUrl: "https://yourapp.com/api/webhooks/offload",
});Verifying Webhooks
// Next.js example - app/api/webhooks/offload/route.ts
import { handleWebhook } from "@offload-run/sdk";
export async function POST(req: Request) {
try {
const payload = await handleWebhook(req, process.env.WEBHOOK_SECRET!);
// Process the webhook
console.log("Job completed:", payload.jobId);
console.log("Result:", payload.result);
return new Response("OK", { status: 200 });
} catch (error) {
console.error("Webhook error:", error);
return new Response("Unauthorized", { status: 401 });
}
}For Express.js, use parseWebhook() or webhookMiddleware() - see SDK exports for details.
API Reference
OffloadClient
Constructor
new OffloadClient({
apiKey: string;
baseUrl?: string;
timeout?: number;
})Methods
enqueueJob(params)
Enqueue a new job.
await client.enqueueJob({
type: 'videoThumbnail' | 'compressImage' | 'compressVideo',
params: { /* job-specific params */ },
priority?: number, // 1-10, lower = higher priority
webhookUrl?: string,
webhookSecret?: string,
});getJob(jobId)
Get job status and result.
cancelJob(jobId)
Cancel a pending or processing job.
waitForJob(jobId, options)
Wait for job to complete by polling.
enqueueAndWait(params, waitOptions)
Enqueue a job and wait for it to complete. Returns the completed job with result.
Error Handling
try {
const job = await client.waitForJob(jobId);
if (job.status === "failed") {
console.error("Job failed:", job.error);
} else {
console.log("Success:", job.result);
}
} catch (error) {
if (error.response?.status === 401) {
console.error("Invalid API key");
} else if (error.response?.status === 404) {
console.error("Job not found");
} else {
console.error("Error:", error.message);
}
}Rate Limits
Rate limits depend on your plan:
- Free: 2 concurrent jobs, 100 jobs/hour
- Pro: 10 concurrent jobs, 1000 jobs/hour
- Enterprise: 50 concurrent jobs, 10000 jobs/hour
TypeScript Support
The SDK is written in TypeScript and provides full type safety:
import type { Job, CompressImageResult } from "@offload-run/sdk";
const job: Job<"compressImage"> = await client.getJob(jobId);
// Result is properly typed
const result: CompressImageResult = job.result!;
console.log(result.compressedUrl); // Type-safe accessLicense
MIT
Support
- Documentation: https://docs.offload.run
- Issues: https://github.com/ludovicgueth/offload/issues
- Email: [email protected]
