AppleScript that Mirrors iPhone to QuickTime

Like many, I’m guilty of playing mobile games on my iPhone. For the games that have controller support, I’ll stream the video on a larger screen. As mentioned in my previous article, I’ll sometimes play on my exercise bike. In this situation, I’ll mirror my iOS device through QuickTime so that I can play on a larger screen with a controller.
Manual Steps
There are a number of steps that I have to complete to mirror my iPhone to QuickTime:
  • Enable KeepingYouAwake (so monitor doesn’t go to sleep with no inputs)
  • Open QuickTime
  • Make a new Movie Recording
  • Select my iPhone for video input
  • Select my iPhone for audio input
  • Drag the volume slider to 100%.
  • Maximize Quicktime window
  • Sweet Automation
    This GIF demonstrates the automation that covers all seven manual steps. I launch it using Alfred.
    The Code
    I may be biased, but the source code is organized quite well in my opinion. The first eight lines cover all necessary customization needs as they are just function calls. If you need to, you can always dive into the functions themselves. The following is the code hosted on a Public Gist.
    set deviceName to "Kevin’s iPhone"
    activateScreenKeepAwake()
    readyQuickTime()
    setVideoInput(deviceName)
    setAudioInput(deviceName)
    setVolume(1.0)
    setScreenSize("maximize")
    # ----- Functions -----
    on activateScreenKeepAwake()
    do shell script "open keepingyouawake:///activate"
    end activateScreenKeepAwake
    on readyQuickTime()
    tell application "QuickTime Player"
    set newMovieRecording to new movie recording
    end tell
    tell application "System Events" to tell process "QuickTime Player"
    set frontmost to true
    end tell
    end readyQuickTime
    on openInputsMenu()
    ignoring application responses
    tell application "System Events" to tell process "QuickTime Player"
    click button 2 of window 1
    delay 1
    end tell
    end ignoring
    do shell script "killall 'System Events'"
    end openInputsMenu
    on setVideoInput(inputName)
    my openInputsMenu()
    tell application "System Events" to tell process "QuickTime Player"
    set inputMenu to menu 1 of button 2 of window 1
    set inputList to name of every menu item of inputMenu
    repeat with menuItemPosition from 1 to length of inputList
    if item menuItemPosition of inputList is inputName then
    ignoring application responses
    click menu item menuItemPosition of inputMenu
    exit repeat
    end ignoring
    end if
    end repeat
    end tell
    end setVideoInput
    on setAudioInput(inputName)
    my openInputsMenu()
    tell application "System Events" to tell process "QuickTime Player"
    set inputMenu to menu 1 of button 2 of window 1
    set inputList to name of every menu item of inputMenu
    set skippedFirstInstance to false # First one is for video, second instance is audio
    repeat with menuItemPosition from 1 to length of inputList
    if item menuItemPosition of inputList is inputName then
    if skippedFirstInstance is true then
    click menu item menuItemPosition of inputMenu
    exit repeat
    else
    set skippedFirstInstance to true
    end if
    end if
    end repeat
    end tell
    end setAudioInput
    on setVolume(volumeValue)
    tell application "System Events" to tell process "QuickTime Player"
    tell slider 1 of window 1
    set its value to volumeValue
    end tell
    end tell
    end setVolume
    on setScreenSize(method)
    tell application "System Events" to tell process "QuickTime Player"
    if method is "fullscreen" then
    set value of attribute "AXFullScreen" of window 1 to true
    end if
    if method is "maximize" then
    delay 3 # Gives time for the video to show up with right aspect ratio
    perform action "AXZoomWindow" of (first button whose subrole is "AXFullScreenButton") of window 1
    end if
    end tell
    end setScreenSize
    view raw mirror.scpt hosted with ❤ by GitHub
    Challenges
    Selecting a video input
    I had to select my iPhone for the video/audio inputs in QuickTime using AppleScript. A quick search turned up this Stack Overflow question. It turns out that you should be able to do the following:
    tell application "QuickTime Player"
        set newMovieRecording to new movie recording
        tell newMovieRecording
            set current camera of newMovieRecording to "Kevin's iPhone"
            set current microphone of newMovieRecording to "Kevin's iPhone"
        end tell
    end tell
    Unfortunately, it doesn’t work as you get hit with Can’t make "Kevin's iPhone" into type video recording device. This would have made things much easier.
    Instead, we have to click the button to open the inputs list and then make the selections via AppleScript. This wasn’t too bad initially, as it was just iterating the list of menu items and clicking the one which matched my device’s name.
    Same name for audio/video inputs
    After I was able to select the video input, the next problem is selecting the audio input. The problem now is that the audio and video input share the same name and are within the same list. I would have to skip the first one (video input) to select the audio input. This wasn’t too hard but was just another hurdle to get over. Ideally, the list of inputs would have been separated by video/audio, or somehow have a different key to reference them by.
    Inputs menu was slow to close
    I had noticed earlier that when the inputs menu was opened it would stay open for 7-8 seconds before making the menu item selection. I wasn’t too concerned at the time, but after the whole automation was done it took just under 20 seconds to mirror my device.
    It took a lot of digging but I found a Stack Overflow answer that provided the solution.
    on openInputMenu()
        ignoring application responses
            tell application "System Events" to tell process "QuickTime Player"
                click button 2 of window 1
                delay 1
            end tell
        end ignoring
        do shell script "killall 'System Events'"
    end openDeviceMenu
    This function for opening the menu is explicitly telling it to ignore the application responses (i.e., don’t wait for feedback). A manual delay of a second is injected to give time for the menu to open up. It also kills the System Events, which ends up forcing the script to continue execution to future actions. I’ll be honest, I’m not 100% on the specifics but it worked – the menu opens and the selections are made in just over a second now.

    29

    This website collects cookies to deliver better user experience

    AppleScript that Mirrors iPhone to QuickTime