Skip to main content

voice-memo-export

CI Release License: MIT Python 3.12+ Platform Poetry

Ruff mypy

A Python CLI tool to export Apple Voice Memos on macOS to a directory of your choice, with customizable filenames.

Why this script?

Recording many voice memos on Apple devices will over time clutter every device synced via iCloud and eats into your iCloud storage. This tool gives you a clean local copy you can archive, organise, or back up however you want.

The script is non-destructive: original recordings in the Voice Memos library are never modified or deleted.

Features

  • Command-line interface for quick exports
  • Export all Voice Memos in one run
  • Preserves original recording timestamps on exported files
  • Flexible filename formatting using Jinja2 variables and filters
  • Auto-detects the Voice Memos database location (overridable via --source)
  • Skips files that already exist at the destination, so re-runs are safe
  • Tested on macOS Monterey / Ventura / Sonoma / Sequoia / Tahoe

Prerequisites

  • macOS Monterey (12) or later
  • Python 3.12 or higher
  • Poetry 2.1.0 or higher
  • Full Disk Access granted to your terminal application (see below)

Granting Full Disk Access

Recent versions of macOS protect the Voice Memos database under TCC (Transparency, Consent, and Control). Without Full Disk Access, the script cannot read the source database and will fail with a permission error.

To grant access:

  1. Open System Settings → Privacy & Security → Full Disk Access
  2. Add your terminal application (Terminal, iTerm2, Warp, etc.)
  3. Restart the terminal

If you run the script via an IDE's integrated terminal, that IDE needs the permission instead.

Installation

Install Poetry if you haven't already:

curl -sSL https://install.python-poetry.org | python3 -

Clone this repository:

git clone https://github.com/bulletinmybeard/voice-memo-export.git
cd voice-memo-export

Install dependencies:

poetry install

Usage

Basic usage

Run with default settings (exports to ~/Voice Memos Export):

poetry run vmexport

Run with custom settings:

poetry run vmexport \
  --output ~/Documents/VoiceMemoBackup \
  --format "{{ZDATE.strftime('%Y%m%d')}}_{{ZENCRYPTEDTITLE}}"

Get help:

poetry run vmexport --help

CLI arguments

Argument Short Description Default
--source -s Path to the Voice Memos source directory Auto-detected based on macOS version
--output -o Path to the export folder ~/Voice Memos Export
--format -f Jinja2 template for the exported filename {{ZDATE.strftime('%Y%m%d%H%M%S')}}_{{ZENCRYPTEDTITLE|replace(' ', '_')}}_{{ZUNIQUEID}}

Output

Exported files keep their original .m4a extension; no transcoding is performed. The extension is appended automatically, so your --format template should describe the filename stem only (no .m4a needed).

If an identical export already exists at the destination (matched by file size), it is skipped and shown as [○]. This makes incremental exports safe: run the command again later and only new memos are copied. When two memos produce the same filename, a numeric suffix (_1, _2, …) is used automatically.

Filename format

The --format option customises the filename of each exported memo using a Jinja2 template.

Available variables

Variable Description Example value
{{ZDATE}} Recording date and time (datetime object) 2024-03-17 14:30:22
{{ZDURATION}} Duration in seconds (float) 180.5
{{ZENCRYPTEDTITLE}} Memo title Meeting Notes
{{ZCUSTOMLABEL}} Custom label, if set Important
{{ZCUSTOMLABELFORSORTING}} Custom label used for sorting Work - Project A
{{ZUNIQUEID}} Unique identifier for the memo A1B2C3D4-E5F6-G7H8-I9J0-K1L2M3N4O5P6
{{ZFLAGS}} Internal flags (integer) 4

Filters and functions

Standard Jinja2 filters are available, plus a custom slugify filter added by this tool.

Filter / function Description Example usage Example output
strftime() Format a datetime {{ZDATE.strftime('%Y-%m-%d')}} 2024-03-17
replace() Replace characters {{ZENCRYPTEDTITLE|replace(' ', '_')}} Meeting_Notes
truncate() Limit string length {{ZENCRYPTEDTITLE|truncate(20, true, '')}} Meeting Notes for P
slugify (custom) Slugify a string {{ZENCRYPTEDTITLE|slugify}} ai-machine-learning-trends-2024
lower Convert to lowercase {{ZENCRYPTEDTITLE|lower}} meeting notes
upper Convert to uppercase {{ZENCRYPTEDTITLE|upper}} MEETING NOTES

When using these in the shell, escape special characters as needed.

Example templates

Basic, with date and title

{{ZENCRYPTEDTITLE}}_{{ZDATE.strftime('%Y-%m-%d_%H-%M-%S')}}

Result: My Voice Memo_2024-03-17_14-30-00.m4a

Using duration and a short ID suffix

{{ZDATE.strftime('%Y%m%d')}}_{{ZDURATION|int}}s_{{ZUNIQUEID[-8:]}}

Result: 20240317_180s_A1B2C3D4.m4a

Conditional formatting

{% if ZCUSTOMLABEL %}{{ZCUSTOMLABEL}}_{% endif %}{{ZDATE.strftime('%Y-%m-%d')}}

Result: Important_2024-03-17.m4a (when ZCUSTOMLABEL is set) or 2024-03-17.m4a (when it isn't)

Complex formatting

{{ZDATE.strftime('%Y-%m-%d')}}_{{ZENCRYPTEDTITLE|replace(' ', '_')|truncate(20, true, '')}}_{{ZUNIQUEID[-8:]}}

Result: 2024-03-17_My_Voice_Memo_Wit_A1B2C3D4.m4a

More example commands

Export all voice memos to the default location:

poetry run vmexport

Export to a specific folder with a custom filename format:

poetry run vmexport \
  --output ~/Downloads/VoiceMemoBackup \
  --format "{{ZDATE.strftime('%Y%m%d')}}_{{ZENCRYPTEDTITLE}}"

Export from a custom source path with a complex filename format:

poetry run vmexport \
  --source /path/to/custom/VoiceMemos \
  --format "{{ZDATE.strftime('%Y-%m-%d')}}_{{ZENCRYPTEDTITLE|replace(' ', '_')|truncate(20, true, '')}}_{{ZUNIQUEID[-8:]}}"

Use conditional formatting in the filename:

poetry run vmexport \
  --format "{% if ZENCRYPTEDTITLE %}{{ZENCRYPTEDTITLE}}_{% endif %}{{ZDATE.strftime('%Y-%m-%d')}}_{{ZDURATION|int}}s"

Troubleshooting

Unable to find the Voice Memos database

Make sure you've recorded at least one memo with the Voice Memos app. If the database still isn't found, point the script at it explicitly with --source.

Permission denied / operation not permitted

Almost always a Full Disk Access issue. See Granting Full Disk Access above. Remember to add the actual terminal binary you're running from, and to restart it afterwards.

Database is locked

Quit the Voice Memos app before running the export. The app holds an exclusive lock on the SQLite database while open.

Write errors at the destination

Confirm the path passed to --output exists or can be created, and that your user has write permission there.

License

This project is licensed under the MIT License.

Metadata

Release files for voice-memo-export 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for voice-memo-export 0.3.0
File Size Uploaded
voice_memo_export-0.3.0.tar.gz 9.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for voice-memo-export 0.3.0
File Interpreter ABI Platform
voice_memo_export-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 19.6 kB

Release files / voice_memo_export-0.3.0.tar.gz

Download URL voice_memo_export-0.3.0.tar.gz
Size 9.4 kB
Tags Source
SHA-256 checksum
How to use checksums
399da8c8123b2d6525bee494231803f265714c6770637700ac7bb862202012e4
BLAKE2b-256 checksum
How to use checksums
22d253b783ac35d0df5c832857a65aa82ab264fe21eb9d42bd8dffdb9ca16338
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.4 CPython/3.12.13 Linux/6.17.0-1018-azure

Release files / voice_memo_export-0.3.0-py3-none-any.whl

Download URL voice_memo_export-0.3.0-py3-none-any.whl
Size 10.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c078bd4ce829c0521f07506f6b1444182b9d903b621066421f537d029fda1104
BLAKE2b-256 checksum
How to use checksums
d6be1b5ef08f5c767255dce4acbe9fdabc24392b31a733360d0906e391735cc8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.4 CPython/3.12.13 Linux/6.17.0-1018-azure

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page