21

Is there a piece of software that allows one to pause (& un-pause) a currently playing YouTube video (or, ideally, any online video/audio media), with a keyboard shortcut or a conveniently accessible button (e.g., a button that sits in the menu bar, located at the top-right of the screen)? The fewer necessary clicks, the better.

The key here is that I want the ability to pause the video in any application, that is, when Google Chrome is not the foremost application (e.g., TextEdit or Microsoft Word is the foremost application).

iOS has this shortcut built-in. If one swipes from the bottom of the screen to the top, media controls appear. These controls can manipulate any and all audio that originates in a Safari tab.

My web browser is Google Chrome.

OS X El Capitan, version 10.11.6.


I would also be open to accomplishing this with an AppleScript (that can then be assigned to a key combination in FastScripts.app). But, I cannot imagine that such a complex task is possible via AppleScript.

5
  • 1
    So, you're looking for a menu bar solution rather than just tapping the Space Bar? Or mouse-clicking on the Play/Pause button?
    – Monomeeth
    Apr 21, 2017 at 2:36
  • 1
    @Monomeeth Please see my edit. I forgot to mention that Chrome is not the active application; the video plays in the background. So, to pause the video, I have to click on the Chrome window, click on the tab that contains the video, and only then can I use the space bar or a left-click to pause the video. Apr 21, 2017 at 2:44
  • 1
    you're looking for something like if i understood the question : beardedspice.github.io
    – enzo
    Apr 21, 2017 at 15:55
  • @enzo I've downloaded BeardedSpice and it is exactly what I am looking for. BeardedSpice is perfect for my needs. If you want to post this as an answer, I will happily accept it. Thanks! Apr 21, 2017 at 17:26
  • I actually wonder why Google hasn't made the keyboard Play/Pause button (F8) work for YouTube, given that it does work as expected when you visit Google Play Music in Chrome.
    – calum_b
    Apr 21, 2017 at 23:03

2 Answers 2

22

********** UPDATED SOLUTION **********

This update is a direct solution to the OP's original question.

This following AppleScript code will add a "Play/Pause YouTube" status menu item with the options to play or pause any YouTube video in either Google Chrome or Safari, whether the browsers are visible or not. Save this following AppleScript code as a "stay open" application in Script Editor.app.

use framework "Foundation"
use framework "AppKit"
use scripting additions

property StatusItem : missing value
property selectedMenu : ""
property defaults : class "NSUserDefaults"
property internalMenuItem : class "NSMenuItem"
property externalMenuItem : class "NSMenuItem"
property newMenu : class "NSMenu"

my makeStatusBar()
my makeMenus()

on makeStatusBar()
    set bar to current application's NSStatusBar's systemStatusBar
    set StatusItem to bar's statusItemWithLength:-1.0
    -- set up the initial NSStatusBars title
    StatusItem's setTitle:"Play/Pause YouTube"
    -- set up the initial NSMenu of the statusbar
    set newMenu to current application's NSMenu's alloc()'s initWithTitle:"Custom"
    newMenu's setDelegate:me (*
    Requied delegation for when the Status bar Menu is clicked  the menu will use the delegates method (menuNeedsUpdate:(menu)) to run dynamically update.*)
    StatusItem's setMenu:newMenu
end makeStatusBar

on makeMenus()
    newMenu's removeAllItems() -- remove existing menu items
    set someListInstances to {"Play/Pause YouTube - Safari", "Play/Pause YouTube - Chrome", "Quit"}
    repeat with i from 1 to number of items in someListInstances
        set this_item to item i of someListInstances
        set thisMenuItem to (current application's NSMenuItem's alloc()'s initWithTitle:this_item action:("someAction" & (i as text) & ":") keyEquivalent:"")
        (newMenu's addItem:thisMenuItem)
        (thisMenuItem's setTarget:me) -- required for enabling the menu item
    end repeat
end makeMenus

on someAction1:sender
    clickClassName2("ytp-play-button ytp-button", 0)
end someAction1:

on someAction2:sender
    clickClassName("ytp-play-button ytp-button", 0)
end someAction2:

on someAction3:sender
    quit me
end someAction3:

to clickClassName2(theClassName, elementnum)
    if application "Safari" is running then
        try
            tell application "Safari"
                tell window 1 to set current tab to tab 1 whose URL contains "youtube"
                do JavaScript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();" in document 1
            end tell
        end try
    end if
end clickClassName2

to clickClassName(theClassName, elementnum)
    tell application "Google Chrome" to (tabs of window 1 whose URL contains "youtube")
    set youtubeTabs to item 1 of the result
    tell application "Google Chrome"
        execute youtubeTabs javascript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();"
    end tell
end clickClassName

enter image description here

If you want your new... Play Pause YouTube Status Menu.app to only be visible in the status menu and not in the Dock, you can right-click on the app in Finder and select the option to "Show Package Contents". In the Contents folder, open the Info.plist file in any text editor and add the following two lines. Then save and close that file.

<key>LSBackgroundOnly</key>
<true/>

If you are not comfortable editing the .plist file directly, this following AppleScript code will allow you to choose the application to hide from the Dock when it is running.

If the chosen application is already set to be hidden from the Dock, the only option you will be given is to unhide the application from being visible in the Dock while it is running… And vice versa.

This script is especially handy for a hiding "stay open applications" with idle handlers' application icons from appearing in the Dock while running.

property fileTypes : {"com.apple.application-bundle"}
property plistFileItem : "  <key>LSBackgroundOnly</key>" & linefeed & " <true/>"

activate
set chosenApp to (choose application with prompt ¬
    "Choose  The Application You Want Hidden From The Dock While It Is Running" as alias)

tell application "System Events" to set appName to name of chosenApp
set plistFile to ((POSIX path of chosenApp) & "/Contents/info.plist") as string
set plistFileContents to (read plistFile)
set plistFileItemExists to plistFileItem is in plistFileContents

if plistFileItemExists then
    activate
    set theChoice to button returned of (display dialog ¬
        "Would you like to un-hide " & quote & appName & quote & ¬
        " from the Dock while it's running?" buttons {"Cancel", "Un-Hide"} ¬
        default button 2 cancel button 1 with title "Make A Choice")
else
    activate
    set theChoice to button returned of (display dialog ¬
        "Would you like to hide " & quote & appName & quote & ¬
        " from the Dock while it's running?" buttons {"Cancel", "Hide"} ¬
        default button 2 cancel button 1 with title "Make A Choice")
end if

if theChoice is "Hide" then
    tell application "System Events" to tell contents of property list file plistFile ¬
        to make new property list item at end with properties ¬
        {kind:string, name:"LSBackgroundOnly", value:true}
else if theChoice is "Un-Hide" then
    tell application "System Events" to tell contents of property list file plistFile ¬
        to make new property list item at end with properties ¬
        {kind:string, name:"LSBackgroundOnly", value:false}
else
    return
end if


************ ORIGINAL SOLUTION ************

This script will click on the Play/Pause button on a video playing in YouTube in Google Chrome, whether or not Google Chrome is visible.

to clickClassName(theClassName, elementnum)
    tell application "Google Chrome" to (tabs of window 1 whose URL contains "youtube")
    set youtubeTabs to item 1 of the result
    tell application "Google Chrome"
        execute youtubeTabs javascript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();"
    end tell
end clickClassName    

clickClassName("ytp-play-button ytp-button", 0)

This is the script version to work with Safari

to clickClassName2(theClassName, elementnum)
    tell application "Safari"
        tell window 1 to set current tab to tab 1 whose URL contains "youtube"
        do JavaScript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();" in document 1
    end tell
end clickClassName2

clickClassName2("ytp-play-button ytp-button", 0)

In an effort to give the OP A complete AppleScript solution, I have taken my original answer one step further..

UPDATE

I finally figured it out. I created an AppleScript application in Xcode. Originally, my project only started with a one button window to control YouTube videos currently active in Chrome or Safari. This project has grown a little bit into an application that contains several utilities. This GIF shows the YouTube Pause button controlling YouTube in Chrome and Safari. I linked the button actions to the AppleScript I originally wrote in script editor.

enter image description here

This is a snapshot of the Xcode application Working in the AppDelegate.applescript file.

enter image description here

Here is the code in that file I created to make the program work.

script AppDelegate

    property parent : class "NSObject"
    
    
    -- IBOutlets
    property theWindow : missing value
    
    to clickClassName(theClassName, elementnum) -- Handler for pausing YouTube in Chrome
        if application "Google Chrome" is running then
            try
                tell application "Google Chrome" to (tabs of window 1 whose URL contains "youtube")
                set youtubeTabs to item 1 of the result
                tell application "Google Chrome"
                    execute youtubeTabs javascript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();"
                end tell
            end try
        end if
    end clickClassName
    
    to clickClassName2(theClassName, elementnum) -- Handler for pausing YouTube in Safari
        if application "Safari" is running then
            try
                tell application "Safari"
                    tell window 1 to set current tab to tab 1 whose URL contains "youtube"
                    do JavaScript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();" in document 1
                end tell
            end try
        end if
    end clickClassName2

    on doSomething:sender -- Calls the Chrome YouTube Handler
        clickClassName("ytp-play-button ytp-button", 0)
    end doSomething:

    on doSomething14:sender -- Calls the Safari YouTube Handler
        clickClassName2("ytp-play-button ytp-button", 0)
    end doSomething14:

    on doSomething2:sender -- Hide and or show the Menu Bar
        tell application "System Preferences"
            reveal pane id "com.apple.preference.general"
        end tell
        tell application "System Events" to tell process "System Preferences" to tell window "General"
            click checkbox "Automatically hide and show the menu bar"
        end tell
        delay 1
        quit application "System Preferences"
    end doSomething2:
    
    on doSomething3:sender -- Sets Display resolution to the second lowest setting (15 inch Built In Retina Display - MBP)
        tell application "System Preferences"
            reveal anchor "displaysDisplayTab" of pane "com.apple.preference.displays"
        end tell
        tell application "System Events" to tell process "System Preferences" to tell window "Built-in Retina Display"
            click radio button "Scaled" of radio group 1 of tab group 1
            click radio button 2 of radio group 1 of group 1 of tab group 1
        end tell
        quit application "System Preferences"
    end doSomething3:
    
    on doSomething4:sender -- Sets Display resolution to the second highest setting (15 inch Built In Retina Display - MBP)
        tell application "System Preferences"
            reveal anchor "displaysDisplayTab" of pane "com.apple.preference.displays"
        end tell
        tell application "System Events" to tell process "System Preferences" to tell window "Built-in Retina Display"
            click radio button "Scaled" of radio group 1 of tab group 1
            click radio button 4 of radio group 1 of group 1 of tab group 1
        end tell
        quit application "System Preferences"
    end doSomething4:
    
    on doSomething5:sender -- Sets Display resolution to the highest setting (15 inch Built In Retina Display - MBP)
        tell application "System Preferences"
            reveal anchor "displaysDisplayTab" of pane "com.apple.preference.displays"
        end tell
        tell application "System Events" to tell process "System Preferences" to tell window "Built-in Retina Display"
            click radio button "Scaled" of radio group 1 of tab group 1
            click radio button 5 of radio group 1 of group 1 of tab group 1
        end tell
        quit application "System Preferences"
    end doSomething5:
    
    on doSomething6:sender -- Sets Display resolution to the lowest setting (15 inch Built In Retina Display - MBP)
        tell application "System Preferences"
            reveal anchor "displaysDisplayTab" of pane "com.apple.preference.displays"
        end tell
        tell application "System Events" to tell process "System Preferences" to tell window "Built-in Retina Display"
            click radio button "Scaled" of radio group 1 of tab group 1
            click radio button 1 of radio group 1 of group 1 of tab group 1
            delay 0.1
            click button "OK" of sheet 1
            quit application "System Preferences"
        end tell
    end doSomething6:

    on doSomething7:sender -- Displays a dialog with your current IP
        tell current application to display dialog (do shell script "curl ifconfig.io") with icon 2 buttons "OK" default button 1 with title "Your Current IP Address Is.." giving up after 5
    end doSomething7:
    
    on doSomething8:sender -- Shows hidden files in Finder
        do shell script "defaults write com.apple.finder AppleShowAllFiles TRUE\nkillall Finder"
    end doSomething8:
    
    on doSomething9:sender -- Hides hidden files in Finder if they are showing
        do shell script "defaults write com.apple.finder AppleShowAllFiles FALSE\nkillall Finder"
    end doSomething9:

    on doSomething10:sender  -- Brightness Highest
        tell application "System Preferences"
            reveal anchor "displaysDisplayTab" of pane "com.apple.preference.displays"
        end tell
        tell application "System Events" to tell process "System Preferences" to tell window "Built-in Retina Display"
        set value of value indicator 1 of slider 1 of group 2 of tab group 1 to 12
        end tell
        quit application "System Preferences"
    end doSomething10:

    on doSomething11:sender -- Brightness Lowest
        tell application "System Preferences"
            reveal anchor "displaysDisplayTab" of pane "com.apple.preference.displays"
        end tell
        tell application "System Events" to tell process "System Preferences" to tell window "Built-in Retina Display"
        set value of value indicator 1 of slider 1 of group 2 of tab group 1 to 0.1
        end tell
        quit application "System Preferences"
    end doSomething11:

    on doSomething12:sender -- Zoom
        tell application "System Events"
            key code 28 using {command down, option down}
        end tell
    end doSomething12:

    on doSomething13:sender -- Dictation On/Off
        tell application "System Events"
            keystroke "x" using {option down}
        end tell
    end doSomething13:

    on doSomething15:sender -- Enables Screensaver as Desktop background
        tell application "System Events"
            do shell script "/System/Library/Frameworks/ScreenSaver.framework/Resources/ScreenSaverEngine.app/Contents/MacOS/ScreenSaverEngine -background"
        end tell
    end doSomething15:

    on doSomething16:sender -- Kills Screensaver Desktop background
        try
            tell application id "com.apple.ScreenSaver.Engine" to quit
        end try
    end doSomething16:


    on applicationWillFinishLaunching:aNotification
        -- Insert code here to initialize your application before any files are opened

    end applicationWillFinishLaunching:
    
    on applicationShouldTerminate:sender
        -- Insert code here to do any housekeeping before your application quits

        
        return current application's NSTerminateNow
    end applicationShouldTerminate:

    on applicationShouldTerminateAfterLastWindowClosed:sender -- Quits app when clicking red x
        
        return TRUE
        
    end applicationShouldTerminateAfterLastWindowClosed:

end script

I updated the code so that the YouTube tab in Chrome doesn't need to be the visible or active tab when clicking the YouTube Pause Button created in Xcode

Here is a link to download the entire Xcode project

enter image description here

WARNING: The desktop screen saver function will freeze the App. After force quit and re-open, The desktop screensaver function to exit active screen saver will work.

Afterthoughts: I probably should have wrapped each of the AppleScript codes in "try" statements to avoid all sorts of error messages for those playing with this project,who don't have the same system and computer type that I do. (MacBook Pro 15" OS Sierra 10.12.6)

For the zoom function To work, it must be enabled in system preferences.

enter image description here

For the toggling of “Dictation on/off” to function correctly, the short cut to enable dictation commands in system preferences must match the shortcut used in the script

enter image description here

on doSomething13:sender -- Dictation On/Off
    tell application "System Events"
        keystroke "x" using {option down}
    end tell
end doSomething13:

Currently I am working on the ability to toggle between the application running windowed or menu bar only

14
  • Setting aside the display dialing ... you only need this one line of code tell application "Google Chrome" to execute front window's active tab javascript "document.getElementsByClassName('ytp-play-button ytp-button')['0'].click();". Since the OP wants to "pause (& un-pause) a currently playing YouTube video", Google is already open and it could be minimized with the active tab playing and the aforementioned one line of code will act upon it. Therefore no need to activate the window or as in your code, use launch as this is what's stated in the documentation, continued in next comment... Apr 22, 2017 at 1:05
  • 3
    This is a very clever solution! I decided to go with the third-party program, BeardedSpice, as previously suggested in a comment by enzo, because BeardedSpice works even if the Chrome window that contains the video is minimized, and this Chrome window will remain minimized. BeardedSpice also works with a litany of online media players (not only YouTube). But, I'm amazed that you figured out how to do this in AppleScript. Apr 25, 2017 at 23:32
  • 1
    It would be very nice if you would zip archive the Xcode Project Files and provide a download link for the archive. :) Jul 28, 2017 at 14:14
  • 1
    I'm just cleaning up the code a bit and I will do what you ask shortly :)
    – wch1zpink
    Jul 28, 2017 at 14:15
  • 1
    Thanks for sharing the project files. If I could up vote your answer again I would. :) Jul 28, 2017 at 22:33
1

Heres how to get in the menu bar with pure AppleScript. Save as Aplication with stay open after run handler:

P.S. I stole the code for the actual play/pause functions from @wch1zpink so please upvote their answer also

--AppleScript: menu bar script -- Created 2017-03-03 by Takaaki Naganoya adapted by Josh Brown
--2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
--http://piyocast.com/as/archives/4502

property aStatusItem : missing value

on run
    init() of me
end run

on init()
    set aList to {"Google Chrome", "⏯", "", "Safari", "⏯​", "", "Quit"}
    set aStatusItem to current application's NSStatusBar's systemStatusBar()'s statusItemWithLength:(current application's NSVariableStatusItemLength)

    aStatusItem's setTitle:"🎛"
    aStatusItem's setHighlightMode:true
    aStatusItem's setMenu:(createMenu(aList) of me)
end init

on createMenu(aList)
    set aMenu to current application's NSMenu's alloc()'s init()
    set aCount to 1
    repeat with i in aList
        set j to contents of i
        if j is not equal to "" then
            set aMenuItem to (current application's NSMenuItem's alloc()'s initWithTitle:j action:"actionHandler:" keyEquivalent:"")
        else
            set aMenuItem to (current application's NSMenuItem's separatorItem())
        end if
        (aMenuItem's setTarget:me)
        (aMenuItem's setTag:aCount)
        (aMenu's addItem:aMenuItem)
        if j is not equal to "" then
            set aCount to aCount + 1
        end if
    end repeat

    return aMenu
end createMenu

on actionHandler:sender
    set aTag to tag of sender as integer
    set aTitle to title of sender as string

    if aTitle is "Quit" then
        current application's NSStatusBar's systemStatusBar()'s removeStatusItem:aStatusItem
    end if
    #Chrome
    if aTitle is "⏯" then
        clickClassName("ytp-play-button ytp-button", 0)
    end if
    #Safari
    if aTitle is "⏯​" then
        clickClassName2("ytp-play-button ytp-button", 0)
    end if
end actionHandler:

to clickClassName(theClassName, elementnum)
    tell application "Google Chrome" to (tabs of window 1 whose URL contains "youtube")
    set youtubeTabs to item 1 of the result
    tell application "Google Chrome"
        execute youtubeTabs javascript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();"
    end tell
end clickClassName

to clickClassName2(theClassName, elementnum)
    tell application "Safari"
        tell window 1 to set current tab to tab 1 whose URL contains "youtube"
        do JavaScript "document.getElementsByClassName('" & theClassName & "')[" & elementnum & "].click();" in document 1
    end tell
end clickClassName2
6
  • 1
    Two issue I see, the first being if you quit from the menu bar the AppleScript Application Dock Tile is still there and the app then has to be quit separately. You could add a quit command to the if aTitle is "Quit" then block after the current application's ... line of code to resolve this. The second issue is symbols you're using do not show well when the Use dark menu bar and Dock General System Preference is selected. You really can't see the symbols until you mouse over them. You might consider adding text to the menu item with the symbols., e.g.: Play/Pause YouTube ⏯​ Jul 17, 2018 at 21:54
  • Thanks for suggestions regarding dark mode will adjust. I will fix quit issue.
    – JBis
    Jul 17, 2018 at 21:55
  • 1
    Also, when creating a menu extra app such as this, I like to hide the App's Dock Tile with LSUIElement = 1 added to the name.app/Contents/Info.plist file. IMO There is no need to have the App's Dock Tile show for this type of menu extra app. Jul 17, 2018 at 22:01
  • @user3439894 Knew about that I have more my apps just forgot to add feel free to edit that in.
    – JBis
    Jul 17, 2018 at 22:02
  • Also note that the --http://piyocast.com/as/archives/4502 comment in the code is no longer valid however this answer Applescript run from menu bar? by the original code author contains the original code that used to be at that URL. The answer also includes the defaults command for hiding the Dock Tile, e.g: defaults write /Applications/name_of_app.app/Contents/Info.plist LSUIElement -bool yes Jul 17, 2018 at 22:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .