Retry

Configurable retry with exponential backoff for transcript requests

Overview

The transcript module supports automatic retry with exponential backoff for transient HTTP failures. This is useful when YouTube returns rate-limit responses (429) or server errors (5xx).

import { transcribeVideo } from 'lyra-sdk/transcript'

const lines = await transcribeVideo('dQw4w9WgXcQ', {
  retries: 3,
  retryDelay: 1000,
})

How it works

When a fetch request returns a retryable status code, the module waits with exponential backoff before retrying:

delay * 2^attempt
AttemptWait time (delay=1000ms)
01000ms
12000ms
24000ms
38000ms

Retryable status codes

StatusMeaning
429Rate limited
500599Server error

Non-retryable responses (e.g. 404, 403) are returned immediately without retry.


Options

PropertyTypeDefaultDescription
retriesnumber0Maximum retry attempts (0 = no retries)
retryDelaynumber1000Base delay in milliseconds for backoff

Both options are part of TranscriptOptions and work with transcribeVideo(), listCaptionTracks(), and TranscriptClient.


Basic usage

import { transcribeVideo } from 'lyra-sdk/transcript'

// Retry up to 3 times with 500ms base delay
const lines = await transcribeVideo('dQw4w9WgXcQ', {
  retries: 3,
  retryDelay: 500,
})

With TranscriptClient

import { TranscriptClient } from 'lyra-sdk/transcript'

const client = new TranscriptClient({
  retries: 2,
  retryDelay: 1000,
})

// All requests through this client inherit retry settings
const lines = await client.transcribe('dQw4w9WgXcQ')

AbortSignal support

The retry loop checks AbortSignal between attempts. If aborted, the pending retry is cancelled immediately:

const controller = new AbortController()

// Abort after 5 seconds
setTimeout(() => controller.abort(), 5000)

try {
  const lines = await transcribeVideo('dQw4w9WgXcQ', {
    retries: 5,
    retryDelay: 1000,
    signal: controller.signal,
  })
} catch (error) {
  console.log('Request was aborted or failed after retries')
}

What gets retried

All three HTTP phases of a transcript fetch are wrapped with retry:

PhaseURLMethod
Watch pageyoutube.com/watch?v=...GET
Innertube APIyoutube.com/youtubei/v1/player?...POST
Transcript XMLyoutube.com/api/timedtext?...GET

Each phase retries independently. A failure in the watch page triggers a retry of just that request, not the entire flow.


Error handling with retries

When all retries are exhausted, the module throws the appropriate error based on the last response:

import {
  transcribeVideo,
  TranscriptVideoUnavailableError,
  TranscriptRateLimitError,
} from 'lyra-sdk/transcript'

try {
  const lines = await transcribeVideo('dQw4w9WgXcQ', {
    retries: 2,
    retryDelay: 500,
  })
} catch (error) {
  if (error instanceof TranscriptRateLimitError) {
    // All retries returned 429 — still rate limited
    console.log('Rate limited after 3 attempts')
  } else if (error instanceof TranscriptVideoUnavailableError) {
    // Non-retryable error returned immediately (no retries)
    console.log('Video unavailable')
  }
}

retries: 0 (default) means no retries — the first response is returned or thrown immediately. This preserves backward compatibility.

On this page