EmacsConf backstage: Trimming the BigBlueButton recordings based on YouTube duration

| emacsconf, emacs, youtube, video

I wanted to get the Q&A sessions up quickly after the conference, so I uploaded them to YouTube and added them to the EmacsConf 2023 playlist. I used YouTube's video editor to roughly guess where to trim them based on the waveforms. I needed to actually trim the source videos, though, so that our copies would be up to date and I could use those for the Toobnix uploads.

My first task was to figure out which videos needed to be trimmed to match the YouTube edits. First, I retrieved the video details using the API and the code that I added to emacsconf-extract.el.

(setq emacsconf-extract-youtube-api-video-details (emacsconf-extract-youtube-get-video-details emacsconf-extract-youtube-api-playlist-items))

Then I made a table comparing the file duration with the YouTube duration, showing rows only if the difference was more than 3 minutes.

(append
 '(("type" "slug" "file duration" "youtube duration" "diff"))
 (let ((threshold-secs (* 3 60))) ; don't sweat small differences
   (seq-mapcat
    (lambda (talk)
      (seq-keep
       (lambda (row)
         (when (plist-get talk (cadr row))
           (let* ((video (emacsconf-extract-youtube-find-url-video-in-list
                          (plist-get talk (cadr row))
                          emacsconf-extract-youtube-api-video-details))
                  (video-duration (if (and video (emacsconf-extract-youtube-duration-msecs video))
                                      (/ (emacsconf-extract-youtube-duration-msecs video) 1000.0)))
                  (file-duration (ceiling
                                  (/ (compile-media-get-file-duration-ms (emacsconf-talk-file talk (format "--%s.webm" (car row))))
                                     1000.0))))
             (when (and video-duration (> (abs (- file-duration video-duration)) threshold-secs))
               (list (car row)
                     (plist-get talk :slug)
                     (and file-duration (format-seconds "%h:%z%.2m:%.2s" file-duration))
                     (and video-duration (format-seconds "%h:%z%.2m:%.2s" video-duration))
                     (emacsconf-format-seconds
                      (abs (- file-duration video-duration))))))))
       '(("main" :youtube-url)
         ("answers" :qa-youtube-url))))
    (emacsconf-publish-prepare-for-display (emacsconf-get-talk-info)))))

Then I got the commands to trim the videos.

 (mapconcat (lambda (row)
              (let ((talk (emacsconf-resolve-talk (elt row 1))))
                (format "ffmpeg -y -i %s--%s.webm -t %s -c copy %s--%s--trimmed.webm"
                        (plist-get talk :file-prefix)
                        (car row)
                        (concat (elt row 3) ".000")
                        (plist-get talk :file-prefix)
                        (car row))))
            (cdr to-trim)
            "\n"))

After quickly checking the results, I copied them over to the original videos, updated the video data in my conf.org, and republished the info pages in the wiki.

The time I spent on figuring out how to talk to the YouTube API feels like it's paying off.

You can comment with Disqus or you can e-mail me at sacha@sachachua.com.