在 R 中提取托管音频文件的持续时间(无需下载文件)

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

我有一个托管音频文件列表,我想获取这些文件的持续时间,而无需自己下载文件。

我可以通过创建 html DOM element <audio> and extracting the duration with the duration attribute 来做到这一点。这在以下 shinyapp 中运行良好:单击“单击我”按钮时,会在警报中返回持续时间。

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);")
    })
  }
)

这是我卡住的地方:如何利用此方法提取多个(> 1'000)mp3 的持续时间?

  1. 如何替换 src= 并迭代 mp3 列表?
  2. 如何写出持续时间,以便在 R 中进一步处理?

此答案仅适用于一个音频文件

要获取音频的持续时间并打印它,我们需要使用jsshinyjs中的一个环境如下:

定义 get_duration 作为我们的 JS 并指定当输入通过 Shiny.onInputChange 改变时会发生什么。在这里,我还使用 reactiveValues 来存储变化的持续时间。

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)

感谢@NelsonGon 的回答,它解决了部分问题,我能够针对我的问题开发一个解决方案,该解决方案可以扩展并因此适用于多个 urls。它解决了以下问题:

  1. 它不会等待用户单击按钮,而是尝试每秒获取持续时间直到成功(因为下载元数据需要一段时间)
  2. 闪亮的应用程序被包装成一个函数,因此可以输入源的url
  3. 成功后返回时长值
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)
}

它是 运行 如下:

get_duration("https://download.samplelib.com/mp3/sample-3s.mp3")
[1] 3.239184