Search code examples
rvideoffmpegtrimcut

Can I use R to trim a video, like I do with ffmpeg?


I have several video files that I need to trim/cut (i.e., cut 00:05:00 - 00:10:00 among 2-hour-long video). I can trim/cut each video by using ffmpeg. However, since I have +100 video files that need to be trimmed, I would like to use R loop function to do it.

I've found that there are several R packages that people use for video processing, such as imager or magick, but I cannot find a way to trim a video using R.

Can you help me? Thanks!


Solution

  • The basic approach to trimming a video with ffmpeg would be something like this:

    ffmpeg -i input.mp4 -ss 00:05:00 -to 00:10:00 -c copy output.mp4
    

    To create a batch file, you can put the following in a text file and save it as something like "trimvideo.bat" and run it in the relevant folder.

    @echo off
    :: loops across all the mp4s in the folder
    for %%A in (*.mp4) do ffmpeg -i "%%A"^
      :: the commands you would use for processing one file
      -ss 00:05:00 -to 00:10:00 -c copy ^
      :: the new file (original_trimmed.mp4)
      "%%~nA_trimmed.mp4"
    pause
    

    If you wanted to do this through R, you could do something like:

    # get a list of the files you're working with
    x <- list.files(pattern = "*.mp4")
    
    for (i in seq_along(x)) {
      cmd <- sprintf("ffmpeg -i %s -ss 00:05:00 -to 00:10:00 -c copy %_trimmed.mp4",
                     x[i], sub(".mp4$", "", x[i]))
      system(cmd)
    }
    

    I've used a similar approach in the past when I've wanted to cut specific parts from a file or multiple files. In those cases, I start with a data.frame similar to the following:

    df <- data.frame(file = c("file_A.mp4", "file_B.mp4", "file_A.mp4"),
                     start = c("00:01:00", "00:05:00", "00:02:30"),
                     end = c("00:02:20", "00:07:00", "00:04:00"),
                     output = c("segment_1.mp4", "segment_2.mp4", "segment_3.mp4"))
    df
    #         file    start      end        output
    # 1 file_A.mp4 00:01:00 00:02:20 segment_1.mp4
    # 2 file_B.mp4 00:05:00 00:07:00 segment_2.mp4
    # 3 file_A.mp4 00:02:30 00:04:00 segment_3.mp4
    

    I use sprintf to create the ffmpeg commands I want to run:

    cmds <- with(df, sprintf("ffmpeg -i %s -ss %s -to %s -c copy %s", 
                             file, start, end, output)) 
    cmds
    # [1] "ffmpeg -i file_A.mp4 -ss 00:01:00 -to 00:02:20 -c copy segment_1.mp4"
    # [2] "ffmpeg -i file_B.mp4 -ss 00:05:00 -to 00:07:00 -c copy segment_2.mp4"
    # [3] "ffmpeg -i file_A.mp4 -ss 00:02:30 -to 00:04:00 -c copy segment_3.mp4"
    

    And I run it using lapply(..., system):

    lapply(cmds, system)
    

    You can also look at the av package, but I've always just preferred using a loop at the terminal or creating the commands to be run using sprintf and using system().