Skip to content

Latest commit

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..

README.md

Transcript Create Python Client

PyPI versionPython 3.11+License

Official Python client library for the Transcript Create API. Create searchable, exportable transcripts from YouTube videos with Whisper transcription and optional speaker diarization.

Features

  • Async/await support - Built with httpx for modern async Python
  • 🔄 Automatic retries - Exponential backoff with configurable retry logic
  • 🚦 Rate limiting - Client-side rate limiting with adaptive adjustment
  • 📝 Type hints - Full type annotations with Pydantic models
  • 🎯 Custom exceptions - Clear error handling with specific exception types
  • ⏱️ Job polling - Built-in support for waiting on job completion
  • 📤 Multiple export formats - SRT, VTT, PDF, and JSON

Installation

pip install transcript-create-client

For development:

pip install transcript-create-client[dev]

Quick Start

importasynciofromtranscript_create_clientimportTranscriptClientasyncdefmain():
asyncwithTranscriptClient(base_url="http://localhost:8000") asclient:
# Create a transcription jobjob=awaitclient.create_job(
url="https://youtube.com/watch?v=dQw4w9WgXcQ",
kind="single"
)
print(f"Created job: {job.id}")
# Wait for completioncompleted_job=awaitclient.wait_for_completion(job.id, timeout=3600)
print(f"Job completed: {completed_job.state}")
# Get the transcripttranscript=awaitclient.get_transcript(completed_job.id)
forsegmentintranscript.segments:
print(f"[{segment.start_ms}ms] {segment.text}")
asyncio.run(main())

Usage Examples

Creating Jobs

# Single videojob=awaitclient.create_job(
url="https://youtube.com/watch?v=VIDEO_ID",
kind="single"
)
# Entire channeljob=awaitclient.create_job(
url="https://youtube.com/@channel",
kind="channel"
)

Checking Job Status

# Get current statusjob=awaitclient.get_job(job_id)
print(f"State: {job.state}")
# Wait for completion with pollingjob=awaitclient.wait_for_completion(
job_id,
timeout=3600, # Maximum wait time in secondspoll_interval=5.0# Check every 5 seconds
)

Getting Transcripts

# Get raw Whisper transcript (default)transcript=awaitclient.get_transcript(video_id)
forsegmentintranscript.segments:
speaker=segment.speaker_labelor"Unknown"print(f"[{speaker}] {segment.text}")
# Get cleaned transcript with filler removal and punctuationcleaned=awaitclient.get_transcript(video_id, mode="cleaned")
forsegmentincleaned.segments:
print(f"Raw: {segment.text_raw}")
print(f"Cleaned: {segment.text_cleaned}")
print(f"Stats: {cleaned.stats}")
# Get fully formatted transcriptformatted=awaitclient.get_transcript(video_id, mode="formatted")
print(formatted.text) # Formatted text with speaker labels and paragraphsprint(f"Format: {formatted.format}") # inline/dialogue/structured# Get YouTube captionsyt_transcript=awaitclient.get_youtube_transcript(video_id)
print(yt_transcript.full_text)

Transcript Modes:

The get_transcript method supports three modes:

  1. raw (default): Raw Whisper segments without processing

    • Returns: TranscriptResponse with list of Segment objects
    • Use when you need unmodified transcription output
  2. cleaned: Segments with cleanup applied

    • Returns: CleanedTranscriptResponse with list of CleanedSegment objects
    • Features: Filler removal, punctuation, normalization
    • Each segment includes both text_raw and text_cleaned
    • Response includes cleanup statistics and configuration
  3. formatted: Fully formatted text output

    • Returns: FormattedTranscriptResponse with single text field
    • Features: Speaker labels, paragraph structure, sentence segmentation
    • Best for human-readable output or document generation

Searching

# Search native transcriptsresults=awaitclient.search(
query="machine learning",
source="native",
limit=50
)
forhitinresults.hits:
print(f"Video: {hit.video_id}")
print(f"Time: {hit.start_ms}ms - {hit.end_ms}ms")
print(f"Snippet: {hit.snippet}")
# Search YouTube captionsresults=awaitclient.search(
query="python",
source="youtube",
video_id=specific_video_id# Optional: limit to specific video
)

Exporting

# Export as SRTsrt_content=awaitclient.export_srt(video_id)
withopen("transcript.srt", "wb") asf:
f.write(srt_content)
# Export as VTTvtt_content=awaitclient.export_vtt(video_id)
# Export as PDFpdf_content=awaitclient.export_pdf(video_id)
withopen("transcript.pdf", "wb") asf:
f.write(pdf_content)

Configuration

Client Options

client=TranscriptClient(
base_url="https://api.example.com",
api_key="your-api-key", # Optional: if authentication requiredtimeout=30.0, # Request timeout in secondsmax_retries=3, # Maximum retry attemptsrate_limit=10.0, # Max requests per secondadaptive_rate_limiting=True, # Adjust rate based on 429 responses
)

Custom Retry Configuration

fromtranscript_create_client.retryimportRetryConfigretry_config=RetryConfig(
max_retries=5,
initial_delay=1.0,
max_delay=60.0,
exponential_base=2.0,
jitter=True,
retryable_status_codes={408, 429, 500, 502, 503, 504}
)
client=TranscriptClient(
base_url="https://api.example.com",
retry_config=retry_config
)

Error Handling

The client provides specific exception types for different error scenarios:

fromtranscript_create_clientimport (
APIError,
AuthenticationError,
InvalidAPIKeyError,
NotFoundError,
TranscriptNotFoundError,
ValidationError,
RateLimitError,
QuotaExceededError,
NetworkError,
TimeoutError,
)
try:
transcript=awaitclient.get_transcript(video_id)
exceptTranscriptNotFoundError:
print("Transcript hasn't been generated yet")
exceptQuotaExceededError:
print("API quota exceeded - upgrade your plan")
exceptRateLimitErrorase:
print(f"Rate limited - retry after {e.retry_after} seconds")
exceptValidationErrorase:
print(f"Invalid request: {e.message}")
print(f"Details: {e.details}")
exceptAPIErrorase:
print(f"API error: {e.message} (status: {e.status_code})")

Advanced Usage

Manual Resource Management

client=TranscriptClient(base_url="https://api.example.com")
try:
awaitclient._ensure_client() # Initialize HTTP clientjob=awaitclient.create_job(url="...", kind="single")
finally:
awaitclient.close() # Clean up resources

Batch Processing

asyncdefprocess_videos(video_urls):
asyncwithTranscriptClient() asclient:
jobs= []
# Create all jobsforurlinvideo_urls:
job=awaitclient.create_job(url=url)
jobs.append(job)
# Wait for all completionscompleted=awaitasyncio.gather(
*[client.wait_for_completion(job.id) forjobinjobs],
return_exceptions=True
)
# Process resultsforjob, resultinzip(jobs, completed):
ifisinstance(result, Exception):
print(f"Job {job.id} failed: {result}")
else:
print(f"Job {job.id} completed")

Development

Setup

cd clients/python
pip install -e ".[dev]"

Running Tests

# Run all tests
pytest
# Run with coverage
pytest --cov=transcript_create_client --cov-report=html
# Run specific test file
pytest tests/test_client.py -v

Linting

# Check code
ruff check transcript_create_client tests
black --check transcript_create_client tests
mypy transcript_create_client
# Auto-fix
ruff check --fix transcript_create_client tests
black transcript_create_client tests

API Reference

See the main API documentation for complete endpoint details.

Client Methods

Jobs

  • create_job(url, kind) - Create transcription job
  • get_job(job_id) - Get job status
  • wait_for_completion(job_id, timeout, poll_interval) - Wait for job to complete

Videos

  • get_video(video_id) - Get video information
  • get_transcript(video_id, mode='raw') - Get Whisper transcript
    • mode='raw' - Raw segments (default)
    • mode='cleaned' - Cleaned segments with stats
    • mode='formatted' - Formatted text with speaker labels
  • get_youtube_transcript(video_id) - Get YouTube captions

Search

  • search(query, source, video_id, limit, offset) - Search transcripts

Exports

  • export_srt(video_id, source) - Export as SRT
  • export_vtt(video_id, source) - Export as VTT
  • export_pdf(video_id) - Export as PDF

Contributing

Contributions are welcome! Please see the main contributing guide.

License

Apache License 2.0 - see LICENSE

Support

Related Projects