Serguei
Serguei

Reputation: 23

conditionally embed video in R-markdown (bookdown)

If I simply copy and paste an HTML code provided by YouTube into a .Rmd file, this works fine for gitbook output. Here is an example of the code

<iframe width="560" height="315" src="https://www.youtube.com/embed/9AI3BkKQhn0"
frameborder="0" allow="accelerometer; autoplay; encrypted-media;
gyroscope; picture-in-picture" allowfullscreen>
</iframe>

However, I get error messages for PDF and EPUB outputs. In order to avoid this, I thought I could use conditional compilation, e.g.

```{r}
if (knitr::is_html_output(excludes = "epub")) {
  <iframe width="560" height="315" 
  src="https://www.youtube.com/embed/9AI3BkKQhn0"
  frameborder="0" allow="accelerometer; autoplay; encrypted-media;
  gyroscope; picture-in-picture" allowfullscreen>
  </iframe>
}
```

However, this gets crossed out already in the RStudio editor for unexpected tokens. What is wrong here? Is there a way around this issue?

Upvotes: 2

Views: 848

Answers (2)

Andrew Olney
Andrew Olney

Reputation: 741

I wrote a function specifically for YouTube based on this R package and this example of how to reference images.

Here's a complete example of what it would look like in your document:

...as shown in the video \@ref(fig:sample-video).

(ref:sample-video) View the [YouTube video](https://youtu.be/M3_TWyva5yc), which enables readers of non-HTML editions to view it. YouTube formatting in Bookdown seems cleaner than Vimeo formatting. Add link to full video on a historical preservation server (such as CTDA) to avoid auto-play issue.

```{r sample-video, fig.cap="(ref:sample-video)", echo = F}
embed_youtube("M3_TWyva5yc")
```

The embed_youtube function must be defined in an .R file sourced by your bookdown project. In the bookdown example template, one such file is _common.R. Here's what that file looks like with embed_youtube added:

# example R options set globally
options(width = 60)

# example chunk options set globally
knitr::opts_chunk$set(
  comment = "#>",
  collapse = TRUE
  )

library(stringr)
embed_youtube <- function(youtube_id) {
  if (knitr::is_html_output(excludes = "epub")) {
    url <- str_c("https://www.youtube.com/embed/", youtube_id)
    return(knitr::include_url(url))
  } else {
    # Download thumbnail and use that
    dir_path <- 'downloadFigs4latex'
    if (!dir.exists(dir_path)) dir.create(dir_path)
    file_path <- str_c(dir_path, '/', knitr::opts_current$get()$label, '.jpg')
    if (!file.exists(file_path)) download.file( str_c("https://img.youtube.com/vi/", youtube_id, "/mqdefault.jpg"), destfile = file_path)
    return(knitr::include_graphics(file_path))
  }
}

This allows you to embed a YouTube video when the output is HTML but keep a link and a thumbnail of the video in the same location when the output is PDF or EPUB. You can maintain consistent url colors by putting urlcolor: blue in your index.Rmd file next to the other top-level yaml configuration like title and author.

Upvotes: 0

Martin C. Arnold
Martin C. Arnold

Reputation: 9668

Welcome to stackoverflow!

  • You are right, conditional compilation is a way to solve this. For this, we need to tell knitr whether the code chunk should be evaluated (conditional on the output format). This must be specified via the chunk option eval, not inside the code chunk.

  • Note that R cannot parse plain HTML code. Instead, you could pass HTML code as a string to cat() (which prints the string) and tell knitr to include the results using the chunk option results = 'asis'.

```{r, eval=knitr::is_html_output(excludes = "epub"), results = 'asis', echo = F}
cat(
'<iframe width="560" height="315" 
  src="https://www.youtube.com/embed/9AI3BkKQhn0"
  frameborder="0" allow="accelerometer; autoplay; encrypted-media;
  gyroscope; picture-in-picture" allowfullscreen>
  </iframe>'
)
```

Note that I've also set echo = F such that the code is not printed in the output.

Fore more on knitr options, see Yihui's excellent documentation.

Upvotes: 3

Related Questions