How to get data from terminal commands through Applescript?

So I am trying to fun a command to get the FPS of a gif so I can do something with it in ffmpeg. Usually I can “set someVar to do script script…” and AS will return the output of my data. But for some reason, it refuses to work with the command I’m running. When

If I run this in Terminal

/usr/local/bin/ffprobe /Users/pp/Desktop/file_test.gif

I get a wall of data that contains the data I need (16.92 fps), shown below:

ffprobe version 4.3.1 Copyright (c) 2007-2020 the FFmpeg developers
  built with Apple clang version 11.0.3 (clang-1103.0.32.62)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/4.3.1 --enable-shared --enable-pthreads --enable-version3 --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librtmp --enable-libspeex --enable-libsoxr --enable-videotoolbox --disable-libjack --disable-indev=jack
  libavutil      56. 51.100 / 56. 51.100
  libavcodec     58. 91.100 / 58. 91.100
  libavformat    58. 45.100 / 58. 45.100
  libavdevice    58. 10.100 / 58. 10.100
  libavfilter     7. 85.100 /  7. 85.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  7.100 /  5.  7.100
  libswresample   3.  7.100 /  3.  7.100
  libpostproc    55.  7.100 / 55.  7.100
Input #0, gif, from '/Users/pp/Desktop/file_test.gif':
  Duration: 00:00:05.50, start: 0.000000, bitrate: 8611 kb/s
    Stream #0:0: Video: gif, bgra, 540x304, 16.92 fps, 50 tbr, 100 tbn, 100 tbc

This command refuses to return any data if run from an Applescript, like this:

set theResult to do shell script "/usr/local/bin/ffprobe /Users/pp/Desktop/file_test.gif"

It just returns no data. Does anyone understand why not?

So, I thought, I’ll brute force it by outputting the data to a file i can then work with. This command in Terminal

/usr/local/bin/ffprobe /Users/pp/Desktop/file_test.gif |& tee ~/documents/output.txt

nicely outputs the data I need to a text file. But the command run from Applescript

do shell script "/usr/local/bin/ffprobe /Users/pp/Desktop/file_test.gif |& tee ~/documents/output.txt"

always gives an error because it doesn’t like the & character.

Can anyone help a fellow Applescripter out? Alternately if there’s a way to cut out just the FPS info I need using grep, cut, or awk that would be helpful, but this is super hard for me to figure out.

Thanks in advance for any help you can offer!

ffmpeg and ffprobe are odd Unix commands because they routinely send all of their output to standard error rather than standard output.

For example, if you ran this command in Terminal:

FOO=$(ffprobe "$HOME/Pictures/Some Image Here.gif")

The variable $FOO would be empty, and you would see the output in Terminal.

In order for that output to be put to into the variable, you need to use 2>&1 to redirect standard error to standard output.

FOO=$(ffprobe "$HOME/Pictures/Some Image Here.gif" 2>&1)

If you are going to do this frequently via AppleScript, I would recommend making a shell script that does all of the parsing that you need and simply outputs the information you want:

#!/bin/zsh

FPS=$(ffprobe "$@" 2>&1 | awk -F' ' '/^  Stream/{print $7}')

if [[ "$FPS" == "" ]]
then

	echo "No FPS found for $@" >>/dev/stderr
	exit 1

else

	echo "$FPS"

fi

exit 0

# EOF

Save that to something like "giffps.sh" and then call giffps.sh from your AppleScript.

That’s what I would do. FWIW.

3 Likes

Wow, thanks very much, that works great! I have learned a lot about how to not do certain things between Applescript and Terminal from all this.

2 Likes