Search code examples
rimagevideoavi

R, edit movie files or avi files?


I have a bunch of .avi files I would like to load into R, breakdown each frame as an individual image, arrange the images, and save as a separate image. In spite of a sincere effort to try to find a package to load .avi files, I can't find anything.

1) is it possible to load and work with avi files in r?

2) how is this done?

3) is there a specific library for this?

Ive seen several examples using linux, such as this post, but I'm hoping for an R solution.

Converting AVI Frames to JPGs on Linux


Solution

  • I figured this out. As indicated in the comments section, ffmpeg is the package called by various packages in R to load videos into the R environment. The Imager package has a function called "load.video.internal" that works well and uses ffmpeg. I had to down load the package from github because this function was not available in the version I installed using "install.packages". I ended up copy/pasting the function from the source package and commenting out the reference to the "has.ffmpeg" function because it kept hanging at this step. Using paste, I was able to indicate the file path and load an avi file successfully.

    Modified load.video.internal function:

    load.video.internal <- function(fname,maxSize=1,skip.to=0,frames=NULL,fps=NULL,extra.args="",verbose=FALSE)
    {
      # if (!has.ffmpeg()) stop("Can't find ffmpeg. Please install.")
      dd <- paste0(tempdir(),"/vid")
      if (!is.null(frames)) extra.args <- sprintf("%s -vframes %i ",extra.args,frames)
      if (!is.null(fps)) extra.args <- sprintf("%s -vf fps=%.4d ",extra.args,fps)
    
      arg <- sprintf("-i %s %s -ss %s ",fname,extra.args,as.character(skip.to)) %>% paste0(dd,"/image-%d.bmp")
      tryCatch({
        dir.create(dd)
        system2("ffmpeg",arg,stdout=verbose,stderr=verbose)
        fls <- dir(dd,full.names=TRUE)
        if (length(fls)==0) stop("No output was generated")
        ordr <- stringr::str_extract(fls,"(\\d)+\\.bmp") %>% stringr::str_split(stringr::fixed(".")) %>% purrr::map_int(~ as.integer(.[[1]])) %>% order
        fls <- fls[ordr]
        #Check total size
        imsz <- load.image(fls[[1]]) %>% dim %>% prod
        tsz <- ((imsz*8)*length(fls))/(1024^3)
        if (tsz > maxSize)
        {
          msg <- sprintf("Video exceeds maximum allowed size in memory (%.2d Gb out of %.2d Gb)",tsz,maxSize)
          unlink(dd,recursive=TRUE)
          stop(msg)
        }
        else
        {
          out <- map_il(fls,load.image) %>% imappend("z")
          out
    
        } },
        finally=unlink(dd,recursive=TRUE))
    
    }
    

    Example of its use:

    vid_in <- load.video.internal(paste("/home/phil/Documents/avi_files/Untitled.avi"))
    

    UPDATED SIMPLER VERSION:

    the magick package will read avi files using the image_read function.