From def383660144df547b7ce41cf4322222e39336d1 Mon Sep 17 00:00:00 2001 From: Sacha Chua Date: Sun, 30 Oct 2022 19:25:19 -0400 Subject: Publishing updates --- emacsconf-publish.el | 260 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 185 insertions(+), 75 deletions(-) (limited to 'emacsconf-publish.el') diff --git a/emacsconf-publish.el b/emacsconf-publish.el index 531a94b..29551f7 100644 --- a/emacsconf-publish.el +++ b/emacsconf-publish.el @@ -24,12 +24,13 @@ ;;; Code: +(require 'emacsconf-schedule) (defcustom emacsconf-media-base-url "https://media.emacsconf.org/" "Base URL for published media files." :type 'string :group 'emacsconf) -(defcustom emacsconf-main-extensions '(".org" ".odp" ".pdf" ".el" "--compressed56.webm" "--main.vtt" "--main_fr.vtt" "--main_ja.vtt" "--chapters.vtt" "--main--chapters.vtt" "--script.fountain") +(defcustom emacsconf-main-extensions '("--main.org" ".org" ".odp" ".pdf" ".el" "--compressed56.webm" "--main.vtt" "--main_fr.vtt" "--main_ja.vtt" "--chapters.vtt" "--main--chapters.vtt" "--script.fountain") "Extensions to list on public pages." :type '(repeat string) :group 'emacsconf) @@ -37,7 +38,8 @@ (defcustom emacsconf-backstage-extensions '(".en.srv2" ".srt") "Extensions to list in the staging area." :group 'emacsconf) -(defcustom emacsconf-public-media-directory nil "Can be over TRAMP" :type 'string :group 'emacsconf) +(defcustom emacsconf-public-media-directory (concat "/ssh:media:/var/www/media.emacsconf.org/" emacsconf-year "/") + "Can be over TRAMP" :type 'string :group 'emacsconf) (defun emacsconf-update-talk (talk) "Publish the schedule page and the page for this talk." @@ -86,8 +88,9 @@ (emacsconf-generate-talk-pages info force) (magit-status emacsconf-directory)))) -(defun emacsconf-update-schedules-in-wiki () +(defun emacsconf-update-schedule () (interactive) + (require 'emacsconf-ical) (emacsconf-publish-with-wiki-change (emacsconf-publish-info-pages) (emacsconf-generate-main-schedule) @@ -107,9 +110,9 @@ (defun emacsconf-update-media () (interactive) - (emacsconf-make-public-index-on-wiki) + (emacsconf-publish-public-index-on-wiki) (when emacsconf-public-media-directory - (emacsconf-make-public-index (expand-file-name "index.html" emacsconf-public-media-directory)) + (emacsconf-publish-public-index (expand-file-name "index.html" emacsconf-public-media-directory)) (emacsconf-generate-playlist (expand-file-name "index.m3u" emacsconf-public-media-directory) (concat emacsconf-name emacsconf-year) (emacsconf-public-talks emacsconf-info) @@ -124,7 +127,8 @@ (defun emacsconf-index-card (talk &optional extensions) "Format an HTML card for TALK, linking the files in EXTENSIONS." (let* ((video-slug (plist-get talk :video-slug)) - (video-file (and (plist-get talk :video-file) (expand-file-name (plist-get talk :video-file) emacsconf-captions-directory))) + (video-file (and video-slug + (emacsconf-get-preferred-video (plist-get talk :video-slug) (plist-get talk :files)))) (video (emacsconf-index-card-video (or (plist-get talk :video-id) "mainVideo") video-file talk extensions))) ;; Add extra information to the talk (setq talk @@ -142,8 +146,50 @@ talk "
${video-html}${resources}${extra}${chapter-list}
")))) +(defun emacsconf-publish-res-index () + (interactive) + (let ((info (mapcar (lambda (o) + (if (plist-get o :bbb-room) + (append (list + :qa-link + (format "Join Q&A" (plist-get o :bbb-room)) + :url + (plist-get o :bbb-room)) + o) + o)) + (emacsconf-prepare-for-display (emacsconf-get-talk-info))))) + (mapc (lambda (track) + (let ((track-talks (seq-filter (lambda (o) (string= (plist-get o :track) + (plist-get track :name))) + info))) + (with-temp-file (expand-file-name (format "index-%s.html" (plist-get track :id)) emacsconf-res-dir) + (insert + " +
" + (with-temp-buffer + (svg-print (emacsconf-schedule-svg 800 300 info)) + (buffer-string)) + "
" + (mapconcat + (lambda (o) + (concat + "" + "" + "" + "" + "" + "" + "")) + info "\n") + "
" (plist-get o :qa-link) + "" (if (plist-get o :pad-url) + (format "Open pad" (plist-get o :pad-url)) + "") + "" (format-time-string "%-l:%M" (plist-get o :start-time) emacsconf-timezone) "" (or (plist-get o :slug) "") "" (or (plist-get o :title) "") "
")))) + emacsconf-tracks))) + (defun emacsconf-index-card-video (video-id video-file talk extensions &optional backstage) - (let* ((video-base (file-name-base (replace-regexp-in-string "--\\(normalized\\|reencoded\\)" "--main" video-file))) + (let* ((video-base (file-name-base video-file)) (chapter-info (and video-file (emacsconf-make-chapter-strings (expand-file-name @@ -163,7 +209,7 @@ (and video-file (let ((tracks (emacsconf-video-subtitle-tracks - (concat video-base ".vtt") + (concat video-base ".vtt") (or (plist-get talk :track-base-url) (plist-get talk :base-url)) (plist-get talk :files)))) @@ -181,8 +227,6 @@ (plist-get chapter-info :html)) "") :video-id video-id - :video-duration (if (and video-file (file-exists-p video-file)) - (format-seconds "%m:%.2s" (/ (compile-media-get-file-duration-ms video-file) 1000))) :video-file-size (if (and video-file (file-exists-p video-file)) (file-size-human-readable (file-attribute-size (file-attributes video-file)))) :other-files @@ -314,7 +358,7 @@ resources." :toobnix-url nil :video-file (expand-file-name (concat (file-name-sans-extension (plist-get o :video-slug)) "--answers.webm") - emacsconf-captions-directory)) + emacsconf-cache-directory)) o) (list "--answers.vtt" "--answers--chapters.vtt" "--answers--compressed32.webm"))) ""))) @@ -484,6 +528,10 @@ Back to the [[talks]] \n" " "))))))) +(defun emacsconf-prepare-for-display (info) + "Sort by scheduled and remove cancelled talks." + (seq-remove (lambda (o) (string= (plist-get o :status) "CANCELLED")) + (sort (emacsconf-filter-talks info) #'emacsconf-sort-by-scheduled))) (defun emacsconf-publish-info-pages (&optional info) "Populate year/info/*-nav, -before, and -after files." (interactive) @@ -764,18 +812,56 @@ Entries are sorted chronologically, with different tracks interleaved." (defun emacsconf-sum (field talks) (apply '+ (seq-map (lambda (talk) (string-to-number (or (plist-get talk field) "0"))) talks))) -(defun emacsconf-publish-backstage-index (filename) - (interactive (list (expand-file-name "index.html" emacsconf-backstage-dir))) +(defun emacsconf-publish-backstage-add-to-todo-hook () + (interactive) + (with-current-buffer (find-file-noselect emacsconf-org-file) + (add-hook 'org-after-todo-state-change-hook #'emacsconf-publish-backstage-org-after-todo-state-change nil t))) +(defun emacsconf-publish-backstage-remove-from-todo-hook () + (interactive) + (with-current-buffer (find-file-noselect emacsconf-org-file) + (remove-hook 'org-after-todo-state-change-hook #'emacsconf-publish-backstage-org-after-todo-state-change t))) + +(defun emacsconf-publish-backstage-org-after-todo-state-change () + (when (member org-state '("TO_CAPTION")) + (unless (org-entry-get (point) "CAPTIONER") + (org-entry-put (point) "CAPTIONER" + (assoc-default "CUSTOM_ID" (emacsconf-complete-volunteer))))) + (when (member org-state '("TO_ASSIGN" "TO_CAPTION" "TO_STREAM")) + (emacsconf-publish-backstage-index))) + +(defun emacsconf-publish-copy-main-files-from-backstage-to-media-root (talk) + (interactive (list (emacsconf-complete-talk-info))) + (let ((files (directory-files emacsconf-backstage-dir nil (concat (plist-get talk :video-slug) + ".*" + (regexp-opt (append + emacsconf-main-extensions + (list "--main.webm" + "--questions.webm")) t) + "$")))) + (mapc + (lambda (f) + (copy-file + (expand-file-name f emacsconf-backstage-dir) + (expand-file-name f emacsconf-public-media-directory) t t)) + files) + (message "Copied %s" (string-join files ", ")))) + +(defun emacsconf-publish-backstage-index (&optional filename) + (interactive) + (setq filename (or filename (expand-file-name "index.html" emacsconf-backstage-dir))) (setq emacsconf-info (emacsconf-get-talk-info)) (with-temp-file filename - (let* ((talks (seq-filter (lambda (o) (plist-get o :video-file)) (emacsconf-filter-talks emacsconf-info))) + (let* ((talks (emacsconf-filter-talks emacsconf-info)) (by-status (seq-group-by (lambda (o) (plist-get o :status)) talks)) (files (directory-files emacsconf-backstage-dir))) (insert "" + (format "

Waiting for %d talks (~%d minutes)

" + (length (assoc-default "WAITING_FOR_PREREC" by-status)) + (emacsconf-sum :time (assoc-default "WAITING_FOR_PREREC" by-status))) (let ((list (append (assoc-default "TO_PROCESS" by-status) (assoc-default "TO_ASSIGN" by-status)))) - (format "

%s talk(s) to be captioned (%d minutes)

You can e-mail sacha@sachachua.com to call dibs on editing the captions for one of these talks. This year, we're experimenting with using OpenAI Whisper (the .vtt files) along with YouTube (the .srt files, when available) to provide auto-generated captions. You can decide which one prefer to use as a starting point, or you can write the captions from scratch. If you're writing them from scratch, you can choose to include timing information, or we can probably figure them out afterwards with a forced alignment tool. Also, if you feel like making chapter markers, that's cool too. More info: captioning tips