Metadata-Version: 2.5
Name: capslane
Version: 0.2.0
Summary: Python client for retrieving YouTube transcripts through the Capslane API.
Project-URL: Documentation, https://capslane.com/docs
Project-URL: Repository, https://github.com/Webba-Creative-Technologies/capslane-python
Author-email: Webba Creative Technologies <luca.deguin@webba-creative.fr>
License-Expression: MIT
License-File: LICENSE
Keywords: api,captions,langchain,rag,transcript,video-to-text,youtube
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Typing :: Typed
Requires-Python: >=3.10
Provides-Extra: langchain
Requires-Dist: langchain-core<2,>=1.6.2; extra == 'langchain'
Description-Content-Type: text/markdown

# Capslane Python SDK

Retrieve transcripts from public YouTube videos. Capslane can return captions immediately or accept a generation job when no usable caption track is available.

## Installation

Use Python 3.10 or later. The base package uses the standard library and has no runtime dependency. The optional LangChain extra below adds its own dependencies. Create a server key in [Capslane API Keys](https://capslane.com/api-keys) and store it in the CAPSLANE_API_KEY environment variable.

```bash
python -m pip install capslane
```

## Retrieve a transcript

Save this example as transcript_sdk.py and run `python transcript_sdk.py`. Auto mode can start audio generation. Choose native mode if your first call must never start generation.

```python
import json
import os
import sys

from capslane import CapslaneClient, CapslaneError

client = CapslaneClient(api_key=os.environ["CAPSLANE_API_KEY"], timeout=45)

try:
    result = client.transcript("dQw4w9WgXcQ", mode="auto")
    if "content" not in result:
        print("Accepted job:", result["jobId"], file=sys.stderr)
        result = client.wait_for_transcript(result, timeout=20 * 60)
    print(json.dumps(result, indent=2))
except CapslaneError as error:
    print(error.code, error.status, error.request_id, file=sys.stderr)
    raise
```

A ready result contains content. An accepted job contains jobId and a status. Check for content first: a completed job response contains both. The example records the job ID so you can resume waiting after a client failure.

## Method contract

The signature is `client.transcript(url, *, lang=None, text=None, chunk_size=None, mode=None)`. Only `url` is required. The other arguments are optional and keyword-only. `mode` accepts `native`, `auto` or `generate`; omitting it uses `auto`. Omitting `text` uses `false` at the API.

The returned dictionary contains either a ready `content` value or an accepted `jobId`. `content` is a list of segment dictionaries by default, or a string for an immediate `text=True` result. Completed jobs always return segments. For example, the default content shape is:

```json
{
  "content": [{ "text": "Example segment.", "offset": 8150, "duration": 1200, "lang": "en" }],
  "lang": "en",
  "availableLangs": ["en"],
  "source": "native",
  "cached": false,
  "requestId": "req_example"
}
```

## Resume an accepted job

Using the client created above, set CAPSLANE_JOB_ID to the accepted job ID and check its state:

```python
result = client.transcript_job(os.environ["CAPSLANE_JOB_ID"])
transcript = result if "content" in result else client.wait_for_transcript(result, timeout=20 * 60)
```

`transcript_job` checks once. `wait_for_transcript` polls at two-second intervals by default, returns content when ready and raises CapslaneError on a failed or cancelled job. Successful status requests return HTTP 200 even while the job is pending or has failed. Status checks do not reserve another transcript unit.

## Modes, languages and output

Capslane checks the cache before applying the requested mode. Any mode can return cached native or generated content. Inspect source and cached in the response. On a cache miss, native fetches captions without starting audio generation; auto starts generation only after a confirmed absence of usable captions; generate starts or reuses a generation job directly. A temporary upstream error does not trigger the auto fallback.

| Option | Meaning |
| --- | --- |
| url | Public HTTPS YouTube watch, Shorts or youtu.be URL, or an 11-character video ID. |
| lang | Preferred language, such as en or fr-FR. Check the returned lang and availableLangs; this does not request translation. |
| mode | native, auto or generate. Defaults to auto. |
| text | Request one string in an immediate response. Defaults to false. |
| chunk_size | Character budget from 50 to 10,000 for grouping whole segments in an immediate response. |

Segment offset and duration values are milliseconds. An individual source segment may exceed the chunk budget. When text is true, it takes precedence over chunking.

Completed jobs return canonical timestamped segments. The public job endpoint and SDK wait helper do not reapply text or chunk size from the initial request. To obtain plain text from either result shape, run this after the quickstart finishes:

```python
content = result["content"]
plain = content if isinstance(content, str) else " ".join(segment["text"] for segment in content)
```

## Timeouts and errors

The client defaults to a twenty-second network timeout; the quickstart sets `timeout=45`. The wait helper defaults to a twenty-minute polling window, checked between iterations. An in-flight network call has its own timeout. For a shared deadline across submission and polling, use the [Python HTTP example](https://capslane.com/guides/youtube-transcript-api-python#http). Stopping a client request does not cancel an accepted server job. Preserve its ID before deciding whether to submit again.

API request failures raise CapslaneError with status, code and request_id. Network, cancellation or response parsing failures may surface separately. The quickstart propagates failures to its caller instead of reporting an incomplete job as a success.

A 429 response may indicate a short rate limit, a concurrency limit or an exhausted allowance. Read the code. Short rate limits use request_failed with Retry-After at the HTTP layer; current SDK errors do not expose that header. Monthly request or generated-minute limits need an allowance change or reset. Apply bounded backoff only where a retry can help, and retry the same job ID when polling. See [errors and retries](https://capslane.com/guides/youtube-transcript-api-errors).

## Authentication and accounting

The client calls https://capslane.com with an x-api-key header. Use it from a trusted server and keep keys out of browser bundles and source control. A dashboard session cookie does not replace an API key.

One transcript request reserves one monthly unit before extraction and cache lookup. Cache hits and later extraction failures can consume that unit. Repeating the initial request can reserve another. Job status and account checks do not consume transcript units. Free workspaces include 50 requests and 15 generated minutes per month, with one active generation; see [current plans](https://capslane.com/pricing).

The current SDK has no account method. Call GET /v1/account with x-api-key to validate a connection and read workspace, plan and monthlyLimit without starting a transcript.

## LangChain documents and retrieval

Version 0.2.0 adds an optional document loader:

```sh
python -m pip install "capslane[langchain]==0.2.0"
```

```python
from capslane.langchain import CapslaneLoader

loader = CapslaneLoader("dQw4w9WgXcQ", lang="en", chunk_size=1000)
documents = loader.load()
for document in documents:
    print(document.metadata["source"], document.page_content)
```

The loader uses CAPSLANE_API_KEY from the environment and native mode by default. It groups whole timestamped segments into real LangChain Documents, with start_ms, end_ms and a playback URL in metadata. Generated jobs receive the same local chunking. Use mode="auto" only when generation is allowed; retain loader.job_id if waiting fails. A reused loader instance keeps ready content and resumes an accepted job instead of submitting again. Use separate instances for concurrent operations.

Read the [complete LangChain guide](docs/langchain.md) or the [website guide](https://capslane.com/integrations/langchain). The [search example](examples/search_transcript.py) performs keyword retrieval through RunnableLambda without requiring an LLM or an embedding service. The extra requires langchain-core>=1.6.2,<2; the base SDK remains independent of LangChain.

## Reference

Read the [documentation](https://capslane.com/docs), [API reference](https://capslane.com/api-reference) or [Markdown reference](https://capslane.com/api-reference.md). [OpenAPI JSON](https://capslane.com/openapi.json) defines request and response schemas. The [Python integration guide](https://capslane.com/guides/youtube-transcript-api-python) includes a complete HTTP alternative.

## License

MIT
