I recently had a problem, “When I run ffmpeg in the background, how do I prevent suspended (tty output)?”. I solved it. Here is my solution, in the hopes that it will help others seeing the same problem.

I have a sh script which calls ffmpeg on several files. When I try to run this script in the background, redirecting output to a file, the job starts but then immediately suspends:

% bin/mp3convert.sh path/a/b &> ~/tmp/log.txt &
[1] 93352
% [1]  + suspended (tty output)  bin/mp3convert.sh path/a/b &>

If I try making the script continue in the background, it immediately suspends again:

% jobs[1]
+ suspended (tty output)  bin/mp3convert.sh path/a/b &>
% bg %1
[1]  + continued  bin/mp3convert.sh path/a/b &>
% jobs
[1]  + suspended (tty output)  bin/mp3convert.sh path/a/b &>
%

I can make the script continue, by making it the foreground, but then my terminal is occupied until the script finishes. That means I don’t get the benefit of running the script in the background.

% [1]  + suspended (tty output)  bin/mp3convert.sh path/a/b &>
% fg %1
[1]  + continued  bin/mp3convert.sh path/a/b &>
% # much time passes with no activity on terminal, then script finishes
%

How can I make the script run cleanly in the background?

A simplified version of my script is:

#!/bin/sh# mp3convert.shfor f in "$1"/*.flac; do
    ffmpeg -i "$f" -c:v copy path/to/dest/"$(basename -s .flac "$f")".mp3
done

I am running on Mac OS X 10.11.6, with ffmpeg version 3.4  supplied by MacPorts.

An apparently related question is StackOverflow’s why do I get “Suspended (tty output)” in one terminal but not in others?. The answer there is to set the terminal state with stty -tostop. That didn’t help me; I already had that state set.

Here is the answer I discovered:

ffmpeg enables interaction with stdin by default. (See the documentation on its -stdin option.) On Mac OS X and Linux systems, this causes an ffmpeg job running in the background to suspend, though oddly with a message about “tty output” rather than “tty input”.

Adding option -nostdin to the invocation causes ffmpeg to not enable stdin interaction, and so avoids suspending the background process.

So, when I changed my invocation from:

    ffmpeg -i "$f" -c:v copy path/to/dest/"$(basename -s .flac "$f")".mp3

to:

    ffmpeg -nostdin -i "$f" -c:v copy path/to/dest/"$(basename -s .flac "$f")".mp3

then the script ran without suspending.

You can get a similar effect by redirecting input to /dev/null. This can be done at the ffmpeg call, or at the invocation to the shell script where you send the run to the background. The nice thing about this is that you can work around ffmpeg’s need for stdin without having to modify the script which invokes ffmpeg. The drawback of this is that it works differently on Windows than on Linux and Mac OS X.

You would change the script invocation from:

% bin/mp3convert.sh path/a/b &> ~/tmp/log.txt &

to:

% bin/mp3convert.sh path/a/b < /dev/null &> ~/tmp/log.txt &

Note: I also posted this question and its answer at StackOverflow: When I run `ffmpeg` in the background, how do I prevent `suspended (tty output)`? Helpful information may get posted there. And, that question might migrate to SuperUser, or another more-appropriate site.

Editorial comment: it seems unhelpful that ffmpeg enables interaction with stdin by default. From my point of view, it would be better if it enabled stdin only if needed interaction. I haven’t been able to find a page on the ffmpeg site which explains this design decision. If you know of one, please tell me in the comments below.