No internet connection
  1. Home
  2. How to

Batch GarageBand export...

By Dan Bozek @Dan_Bozek
    2021-02-21 21:32:19.193Z

    Yeah, yeah. I know. Hear me out before you judge. Ha ha ha. I frequently have people send me pretty decent demos of tunes in GarageBand format and that I export and bring into Pro Tools to begin producing, etc... And the best way to do that seems to be:

    1. Muting all the tracks.
    2. Unmuting the first track.
    3. Menu item to export it.
    4. Mute first track, unmute second track, repeat.

    A task READY for a coffee break and automation if there are 20 interesting vocals parts in the demo that I'd like to be able to have individually to solo in Pro Tools later but do not want to bounce myself now.

    Has anyone tried doing anything like this? I would imagine GB is a lot like Logic? It seems like it might be possible, but I'm not sharp enough to script it all myself quite yet.

    • 6 replies
    1. D
      Dan Bozek @Dan_Bozek
        2021-02-21 21:41:49.510Z

        Hmm... You know... I just pulled up a podcast in GarageBand that I need to edit, and I might be able to do this with mostly keyboard shortcuts. Gonna try that now, but if it does work I'm not sure how to make SF know that it has reached the bottom of the tracks.

        1. samuel henriques @samuel_henriques
            2021-02-21 23:01:01.609Z2021-02-22 10:02:51.601Z

            hey @Dan_Bozek,
            Just made this, it worked for me, but don't know how stable it is.
            Hope it works as stating point for you. Couldn't get the track names, so the script is naming the exports by track number.

            
            
            function exportSongToDisk(trackNumber) {
            
                let exportSongWin = sf.ui.app('com.apple.garageband10').windows.whoseTitle.is('Export Song to Disk').first
            
                sf.ui.app('com.apple.garageband10').menuClick({ menuPath: ["Share", "Export"], looseMatch: true });
            
                exportSongWin.textFields.first.elementSetTextFieldWithAreaValue({
                    value: "Track " + ++trackNumber
                });
            
                exportSongWin.radioGroups.allItems[1].radioButtons.whoseTitle.is('WAVE').first.elementClick();
            
                exportSongWin.buttons.whoseTitle.is('Export').first.elementClick();
            
            }
            
            
            sf.ui.app('com.apple.garageband10').appActivate()
            
            sf.ui.app('com.apple.garageband10').menuClick({ menuPath: ["Edit", "Select All"] });
            
            let track = sf.ui.app('com.apple.garageband10').mainWindow.groups.whoseDescription.is('Tracks').first.splitGroups.first.splitGroups.allItems[1].scrollAreas.first.groups.whoseDescription.is('Tracks header').first.children.whoseRole.is("AXLayoutItem")
            
            let tracksLength = track.map(x => x.title).length
            
            for (var i = 0; i < tracksLength; i++) {
            
            
                track.allItems[i].checkBoxes.whoseDescription.is('Solo').first.elementClick();
            
                exportSongToDisk(i)
            
                sf.ui.app('com.apple.garageband10').windows.whoseTitle.is("GarageBand").first.elementWaitFor({
                    timeout: -1,
                    waitType: "Appear"
            
                });
            
                sf.ui.app('com.apple.garageband10').windows.whoseTitle.is("GarageBand").first.elementWaitFor({
                    timeout: -1,
                    waitType: "Disappear"
            
                });
            
                sf.wait()
            
                track.allItems[i].checkBoxes.whoseDescription.is('Solo').first.elementClick();
            
            }
            alert("Done!")
            

            UPDATE: cleaned it a bit to be easier to read
            UPDATE: Waiting from export to finish was wrong

            1. DDan Bozek @Dan_Bozek
                2021-02-23 00:51:50.549Z

                WOW. That was fast. For some reason it hung for me on the choice of WAVE radio button, but when I commented out line 11 it ran. MUCHOS GRACIAS!! :)

                Is there an easy trick for finding the names of all of those UI elements? You seemed to have done it near instantly. Ha ha ha.

                1. samuel henriques @samuel_henriques
                    2021-02-23 01:00:19.341Z

                    Awesome Dan,
                    you might have the wave menu slightly different than mine, I'm not sure of my version of garage band. But when you get to the menu if the default is good for you, it's done.

                    As for getting to the elements, check out Kitch's video for some inspiration:

                    This is the way I was trying to get the track names, but it's a bit more complex than protools.

              • S
                In reply toDan_Bozek:
                Steven Moreland @Steven_Moreland
                  2024-07-09 14:54:23.286Z

                  Thank you for this start! It does run, but it is not soloing the tracks. I changed line 13 because it was having errors with the clicking WAVE. It is just exporting to disk and labeling the Track 1, 2, 3 but they are not being soloed. I've tried a couple different things, but can't get it to solo. Any thoughts to help point me in the right direction? Here is the script:

                  
                  
                  function exportSongToDisk(trackNumber) {
                  
                      let exportSongWin = sf.ui.app('com.apple.garageband10').windows.whoseTitle.is('Export Song to Disk').first
                  
                      sf.ui.app('com.apple.garageband10').menuClick({ menuPath: ["Share", "Export"], looseMatch: true });
                  
                      exportSongWin.textFields.first.elementSetTextFieldWithAreaValue({
                          value: "Track " + ++trackNumber
                      });
                  
                      exportSongWin.radioButtons.whoseTitle.is('WAVE').first.elementClick();
                  
                      exportSongWin.buttons.whoseTitle.is('Export').first.elementClick();
                  
                  }
                  
                  sf.ui.app('com.apple.garageband10').appActivate()
                  
                  sf.ui.app('com.apple.garageband10').menuClick({ menuPath: ["Edit", "Select All"] });
                  
                  let track = sf.ui.app('com.apple.garageband10').mainWindow.groups.whoseDescription.is('Tracks').first.splitGroups.first.splitGroups.allItems[1].scrollAreas.first.groups.whoseDescription.is('Tracks header').first.children.whoseRole.is("AXLayoutItem")
                  
                  let tracksLength = track.map(x => x.title).length
                  
                  for (var i = 0; i < tracksLength; i++) {
                  
                  
                      track.allItems[i].checkBoxes.whoseDescription.is("Solo").first.elementClick();
                  
                      exportSongToDisk(i)
                  
                      sf.ui.app('com.apple.garageband10').windows.whoseTitle.is("GarageBand").first.elementWaitFor({
                          timeout: -1,
                          waitType: "Appear"
                  
                      });
                  
                      sf.ui.app('com.apple.garageband10').windows.whoseTitle.is("GarageBand").first.elementWaitFor({
                          timeout: -1,
                          waitType: "Disappear"
                  
                      });
                  
                      sf.wait()
                  
                      track.allItems[i].checkBoxes.whoseDescription.is('Solo').first.elementClick();
                  
                  }
                  alert("Done!")
                  
                  
                  1. A
                    In reply toDan_Bozek:
                    Adrian Breakspear @Adrian_Breakspear
                      2024-11-28 01:59:25.838Z

                      For the record, I'd pay for this script! the above doesn't work for me - it bounces out the mix but nothing else. Surely shouldn't take much for it to click through tracks one at at a time..I reckon I could write it for PT by amending existing commands, but I'm not good enough at JS to do it here!