Org Mode: Insert YouTube video with separate captions
| emacsI'm playing around with some ideas for making it easier to post a video with its captions on a webpage or in an Org file so that it's easier to skim or search.
This requires the youtube-dl
command. I'm also learning how to use dash.el
‘s threading macro, so you'll need to install that as well if you want to run it.
(require 'dash) (defun my/msecs-to-timestamp (msecs) "Convert MSECS to string in the format HH:MM:SS.MS." (concat (format-seconds "%02h:%02m:%02s" (/ msecs 1000)) "." (format "%03d" (mod msecs 1000)))) (defun my/org-insert-youtube-video-with-transcript (url) (interactive "MURL: ") (let* ((id (if (string-match "v=\\([^&]+\\)" url) (match-string 1 url) url)) (temp-file (make-temp-name "org-youtube-")) (temp-file-name (concat temp-file ".en.srv1")) data) (when (and (call-process "youtube-dl" nil nil nil "--write-sub" "--write-auto-sub" "--no-warnings" "--sub-lang" "en" "--skip-download" "--sub-format" "srv1" "-o" temp-file (format "https://youtube.com/watch?v=%s" id)) (file-exists-p temp-file-name)) (insert (format "#+begin_export html <iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/%s\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n#+end_export\n" id) "\n" (mapconcat (lambda (o) (format "| [[https://youtube.com/watch?v=%s&t=%ss][%s]] | %s |\n" id (dom-attr o 'start) (my/msecs-to-timestamp (* 1000 (string-to-number (dom-attr o 'start)))) (->> (dom-text o) (replace-regexp-in-string "[ \n]+" " ") (replace-regexp-in-string "'" "'") (replace-regexp-in-string """ "\"")))) (dom-by-tag (xml-parse-file temp-file-name) 'text) "")) (delete-file temp-file-name))))
It makes an embedded Youtube video and a table with captions below it. The Org file doesn't look too bad, either.
I decided to stick to standard Org syntax so that I can read it in Emacs too. With the current implementation, clicking on the timestamps jumps to that position in the video, but on the Youtube website. I haven't coded anything fancy like keeping the embedded video at a fixed position, controlling it from the clicks, or highlighting the current position. It's a start, though!
Here's the output of running it with my talk from the last EmacsConf.
00:00:00.000 | I'm Sacha Chua, and welcome to EmacsConf 2020. |
00:00:04.000 | To kick things off, here are ten cool things |
00:00:07.000 | that people have been working on |
00:00:08.000 | since the conference last year. |
00:00:10.000 | If you want to follow the links |
00:00:11.000 | or if you'd like to add something I've missed, |
00:00:14.000 | add them to the collaborative pad |
00:00:16.000 | if you're watching this live |
00:00:17.000 | or check out the EmacsConf wiki page for this talk. |
… (omitted for brevity)