如何在Shiny中播放会话期间生成的无路径音频文件?
解决Shiny中播放会话生成音频的问题
这个问题我之前做项目时也碰到过!针对这种没有预设文件路径、会话期间动态生成的音频,有两个实用的解决思路,结合你的需求给你详细拆解:
方法1:将音频转为Base64编码直接嵌入
tags$audio的src属性不仅支持文件路径,还能接受Data URI格式的内容——也就是把音频文件编码成Base64字符串直接嵌入到HTML里,完全不需要文件路径。
具体实现步骤:
- 生成音频后,将其转为原始二进制数据
- 用Base64编码工具把二进制数据转成字符串
- 把编码后的字符串拼接到
data:audio/wav;base64,后面,作为tags$audio的src值
给你写个可运行的示例:
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




