Terminal: Calculating the difference (duration) between two time stamps

I tweeted a shorter version of this yesterday. There are several places on the web where you can readily get the following information, but I couldn't find this particular function in one place, so here it is. Any media player can show you the time stamp indicating the point where the playhead is at any given time. What's not quite as simple is determining the difference or duration between any two points in a media file, and that's what ffmpeg needs to produce a clip. Here's an example of shell script snippet that does it on a Mac. The first point or time stamp in the audio or video file is "00:46:27" and the second is "02:32:11". You can paste this into a Terminal window and press return to see it in action.

s=$(date -j -f '%H:%M:%S' "00:46:27" '+%s')
e=$(date -j -f '%H:%M:%S' "02:32:11" '+%s')
i=`expr $e - $s`
date -u -r $i +%T

The information that ffmpeg would need to specify that passage in a media file is:

-ss 00:46:27 -t 01:45:44

Below is an example of an AppleScript that would help you build the above snippet using the shell script.

set _start to (text returned of (display dialog "Start time of desired passage:" default answer "00:46:27"))
set _end to (text returned of (display dialog "End time of desired passage:" default answer "02:32:11"))
set theshellsnippet to "s=$(date -j -f '%H:%M:%S'" & space & _start & space & "'+%s')
e=$(date -j -f '%H:%M:%S' " & space & _end & space & " '+%s')
i=`expr $e - $s`
date -u -r $i +%T"
set theResult to (do shell script theshellsnippet)
set thesnippet to "-ss" & space & _start & space & "-t" & space & theResult
display dialog "Place the snippet on the clipboard?" buttons {"Cancel", "OK"} default button 2
if the button returned of the result is "OK" then set the clipboard to thesnippet
1 Like

Hey Laine,

Nice script.

But why use AppleScript when you can use a Keyboard Maestro Prompt for User Input action and an Execute a Shell Script action?

That way you can leave AppleScript out of the mix, and you can enter both values in one dialog.

-Chris

Thanks, Chris.
No reason, except that I figured I'd leave the Keyboard Maestro manipulations to folks who are better at it than I am.
I could still use some help with this, if you're up for it. My reply is finished now, I think.

Hey Laine,

Okay, here's a really basic macro that does the job.

-Chris


Calculating the duration between two time stamps v1.00.kmmacros (6.8 KB)

Macro-Image

Keyboard Maestro Export

Thanks!

BTW, there was a link for "this" (hint, hint, nudge, nudge, wink, wink).

Missed that. See that thread for my answer.

Heard this before? (I know) I can copy the command to clipboard and it executes fine in Terminal, but the engine.log tells me that ffmpeg thinks the first selected file doesn't exist. BTW, this is the full ffmpeg command for creating a clip from a video.

I've removed the previously posted macro in this reply, and I'll reply again shortly with a fresh version of the macro with a more appropriate name and other details.

This macro prompts the user for the necessary information, then creates the command line for creating a specified clip from a movie using ffmpeg. The command it generates can be pasted into Terminal, then run without issues if a compatible installation of ffmpeg exists. What I don't understand is why the execution step when run in KM results in a "No such file or directory" error in ffmpeg. The workaround, of course, is to copy the completed command, open a Terminal window then paste and run the command. But I'm still interested in learning why ffmpeg has a problem with it when executed by KM. Thanks.

Calculate duration from two time stamps and save a clip using ffmpeg v1.00 Macro (v10.0.1)

Calculate duration from two time stamps and save a clip using ffmpeg v1.00.kmmacros (29 KB)

BTW, the easiest way to copy the complete shell command is probably to prepend the text of the final execution action with "echo ".

Hey Laine,

My general rule-of-the-thumb is to never assemble complex shell commands in an Execute a Shell Script action.

I always assemble them in a variable first, so I can eyeball them – and I don't have to worry about anything getting executed by accident.

Calculate duration from two time stamps and save a clip using ffmpeg v1.01.kmmacros (11 KB)

Run this and see what your command line looks like.

In particular – see how you're using single (non-interpolated) quotes incorrectly.

-Chris

OK, I'll try it, but don't forget that in my macro, when I simply place "echo" and a space in front of the final Execute action text and select clipboard as the destination for the result, I can open a Terminal window and paste directly (no changes whatsoever), and the script performs as expected. So there's nothing wrong with the building of the command. It has to be the way ffmpeg gets it from KM.

I did make a change to the macro after the first version of the reply (forgot I had made a more recent attempt to troubleshoot). If the version you looked at doesn't perform that way, maybe you're working from the version that came in a reply notification.

I copied this from the window that appeared at the finish when I ran your version with no changes:

/usr/local/bin/ffmpeg -i "'""$KMVAR_local_ffmpegClipExport""'" -ss "$KMVAR_local_Start_Time" -t "$KMVAR_local_clipDuration" -async 1 -codec copy -map 0 -movflags +faststart "'""$KMVAR_local_saveLocation""/""$KMVAR_local_ClipName""$KMVAR_local_NameExt""'"

Here's what was placed on the clipboard when I ran my version with System Clipboard selected as destination for result and "echo " prepended to the last action (minor privacy edits):

/usr/local/bin/ffmpeg -i '/Users/[me]/Downloads/SPOILERS.mkv' -ss 00:01:00 -t 00:02:00 -async 1 -codec copy -map 0 -movflags +faststart '/Users/[me]/Downloads/My Movie Clip.mkv'

I had to reply with ".mkv" to the final dialog because the input file was ".mkv"

The unedited version of my macro's result runs correctly if I paste it directly into a Terminal window.

Did you mean for the last Display Text in your version to show the variable names (the first result, what I saw when I ran it), or the version with the variables' values (the 2nd result, copied to clipboard when I ran mine with "echo " prepended)?

OK, I may have figured out why ffmpeg reported "no such file or directory" when it received the command from the macro but performed as expected when the action script was "echoed" to the Terminal.

Although the variables' values were updated in the command output string, when I checked them in KM preferences, they didn't reflect their values as entered at the latest running of the macro. It has nothing to do with single (non-interpolated) quotes. (The only requirement for those quotes is that they not be "curly", putting them inside double quotes won't prevent them from being curly, the styling has to be removed.)

Am I doing something wrong in the way I name or call the variables that keeps them from updating each time the macro is run? I need to find out how to make sure that the variables are updated on every run of the macro.

OK, I have to concede that, although Terminal has no problem with single quotes, KM does. I removed the single quotes then ensured that none of the file system objects included in responses to the macro's prompts contained spaces. That allowed the macro to deliver a compatible command to ffmpeg. That leaves the issue of escaping spaces in file paths. Does that mean I have to write another action series for the KM compatible version of the shell script that will escape spaces, or is there any other option for the Execute Shell Script that will do that for me?

I would prefer that KM accommodate any shell scripting properties honored by Terminal. If Terminal accepts single quotes to designate file paths containing spaces, KM should too. I mean, how can I predict what other terminal conventions KM will ignore when running shell scripts?

If I want to put the shell script on the clipboard so I can run it in Terminal, I'll need to use AppleScript to apply a "quoted form of" operation to the file path constructs.

Calculate duration from two time stamps and save a clip using ffmpeg v1.01 Macro (v10.0.1)

Calculate duration from two time stamps and save a clip using ffmpeg v1.01.kmmacros (29 KB)

Hey Laine,

You're mistaken.

You just don't fully understand how quoting or variable expansion works.

Your script could be written like this.

ffmpeg -i "$KMVAR_local_ffmpegClipExport" -ss "$KMVAR_local_Start_Time" -t "$KMVAR_local_clipDuration" -async 1 -codec copy -map 0 -movflags +faststart "$KMVAR_local_saveLocation/$KMVAR_local_ClipName$KMVAR_local_NameExt"

Double-quoting a path in a variable allows for spaces in the path. It is similar to enclosing a literal path in single quotes but allows some interpolation.

Here's some explanation.

action:Execute a Shell Script [Keyboard Maestro Wiki]

Quoting in the shell is the bane of many a programmer.

-Chris