Guide
Mac say Command: Flags, File Output, and Quality Limits
A tested guide to the macOS say command: voice and rate flags, writing AIFF, CAF and M4A, the WAV failure, and the 22 kHz quality limit to plan around.
Free plan with Kokoro voices, 3,000 characters a day · 3-day Pro trial, then $49 once
Short answer: The macOS say command converts text to speech straight from Terminal. Run say -v Samantha -o notes.aiff -f script.txt to read a file and write an audio file, or say "Ready" to just play the words aloud. The -v flag picks the voice, -r sets words per minute, and -o writes AIFF by default, and the tool ships with every Mac, so it needs no install or account.
Everything below was tested on macOS 27 (build 26A434) with the built-in /usr/bin/say. The default output measured mono, 22050 Hz, 16-bit, and a plain .wav path failed until an explicit data format was supplied. Voice lists and file behavior change between macOS releases, so confirm the details on your own machine before you build a workflow on them.
What the say command actually does
say is a command-line front end to the same on-device speech synthesis that Mac apps reach through Apple's AVFAudio framework. Apple documents that speech synthesis creates an utterance, configures a voice and rate, and passes it to a synthesizer that produces audio. The say tool exposes the common parts of that pipeline without any code. It reads input from three places: a string on the command line, a file given with -f, or standard input when you pipe text in. It then either plays the result through your chosen output device or writes it to a file.
| Task | Command | What happens |
|---|---|---|
| Speak a string | say "Build finished" | Plays through the default output device |
| Speak a file | say -f script.txt | Reads the file and speaks its contents |
| Read from a pipe | cat script.txt | say | Speaks text received on standard input |
| Write audio | say -o take1.aiff "Take one" | Writes an AIFF file instead of playing |
| List voices | say -v '?' | Prints every installed voice and language |
| List formats | say --file-format='?' | Prints the writable file formats |
Notice that playing and writing are the same action with a different destination. If you omit -o, the audio goes to your speakers and disappears. If you provide -o, you get a file and nothing is heard. That single distinction is what makes say useful both as a notification tool and as a rough audio generator.
The flags that matter most
The default voice is whatever you selected in System Settings, so a script that names a voice explicitly is more predictable for automation. Rate is set in words per minute with -r. In a test on the same sentence, 120 wpm produced about 3.69 seconds of audio while 240 wpm produced about 2.58 seconds, so rate changes are easy to hear and easy to measure. The same sentence always produces the same length at a fixed rate, which makes say handy for estimating how long a draft will run.
-v voiceselects a voice. Use-v '?'to print the installed list, which varies by macOS version.-r ratesets the speech rate in words per minute.-o filewrites audio to a file instead of playing it.-f filereads text from a file. Pass-, or pipe text in, to read from standard input.-a deviceroutes playback to a named audio device.-n name:portsends speech over the network through AUNetSend.--data-formatand--file-formatcontrol the container and codec.--progressprints a progress meter during synthesis.-ihighlights and speaks text line by line as it is synthesized.
say -v '?' | head say -v Samantha "Listen to this sentence" say -v Samantha -r 150 -o take.aiff -f script.txt say -v Samantha -o take.m4a --data-format=aac -f script.txt
Terminal
You can also insert pauses inside the text. Apple's own examples use inline commands such as [[slnc 1500]] to hold for 1.5 seconds. In a test, adding that command to a two-word phrase grew the clip by roughly 1.3 seconds, so the markup works, but it is Apple-specific and not a portable standard. If you need pauses to survive a move to another engine, keep a plain-text master and add pauses as a separate step.
Output to a file, and the WAV trap
The safest output is AIFF. The file extension usually selects the container, but not every combination is accepted. On the tested build, AIFF, AIFC, CAF, and M4A all wrote without extra flags, while a plain .wav path failed with Opening output file failed: fmt? until a data format was added. AIFF also rejected the raw @samplerate syntax that CAF accepted, which is a useful warning against assuming the flags behave the same on every container.
| Output file | Result on the tested build | Notes |
|---|---|---|
| voice.aiff | Works. AIFF, mono, 22050 Hz, 16-bit | Big-endian PCM and the safe default |
| voice.caf | Works. Core Audio Format | Accepted --data-format=LEI16@44100 to request 44.1 kHz |
| voice.m4a | Works. AAC, mono, 22050 Hz | Add --data-format=aac for compressed audio |
| voice.wav | Failed with a fmt? error | Add --data-format=LEI16@22050 to write a WAV file |
say -v Samantha -o take.aiff -f script.txt say -v Samantha -o take.caf --data-format=LEI16@44100 -f script.txt say -v Samantha -o take.m4a --data-format=aac -f script.txt say -v Samantha -o take.wav --data-format=LEI16@22050 -f script.txt
Terminal
Always confirm what you actually wrote instead of trusting the request. Run afinfo take.aiff, or ffprobe take.m4a if FFmpeg is installed, and read the channel count, sample rate, and codec from the header. A file that exists is not proof that it is the format you asked for. This check takes a second and prevents a wrong-format file from reaching an editor or a phone system.
Quality limits to understand before you ship
It helps to know what say is not. The Apple voices are convenient and free, but the output is a system text-to-speech engine, not a narration studio. The following limits come from the official man page and from measurement, and they define where say stops being enough.
- Output is mono by default at a 22050 Hz sample rate on the tested build.
- SS64's
sayreference notes that many macOS voices are sampled at around 11 kHz, so resampling higher does not recreate detail that was never captured. - Novelty voices such as Bells, Boing, and Bubbles ship with the system but are not narration voices.
- There is no SSML. Apple's inline commands, such as
[[slnc]]for a pause, are the available markup and they are specific to this engine. - Expression control is limited to voice and rate. You cannot request a mood, a style, or an emotion.
- The
--bit-rateand--qualityoptions frequently just re-encode or upsample. SS64 warns that they can increase file size without improving the sound.
I can measure a say file, but I cannot tell you whether the voice suits your project. Generate a short sample, listen on the speakers or headphones your audience will use, and decide from the audio. Do not ship a long narration you never auditioned, and do not assume a higher requested sample rate fixed a thin or robotic source.
When say is the right tool, and when it is not
Use say when the job is quick, scriptable, and does not need a performance. Reach for a dedicated engine or a local model when the audio itself has to carry the message.
| Choose say when | Choose something else when |
|---|---|
| You want spoken alerts from a shell script, cron job, or CI step | You need natural, expressive narration for a published video or audiobook |
| You need read-aloud on a locked-down Mac with no installs allowed | You need voice cloning or a specific brand voice |
| You want a rough timing and pronunciation preview before committing | You need multi-speaker projects assembled and exported as one file |
| You want zero cost, zero account, and offline operation | You need Windows, Linux, iPhone, Android, or a cloud pipeline |
| The text is short and subtle prosody does not matter much | You need fine control over pacing, emphasis, or names at scale |
The strength of say is that it is already there. There is nothing to license, download, or configure, and it runs entirely on the machine. That is exactly why it is a bad fit when you need emotion, cloning, or a repeatable house voice, because those are qualities the system engine was never designed to deliver.
A practical script-to-audio workflow
- Write the script in a plain text file, one paragraph per thought, so you can regenerate a single section later.
- List the installed voices with
say -v '?', then record a short sample with two or three candidates at your intended rate. - Set the rate deliberately. A slower rate is easier to follow for accessibility, while a faster rate fits more words into a fixed window.
- Generate one file per section. If a word is mispronounced, rewrite that word or spell it out and regenerate only that section.
- Join the sections with your editor or a tool such as FFmpeg, then export the delivery format your destination expects.
- Keep the script next to the audio so a later edit maps back to the exact line that changed.
The Mac text to speech workflow covers the script-to-audio handoff in more depth, and the WAV, M4A, and MP3 export guide explains the difference between a master file and a delivery copy. If the job grows past a few files, the local TTS automation and batch guide walks through job queues, idempotency, and safe retries.
Where a local voice studio goes further
When a rough system voice is not enough, a local model app is the next step. Murmur is a local voice studio for Apple Silicon and Intel Macs running macOS 15 or later. It bundles Kokoro, a fast preset-voice model with 10 or more built-in voices, and it can also run larger cloning and voice-design models, which want 16 GB of memory or more. Generation happens on your Mac with no per-character fees and no cloud upload. Murmur costs $49 one-time, has a free plan and a 3-day Pro trial, and offers a 7-day refund policy, so audition the published samples before you buy.
It is not the right tool for every situation. If you need Windows, an iPhone or Android app, a browser interface, or live streaming speech, Murmur does not provide those, and it does not do speech-to-text. For a quick notification sound or a throwaway draft, say remains the simpler answer, and the two tools are not really competitors for the same job.
For a wider comparison of reading and production apps, see best text to speech apps for Mac. For a no-code route to daily read-aloud, the Mac text to speech shortcut guide builds the same capability into Shortcuts.
Frequently asked questions
Sources
- SS64: say command reference, options, and format notesAccessed 2026-10-14
- Apple Support: Change the voice your Mac uses to speak textAccessed 2026-10-14
- Apple Developer: Speech synthesis (AVFAudio)Accessed 2026-10-14
Generate production narration on your Mac
Murmur runs local voice models on Apple Silicon and Intel Macs with macOS 15 or later. The website edition costs $49 one-time, has a free plan and a 3-day Pro trial, and offers a 7-day refund policy. Use the say command for quick previews, then reach for Murmur when the audio has to ship.
macOS 15+ · Apple Silicon and Intel Macs · Windows beta · 7-day refund policy