Turn personal voice recordings into organized Markdown records.
Audio Journal Transcriber is a self-hosted, filesystem-first pipeline. It watches an input directory, creates a dated bundle for each recording, and transcribes the audio through an OpenAI-compatible transcription API. It can also use an OpenAI-compatible chat API to detect spoken commands and optionally generate structured summaries and readable titles.
A bundle is a self-contained directory that keeps a recording together with its transcript, optional summary and user-provided context, and the state needed to process it over time. Bundles can be browsed with any tool that reads Markdown; storing them in an Obsidian vault is one convenient option.
- The transcriber scans an input directory recursively for recognized recording files.
- Each new recording is moved into a dated bundle in the managed store directory.
- The audio is sent to the configured transcription API and saved as
transcript.md. - The transcript is inspected for spoken commands, such as merging with the previous recording or assigning a title.
- When summaries are enabled, a chat model creates
summary.mdand a short directory title. - In daemon mode, the input directory remains watched and failed work is retried automatically.
- Run once or continuously as a filesystem-watching daemon.
- Discover
.mp3,.wav,.m4a,.flac,.ogg,.aac,.mkv, and.mp4recordings. Processing also depends on FFmpeg being able to inspect the file and the configured transcription service accepting its format. - Use separately configurable OpenAI-compatible APIs and models for transcription and text processing.
- Produce plain Markdown transcripts and structured summaries with topics, a narrative summary, and action items.
- Keep the recording and its generated files together in a persistent bundle, with metadata and command state for later processing.
- Generate chronological, readable directory names from the recording date and summary.
- Optionally add your own recording-specific context in
custom_context.md; changing that context triggers summary regeneration. - Use spoken commands to merge recordings, delete a recording, or assign a persistent manual title.
- Resume incomplete bundles and retry failures with increasing delays in daemon mode.
- Filter recordings by duration and optionally remove processed source audio after a retention period.
- Preview processing without modifying bundles with
--dry-run. - Move user-deleted bundles to a recoverable
_deleteddirectory with safe deletion.
Install the project dependencies from the repository root:
uv syncCopy the example configuration to the working directory:
cp docs/config.custom.toml.example config.custom.tomlEdit config.custom.toml with your directories, API endpoints, credentials, and model names. Ensure that the configured input directory already exists, then process all pending recordings:
uv run transcriberSee Configuration for every setting and environment-variable equivalents.
A processed recording produces a directory similar to:
store/
└── 2026-08-01 14.30 Unexpected fox encounter/
├── Recording 20260801143000.m4a
├── transcript.md
├── summary.md
├── custom_context.md
├── _commands.md
└── _metadata.md
transcript.md, summary.md, and custom_context.md are intended to remain readable and editable. Files prefixed with _ hold application state and should normally be left to the transcriber.
custom_context.md can be used to provide additional context for this bundle to the summarizer. Changing its content causes the summary to be regenerated on the next processing run.
The transcriber recognizes unambiguous, year-first dates and timestamps anywhere in
a filename. Dates may be compact or use -, _, or . separators. Times may be
compact or use :, -, _, or . separators, and may include seconds.
Recording 20260801143000.m4a
Recording_20260801_143000.m4a
2026-08-01_recording.m4a
meeting_2026-08-01_14-30-00.m4a
Voice 002_W_20230102_213412.m4a
2026-08-01T14:30:00Z_interview.m4a
GMT20260801-143000_call.mp3
Supported timestamps always put the year first. Date-only values are interpreted at
midnight in the configured time zone. A timestamp without an explicit time zone uses
the configured time zone; Z and GMT explicitly indicate UTC. Ambiguous
locale-dependent dates such as 08-01-2026 are intentionally not inferred.
If the filename contains conflicting timestamps, no valid timestamp, or no supported format, the file modification time is used.
The generated bundle directory name combines the recording date with a short summary-derived or user-provided title.
Show all command-line options:
uv run transcriber --helpCommon modes:
# Process pending work and exit
uv run transcriber
# Continue watching the input directory
uv run transcriber --daemon
# Show intended work without modifying bundle files
uv run transcriber --dry-run- Configuration: TOML files, environment variables, and setting reference.
- Voice commands: Command boundaries and supported recording operations.
- Container deployment: Docker and Podman builds and runtime configuration.
- Example phone sync setup: One way to send recordings automatically from a phone to the daemon.
Run the full test suite from the repository root:
uv run pytestRun a single test file:
uv run pytest tests/test_transcribe_bundle.py