When using the say
command I can give it an option -o (file name)
for it to record to a file. However, that suppresses the audio output.
Is there a way to make it do both in one command?
It appears difficult or impossible with the built-in say
command.
You may be able to redirect the audio from say
into a listening AUNetSend that in turn writes to disk and plays the audio; see Audio Hijack below.
You can use the open source espeak
and ffplay
tools to achieve this. The following command both says "Hello world" and creates a .wav
file of the recording:
espeak --stdout "hello world" | tee -a hello.wav | ffplay -i -
The command combines three tools:
espeak
converts the text into audio.tee
is used to divert a copy of stdout
to a file.ffplay
plays the audio.espeak
can read from a file or web page using the f
flag:
espeak --stdout -f myfile.txt | tee -a myfile.wav | ffplay -i -
Another tool such as ffmpeg
or iTunes can be used to convert the wav
file to an MP3 or AAC file.
To install espeak and ffplay, use HomeBrew or MacPorts. With HomeBrew set up, the install command is:
brew install espeak ffmpeg
Alternatively, a good option is to use a third party tool like Audio Hijack:
Record any audio, with Audio Hijack! Save audio from applications like iTunes, Skype or Safari, or from hardware devices like microphones and mixers.
This screen shot shows Audio Hijack taking output from Skype, recording to disk and playing back through the speaker.
AUNetSend
module is likely your best option. Good luck.
Commented
Aug 21, 2015 at 12:02
In one command with the built-in say
command, no; in two built-in commands (say
and afplay
), yes:
$ say -o /tmp/output-file.aiff Hello
$ afplay /tmp/output-file.aiff
In my example, this introduces a very small delay:
$ time sh -c "say Hello"
real 0m0.778s
user 0m0.008s
sys 0m0.012s
$ time sh -c "say -o /tmp/output-file.aiff Hello && afplay /tmp/output-file.aiff"
real 0m1.048s
user 0m0.050s
sys 0m0.048s