Video Summarizer
Turn any video — a lecture, TikTok, or Drive recording — into distilled markdown: Q&A, fact-checks, tutorials, Mermaid diagrams, essays, and more.
- 11+ sources: Local-first summarization for YouTube, Instagram, TikTok, X, Reddit, Facebook, Drive, Dropbox, local files
- Bring your own API keys: Works with any OpenAI-compatible LLM, Perplexity models, LiteLLM
- CLI · Streamlit · HTTP API · Docker · Raycast · Agent skill
- Transcript cache + optional JEV prefiltering + optional Cobalt sidecar for yt-dlp fallbacks + optional vision mode
- Documentation: https://summarize.martino.im
- Background: more on this project
Quick Start
Requires Python 3.7+, ffmpeg on PATH, and an OpenAI-compatible API key in .env.
Recommended: install with pipx for an isolated environment.
Groq (GROQ_API_KEY) offers a free tier; OPENAI_API_KEY works with --provider openai.
pipx install martino-summarize
summarizer --init-config
echo "GROQ_API_KEY=your_key_here" > .env
summarizer --source "https://www.youtube.com/watch?v=arj7oStGLkU"
Output: summaries/watch_YYYYMMDD_HHMMSS.md.
Configuration lives in summarizer.yaml and .env.
Prefer Docker?
git clone https://github.com/martinopiaggi/summarize.git && cd summarize
cp summarizer.docker.yaml summarizer.yaml
echo "GROQ_API_KEY=your_key_here" > .env
docker compose up -d # → http://localhost:8501
Or pull the pre-built image: docker pull ghcr.io/martinopiaggi/summarize:latest.
Optional JEV prefilter
Full guide: JEV Prefiltering.
Check Use JEV prefiltering to reveal two optional fields:
- I want to include only… — e.g.
a particular concept about this video to filter. Selects that subject even when it is not the main topic. Blank means general relevance to the video. - I want to exclude… — e.g.
Sponsorship and self-promotion. Removes matching passages. Blank means no additional exclusions. Exclusions win when a passage matches both fields.
JEV selects original passages before the existing LLM request. It does not rewrite the transcript, change the summary prompt/model, or modify the cached transcript. The selected passages stay in source order. With JEV off, the existing pipeline is unchanged.
defaults:
use-jev-prefiltering: true
jev-provider: openrouter
jev-include: "a particular concept about this video to filter"
jev-exclude: "Sponsorship and self-promotion"
jev-keep-ratio: 0.35
Uses the existing OpenRouter (default) or TypeSafe provider's API key, with a JEV model instead of its chat model. /systemone is the structured scoring endpoint, not a system prompt. No separate provider entry is needed.
CLI: --use-jev-prefiltering --jev-include "X" --jev-exclude "Sponsorship". YAML accepts jev-include / jev-exclude; HTTP single/batch/upload requests accept jev_include / jev_exclude. Empty strings clear configured rules.
Compression and limits:
- Bounded batched scoring requests per eligible chunk (more than one for large chunks), with existing concurrency limits and no retries. The summary chunk size is unchanged. Independent inclusion/exclusion scores prevent a high inclusion score from overriding an exclusion.
- The default budget is about 35% of each original chunk, including when using exclusion only. It is a ceiling, not a quota: irrelevant text never fills unused space. Whole units are retained; one best matching unit can exceed the budget. Set
jev-keep-ratio: 1.0in YAML to retain all qualifying units instead of ranking down to 35%. - All-rejected chunks are omitted; if none remain, return a no-match message without calling the LLM.
- Every non-empty text chunk is scored when enabled, including single-unit chunks. On timeout, malformed response, HTTP error or an unsplittable request, explicit rules stop before any summary request rather than sending unfiltered text. With both fields blank, scoring failure warns and falls back to the original chunk.
- Visual mode and grammar correction bypass JEV entirely, with a warning that selection rules do not apply.
- JEV works with any configured summary
chunk-size: it divides oversized scoring work into bounded requests (28 KB state / 60 KB total JSON each), then ranks all scored units across the original chunk. Short captions may be merged locally to fit; no source text is deleted. Explicit-rule requests are planned before sending any scoring or summary requests. A single unsplittable unit or scoring error stops explicit-rule runs rather than leaking unfiltered text. - Semantic classification is not guaranteed. Long chunks use roughly 800–1,200-character units; an exclusion in a mixed unit drops the whole unit, potentially losing useful neighboring text. Compare with an unfiltered summary for important material.
Progress reports retained characters, requests, exclusions, fallbacks and elapsed time. Automated tests use mocked scores; live classification quality, cost and latency are not benchmarked.
Contributing
git clone https://github.com/martinopiaggi/summarize.git && cd summarize
pip install -e ".[all]" pytest && pytest tests/
See CONTRIBUTING.md. License: MIT.
Release files for martino-summarize 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| martino_summarize-0.3.2.tar.gz | 84.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| martino_summarize-0.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 155.3 kB
Release files / martino_summarize-0.3.2.tar.gz
| Download URL | martino_summarize-0.3.2.tar.gz |
|---|---|
| Size | 84.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e3ed81593bca09444f2a0c52b37819146a1e338a32bfcf14be405c86ed620800
|
|
BLAKE2b-256 checksum How to use checksums |
5e81459544d9d70a17c19059fce785f05ea37e64ce74d4027f02dab90c037985
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 25, 2026.
Transparency logRelease files / martino_summarize-0.3.2-py3-none-any.whl
| Download URL | martino_summarize-0.3.2-py3-none-any.whl |
|---|---|
| Size | 71.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
64ca3380e16b5f95afe74910021634e80b1492fbdeed1d1d40ea4fdbbbb07a7f
|
|
BLAKE2b-256 checksum How to use checksums |
afff11e112cab4daf9523460b2ca0e2885bf0c2086afc9f3e2fd977e77abe914
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 25, 2026.
Transparency log