rshinypngmp4shinyapps

Shiny app with mp4 movie runs locally, but not on shinyapps.io


Consider the following minimal reprex:

library(shiny)
library(stringr)
library(av)

ui <- fluidPage(
   
   sidebarPanel(

      actionButton('movie_run', "Let's Go!")
      
   ), 
   
   mainPanel(uiOutput("movie"))
   
)


server <- function (input, output) {
   
   observeEvent(input$movie_run, {
      
      output$movie <- NULL
      
      for (i in 1:48) {
         
         plot.mat <- matrix(data = rnorm(n = 100), nrow = 10, ncol = 10)
         
         png(filename = file.path("www", paste0(str_pad(
             string = i, width = 3, side = "left", pad = "0"), ".png")))
         
         print("PNG file successfully created!")
         
         par(mar = rep(0,4))
         
         print("Margins successfully set!")
         
         image(plot.mat)
         
         print("Image successfully plotted!")
         
         dev.off()
         
         print("Plotting Device successfully closed!")
         
      }
      
      png.files <- file.path("www", list.files(path = "www", pattern = "\\.png$"))
      
      av_encode_video(input = png.files, 
                      output = file.path("www", "movie.mp4"), 
                      framerate = 24)
      
      unlink(x = png.files)
      
      output$movie <- renderUI({
         
         tags$video(
            width="auto", height="auto", controls="", autoplay = "", loop = "", 
            tags$source(src=paste0("movie.mp4"), type="video/mp4")
         )
         
      })
      
   })
   
}

(The app requires to have a folder called "www" in the app folder)

The app runs fine on my local machine (specs see below), but on shinyapps.io I get in the logs:

[1] "PNG file successfully created!"
[1] "Margins successfully set!"
Warning: Error in plot.new: could not open file 'www/001.png'
15: <Anonymous>
13: fn
8: retry
7: connect$retryingStartServer
6: eval
5: eval
4: eval
3: eval
2: eval.parent
1: local

And the application greys out and shows a "Disconnected from the Server. Reload" message.

I have consulted this FAQ and this SO answer, which suggests to use file.path for platform-independent file paths and graphics.off to close plotting devices, to no avail. This related question was solved by using relative file paths, which I did anyway.

Curiously enough, the app sometimes, but rarely works.

I'm wondering whether my storage space on shinyapps.io could be the problem (other apps running), but according to the shinyapps.io documentation, this should not be the case (ephemeral storage, data deleted after a session is closed).

Local sessionInfo():

R version 4.3.0 Patched (2023-05-02 r84382)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.0.1

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/C/en_US.UTF-8

time zone: Europe/Zurich
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] rsconnect_1.0.1 av_0.8.3        stringr_1.5.0   shiny_1.7.4    

loaded via a namespace (and not attached):
 [1] crayon_1.5.2     vctrs_0.6.2      cli_3.6.1        rlang_1.1.1      stringi_1.7.12   renv_1.0.0       promises_1.2.0.1
 [8] jsonlite_1.8.4   xtable_1.8-4     glue_1.6.2       openssl_2.0.6    askpass_1.1      htmltools_0.5.5  httpuv_1.6.9    
[15] sass_0.4.6       jquerylib_0.1.4  ellipsis_0.3.2   fastmap_1.1.1    lifecycle_1.0.3  memoise_2.0.1    compiler_4.3.0  
[22] Rcpp_1.0.11      rstudioapi_0.14  later_1.3.1      digest_0.6.31    R6_2.5.1         curl_5.0.2       magrittr_2.0.3  
[29] bslib_0.4.2      tools_4.3.0      withr_2.5.0      mime_0.12        cachem_1.0.8

Any ideas?


Solution

  • As mentioned in the comments, rsconnect::deployApp does not copy empty directories to the remote server. The problem is solved when you put a .txt file (or presumably any other file) into www locally and deploy then. This way, www is copied and the app works as desired.

    Thanks to r2evans for pointing me in the right direction.