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

@royalti/syynk

v0.2.0

Published

TypeScript SDK for Syynk API - transcribe audio and export synchronized lyrics/subtitles

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/syynk

Quick 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: string

getFormats()

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: number

getProject(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