198

When I run R scripts I go do something else on a different desktop. If I don't check frequently, I never know when something is finished. Is there a way to invoke a beep (like a system beep) or get R to play a sound or notify growl via some code at the end of my script?

Maiasaura
  • 32,226
  • 27
  • 104
  • 108

22 Answers22

215

I have a package (beepr) with the sole purpose of making notification sounds in R which should work cross-platform. Run the following to install beepr and make a sound:

install.packages("beepr")
library(beepr)
beep()

More info at github: https://github.com/rasmusab/beepr

Rasmus Bååth
  • 4,827
  • 4
  • 29
  • 29
106
alarm()

The alarm function. It works by sending \a to the console

Mathias711
  • 6,568
  • 4
  • 41
  • 58
deinst
  • 18,402
  • 3
  • 47
  • 45
  • 1
    Simple and perfect, but useless if you've disabled PC speaker. Though I have no idea how does it run on Windows. – aL3xa Jul 29 '10 at 19:07
  • @Mulone: works for me, MacOSX 10.11.1, R 3.2.2; you hear the faint "poump" sound. – Benjamin Nov 12 '15 at 00:32
  • 11
    Doesn't work for me on Windows 7, x64, R 3.2.2. The `beepr` package below works fine though. – Augustin Jan 08 '16 at 18:17
69

On MacOSX you can let the computer speak:

system("say Just finished!")

and you can also change the artificial voice that will speak:

system("say -v Kathy Just finished!")

You can pick any voice that is available on your computer. On Yosemite you can see which voices are installed in System Preferences -> Dictation & Speech -> Text to Speech.

VLC
  • 1,119
  • 1
  • 12
  • 14
52

You should have it tweet when it's done: http://cran.r-project.org/web/packages/twitteR/index.html

CruelCow
  • 119
  • 1
  • 6
Ken Williams
  • 22,756
  • 10
  • 85
  • 147
  • 2
    Ken: That is f'ing brilliant! Now I don't even have to hang in the same room. I can go to happy hour and have a beer or few till I see a dm saying code is done! I just tried it out and it works great. – Maiasaura Jul 29 '10 at 22:32
42

alarm doesn't work on my Windows machine so I created a function that does actually make noise.

beep <- function(n = 3){
    for(i in seq(n)){
        system("rundll32 user32.dll,MessageBeep -1")
        Sys.sleep(.5)
    }
}

This clearly could only work on Windows but I don't guarantee it will even run on an arbitrary Windows computer. I've only tested it on my machine but I figured I'd post it in case anybody has the same problem with alarm that I do.

Dason
  • 60,663
  • 9
  • 131
  • 148
  • 1
    Weird. `alarm()` makes my machine make a noise (XP, running R interactively) – BenBarnes Aug 29 '12 at 09:14
  • 1
    Dason's code does not appear to work on my Windows 7 machine. – russellpierce Feb 27 '13 at 23:44
  • 1
    @drknexus The other options didn't work on my machine. This one worked on my machine. I never claimed it would work on any arbitrary machine but only provided it since `alarm()` didn't work on my machine and for some reason this does. – Dason Feb 28 '13 at 00:24
29

cat('Hello world!\a')

mpk
  • 319
  • 2
  • 3
  • Sorry Mario but that does not help at all. If I can see the screen then I can most certainly tell when it's done. I don't need to output anything more. I was looking for something audible. Sorry I dinged your answer (can't seem to undo that). – Maiasaura Jul 29 '10 at 22:36
  • 8
    Why is this getting downvoted? Look at the `alarm` source and you will see that what it does is just a `cat("\a")` call. – nico Jul 30 '10 at 06:38
  • Well, what do you know... here's a description: _Gives an audible or visual signal to the user._ but it's the same thing as `cat("foo\a")`. Maybe the users have read this as `cat("Hello world!\n")`? Hard to tell... – aL3xa Jul 30 '10 at 11:38
  • 3
    Didn't realize alarm() = cat('\a'), thanks for the tip. As a side note one can also do '\a' in C and C++ (which is how I have been using it to notify me of things being done). A second side note, if you are on OS X and do 'System Preferences' > 'Universal Access' > 'Hearing' > enable 'Flash the screen...' your whole screen blinks when 'a' is executed. – mpk Jul 30 '10 at 16:46
22

How about something reasonably OS independent for OSes with GUIs and web-browsers? It even works on RStudio Server!

browseURL('https://www.youtube.com/watch?v=QH2-TGUlwu4')
Zoe
  • 27,060
  • 21
  • 118
  • 148
russellpierce
  • 4,583
  • 2
  • 32
  • 44
17

Not only that, you can also also put some epic music from Youtube when the program is done looping :) (For Ubuntu/Debian:)

system("xdg-open 'http://www.youtube.com/watch?v=9jK-NcRmVcw'")
Dason
  • 60,663
  • 9
  • 131
  • 148
moldovean
  • 3,132
  • 33
  • 36
16

UPDATE:

With macOS 10.9 (Mavericks) and later, you can post notifications using plain AppleScript:

theTitle <- "A Title"
theMsg <- "A message here"

cmd <- paste("osascript -e ", "'display notification ", '"', theMsg, '"', ' with title ', '"', theTitle, '"', "'", sep='')
system(cmd)

This removes the need to install terminal-notifier, referenced below.

--

I've got terminal-notifier installed on my Mac to get desktop notifications from the command line. You can then wrap up a call to the system() command like this (change the path, obviously):

notify <- function(msgString='Message from R', titleString='Message from R', speakIt=FALSE) {
    cmd <- paste('~/terminal-notifier/terminal-notifier.app/Contents/MacOS/terminal-notifier -message ', '"', msgString, '"  -title "', titleString, '"', sep='')
    system(cmd)

    if (speakIt) {
        system(paste('say', msgString))
    }

}

You can call the function like this

notify("R is done", "Message from R", speakIt=TRUE)

to get a message like this:

enter image description here

Update: Included @VLC's say command.

Stewart Macdonald
  • 2,062
  • 24
  • 27
12

Please use shell.exec("url") to open some YouTube clip on Windows

nwinkler
  • 52,665
  • 21
  • 154
  • 168
Sweden
  • 129
  • 1
  • 3
10

Or if you're using GNU/Linux distro and have pcspkr module blacklisted (PC speaker was always annoying me), try combining system with some auditive/visual notification, e.g.

system("aplay -t wav /usr/share/sounds/phone.wav") # for auditive bell (an I mean it literary)
system("zenity --title=\"R script info\" --text=\"Script has finished with zero exit status\" --info") # for GTK dialog

You can check zenity manual if you prefer alert in, say, notification area... But, with system function, you can do pretty much anything: send an email, run some other script, reboot the machine, sudo rm -rf *.*, etc. anything... and I mean it.

But this stands only IF you're running GNU/Linux (or UNIX) distribution, otherwise, stick to Windows specific commands, though in that case, I can't give you much info...

aL3xa
  • 35,415
  • 18
  • 79
  • 112
  • 7
    The MacOSX equivalent to this is the `growlnotify` script (packaged with Growl (http://growl.info/): `system("growlnotify -t 'R script info' -m 'Finished!'")` – Michael Dunn Jul 30 '10 at 09:00
7

Inspired by beepr, this is the function I'm currently using for these kind of problems :D

work_complete <- function() {
  cat("Work complete. Press esc to sound the fanfare!!!\n")
  on.exit(beepr::beep(3))

  while (TRUE) {
    beepr::beep(4)
    Sys.sleep(1)
  }
}
Mullefa
  • 1,237
  • 1
  • 15
  • 27
7

take a look at this package: RPushBullet

An R interface to the Pushbullet messaging service which provides fast and efficient notifications (and file transfer) between computers, phones and tablets

RPushbullet is completely free and multi platform. As for your question, you can use this library to send a Push to your browser, but obviously it becomes amazing when you need something than can notify you while you are away. Moreover, the creator of the R package is the same of the well known Rcpp, Dirk Eddelbuettel. I'd say it's worth a shot!

Meme
  • 129
  • 1
  • 4
7

How about playing some music?

shell.exec("foo/Born.to.be.wild.mp3")
Chirayu Chamoli
  • 2,076
  • 1
  • 17
  • 32
3

Do this:

song <- function() {
    for(i in 1:2) {
        for(i in 1:4) {
            for(i in 1:4) {
                beep(7)
                Sys.sleep(0.25)
                beep()
                Sys.sleep(0.22)
            }
            beep(2)
        }
        beep(11)
    }
    beep(4)
} 

song()

You can jam out to it.

kraggle
  • 196
  • 2
  • 9
3

This thread is really old, but it is still one of the top Google results for this question and led me to use beepr for a while. Unfortunately, beepr appears to be abandoned and even more unfortunately, it causes frequent crashes (at least on Windows 10 with RStudio).

Luckily, it appears that R has added some functionality since this post was made that enables you to play sound fairly easily:

library(audio)
fname = "C:\\sounds\\sound.wav"
sfx <- load.wave(fname)
play(sfx)

However, this is pretty much exactly how beepr plays sound, so it is likely to crash in the same instances. @MikolajM's solution works on Windows 10, but it is a bit less robust and more unwieldy (and not as fun). For Windows, the solution proposed by @aL3xa seems the most promising, although it requires some prior setup. You need a program that can play sound from the command line like VLC. With VLC you will need to add it to your system PATH. Once you've done that, you can use the same approach they suggested like so:

system("vlc -I dummy --dummy-quiet c:\\sounds\\sound.wav vlc://quit", ignore.stdout = TRUE, ignore.stderr = TRUE)

The ignores are optional, but without them the command returns some gibberish that I prefer not to see in my console.

imfm
  • 119
  • 7
1

How about using Windows SpeechSynthesizer?

message <- "job done!"

system2(command = "PowerShell", 
        args = c("-Command", 
                 "\"Add-Type -AssemblyName System.Speech;",
                  "$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;",
                  paste0("$speak.Speak('", message, "');\"")
        ))
                                               

This may by nicely used in iterating operations and read something like "First job done", "Second job done" etc.:

say_something <- function(message) {
    
     message <- paste0("$speak.Speak('", message, "');\"")
    
     system2(command = "PowerShell", 
             args = c("-Command", 
                       "\"Add-Type -AssemblyName System.Speech;",
                       "$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;",
                                    
                       message
            ))
  }

operations <- c("1st.", "2nd.", "3rd.")
lapply(operations, function(x) say_something(message=paste(x, "job done")))

 

*Note, that this uses system defaul language settings. The example is based on english lector, it can be changed using SelectVoice method. To check available lectors use:

  system2(command = "PowerShell", 
        args = c("-Command", 
                 "\"Add-Type -AssemblyName System.Speech;",
                  "$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;",
                 "$speak.GetInstalledVoices().VoiceInfo")
        )

That gives:

    Gender                : Female
Age                   : Adult
Name                  : Microsoft Paulina Desktop
Culture               : pl-PL
Id                    : TTS_MS_PL-PL_PAULINA_11.0
Description           : Microsoft Paulina Desktop - Polish
SupportedAudioFormats : {}
AdditionalInfo        : {[Age, Adult], [Gender, Female], [Language, 415], [Name, Microsoft Paulina Desktop]...}

Gender                : Male
Age                   : Adult
Name                  : Microsoft David Desktop
Culture               : en-US
Id                    : TTS_MS_EN-US_DAVID_11.0
Description           : Microsoft David Desktop - English (United States)
SupportedAudioFormats : {}
AdditionalInfo        : {[Age, Adult], [Gender, Male], [Language, 409], [Name, Microsoft David Desktop]...}

Finally a function to select the lector by his "name" like "David", "Paulina" or "Hazel":

say_something <- function(message , voice) {
        
  voice <- paste0("\"$speak.SelectVoice('Microsoft ", voice, " Desktop');" )
  message <- paste0("$speak.Speak('", message, "');\"")
      
  system2(command = "PowerShell", 
          args = c("-Command", 
                    "\"Add-Type -AssemblyName System.Speech;",
                    "$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;",
                    voice,
                    message
          ))
}


operations <- c("1st.", "2nd.", "3rd.")

lapply(operations, function(x) say_something(message=paste(x, "job done"), voice="David"))
MikolajM
  • 354
  • 1
  • 8
1

Dason's answer is great, obviously, because it will work on basically any Windows machine without requiring anything except R itself.

But one thing I have been wondering is how to make these functions actually beep after a code is run.

If you do something like this:

beepR <- function(x, n = 3){
  for(i in seq(n)){
    system("rundll32 user32.dll,MessageBeep -1")
    Sys.sleep(.5)
  }
    return(x)
}

You can just pipe anything to it and it will return whatever you piped, so you can do like. See the example below.

fa <- psych::fa(x, 1) |> beepR()

I'm using here the native pipe |> that was introduced in R 4.1, but you can use the %>% pipe from the maggitr package if you like; they work the exact same way. Anyway, that will beep as soon as the analysis ends, and the variable fa will contain the results of the factor analysis.

Of course, here I used the beep function that Dason provided you, but you could just as easily add anything where I indicated below.

beepR <- function(x){
        # your code here #
        return(x)
    }

If you wish to add that function every time RStudio opens, refer to RStudio's Managing R with .Rprofile, .Renviron, Rprofile.site, Renviron.site, rsession.conf, and repos.conf to learn how to use a .Rprofile file.

0

You can use notify-send command:

system("notify-send \"R script finished running\"")
JonnyRobbie
  • 526
  • 5
  • 16
0

Because of these many ideas, I have created a solution without Internet access, because I work with a VPN client with Windows. So it plays a typical Windows sound, which is usually on any Windows operating system.

#Function with loop, press Esc to stopp      
    alarm2 <- function(){
      while(TRUE){
        system("cmd.exe",input="C:/Windows/WinSxS/amd64_microsoft-windows-shell-sounds_31bf3856ad364e35_10.0.17134.1_none_fc93088a1eb3fd11/tada.wav")
        Sys.sleep(1)
      }
    }

Function without loop

    alarm3 <- function(){
        system("cmd.exe",input="C:/Windows/WinSxS/amd64_microsoft-windows-shell-sounds_31bf3856ad364e35_10.0.17134.1_none_fc93088a1eb3fd11/tada.wav")
        Sys.sleep(1)
    }
  • 1
    Though you have answered this question in well format, Please refer this help page for better way to answer [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer) – v8-E Oct 01 '18 at 10:01
0

The following code produces a beep and does not depend on a .mp3 or .wav file:

switch(Sys.info()[['sysname']],
Linux = {
    system('play -n synth 0.1 tri  1000.0')}
)
dzmanto
  • 216
  • 2
  • 6
0

Combining some ideas on the thread, I implement this:

options(error = function() {
    if (interactive()) {
        # require("beepr"); beep(10)
        system("mplayer /usr/share/sounds/freedesktop/stereo/dialog-warning.oga ")
        system("notify-send -u normal 'R session' 'An error occured!'")
    }
})

I regularly use stop() on interactive session like Rstudio, on scripts I am working and want to re-run to a point. This way I can switch to another desktop while waiting. I may test it to '.Rprofile'

ThanasisN
  • 73
  • 1
  • 9