I have a list of hosted audio files for which I would like to get the duration of, without having to download the files themselves.
I can do this by creating a html DOM element <audio> and extracting the duration with the duration attribute. This works nicely in the following shinyapp: When clicking on the button "Click me", the duration is returned in an alert.
shinyApp(
ui = fluidPage(
useShinyjs(),
actionButton("btn", "Click me"),
tags$audio(id = "myaudio",
src = "https://download.samplelib.com/mp3/sample-3s.mp3",
type = "audio/mp3", autoplay = NA, controls = NA)
),
server = function(input, output) {
observeEvent(input$btn, {
runjs("alert(myaudio.duration);")
})
}
)
This is the point where I am stuck: How can I leverage this method to extract the duration of multiple (> 1'000) mp3s?
src= and iterate of a list of mp3s?R?This answer only works for one audio file
To get the duration of the audio and print it, we need to use js, an environment in shinyjs as follows:
Define get_duration as our JS and specify what happens when the input changes via Shiny.onInputChange. Here I have also used reactiveValues to store durations on change.
library(shinyjs)
library(shiny)
get_duration <- 'shinyjs.aud_duration = function(params) {
var duration = myaudio.duration;
Shiny.onInputChange("aud_duration", duration);
}'
ui <- fluidPage(
useShinyjs(),
extendShinyjs(text = get_duration, functions = "aud_duration"),
actionButton("btn", "Click me"),
tags$audio(id = "myaudio",
src = "https://download.samplelib.com/mp3/sample-3s.mp3",
type = "audio/mp3", autoplay = NA, controls = NA),
verbatimTextOutput("aud_duration")
)
server <- function(input, output) {
js$aud_duration()
durations <- reactiveValues(duration = NA)
observeEvent(input$btn,
durations$duration <- input$aud_duration
)
output$aud_duration <- renderText(durations$duration)
}
shinyApp(ui, server)
Thanks to @NelsonGon's answer, which solved part of the problem, I was able to develop a solution to my problem which scales and thus works on multiple urls. It solves the following problems:
get_duration <- function(src){
library(shinyjs)
library(shiny)
get_duration <- 'shinyjs.aud_duration = function(params) {
var duration = myaudio.duration;
Shiny.onInputChange("aud_duration", duration);
}'
ui <- fluidPage(
useShinyjs(),
extendShinyjs(text = get_duration, functions = "aud_duration"),
tags$audio(id = "myaudio",
src = src),
)
server <- function(input, output) {
js$aud_duration()
durations <- reactiveValues(duration = NA)
observe({
invalidateLater(1000)
if(!is.null(isolate(input$aud_duration))){
stopApp(input$aud_duration)
}
})
}
shiny::runGadget(ui, server)
}
it an be run as follows:
get_duration("https://download.samplelib.com/mp3/sample-3s.mp3")
[1] 3.239184