Focus Feed
Transform your education content into mobile-friendly RSS feeds for podcast and article consumption.
Project Summary
Turn disorganized PDF, HTML, and MP4 audio files into RSS feeds for mobile apps.
- Podcast feed - For MP4 audio (Antennapod and other podcast apps)
- Articles feed - For PDF/HTML documents (any RSS reader)
- Per-folder feeds - Organize with
feed.jsonin subfolders - Discovery - Auto-generated
index.htmllists all available feeds
All processing uses your configured endpoints. Optional local transcription available.
Documentation:
- Proposal - Problem and scope
- Specifications - Detailed requirements
- Design Document - Architecture
Quick Start
-
Configure via environment variables or
.envfile -
Process your content (targeting specific files or directories):
uv run focus-feed process ./videos/lecture.mp4 uv run focus-feed process ./documents/ ./videos/
-
Access your feeds at
{BASE_URL}/index.html
To process all files, pass your data directory:
uv run focus-feed process ./data
Configuration
Required Environment Variables
BASE_URL- Root URL where data directory is served (e.g.,https://example.com)LLM_ENDPOINT- OpenAI-compatible API endpoint for summarization (can be remote or local)LLM_API_KEY- API key for LLM endpointLLM_MODEL- Model identifier for summarizationPROMPT_ARTICLE- Article summarization prompt (PDF/HTML)PROMPT_PODCAST- Podcast summarization prompt (MP4)PROMPT_TITLE- Title generation prompt
Optional Environment Variables
PROMPT_ARTICLE_REFLECTION- Article summarization with reflection questions (default:PROMPT_ARTICLE)PROMPT_PODCAST_REFLECTION- Podcast summarization with reflection questions (default:PROMPT_PODCAST)TRANSCRIPTION_ENDPOINT- Remote transcription API endpoint (enables remote mode)TRANSCRIPTION_API_KEY- Remote transcription API keyTRANSCRIPTION_REMOTE_MODEL- Remote transcription model overrideTRANSCRIPTION_MODEL- Local transcription model (default:large-v3-turbo)TRANSCRIPTION_DEVICE- Transcription device (cuda/cpu) (default:cuda)TRANSCRIPTION_COMPUTE_TYPE- Compute type for transcription (default:float16)
Example .env File
# Required
BASE_URL=https://example.com
LLM_ENDPOINT=https://llm.example.com/v1
LLM_API_KEY=your-api-key
LLM_MODEL=mistralai/Mistral-7B-Instruct
# Prompts
PROMPT_ARTICLE="Summarize key takeaways from this document concisely in a few paragraphs."
PROMPT_PODCAST="Summarize key takeaways from this podcast transcript concisely in a few paragraphs."
PROMPT_TITLE="Generate a concise, descriptive title (5-10 words) for the given content."
# Optional
PROMPT_ARTICLE_REFLECTION="Summarize with reflection questions: ..."
PROMPT_PODCAST_REFLECTION="Summarize with reflection questions: ..."
# Transcription (default: local faster-whisper on GPU)
TRANSCRIPTION_MODEL=large-v3-turbo
TRANSCRIPTION_DEVICE=cuda
TRANSCRIPTION_COMPUTE_TYPE=float16
# Remote transcription (optional - overrides local when set)
# TRANSCRIPTION_ENDPOINT=https://transcription.example.com/v1
# TRANSCRIPTION_API_KEY=your-transcription-api-key
Note: When TRANSCRIPTION_ENDPOINT is configured, remote transcription mode is used instead of local faster-whisper.
Processing Modes
Batch Mode
Process all files at once:
uv run focus-feed process ./data
Incremental Mode
Watch for new/updated files:
uv run focus-feed watch ./data
Granular Processing
Target specific steps or files by passing files and directories as positional arguments:
transcribe- Transcribe MP4 files to markdownsummarize- Generate summaries from transcripts or document contentextract- Extract metadata from PDF/HTML filestitle- Generate titles for files that lack proper titlesfeeds- Generate RSS feeds and index.htmlvalidate- Validate all metadata filescreate-feed- Create a templatefeed.jsonin a directorycleanup- Remove unknown keys from JSON metadata files
Common Flags
--force- Force re-processing even if complete--dry-run- Preview without making changes (transcribe, summarize, extract)--config-file <path>- Use custom.envfile
Examples
# Process a single file
uv run focus-feed process ./videos/lecture.mp4
# Force re-transcription of a specific file
uv run focus-feed transcribe ./videos/lecture.mp4 --force
# Summarize a PDF
uv run focus-feed summarize ./documents/report.pdf
# Process all files in a directory
uv run focus-feed process ./documents/
# Process multiple files and directories at once
uv run focus-feed process ./videos/lecture.mp4 ./documents/report.pdf ./course1/
# See what would be transcribed
uv run focus-feed transcribe --dry-run
File Organization
Directory Structure
data/
├── index.html # Auto-generated: lists all feeds
├── feed.json # REQUIRED for root-level feeds
├── podcast.xml # Generated if MP4 files present
├── articles.xml # Generated if PDF/HTML files present
└── Course1/
├── feed.json # REQUIRED for per-folder feeds
├── podcast.xml # Course1 audio feed
├── articles.xml # Course1 articles feed
├── lecture.mp4
├── lecture.mp4.json # Auto-generated metadata
└── reflection.md # Optional: reflection questions
feed.json Format
{
"title": "Course 1: Introduction to AI",
"description": "All materials for Course 1",
"language": "en-us",
"author": "Course Author"
}
Required: title
Optional: description, language, author, link, image
reflection.md (Optional)
Place a reflection.md file in any folder to focus summarization on specific questions:
# Reflection Questions
1. What are the key frameworks or mental models presented?
2. What analytical tools can help develop critical thinking?
3. How does this content relate to systems thinking?
Note: Works with both MP4 and PDF/HTML files. Completely optional.
Feed Generation Rules
- Podcast feed (
podcast.xml): Generated only iffeed.jsonexists AND at least one MP4 file is processed - Articles feed (
articles.xml): Generated only iffeed.jsonexists AND at least one PDF/HTML file is processed - Root-level feeds: Require
feed.jsonin the data directory root - Per-folder feeds: Require
feed.jsonin the subfolder - Index page (
index.html): Auto-generated at root, lists all feeds from all folders
Supported File Types
- MP4 (audio) - Transcribed + summarized, Podcast feed,
description="",summary=key takeaways,content=transcript - PDF - Metadata + content extracted, Articles feed,
description=metadata,content=text,summary=null (unless summarized) - HTML - Metadata + content extracted, Articles feed,
description=metadata,content=text,summary=null (unless summarized)
Requirements
Software
- Python 3.14+
- uv - For dependency management
- LLM Endpoint - OpenAI-compatible API for summarization (can be remote or local)
- Optional:
ffprobe- For audio metadata extraction (falls back to file metadata)
Optional: Local Transcription
- Nvidia GPU with CUDA - Required for efficient local transcription
- CUDA Toolkit - Must be installed
- Models: faster-whisper models (downloaded automatically, ~2-6 GB)
Models
- Summarization: Any OpenAI-compatible model with 128K+ context window recommended
Optional Dependencies
Local Transcription (GPU-accelerated)
uv sync --extra local-transcription
Installs faster-whisper and av for local GPU-accelerated transcription.
Troubleshooting
Transcription Issues
- Large files take time: No time constraints; acceptable for personal use
- CUDA out of memory: Use smaller model (
medium,small,base) orint8compute type - Model not found: Verify model name or installation
Remote Transcription Issues
- Audio exceeds maximum duration: Configure vLLM server with
VLLM_MAX_AUDIO_DECODE_DURATION_S=3600(or higher) - Connection errors: Verify
TRANSCRIPTION_ENDPOINTandTRANSCRIPTION_API_KEY
Feed Issues
- Missing feeds: Ensure
feed.jsonexists and files are processed (check.jsonmetadata) - No root feeds: Root-level
feed.jsonis required - Invalid characters: Control characters in PDF/HTML are automatically removed
File Processing Issues
- Special characters: Warnings are generated; filenames are preserved
- Orphaned JSON: Delete
.jsonfile to re-process - Force re-processing: Use
--forceflag
Project Artifacts
- Proposal - Problem and scope
- Specifications - Detailed requirements
- Design Document - Architecture
- Tasks - Implementation plan
Metadata
Release files for focus-feed 1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| focus_feed-1.1.tar.gz | 275.0 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| focus_feed-1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 363.3 kB
Release files / focus_feed-1.1.tar.gz
| Download URL | focus_feed-1.1.tar.gz |
|---|---|
| Size | 275.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fc6ae8e4173635b238ebc126c3a65d6b1421fe7fa94fb9179d40f0836209084b
|
|
BLAKE2b-256 checksum How to use checksums |
f91503c51eef619c4c484de579f1d91e9229977da10dc32ab8b7fff6c537f04b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / focus_feed-1.1-py3-none-any.whl
| Download URL | focus_feed-1.1-py3-none-any.whl |
|---|---|
| Size | 88.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
05cd69012f252ec8d00d9b2ddd666d57fa7e14fb38cef01faa62a9e2543b843f
|
|
BLAKE2b-256 checksum How to use checksums |
bb012d30eb847d5e11ee9d77f75ef156957cff95383ff6c154ea8b366a6041b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logSecurity for focus-feed 1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for focus_feed-1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.