Loading repository data…
Loading repository data…
nothingmn / repository
Welcome to echonotes! This is an exciting and powerful Python application designed to automate the process of extracting handwritten notes from PDFs and summarizing them using a local AI model.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
EchoNotes is a Python-based application that monitors a folder for new files, extracts the content (text, audio, video), summarizes it using a local instance of an LLM model, and saves the summarized output back to disk. It supports offline operation and can handle multiple file formats, including PDFs, Word documents, text files, video/audio files.
incoming/ folder.Speaker 1, Speaker 2, and so on.vault/.Create a config directory and place your runtime files there:
mkdir -p config incoming vault model-cache
cp config.sample.yml config/config.yml
cp summarize-notes.md config/summarize-notes.md
Edit config/config.yml for your LLM endpoint, model, tokens, and any diarization settings.
Run the persistent worker container:
docker run -d --name echonotes \
-v /path/to/incoming:/app/incoming \
-v /path/to/vault:/app/vault \
-v /path/to/config:/app/config \
-v /path/to/model-cache:/app/model-cache \
echonotes:latest
Example from the repo root:
docker run -d --name echonotes \
-v "$(pwd)/incoming:/app/incoming" \
-v "$(pwd)/vault:/app/vault" \
-v "$(pwd)/config:/app/config" \
-v "$(pwd)/model-cache:/app/model-cache" \
echonotes:latest
The model cache mount is optional but recommended for local/dev use. If /app/model-cache is empty, EchoNotes downloads the configured WhisperX model at startup. If whisper_model is not configured, it defaults to base on CPU and small on GPU.
Published image tags follow this pattern:
echonotes:latest: CPU imageechonotes:latest-cuda12.8: default GPU imageechonotes:gpu: alias for the default GPU imageVersioned releases follow the same split:
echonotes:1.4.1echonotes:1.4.1-cuda12.8Build the Docker Images:
EchoNotes currently supports two local build variants:
echonotes:latestechonotes:latest-cuda12.8Build the CPU image:
docker build -t echonotes:latest .
The default Docker build is the CPU variant. It uses the official PyTorch CPU wheel path so the image does not pull the CUDA package set.
Build the GPU image:
docker build \
--build-arg IMAGE_VARIANT=gpu \
--build-arg GPU_BASE_IMAGE=nvidia/cuda:12.8.1-cudnn-runtime-ubuntu22.04 \
--build-arg TORCH_INDEX_URL=https://download.pytorch.org/whl/cu128 \
--build-arg TORCH_EXTRA_INDEX_URL= \
--build-arg TORCH_PACKAGE_SPEC=torch==2.8.0 \
--build-arg TORCHAUDIO_PACKAGE_SPEC=torchaudio==2.8.0 \
--build-arg TORCH_INSTALL_NO_DEPS=1 \
--build-arg TORCH_PYTHON_DEPS=filelock,fsspec,jinja2,markupsafe,mpmath,networkx,sympy,typing-extensions \
-t echonotes:latest-cuda12.8 .
Optional local alias for the GPU image:
docker tag echonotes:latest-cuda12.8 echonotes:gpu
If you want both local variants available in one pass, run both commands above.
The GPU build uses the NVIDIA CUDA runtime image directly and keeps only the extra CUDA libraries that PyTorch still needs beyond that base, which avoids duplicating the full nvidia-* pip wheel bundle.
Run the Docker Container:
Run the long-lived worker container with the three runtime mounts:
docker run -d --name echonotes \
-v /path/to/incoming:/app/incoming \
-v /path/to/vault:/app/vault \
-v /path/to/config:/app/config \
-v /path/to/model-cache:/app/model-cache \
echonotes:latest
Pre-download WhisperX Models:
The recommended way to pre-download WhisperX models is to mount a host cache directory to /app/model-cache and warm it before your first long run.
Build the CPU image and warm an empty local cache:
./build.sh --model-cache-dir ./model-cache
Build the GPU image and warm an empty local cache through the NVIDIA runtime:
./build.sh --gpu --model-cache-dir ./model-cache
Those commands build the image first, then warm the cache. build.sh only performs the automatic warmup step when the target cache directory is empty, unless you explicitly pass --model.
To warm the cache without building:
You can use Docker Compose to manage the container:
version: '3.8'
services:
echonotes:
image: echonotes:latest
volumes:
- ./incoming:/app/incoming
- ./vault:/app/vault
- ./config:/app/config
- ./model-cache:/app/model-cache
restart: unless-stopped
Run the service with:
docker-compose up -d
For a GPU host, switch the image tag to echonotes:gpu or echonotes:latest-cuda12.8 and add the appropriate GPU runtime settings for your Docker installation.
EchoNotes monitors the /app/incoming directory continuously. When it detects a new file, it processes it according to the file type:
python-docx.Once the text is extracted, it can be summarized by sending the text and a customizable markdown prompt to a configured LLM provider. If no LLM provider is configured, EchoNotes will still extract and transcribe files, but it will skip LLM-based formatting and summarization.
Files placed in hidden folders or dot-paths such as .obsidian, .stfolder, or .syncthing* are ignored. Temporary partial-download files such as .part, .tmp, and .crdownload are also ignored.
Audio
Video
Documents
The application is configured via /app/config/config.yml. The image also includes baked defaults in /app/config-defaults, so if a prompt file is missing from the mounted config directory EchoNotes falls back to the image default where available. An example configuration file is shown below:
path_to_watch: "/app/incoming"
incoming_rescan_interval_seconds: 5 # Periodic fallback scan for missed filesystem events; set 0 to disable
llm:
provider: "openwebui"
model: "gpt-4o-mini"
base_url: "http://openwebui:3000/api"
api_key: "your_api_token_here"
timeout_seconds: null
max_tokens: 2048
whisper_model: "base" # Optional; defaults to 'base' on CPU and 'small' on GPU when omitted
whisper_batch_size: null # Optional; defaults to 16 on GPU and 4 on CPU
whisper_min_batch_size: 1 # On GPU, OOM retries back off down to this batch size
gpu_oom_fallback: "cpu" # One of: cpu, fail
worker_count: 2 # Number of background workers to run concurrently; on GPU start with 1
diarization_enabled: true # Enable Whisp
.obsidian and .stfolder are ignored../build.sh --warm-model-cache-only --model-cache-dir ./model-cache
If you omit --model, build.sh presents an interactive list of supported WhisperX models and lets you choose one. To skip the prompt:
./build.sh --warm-model-cache-only --model large-v3 --model-cache-dir ./model-cache
./build.sh --warm-model-cache-only --gpu --model turbo --model-cache-dir ./model-cache
To print the currently supported model names:
./build.sh --list-models
To pre-download without rebuilding, use the warm-only mode:
./build.sh --warm-model-cache-only --model-cache-dir ./model-cache
./build.sh --warm-model-cache-only --gpu --model-cache-dir ./model-cache
You can also warm the cache by starting the real worker once with the cache mounted and then stopping it after startup finishes:
docker run --rm \
-v "$(pwd)/incoming:/app/incoming" \
-v "$(pwd)/vault:/app/vault" \
-v "$(pwd)/config:/app/config" \
-v "$(pwd)/model-cache:/app/model-cache" \
echonotes:latest
For GPU:
docker run --rm --gpus all \
-v "$(pwd)/incoming:/app/incoming" \
-v "$(pwd)/vault:/app/vault" \
-v "$(pwd)/config:/app/config" \
-v "$(pwd)/model-cache:/app/model-cache" \
echonotes:latest-cuda12.8
To override the PyTorch wheel source during build:
./build.sh --torch-index-url https://download.pytorch.org/whl/cpu