Company logo
  • Empleos
  • Bootcamp
  • Acerca de nosotros
  • Para profesionales
    • Inicio
    • Empleos
    • Cursos y retos
    • Preguntas
    • Profesores
    • Bootcamp
  • Para empresas
    • Inicio
    • Nuestro proceso
    • Planes
    • Pruebas
    • Nómina
    • Blog
    • Comercial
    • Calculadora

0

103
Vistas
Extract the duration of hosted audio files in R (without downloading the file)

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?

  1. How can I replace the src= and iterate of a list of mp3s?
  2. How can I write out the duration so that I can further process this in R?
7 months ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

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)
7 months ago · Juan Pablo Isaza Denunciar

0

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:

  1. it does not wait for a user to click a button but tries to get the duration every second until it succeeds (since it takes a while for the metadata to get downloaded)
  2. the shiny app is wrapped into a function, so that the url of the source can be input
  3. upon success, the duration value is returned
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

7 months ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos