Content Core 2.2 reads OpenDocument files, fetches YouTube transcripts through cookies or a proxy, and lets you set how long audio segments are. One change touches code you already run. When extraction fails, it now raises a typed error instead of returning empty content.
Content Core 2.2 reads OpenDocument files, fetches YouTube transcripts through cookies or a proxy, and lets you set how long audio segments are. One change touches code you already run. When extraction fails, it now raises a typed error instead of returning empty content.
Slide text
Content Core 2.2 reads OpenDocument files, gets YouTube through a proxy, and raises typed errors on failure
OpenDocument is the LibreOffice family of formats, and its text documents, spreadsheets and presentations now extract to Markdown. A spreadsheet becomes one table per sheet, and a presentation one block per slide, the same shape Excel and PowerPoint files get. Detection reads the file's mimetype, so a missing extension still works.
Slide text
LibreOffice files now come out as Markdown
.odtheadings, paragraphs, lists, tables
.odsone table per sheet
.odpone block per slide
file.ods → content
# Sheet: Cities…
| Buenos Aires | Argentina |
…# Sheet: Rivers…
| Parana | 4880 |
Detected from the archive's mimetype, so a wrong or missing extension still works. New core dependency: odfpy.
content-core v2.2.0 · #43 #96added
On networks YouTube has flagged, such as cloud hosts and VPNs, transcript requests get refused. Two new settings help: a cookies file from a logged-in browser, or a proxy for every YouTube request. Use a residential proxy, because datacenter proxies get blocked. Blocked requests are retried, so a rotating proxy gets a fresh IP. With neither set, behavior stays the same.
Slide text
YouTube transcripts can get through blocked networks with cookies or a residential proxy
Use a residential proxyDatacenter proxies get blocked. Blocked requests are retried, so a rotating proxy gets a new IP.
Off by defaultWith neither set, behavior is unchanged. Cookie values are never logged.
content-core v2.2.0 · #46 #95 #99added
Long audio is split into ten-minute segments before transcription. Now you choose that length, and zero sends the file whole, which suits a self-hosted speech-to-text server without an upload limit. On a cloud provider, keep the default. OpenAI rejects uploads over 25 megabytes.
Slide text
Choose how long audio is cut before transcription, or send it whole
default · audio_segment_minutes = 10
10 min
10 min
10 min
10 min
10 min
10 min
CCORE_AUDIO_SEGMENT_MINUTES=0
the whole file
On a cloud provider, keep the default. OpenAI rejects uploads over 25 MB.
content-core v2.2.0 · #94 · thanks @kyxap1added
Now the change that can affect code you already have. In 2.1, a failed extraction could come back as empty content, and the simple URL engine returned its error message as the page text. In 2.2, an empty string means the source really was empty. Failures raise.
Slide text
2.1: a failure could come back as empty content
content == ""
now only means the source was empty.
content-core v2.2.0 · #60 #97changed
If your code tests for empty content to spot a failure, that branch won't see failures anymore. They arrive as exceptions. Wrap the call and catch ContentCoreError, the base of every typed error. The same applies to the command line tool and the MCP server.
Slide text
If you checked for empty content, catch ContentCoreError instead
before · 2.1
result = await content_core.extract_content(
url=url)
if result.content == "":
... # treated as a failure
after · 2.2
from content_core import ContentCoreError
try:
result = await content_core.extract_content(
url=url)
except ContentCoreError:
... # the failure, typed
content-core v2.2.0 · library, CLI and MCPchanged
Each failure now has its own type. Network errors are retried. Configuration, input and file errors are permanent, so they fail at once. The auto URL engine still tries Firecrawl, Jina, Crawl4AI and simple in turn, and raises only when all of them fail. And a speech model you name that can't be created raises a configuration error, instead of quietly falling back to the default.
Slide text
Each failure now raises a type you can catch
NetworkError
connection, timeout or DNS failure
NotFoundError
HTTP 404 or 410, simple engine
ExternalServiceError
an engine, STT provider or YouTube request fails
InvalidInputError
malformed URL, or a YouTube URL without a video ID
FileOperationError
corrupt PDF or EPUB, ffmpeg or ffprobe failure
NoTranscriptFound
no YouTube transcript can be fetched
ConfigurationError
crawl4ai not installed, or your STT model can't be created
content-core v2.2.0 · #60 #97 #99changed
Upgrading also raises seven minimum versions to releases without known vulnerabilities. In the core install, aiohttp, pillow, click and pydantic settings. In the extras, docling, crawl4ai and langchain core. An upgrade pulls them into an existing environment. Two advisories remain. nltk has no fixed release yet, and the docling extra keeps transformers below version 5.
Slide text
Upgrading also lifts seven dependencies past known vulnerabilities
Still open: nltk, with no fixed release yet, and transformers, held below 5 by the docling extra.
content-core v2.2.0 · #102 #103security
Install 2.2.0 with pip, or try it with uvx and no install at all. Before you do, catch ContentCoreError wherever you treated empty content as a failure. YouTube through a real residential proxy or cookies file, and speech providers other than OpenAI, weren't verified live. Content Core 2.2 reads OpenDocument files, gets YouTube through a proxy, and raises typed errors on failure.
Slide text
Upgrade to 2.2 once your failure checks catch ContentCoreError