Goal
Play an audio clip for navigation whenever the reactive
value of position is in a certain range
What I tried
Based on other questions, I found that a button can be used to play an audio clip. For example:
An example with action button
library(shiny)
addResourcePath("Music", "Music")
audio_file1 <- "Music/in 200 m turn left.mp3"
ui <- fluidPage(
basicPage(
actionButton("play", "Play the Audio")
)
)
server <- function(input, output, session) {
observeEvent(input$play, {
insertUI(selector = "#play",
where = "afterEnd",
ui = tags$audio(src = audio_file1, type = "audio/mp3", autoplay = NA, controls = NA, style="display:none;")
)
})
}
shinyApp(ui, server)
My modifications without an action button
I want to autoplay the audio clip whenever the position x
is a certain value. For keeping the question short, I am providing x
inside server
in this example:
server <- function(input, output, session) {
x <- 1
observeEvent(if (x==1){return(x)}, {
insertUI(selector = "#play",
where = "afterEnd",
ui = tags$audio(src = audio_file1, type = "audio/mp3", autoplay = TRUE, controls = NA, style="display:none;")
)
})
}
However, that threw an error:
Warning: Error in eval_tidy: no function to return from, jumping to top level
[No stack trace available]
I have also separately tried using the uiOutput
and renderUI
as follows (server part):
output$audioo <- renderUI({
if (x > 0.5 & x < 1.5) {
tags$audio(src = audio_file_200_TL, type = "audio/mp3", autoplay = TRUE, controls = NA)
} else {
tags$h1("My header")
}
})
But that plays the audio when the app is just launched and the audio does not play when x
is in the provided range. How can I conditionally play an audio clip without using an action button?
CodePudding user response:
So x
is not an input
nor a reactive
. We need this as R process has to know the time to rerun the cycle. There are other hardcore solution which I am not recommending like shiny::invalidateLater()
.
Try sth like:
x_r <- reactive(x)
observeEvent(x_r(), {
if (x_r() == 1) {
insertUI(selector = "#play",
where = "afterEnd",
ui = tags$audio(src = audio_file1, type = "audio/mp3", autoplay = TRUE, controls = NA, style="display:none;"), immediate = TRUE
)
}
})
Btw be very careful with insertUI
, I do not like to use it as we might add the same element many times. More elegant strategy for me is to add the element by default and later only edit in the DOM, hide/show/edit. we could use shinyjs
package for such action. insertUI
often need immediate = TRUE
argument.
EDIT:
This app is working perfectly for me. The question is what is the x
in your app. mp3 taken from https://samplelib.com/sample-mp3.html.
library(shiny)
addResourcePath("Music", "Music")
audio_file1 <- "Music/sample-3s.mp3"
ui <- fluidPage(
basicPage(
tags$div(id = "AUDIO_MY"),
selectInput("STH", "STH", 1:10, 1)
)
)
server <- function(input, output, session) {
observeEvent(req(input$STH == "1"), {
insertUI(selector = "#AUDIO_MY",
where = "afterEnd",
ui = tags$audio(src = audio_file1, type = "audio/mp3", autoplay = NA, controls = NA, style="display:none;")
, immediate = TRUE)
})
}