jhudsl / ari

:dancers: The Automated R Instructor
https://jhudatascience.org/ari/
Other
146 stars 38 forks source link

Beamer presentation compatibility #30

Closed sebacea closed 3 years ago

sebacea commented 4 years ago

Is there a way to have beamer presentations narrated by ari?

muschellij2 commented 3 years ago

Since beamer compiles to PDF, then you should be able to PDF → PNG using pdftools::pdf_convert and then pass the resulting PNG files into images argument of ari_spin.

How do you see the "script" embedded in the beamer? In comments or some other notes area? Please reopen if that's clear.

sebacea commented 3 years ago

I understood the method in order to narrate beamers presentations. Nevertheless, I did not get the point regarding the embedded script you say.

muschellij2 commented 3 years ago

OK. So your beamer presentation is a PDF. A "script" is a text file with the number of lines equal to the number of slides in the PDF (also empty lines can be in the text file as well).

See example below

library(ari)
library(curl)
library(stringi)
library(pdftools)
#> Using poppler version 0.73.0

Download a Beamer

example beamer presentation

url = "http://www2.informatik.uni-freiburg.de/~frank/ENG/beamer/example/Beamer-class-example1.pdf"
tdir = tempfile()
dir.create(tdir, recursive = TRUE)
destfile = tempfile(fileext = ".pdf", tmpdir = tdir)
curl::curl_download(url, destfile)

Turn the PDF into PNGs

##########################################################
# Convert the PDF into PNGs
# this can be done
##########################################################
# get the number of pages
info = pdftools::pdf_info(destfile)
n_pages = info$pages
images = tempfile(tmpdir = tdir, fileext = "")
images = sprintf("%s_%04.0f.png", images, 1:n_pages)

PDF to PNGs

# converting the PDF to PNGs
out = pdftools::pdf_convert(destfile, filenames = images, dpi = 300)
#> Converting page 1 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0001.png... done!
#> Converting page 2 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0002.png... done!
#> Converting page 3 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0003.png... done!
#> Converting page 4 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0004.png... done!
#> Converting page 5 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0005.png... done!
#> Converting page 6 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0006.png... done!
#> Converting page 7 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0007.png... done!
#> Converting page 8 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0008.png... done!
#> Converting page 9 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0009.png... done!
#> Converting page 10 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0010.png... done!
#> Converting page 11 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0011.png... done!
#> Converting page 12 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0012.png... done!
#> Converting page 13 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0013.png... done!
#> Converting page 14 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0014.png... done!
#> Converting page 15 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0015.png... done!
#> Converting page 16 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0016.png... done!
#> Converting page 17 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0017.png... done!
#> Converting page 18 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0018.png... done!
#> Converting page 19 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431f2805ca/file714347c159dc_0019.png... done!

An example script

##########################################################
# Section to create script
# you wouldn't do this in practice
# but actually make a text file with all the narration
# needed for your video.
##########################################################
# here is the script
paragraphs = stringi::stri_rand_lipsum(n_paragraphs = length(out))
script_file = tempfile(fileext = ".txt")
writeLines(paragraphs, script_file)

Make he video from PNGs

video = ari::ari_spin(images = images, paragraphs = paragraphs)
#> Warning in pollyHTTP(action = "voices", verb = "GET", query = query, ...):
#> Forbidden (HTTP 403).
#> Warning in structure(out[["Voices"]], NextToken = out[["NextToken"]]): Calling 'structure(NULL, *)' is deprecated, as NULL cannot have attributes.
#>   Consider 'structure(list(), *)' instead.
isTRUE(video)
#> [1] TRUE
video_file = attr(video, "outfile")
video_file
#> [1] "/private/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmpf0uU6s/file714370c27c58.mp4"

Using ariExtra

Here we use pdf_to_ari to convert to MD file

####################################################
# You can also use ariExtra
####################################################
res = ariExtra::pdf_to_ari(path = destfile, script_file)
#> Converting PDF to PNGs
#> Converting page 1 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file7143739ffe80.png... done!
#> Converting page 2 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file7143cfdc0ce.png... done!
#> Converting page 3 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file7143677d1b0b.png... done!
#> Converting page 4 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file7143467aa441.png... done!
#> Converting page 5 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431db5cb8d.png... done!
#> Converting page 6 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file7143a46a538.png... done!
#> Converting page 7 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file7143240904cd.png... done!
#> Converting page 8 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71434c1a4136.png... done!
#> Converting page 9 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71434faf6742.png... done!
#> Converting page 10 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71434a446ed.png... done!
#> Converting page 11 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71433d2c73fc.png... done!
#> Converting page 12 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71433172c4c4.png... done!
#> Converting page 13 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file714365d43938.png... done!
#> Converting page 14 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71434ff8bfc2.png... done!
#> Converting page 15 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file714353f58292.png... done!
#> Converting page 16 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431b4f6a4e.png... done!
#> Converting page 17 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71437acc34e3.png... done!
#> Converting page 18 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file714374a46210.png... done!
#> Converting page 19 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file714354224443.png... done!
#> Making output_file directories
# open the file and then do rmarkdown::render
html_embedded_with_video = rmarkdown::render(res$output_file)
#> Writing out Wav for audio
#> Sample rate downsampled to 24000
#> '/usr/local/Cellar/ffmpeg/4.3.2_4/bin/ffmpeg' -y -f concat -safe 0 -i '/private/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmpf0uU6s/ari_input_La5ZNro4sGA4.txt' -i '/private/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmpf0uU6s/ari_audio_dTUDGUkOxfsc.wav' -c:v libx264 -c:a aac -ac 2    -shortest -vsync 2 -pix_fmt yuv420p  -vf fps=5,"scale=trunc(iw/2)*2:trunc(ih/2)*2"   -strict experimental -max_muxing_queue_size 9999 -threads 2 '/private/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmpf0uU6s/file714315afb5dc.mp4'
#> /usr/local/bin/pandoc +RTS -K512m -RTS file714315afb5dc.utf8.md --to html4 --output file714315afb5dc.html
#> 
#> Output created: file714315afb5dc.html
if (interactive()) browseURL(html_embedded_with_video)
ariExtra_video_file = sub(".html", ".mp4", html_embedded_with_video)
file.exists(ariExtra_video_file)
#> [1] TRUE

pass your own path

file = "~/Desktop/output_file.mp4"
file.exists(file)
#> [1] FALSE
res = ariExtra::pdf_to_ari(path = destfile, script_file, output = file,
                           output_file = tempfile(fileext = ".md"))
#> Converting PDF to PNGs
#> Converting page 1 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file7143333dae43.png... done!
#> Converting page 2 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file7143167bcafd.png... done!
#> Converting page 3 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file7143194bb393.png... done!
#> Converting page 4 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file714338fa84de.png... done!
#> Converting page 5 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71434729280b.png... done!
#> Converting page 6 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71435f040eac.png... done!
#> Converting page 7 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file714335f6ef0.png... done!
#> Converting page 8 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71436e6c504a.png... done!
#> Converting page 9 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file714390b62e9.png... done!
#> Converting page 10 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71434a8ab3a2.png... done!
#> Converting page 11 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file7143581776e9.png... done!
#> Converting page 12 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71436c7fe82d.png... done!
#> Converting page 13 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file714341641a01.png... done!
#> Converting page 14 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file714312e75931.png... done!
#> Converting page 15 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431290a9a9.png... done!
#> Converting page 16 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file714357729fc4.png... done!
#> Converting page 17 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file7143265729b6.png... done!
#> Converting page 18 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file714324737f64.png... done!
#> Converting page 19 to /var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//Rtmpf0uU6s/file71431ab090ee.png... done!
#> Making output_file directories
different_html = rmarkdown::render(
  res$output_file
)
#> Writing out Wav for audio
#> Sample rate downsampled to 24000
#> '/usr/local/Cellar/ffmpeg/4.3.2_4/bin/ffmpeg' -y -f concat -safe 0 -i '/Users/johnmuschelli/Desktop/ari_input_NS8KxuyHA6x4.txt' -i '/Users/johnmuschelli/Desktop/ari_audio_UsOQhUyThilB.wav' -c:v libx264 -c:a aac -ac 2    -shortest -vsync 2 -pix_fmt yuv420p  -vf fps=5,"scale=trunc(iw/2)*2:trunc(ih/2)*2"   -strict experimental -max_muxing_queue_size 9999 -threads 2 '/Users/johnmuschelli/Desktop/output_file.mp4'
#> /usr/local/bin/pandoc +RTS -K512m -RTS file71433dfb06f2.utf8.md --to html4 --output file71433dfb06f2.html
#> 
#> Output created: file71433dfb06f2.html
file.exists(file)
#> [1] TRUE

Created on 2021-05-07 by the reprex package (v2.0.0)

Session info ``` r sessioninfo::session_info() #> ─ Session info ─────────────────────────────────────────────────────────────── #> setting value #> version R version 4.0.5 (2021-03-31) #> os macOS Catalina 10.15.7 #> system x86_64, darwin17.0 #> ui X11 #> language (EN) #> collate en_US.UTF-8 #> ctype en_US.UTF-8 #> tz America/New_York #> date 2021-05-07 #> #> ─ Packages ─────────────────────────────────────────────────────────────────── #> package * version date lib #> ari * 0.4.1 2021-04-28 [1] #> ariExtra 0.3.0 2021-03-31 [1] #> askpass 1.1 2019-01-13 [2] #> assertthat 0.2.1 2019-03-21 [2] #> aws.polly 0.1.5.9000 2021-03-25 [1] #> aws.signature 0.6.0 2020-06-01 [2] #> backports 1.2.1 2020-12-09 [1] #> base64enc 0.1-3 2015-07-28 [2] #> cli 2.5.0 2021-04-26 [1] #> crayon 1.4.1 2021-02-08 [1] #> curl * 4.3 2019-12-02 [1] #> DBI 1.1.1 2021-01-15 [1] #> digest 0.6.27 2020-10-24 [1] #> docxtractr 0.6.5 2020-07-05 [2] #> dplyr 1.0.5 2021-03-05 [1] #> ellipsis 0.3.1 2020-05-15 [2] #> evaluate 0.14 2019-05-28 [2] #> fansi 0.4.2 2021-01-15 [1] #> fs 1.5.0 2020-07-31 [2] #> generics 0.1.0 2020-10-31 [1] #> glue 1.4.2 2020-08-27 [1] #> highr 0.9 2021-04-16 [1] #> hms 1.0.0 2021-01-13 [1] #> htmltools 0.5.1.1 2021-01-22 [1] #> httr 1.4.2 2020-07-20 [2] #> jsonlite 1.7.2 2020-12-09 [1] #> knitr 1.33 2021-04-24 [1] #> lifecycle 1.0.0 2021-02-15 [1] #> magrittr 2.0.1 2020-11-17 [1] #> MASS 7.3-53.1 2021-02-12 [1] #> pdftools * 2.3.1 2020-05-22 [2] #> pillar 1.6.0 2021-04-13 [1] #> pkgconfig 2.0.3 2019-09-22 [2] #> prettyunits 1.1.1 2020-01-24 [2] #> progress 1.2.2 2019-05-16 [2] #> purrr 0.3.4 2020-04-17 [2] #> qpdf 1.1 2019-03-07 [2] #> R6 2.5.0 2020-10-28 [1] #> Rcpp 1.0.6 2021-01-15 [1] #> reprex 2.0.0 2021-04-02 [1] #> rlang 0.4.10 2020-12-30 [1] #> rmarkdown 2.7 2021-02-19 [1] #> rvest 1.0.0 2021-03-09 [1] #> sessioninfo 1.1.1 2018-11-05 [2] #> signal 0.7-6 2015-07-30 [2] #> stringi * 1.5.3 2020-09-09 [1] #> stringr 1.4.0 2019-02-10 [2] #> styler 1.4.1 2021-03-30 [1] #> text2speech 0.3.0 2020-12-09 [1] #> tibble 3.1.1 2021-04-18 [1] #> tidyselect 1.1.0 2020-05-11 [2] #> tuneR 1.3.3 2018-07-08 [1] #> utf8 1.2.1 2021-03-12 [1] #> vctrs 0.3.7 2021-03-29 [1] #> webshot 0.5.2 2019-11-22 [2] #> withr 2.4.2 2021-04-18 [1] #> xfun 0.22 2021-03-11 [1] #> xml2 1.3.2 2020-04-23 [2] #> yaml 2.2.1 2020-02-01 [2] #> source #> Github (jhudsl/ari@2638775) #> Github (muschellij2/ariExtra@0049742) #> CRAN (R 4.0.0) #> CRAN (R 4.0.0) #> local #> Github (cloudyr/aws.signature@5689733) #> CRAN (R 4.0.2) #> CRAN (R 4.0.0) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.1) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.0) #> CRAN (R 4.0.2) #> CRAN (R 4.0.0) #> CRAN (R 4.0.0) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.0) #> CRAN (R 4.0.2) #> CRAN (R 4.0.0) #> CRAN (R 4.0.0) #> CRAN (R 4.0.0) #> CRAN (R 4.0.0) #> CRAN (R 4.0.0) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.0) #> CRAN (R 4.0.0) #> CRAN (R 4.0.2) #> CRAN (R 4.0.0) #> CRAN (R 4.0.2) #> Github (muschellij2/text2speech@a0c9f86) #> CRAN (R 4.0.2) #> CRAN (R 4.0.0) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.0) #> CRAN (R 4.0.2) #> CRAN (R 4.0.2) #> CRAN (R 4.0.0) #> CRAN (R 4.0.0) #> #> [1] /Users/johnmuschelli/Library/R/4.0/library #> [2] /Library/Frameworks/R.framework/Versions/4.0/Resources/library ```