Trigger macro when audio recording is done

Hello,

I'm trying to make a macro that pushes wav files into a Python script when they are finished recording in a folder.

I've succeeded in making a macro that triggers when a wav file appears in a folder and pushes it into the Python script, that all works, but the middle part is giving me trouble.

A new 0 byte wav file is created at the same time when the recording of the last one is stopped (Ableton Lives functionality), so the script should be able to handle two files at the same time which I think potentially messes things up. I did try 'ignore partial or changing files', but KM takes the 0 byte file to be complete and continues the script. Also, the first recording doesn’t get it’s final size before the second recording is started.

I've tried several approaches but none of them seem to work, most probably because of the two things happening at the same time, which are 1. A new 0 byte wav file is created (which triggers the macro again) when recording is stopped and 2. Last recorded audio gets its final file size.

Anyone have ideas how to go about building the middle part of this?

I'm not sure if it'll help, but you might look at the method I used in my AppWatcher suite, as I faced a similar issue: I didn't want stuff to start happening until after a file had fully copied.

Look at the Wait for install/copy to complete before proceeding group in the AppWatchAdd > App Added macro. Basically, I take two measurements of file size at slightly different times, and only proceed when there's no difference.

-rob.

2 Likes

That's pretty good, but wouldn't this also work?

image

If the file is being written to, its name/path will show up in the "lsof" command.

2 Likes

Probably would, but I didn't even think about it when I wrote the macro :). Next time I make an update, I'll do some lsof testing.

thanks;
-rob.

Appreciate the suggestions! I went and tried both of these methods.

@Airy lsof didn't work unfortunately because the audio files that are present in Ableton project are shown to be used even when they are not recorded.

Thank you @griffman, I went and did a variation on your macro and during making of that I became aware of the main problem. Which is when Keyboard Maestro %TriggerValue% grabs the files that are created in the recording folder, it affects every other action down the line that mentioned %TriggerValue% and the script becomes confused.

Since Ableton creates many files during recording, including analysis file called .asd and the 0 byte wav file when recording is started, the %TriggerValue% keeps changing and the macro keeps triggering with different files.

Is there a more effective way to trigger folder action in Keyboard Maestro which takes in account the file properties? In such way that for example when a .wav file in specific folder exceeds over 0 bytes it triggers a macro?

Here's a working solution I came up with, it's a bash script that watches a folder (using fswatch, can be installed with "brew install fswatch"), checks .wav files in 5 second intervals for 5 minutes, and when the size exceeds 0 bytes it prints out the path, but I've made my own version which pushes it into a python script.

#!/bin/bash

folder_to_watch=”/folder/to/watch”

processed_files=""

check_interval=5  # Adjust this interval (in seconds) based on your needs

fswatch -0 "$folder_to_watch" 2>/dev/null | while read -d "" event; do
    # Extract the filename from the event and remove the leading '@' symbol
    file=$(echo "$event" | sed 's/^@//')

    # Check if the file has already been processed to avoid duplicates
    if [[ "$processed_files" != *"$file"* && -f "$file" && "$file" == *.wav ]]; then
        elapsed_time=0
        while [[ $elapsed_time -lt 300 ]]; do  # Check for up to 5 minutes
            sleep "$check_interval"
            current_size=$(stat -f%z "$file")

            if [[ $current_size -gt 0 ]]; then
                echo "$file"
                processed_files="$processed_files$file "
                break
            fi

            elapsed_time=$((elapsed_time + check_interval))
        done
    fi
done

Does the job for my needs! I think i'll be using Keyboard Maestro to start and stop the script in a specified folder which changes with different projects.