<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/the-av-package-production-quality-video-in-r/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://ropensci.org/technotes/2018/10/06/av-release/"> rOpenSci - open tools for open science</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>At rOpenSci we are developing on a suite of packages that expose powerful graphics and imaging libraries in R. Our latest addition is <a rel="nofollow" href="https://github.com/ropensci/av#readme" target="_blank">av</a> – a new package for working with audio/video based on the <a rel="nofollow" href="https://www.ffmpeg.org/" target="_blank">FFmpeg</a> AV libraries. This ambitious new project will become the video counterpart of the <a rel="nofollow" href="https://cloud.r-project.org/web/packages/magick/vignettes/intro.html" target="_blank">magick</a> package which we use for working with images.</p>
<pre><code>install.packages(&quot;av&quot;)
av::av_demo()
</code></pre>
<p>The package can be installed directly from CRAN and includes a test function <code>av_demo()</code> which generates a demo video from random histograms.</p>
<h2>Why AV in R?</h2>
<p>One popular application is animating graphics by combining a sequence of graphics into a video. The <a rel="nofollow" href="https://cran.r-project.org/web/packages/animation/index.html" target="_blank">animation</a> and <a rel="nofollow" href="https://github.com/thomasp85/gganimate" target="_blank">gganimate</a> packages have many great examples. However up till now these packages would have to shell out to external software (such as the <code>ffmpeg</code> command line program) to generate the video. This process is inefficient and error prone and requires that the correct version of the external software is installed on the user/server machines, which is often not the case.</p>
<p>The <code>av</code> package takes away this technical burden. It uses the same libraries as FFmpeg, however because we interface directly to the C API, there is no need to shell out or install utilities. Everything we need is linked into the R package, which means that if the package is installed, it always works.</p>
<p>FFmpeg provides a full-featured video editing library, and now that the core package is in place, we can take things a step further. For example you can already enhance an animation with an audio track (to narrate what is going on or show off your karaoke skills) or apply one of the 100+ built-in <a rel="nofollow" href="https://ffmpeg.org/ffmpeg-filters.html#Video-Filters" target="_blank">video filters</a>. In future versions we also want to add things like screen capturing and reading raw video frames and audio samples for analysis in R.</p>
<h2>Create video from images</h2>
<p>The <code>av_encode_video()</code> function converts a set of images (png, jpeg, etc) into a video file with custom container format, codec, fps, and filters. The video format is determined from the file extension (mp4, mkv, flv, gif). Av supports all popular codecs and muxers (codecs compress the raw audio/video and a muxer is the container format which interleaves one or more audio and video streams into a file).</p>
<pre><code># Create some PNG images
png(&quot;input%03d.png&quot;, width = 1280, height = 720, res = 108)
for(i in 1:10){
  print(ggplot2::qplot(rnorm(100)))
}
dev.off()
png_files &lt;- sprintf(&quot;input%03d.png&quot;, 1:10)
av::av_encode_video(png_files, 'output.mp4', framerate = 1)
utils::browseURL('output.mp4')
</code></pre>
<p><video width="100%" controls><source type="video/mp4" src="https://jeroen.github.io/videos/output1.mp4">Your browser does not support the video tag.</video></p>
<h2>Create video from graphics</h2>
<p>The example above illustrates how to generate encode a set of png images into a HD video. For generating a video from the R graphics, av includes <code>av_capture_graphics()</code> – a convenient wrapper which automatically opens and closes the graphics device and then encodes the video:</p>
<pre><code>library(gapminder)
library(ggplot2)
makeplot &lt;- function(){
  datalist &lt;- split(gapminder, gapminder$year)
  lapply(datalist, function(data){
    p &lt;- ggplot(data, aes(gdpPercap, lifeExp, size = pop, color = continent)) +
      scale_size(&quot;population&quot;, limits = range(gapminder$pop)) + geom_point() + ylim(20, 90) +
      scale_x_log10(limits = range(gapminder$gdpPercap)) + ggtitle(data$year) + theme_classic()
    print(p)
  })
}

# Play 1 plot per sec
video_file &lt;- file.path(tempdir(), 'output.mp4')
av::av_capture_graphics(makeplot(), video_file, 1280, 720, res = 144)
utils::browseURL(video_file)
</code></pre>
<p><video width="100%" controls><source type="video/mp4" src="https://jeroen.github.io/videos/gapminder.mp4">Your browser does not support the video tag.</video></p>
<h2>Using av with gganimate</h2>
<p>The latest version of the super cool gganimate package already has built-in support for rendering video with av by using the <code>av_renderer()</code> output function. It is not yet on CRAN so you need to install from GitHub:</p>
<pre><code># Install gganimate
devtools::install_github(&quot;thomasp85/gganimate&quot;, &quot;thomasp85/transformr&quot;)
</code></pre>
<p>Try this example animation:</p>
<pre><code>library(gganimate)

# Create the gganimate plot
p &lt;- ggplot(airquality, aes(Day, Temp)) + 
  geom_line(size = 2, colour = 'steelblue') + 
  transition_states(Month, 4, 1) + 
  shadow_mark(size = 1, colour = 'grey')

# Render and show the video
df &lt;- animate(p, renderer = av_renderer('animation.mp4'), 
	width = 1280, height = 720, res = 104, fps = 25)
utils::browseURL('animation.mp4')
</code></pre>
<p><video width="100%" controls><source type="video/mp4" src="https://jeroen.github.io/videos/animation.mp4">Your browser does not support the video tag.</video></p>
<p>Check the <a rel="nofollow" href="https://github.com/thomasp85/gganimate" target="_blank">gganimate repo</a> for many cool examples.</p>
<h2>Filters</h2>
<p>AV also allows for adding a custom <a rel="nofollow" href="https://ffmpeg.org/ffmpeg-filters.html#Video-Filters" target="_blank">video filter chain</a>. For example this will use the same animation as above, then negate the colors, and apply an orange fade-in effect to the first 15 frames.</p>
<pre><code># Continue on the example above
myrenderer &lt;- av_renderer('animation.mp4', 
	vfilter = 'negate=1, fade=in:0:15:color=orange')
df &lt;- animate(p, renderer = myrenderer, 
	width = 1280, height = 720, res = 104, fps = 25)
utils::browseURL('animation.mp4')
</code></pre>
<p><video width="100%" controls><source type="video/mp4" src="https://jeroen.github.io/videos/fade.mp4">Your browser does not support the video tag.</video></p>
<p>Note that filters can affect the number of frames and final framerate of the video. Below the same example as we had earlier, however now we added a <code>vfilter</code> which increases the framerate of the video from 1 to 10 by interpolating the intermediate frames, which results in a smoother transition between the frames:</p>
<pre><code>library(gapminder)
library(ggplot2)
makeplot &lt;- function(){
  datalist &lt;- split(gapminder, gapminder$year)
  lapply(datalist, function(data){
    p &lt;- ggplot(data, aes(gdpPercap, lifeExp, size = pop, color = continent)) +
      scale_size(&quot;population&quot;, limits = range(gapminder$pop)) + geom_point() + ylim(20, 90) +
      scale_x_log10(limits = range(gapminder$gdpPercap)) + ggtitle(data$year) + theme_classic()
    print(p)
  })
}

# Play 1 input plot per sec, interpolate frames until 10 FPS
av::av_capture_graphics(makeplot(), 'smooth.mp4', 1280, 720, res = 104, 
	vfilter = 'framerate=fps=10')
utils::browseURL('smooth.mp4')
</code></pre>
<p><video width="100%" controls><source type="video/mp4" src="https://jeroen.github.io/videos/smooth.mp4">Your browser does not support the video tag.</video></p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://ropensci.org/technotes/2018/10/06/av-release/"> rOpenSci - open tools for open science</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/SsK15WqAo48" height="1"></a></div>