How to capture text generated by FFMPEG

When using FFmpeg in Terminal, the -af volumedetect flag generates a bunch of text about a particular file. I'd like to execute this in the "Execute Shell Script" and capture the resulting text in a variable. However, after running the FFmpeg command within KM, the "Save to Variable" option captures nothing, nor do any of the other options for capturing the result.

Is this a limitation of running a shell command in KM, or am I doing something wrong?

Did you just use ffmpeg or /usr/local/bin/ffmpeg ?

Try the full path and see if that helps.

Thanks for the response.

Tried the full path with no luck. ffmpeg works fine when outputting files. I just can't capture any generated text.

Ah, well, the good news is that I think it's not you, and it's not Keyboard Maestro, it's ffmpeg.

Try this instead:

/usr/local/bin/ffmpeg -af volumedetect /path/to/file.ext 2>&1

(If that works, I can explain the background of why it works, but the key is the 2>&1 at the end of the line.)

That did it! Thank you for the help.

If you don't mind, I'd love to know the magic behind 2>&1 and why that FFmpeg behave appropriately.

This is fairly nerdy, but it does come in handy from time-to-time.

There are two kinds of output commands can use:

  1. Standard Output (abbreviated 'stdout')
  2. Standard Error (abbreviated 'stderr')

Most of the time it doesn't really matter, but it can be handy to know.

It might help to look at a practical example. Here’s a command:

find / -print

Which will show a list of all the files/folders on your hard drive, but it will also show errors when it encounters files/folders which cannot be accessed.

Now, suppose you wanted to make a list of all the files/folders on your computer, you could use this:

 find / -print > index.txt

And the file 'index.txt' would end up showing you a list of all the files/folders.

However, you would also see all of the errors. They wouldn't end up in the file, but they would end up on the screen.

But what if you wanted to put the names of all of the files/folders into one file, and all of the errors into another? You can do that by telling the computer to ignore all of the errors by redirecting standard error, like this:

find / -print > index.txt 2>index-errors.txt

Here the number '2' refers to 'standard error' as I mentioned above.

Why '2'? I have no idea. I assume there's some historical reason, but all you need to know for this is that '1' is 'standard output' and '2' is 'standard error'.

So another way of writing that line would be this:

find / -print 1>index.txt 2>index-errors.txt

You don't need to include the '1' because it's the default, but it will work if you do.

So, now that you know what '1' and '2' are, it's probably almost obvious that 2>&1 means "redirect any output that you would have sent to 'standard error' to 'standard output'.

(You couldn't just use 2>1 because that would say “Redirect standard error output to a file named '1' “.)

If you wanted to create a file that showed both the files/folders and the errors, you would use:

find / -print 2>&1 > full-index.txt

Now, I have to admit that sometimes it seems to work better if you enclose the first command in parenthesis, like this:

( find / -print 2>&1 ) > full-index.txt

I'm not entirely sure why that is, but it's just another piece of data.


Now, you might ask yourself, "Why does 'ffmpeg' use 'standard error' instead of 'standard output' when you use-af volumedetect?"

I have absolutely no idea.

How did I know?

Well… a lot of years of experience has taught me that if you try to try to get the output of a command and it doesn't work, try redirecting standard error.

How did I test my theory?

I tried to assign the output of the ffmpeg command to a variable like this:

RESULT=$(ffmpeg -af volumedetect /path/to/file.ext)

That should have resulted in no output, but instead I saw all of the output from the command, and when I tried

echo "$RESULT"

It showed nothing.

That was when I tried this instead:

RESULT=$(ffmpeg -af volumedetect /path/to/file.ext 2>&1)

That worked as expected.

So there's a longer answer than anyone wanted. :slight_smile:

P.s. Oh… just one more thing… you may have seen commands which end with

2>/dev/null

Such as

find / -print 2>/dev/null

In case you’ve ever wondered why, that command says “disregard all error messages and do not show them”. In that case, “/dev/null” is a like a “file” which immediately deletes anything you try to save to it.

I do hope someone found this at least somewhat useful or interesting.

5 Likes

That was pretty damn interesting. Clearly explained too :smiley:

2 Likes

@tjluoma Thank you so much for taking the time to break that down in such a thoughtful and clear manner. You're a ninja. It shows me how little I know about the command line syntax.

And thank you for fixing my problem. Everything is working like a charm!

Glad to help. I've been futzing around the command line since around 1991 (my college was full of NeXT computers, which was my first real exposure to computers, and I fell in the deep end).