You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Shiny中播放会话期间生成的无路径音频文件?

解决Shiny中播放会话生成音频的问题

这个问题我之前做项目时也碰到过!针对这种没有预设文件路径、会话期间动态生成的音频,有两个实用的解决思路,结合你的需求给你详细拆解:

方法1:将音频转为Base64编码直接嵌入

tags$audio的src属性不仅支持文件路径,还能接受Data URI格式的内容——也就是把音频文件编码成Base64字符串直接嵌入到HTML里,完全不需要文件路径。

具体实现步骤:

  1. 生成音频后,将其转为原始二进制数据
  2. 用Base64编码工具把二进制数据转成字符串
  3. 把编码后的字符串拼接到data:audio/wav;base64,后面,作为tags$audiosrc

给你写个可运行的示例:

library(shiny)
library(audio)
library(base64enc)

ui <- fluidPage(
  actionButton("generate", "生成并播放音频"),
  uiOutput("audio_player")
)

server <- function(input, output, session) {
  observeEvent(input$generate, {
    # 会话期间动态生成音频(这里用正弦波示例)
    fs <- 44100
    duration <- 2
    t <- seq(0, duration, length.out = fs * duration)
    wave <- sin(2 * pi * 440 * t)
    audio_obj <- audio::load.wave(raw = TRUE, sample.rate = fs, channels = 1, bits = 16)
    audio_obj@left <- wave
    
    # 将音频转为Base64编码
    temp_file <- tempfile(fileext = ".wav")
    save.wave(audio_obj, temp_file)
    audio_base64 <- base64encode(temp_file)
    file.remove(temp_file) # 清理临时文件
    
    # 渲染音频播放器
    output$audio_player <- renderUI({
      tags$audio(
        src = paste0("data:audio/wav;base64,", audio_base64),
        type = "audio/wav",
        controls = TRUE
      )
    })
  })
}

shinyApp(ui, server)

方法2:用临时文件+Shiny文件服务

如果音频文件比较大,Base64编码会让页面加载变慢,这时候可以把生成的音频保存到Shiny的临时目录,然后用session$fileUrl()生成一个临时访问URL,供tags$audio调用。

具体实现示例:

library(shiny)
library(audio)

ui <- fluidPage(
  actionButton("generate", "生成并播放音频"),
  uiOutput("audio_player")
)

server <- function(input, output, session) {
  observeEvent(input$generate, {
    # 动态生成音频
    fs <- 44100
    duration <- 2
    t <- seq(0, duration, length.out = fs * duration)
    wave <- sin(2 * pi * 440 * t)
    audio_obj <- audio::load.wave(raw = TRUE, sample.rate = fs, channels = 1, bits = 16)
    audio_obj@left <- wave
    
    # 保存到临时文件(用tempfile生成唯一文件名,避免冲突)
    temp_wav <- tempfile(fileext = ".wav")
    save.wave(audio_obj, temp_wav)
    
    # 生成Shiny可访问的临时URL
    audio_url <- session$fileUrl(temp_wav, contentType = "audio/wav")
    
    # 渲染播放器
    output$audio_player <- renderUI({
      tags$audio(
        src = audio_url,
        type = "audio/wav",
        controls = TRUE
      )
    })
    
    # 会话结束后清理临时文件(可选,避免占空间)
    session$onSessionEnded(function() {
      file.remove(temp_wav)
    })
  })
}

shinyApp(ui, server)

小提示:

  • 如果用的是其他音频生成包(比如tuneR),只需要调整生成和保存音频的代码逻辑,Base64或临时文件的思路是通用的
  • 临时文件方法要注意文件名唯一性,tempfile()会自动生成唯一名称,不用担心会话间冲突

内容的提问来源于stack exchange,提问作者AES

火山引擎 最新活动