@royalti/syynk
v0.2.0
Published
TypeScript SDK for Syynk API - transcribe audio and export synchronized lyrics/subtitles
Maintainers
Readme
@royalti/syynk
TypeScript SDK for the Syynk API - transcribe audio and export synchronized lyrics/subtitles.
Installation
npm install @royalti/syynk
# or
yarn add @royalti/syynk
# or
pnpm add @royalti/syynkQuick Start
import { SyynkClient } from '@royalti/syynk';
const client = new SyynkClient({
apiKey: process.env.SYYNK_API_KEY,
});
// Transcribe audio from URL
const result = await client.transcribe({
audioUrl: 'https://example.com/song.mp3',
language: 'en',
});
// Export to LRC format
const lrc = await client.export({
format: 'lrc',
segments: result.segments,
projectName: 'My Song',
});
console.log(lrc.content);Features
- Transcribe audio from URL or file upload
- Export to multiple formats: LRC, SRT, VTT, TTML, JSON, TXT
- Full TypeScript support
- Automatic retry with exponential backoff
- Rate limit handling
- Works in Node.js (18+) and browsers
API Reference
SyynkClient
Create a new client instance:
const client = new SyynkClient({
apiKey: 'your-api-key',
baseUrl: 'https://syynk.to', // optional
timeout: 30000, // optional, in milliseconds
maxRetries: 3, // optional
});Methods
transcribe(options)
Transcribe audio from a URL.
const result = await client.transcribe({
audioUrl: 'https://example.com/song.mp3',
language: 'en', // optional, auto-detected if not specified
projectName: 'My Song', // optional
});
// Result contains:
// - projectId: string
// - editorUrl: string (URL to open in Syynk editor)
// - language: string
// - duration: number (seconds)
// - lyricsText: string (plain text lyrics)
// - segments: Segment[]
// - words: Word[]transcribeFile(file, options?)
Transcribe audio from a file upload.
// Node.js
import fs from 'fs';
const buffer = fs.readFileSync('song.mp3');
const result = await client.transcribeFile(buffer, {
filename: 'song.mp3',
language: 'en',
});
// Browser
const file = document.querySelector('input[type="file"]').files[0];
const result = await client.transcribeFile(file);export(options)
Export segments to a specific format.
const result = await client.export({
format: 'lrc', // 'lrc' | 'srt' | 'vtt' | 'ttml' | 'json' | 'txt'
segments: transcription.segments,
words: transcription.words, // optional, for word-level timing
projectName: 'My Song', // optional
});
// Result contains:
// - content: string
// - filename: string
// - mimeType: string
// - extension: stringgetFormats()
Get information about available export formats.
const formats = await client.getFormats();
// Returns:
// [
// { id: 'lrc', name: 'LRC', supportsWordTiming: false, ... },
// { id: 'ttml', name: 'TTML', supportsWordTiming: true, ... },
// ...
// ]listProjects(options?)
List your projects with optional filtering.
const result = await client.listProjects({
status: 'ready',
type: 'lyricsync',
limit: 20,
offset: 0,
});
// Result contains:
// - projects: ProjectSummary[]
// - total: number
// - limit: number
// - offset: numbergetProject(id, options?)
Get a single project with segments and optionally words.
const result = await client.getProject('project-id', {
includeWords: true, // default: true
});
// Result contains:
// - project: Project (id, name, type, status, editorUrl, audioUrl, etc.)
// - segments: Segment[]
// - words?: Word[] (if includeWords is true)getLyrics(id)
Get plain text lyrics for a project.
const result = await client.getLyrics('project-id');
console.log(result.lyrics);
// "First line of lyrics\nSecond line\n..."deleteProject(id)
Delete a project and all its segments and words.
await client.deleteProject('project-id');
console.log('Project deleted');getRateLimitInfo()
Get the current rate limit status.
const rateLimit = client.getRateLimitInfo();
if (rateLimit) {
console.log(`${rateLimit.remaining}/${rateLimit.limit} requests remaining`);
console.log(`Resets at ${new Date(rateLimit.reset * 1000)}`);
}Error Handling
The SDK provides typed errors for different failure scenarios:
import {
SyynkClient,
AuthenticationError,
RateLimitError,
ValidationError,
NotFoundError,
ServerError,
NetworkError,
TimeoutError,
} from '@royalti/syynk';
try {
const result = await client.transcribe({ audioUrl: 'invalid' });
} catch (error) {
if (error instanceof AuthenticationError) {
// Invalid or missing API key (401)
console.log('Check your API key');
} else if (error instanceof RateLimitError) {
// Rate limit exceeded (429)
console.log(`Retry after ${error.retryAfter} seconds`);
console.log(`Reset time: ${error.getResetDate()}`);
} else if (error instanceof ValidationError) {
// Invalid request data (400)
console.log(error.fieldErrors);
} else if (error instanceof NotFoundError) {
// Resource not found (404)
console.log('Project not found');
} else if (error instanceof ServerError) {
// Server error (500+)
console.log(`Request ID: ${error.requestId}`);
} else if (error instanceof NetworkError) {
// Connection failed
console.log('Check your internet connection');
} else if (error instanceof TimeoutError) {
// Request timed out
console.log(`Timed out after ${error.timeoutMs}ms`);
}
}Type Guards
import { isSyynkError, isRateLimitError, isRetryableError } from '@royalti/syynk';
if (isSyynkError(error)) {
console.log(error.code, error.status);
}
if (isRateLimitError(error)) {
console.log(error.retryAfter);
}
if (isRetryableError(error)) {
// Error is rate limit, network, timeout, or server error
}Types
All types are exported for TypeScript users:
import type {
Segment,
Word,
Project,
ProjectSummary,
ProjectResult,
LyricsResult,
ExportFormat,
TranscribeResult,
ExportResult,
} from '@royalti/syynk';Export Formats
| Format | Extension | Word Timing | Use Case |
|--------|-----------|-------------|----------|
| LRC | .lrc | No | Karaoke players |
| SRT | .srt | No | Video subtitles (VLC, YouTube) |
| VTT | .vtt | No | HTML5 <track> element |
| TTML | .ttml | Yes | Professional broadcast |
| JSON | .json | Yes | Developer integration |
| TXT | .txt | No | Plain text lyrics |
License
MIT
