Subscribe
Search This Blog
Custom Search

Welcome to blogR! 

What is R?

My Goal for this Blog

My Background with R

How to Make a Video Clip with R (Windows only)

What We Will Need

  1. Super (Video Encoder)
  2. encodeVideo.R

Now Super is a lot more than what we need, but it's a wonderful tool if you ever need to convert one video format to another.  From Super, we specifically need mencoder to encode the video and optionally mplayer to play it.  This would also be possible with ffmpeg, but I found mencoder's syntax to be a bit simpler.

Motivation

R has the capacity for many different forms of graphical output with built-in devices jpeg, png, and pdf and can be extended with packages to support vector graphics (svg) like RSvgDevice

This made me wonder if there was a way to capture video with R created from a series of images.  I have often used R plots wrapped inside of a for loop to demonstrate some key ideas.  For example, I illustrate the linear relationship between an x and y variable as the correlation changes from 0 up to 1.


# Set up Data
x <- rnorm(100)
z <- rnorm(100)
z <- resid(lm(z~x)) # Make z orthogonal to x

x <- (x-mean(x)) / sd(x) # Standardize
z <- (z-mean(z)) / sd(z)
corr <- seq(from=0, to=1, length=201)

for(r in corr) {
y <- r*x + sqrt(1-r^2)*z # Makes cor(x,y) = r
plot(x, y,
main = paste("Correlation =", r),
pch = 19,
xlim = c(-3, 3),
ylim = c(-3, 3))
}

I remember seeing this for loop plotting idea for the first time and thinking it was extremely cool.  Now the downside is we have to copy and paste each time we want to run this.  Wouldn't it be nice to save this as a video and then just click play? 

Since each plot can be saved as an image within the for loop, we can create a series of images and then feed the images to a video encoder and create our clip.  For mencoder, we save these as jpegs with numbers for names, padding the front with 0's to ensure for example that 0011.jpg comes after 0002.jpg (2.jpg would come after 11.jpg normally).

Code Usage

encodeVideo.R has two functions in it.  getNumberFileName() is a wrapper to number the files properly with enough leading zeros.   encodeVideo() is the key function.  It requires 2 arguments.  The first argument is a function that creates a plot that requires a single argument.  The second argument is the vector of arguments that are fed into the function.  There are optional arguments like the flag play that says whether we should play the video after it's finished.  The key argument is encodePath which tells R where mencoder is installed.  If you installed Super to the default location, you do not need to set this argument.  encodeVideo() sets up a directory to create the images, invokes the shell function and then cleans up unnecessary files.

 Example


source("encodeVideo.R") # or whatever path it's located
# Set up the initial data
x <- rnorm(100)
z <- rnorm(100)
z <- resid(lm(z ~ x))
x <- (x - mean(x)) / sd(x)
z <- (z - mean(z)) / sd(z)

plotxycor <- function(r) {
# Plotting function for the for loop
y <- r*x + sqrt(1-r^2)*z

plot(x, y,
xlim = c(-3, 3),
ylim = c(-3, 3),
pch = 19,
cex = 1,
col = "blue",
main = paste("r = ", round(r, 4), "\n"))
}
# vector of correlation values going from 0 to 1 to -1 back to 0
corrIter <- c(0:100, 99:-100, -99:0)/100
encodeVideo(plotxycor, corrIter)

 

Output

Here is the output from above along with a few added bells and whistles.  I have also included the regression line, the 45 degree line and a density ellipse.

Regression to the Mean Illustration from Shaun Lysen on Vimeo.

Possible Uses

  • Create videos for pedagogical purposes (e.g. Demonstrating the Central Limit Theorem by showing the sampling distribution for winnings from the Roulette wheel as we increase the number of spins)
  • Embed videos within Presentations.  This is easily done with Powerpoint and for PDFs with the movie15 package (nice example) in LaTeX .  This can be wrapped around the Beamer package which produces beautiful presentations. 
  • Combined with the R2HTML package to add Flash video to dynamically generated webpages.

The possibilities are endless!

Future Plans

This could easily be extended to Linux.  I believe I would just need to change encodePath to /usr/bin/mencoder, using backslashes instead of Windows' stupid forward slashes.