windlass.providers.loaders.media¶
media
¶
Image (OCR) and audio (transcription) loaders.
Both turn non-text media into text so it can be chunked, embedded and retrieved exactly like a document.
Install with::
pip install "windlass[ocr]" # images — also needs the Tesseract binary
pip install "windlass[audio]" # audio
Example
from windlass import Windlass # doctest: +SKIP Windlass.loader("image").load("./scans") # doctest: +SKIP Windlass.loader("audio").load("./meeting.mp3") # doctest: +SKIP
ImageLoader
¶
ImageLoader(
*,
language: str = "eng",
psm: int = 3,
preprocess: bool = True,
min_chars: int = 5,
**config: Any
)
Bases: Loader
Extracts text from images using Tesseract.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
language
|
str
|
Tesseract language code(s), e.g. |
'eng'
|
psm
|
int
|
Tesseract page segmentation mode. |
3
|
preprocess
|
bool
|
Convert to greyscale and auto-contrast before OCR, which measurably improves accuracy on photographs and low-contrast scans. |
True
|
min_chars
|
int
|
Return no document when fewer characters were recognised — below this it is noise, not text. |
5
|
**config
|
Any
|
Forwarded to :class: |
{}
|
Raises:
| Type | Description |
|---|---|
MissingDependencyError
|
When |
IngestionError
|
When the Tesseract binary is not installed, or the image cannot be read. |
Note
pytesseract is a wrapper, not an OCR engine. The Tesseract binary
must be installed separately (apt install tesseract-ocr,
brew install tesseract, or the Windows installer). The error message
says so if it is missing.
Source code in src\windlass\providers\loaders\media.py
aload_source
async
¶
OCR one image.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
SourceLike
|
A path or a bytes payload. |
required |
Returns:
| Type | Description |
|---|---|
list[Document]
|
A single-element list, or empty when too little text was recognised. |
Raises:
| Type | Description |
|---|---|
IngestionError
|
When OCR fails or Tesseract is unavailable. |
Source code in src\windlass\providers\loaders\media.py
AudioLoader
¶
AudioLoader(
*,
model: str = "base",
language: str | None = None,
device: str = "auto",
compute_type: str = "int8",
per_segment: bool = False,
vad_filter: bool = True,
**config: Any
)
Bases: Loader
Transcribes audio using faster-whisper.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
str
|
Whisper model size — |
'base'
|
language
|
str | None
|
Force a language code, or |
None
|
device
|
str
|
|
'auto'
|
compute_type
|
str
|
Quantisation, e.g. |
'int8'
|
per_segment
|
bool
|
One document per transcript segment, each carrying its timestamp — the right choice for anything you want to cite. |
False
|
vad_filter
|
bool
|
Skip silence with voice-activity detection, which speeds up transcription of sparse recordings considerably. |
True
|
**config
|
Any
|
Forwarded to :class: |
{}
|
Raises:
| Type | Description |
|---|---|
MissingDependencyError
|
When |
IngestionError
|
When the audio cannot be transcribed. |
Performance
Transcription is slow and CPU-heavy. It runs on a worker thread so it
never blocks the event loop, but expect roughly real-time on CPU with
the base model.
Source code in src\windlass\providers\loaders\media.py
aload_source
async
¶
Transcribe one audio file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
SourceLike
|
A path. Byte payloads are written to a temporary file first, because the decoder needs a seekable path. |
required |
Returns:
| Type | Description |
|---|---|
list[Document]
|
One document per segment, or one for the whole transcript. |
Raises:
| Type | Description |
|---|---|
IngestionError
|
When transcription fails. |