I’ve been working on a droplet that does a 2-pass video encode using the x264 CLI. The way x264 works, you run its command with a --pass 1 flag, let it finish, then run the command again with a --pass 2 flag. This of course requires the second pass to wait until the first process was complete.
I saw through a search that I should try to check System Events for x264 and when it is no longer running, start the second process. That makes sense, however I just can’t seem to get that into a workable code. Here’s what I have thus far:
on open {dropped_item}
set source to POSIX path of dropped_item
tell application "Terminal"
do script "x264" & " --bitrate 39000 --preset veryslow --tune film --fps 29.97 --input-res 1920x1080 --bluray-compat --pic-struct --vbv-maxrate 40000 --vbv-bufsize 30000 --level 4.1 --keyint 30 --slices 4 --fake-interlaced --colorprim bt709 --transfer bt709 --colormatrix bt709 --sar 1:1 --pass 1 -o " & quoted form of source & ".264 " & " " & quoted form of source
end tell
repeat
tell application "System Events"
if (name of every application process) contains "x264" then
delay 5
else
tell application "Terminal"
do script "x264" & " --bitrate 39000 --preset veryslow --tune film --fps 29.97 --input-res 1920x1080 --bluray-compat --pic-struct --vbv-maxrate 40000 --vbv-bufsize 30000 --level 4.1 --keyint 30 --slices 4 --fake-interlaced --colorprim bt709 --transfer bt709 --colormatrix bt709 --sar 1:1 --pass 2 -o " & quoted form of source & ".264 " & " " & quoted form of source
exit repeat
end tell
end if
end tell
end repeat
end open
This results in both processes being opened simultaneously without delay. I’ve tried to rearrange things in various orders only to have it: A) do one pass and stop B) not do anything C) delay for the 5 secs and then start the second pass (I have no idea how long the first process is going to take, so just adding a delay for a set amount of time won’t be enough) or D) run both simultaneously.
The frustrating part is that yesterday I had a delay code that worked and I accidentally deleted it when I was cleaning up some files before making this final version of the script. I can’t for the life of me recreate it. I’m very new to Applescript, and only moderately versed in coding and logic, so if anyone can point out what I’m missing, it’s greatly appreciated. Thanks!
Doing more research, it seems as if System Events doesn’t list UNIX executable processes so when it checks for x264, it doesn’t find it and continues on to the second pass. Can anyone confirm this or provide a workaround?
EDIT: Confirmed. Started x264 manually and did
tell application "System Events"
count (every process whose name is "x264")
end tell
Got an output of 0.
To get name of every process you can use the following command.
set theProcesses to every paragraph of (do shell script "ps -acwx -o command")
Now you will get a list of every running process in your system.
I got something that works, though it has its limitations.
Special thanks to this post that helped me pull a process ID for x264 from the shell: http://www.hamleshmotah.com/index.php/2011/05/31/applescript-to-kill-an-application-or-process-and-restart/
Here’s the code:
-- This is a droplet for 2-pass encoding of 1080p (--Fake-Interlaced) x264 streams for Bluray compatibility. This stream will be accepted by Encore CS5 as compliant.
-- Make sure you have installed an 8-bit build of x264. At the time of this writing, the Bluray standard does not allow for 10-bit video nor does Encore accept it.
on open {dropped_item}
set source to POSIX path of dropped_item
set app_name to "x264"
set the_pid to "1111"
tell application "Terminal"
do script "x264" & " --bitrate 39000 --preset veryslow --tune film --fps 29.97 --input-res 1920x1080 --bluray-compat --pic-struct --vbv-maxrate 40000 --vbv-bufsize 30000 --level 4.1 --keyint 30 --slices 4 --fake-interlaced --colorprim bt709 --transfer bt709 --colormatrix bt709 --sar 1:1 --pass 1 -o " & quoted form of source & ".264 " & " " & quoted form of source
repeat until the_pid is ""
set the_pid to (do shell script "ps ax | grep " & (quoted form of app_name) & " | grep -v grep | awk '{print $1}'")
if the_pid is not "" then
-- display dialog "Running" & the quoted form of the_pid -- For troubleshooting the_pid output
delay 5
else
do script "x264" & " --bitrate 39000 --preset veryslow --tune film --fps 29.97 --input-res 1920x1080 --bluray-compat --pic-struct --vbv-maxrate 40000 --vbv-bufsize 30000 --level 4.1 --keyint 30 --slices 4 --fake-interlaced --colorprim bt709 --transfer bt709 --colormatrix bt709 --sar 1:1 --pass 2 -o " & quoted form of source & ".264 " & " " & quoted form of source
end if
end repeat
end tell
end open
The limitation I found was in the way that shell script parses process names. It returns the process ID numbers for any process that contains the app_name variable. As an example, my droplet also contained x264 in its name when running, so when I had my script output a dialog with the detected process IDs, I was getting the one for x264 AND my droplet, thus keeping my script from moving on to the else. It’s a small change for me (renaming my droplet) and hardly an issue at all for complex process names, but one to be aware of.