Search code examples
iosvideoencodingquicktime

Automating encoding of videos (and creation of reference movie) for iOS


My iPad app gives users the ability to watch a few hundred videos. Currently the iPad app points them to an MP4 file. However, I would like to point them to a QuickTime Reference Movie instead. (This allows the app to send a lower-bitrate version of the video if the user is connected via 3G vs. wifi.)

Right now, I create the various versions, plus the reference file, in QuickTime by going to File -> Export to Web. However, this process (1) only lets me do one file at a time, and (2) generates lots of useless stuff like HTML and JavaScript.

How can I automate the process? Does anyone know of existing scripts / tools to do this work? I'm sure other devs have had to do it before.


Solution

  • I wrote (and cobbled together from other stuff on the web) this AppleScript to do the job:

    --property exportFolder : (path to documents folder as Unicode text) & "Your Folder:"
    property QTExportPath : (path to movies folder from user domain)
    property completedFolderName : "completion" -- this folder must already exist
    property referenceFiles : {}
    property encodeCount : 0
    
    on run
        choose folder with prompt "Choose folder with video files:" -- with multiple selections allowed
        open (result)
    end run
    
    on open droppedItems
    
        tell application "Finder"
            set allFiles to every file of entire contents of droppedItems as alias list
        end tell
    
        -- Error checking
        repeat with testFile in allFiles
    
            set myChars to characters of basename(testFile)
    
            if count_matches(myChars, ".") > 1 then
                display dialog "ERROR: The file " & basename(testFile) & " has too many periods."
                return
            end if
    
        end repeat
    
        -- Made it past error checking, let's get started
    
        tell application "QuickTime Player"
            activate
            close every window
        end tell
    
        repeat with thisItem in allFiles
    
            tell application "QuickTime Player"
                close every window
    
                open thisItem as alias
    
            end tell
    
            activate application "QuickTime Player"
            tell application "System Events"
                tell process "QuickTime Player"
                    keystroke "E" using command down
                    repeat until exists sheet 1 of window 1
                        delay 0.2
                    end repeat
                    click button "Export" of sheet 1 of window 1
                end tell
            end tell
    
            tell application "Finder"
                set fileExt to name extension of thisItem
            end tell
    
            set fileBaseName to basename(thisItem)
    
            set lengthWithoutExtension to (count of fileBaseName) - (count of fileExt) - 1
    
            set fileBaseNameWithoutExtension to text 1 thru lengthWithoutExtension of fileBaseName
    
            set end of referenceFiles to fileBaseNameWithoutExtension
    
            repeat until startedExporting(fileBaseNameWithoutExtension)
    
                -- wait for this file to start exporting before beginning another
    
            end repeat
    
    
        end repeat
    
        repeat until doneExporting(referenceFiles)
    
            -- wait for exporting to finish
    
        end repeat
    
        cleanUpGarbage(referenceFiles)
    
        tell application "QuickTime Player"
            activate
            close every window
            quit
        end tell
    
        display alert "finished exporting"
    
    end open
    
    on basename(thePath) -- Returns basename of alias
    
        set thePOSIXPath to the POSIX path of thePath
    
        if thePOSIXPath ends with "/" then
            set nameIndex to -2
        else
            set nameIndex to -1
        end if
    
        set ASTID to AppleScript's text item delimiters
        set AppleScript's text item delimiters to "/"
        set thePOSIXPath to text item nameIndex of thePOSIXPath
        set AppleScript's text item delimiters to ASTID
        return thePOSIXPath
    end basename
    
    on startedExporting(fileBaseNameWithoutExtension) -- Checks if QuickTime began exporting a file
    
        set moviesPath to QTExportPath as text
        set fileToTest to ((the POSIX path of moviesPath) & fileBaseNameWithoutExtension & "/Resources/" & fileBaseNameWithoutExtension & ".mov")
        if FileExists(fileToTest) then
            -- do nothing
        else
            return false
        end if
    
    end startedExporting
    
    on doneExporting(referenceFiles) -- Checks if QuickTime is done exporting everything
    
        set moviesPath to QTExportPath as text
        repeat with thisItem in referenceFiles
            set fileToTest to ((the POSIX path of moviesPath) & thisItem & "/Resources/" & thisItem & ".mov")
            if FileExists(fileToTest) then
                -- do nothing
            else
                return false
            end if
        end repeat
    end doneExporting
    
    on FileExists(theFile) -- (String) as Boolean
        tell application "System Events"
            if exists file theFile then
                return true
            else
                if exists folder theFile then
                    return true
                else
                    return false
                end if
            end if
        end tell
    end FileExists
    
    on cleanUpGarbage(referenceFiles)
    
        set moviesPath to QTExportPath as text
        set donePath to (QTExportPath as text) & completedFolderName as text
        set POSIXMovies to the POSIX path of moviesPath
        set POSIXDone to the POSIX path of donePath
    
        repeat with thisItem in referenceFiles
            set directoryToClean to (POSIXMovies & thisItem & "/")
            set m4vcommand to "find '" & directoryToClean & "' -type f -iname '*m4v' -exec cp -n {} '" & POSIXDone & "' \\;"
            set movcommand to "find '" & directoryToClean & "' -type f -iname '*mov' -exec cp -n {} '" & POSIXDone & "' \\;"
    
    
            do shell script m4vcommand
            do shell script movcommand
    
            set thefolder to POSIX file directoryToClean
    
            tell application "Finder"
                delete thefolder
            end tell
    
        end repeat
    end cleanUpGarbage
    
    on count_matches(this_list, this_item)
        set the match_counter to 0
        repeat with i from 1 to the count of this_list
            if item i of this_list is this_item then ¬
                set the match_counter to the match_counter + 1
        end repeat
        return the match_counter
    end count_matches
    

    It assumes:

    • the folder you're starting from has ONLY movie files, AND you want to convert ALL of them.
    • you have already set up whatever export settings you want in QuickTime by doing one manual export to web

    It will export them one at a time. If you want to convert multiple simultaneously, modify the startedExporting method to only check for a folder instead of the .mov file (the .mov file is the last one to generate.)