diff options
Diffstat (limited to '')
-rw-r--r-- | emacsconf-publish.el | 245 |
1 files changed, 125 insertions, 120 deletions
diff --git a/emacsconf-publish.el b/emacsconf-publish.el index 95cfecc..f0388d8 100644 --- a/emacsconf-publish.el +++ b/emacsconf-publish.el @@ -336,6 +336,16 @@ :video-id video-id :video-file-size (if (and (stringp video-file) (file-exists-p video-file)) (file-size-human-readable (file-attribute-size (file-attributes video-file)))) + :links + (concat + (emacsconf-surround "<li><a href=\"" (plist-get talk :pad-url) "\">Open Etherpad</a></li>" "") + (emacsconf-surround "<li><a href=\"" + (and (plist-get talk :backstage) (plist-get talk :bbb-room) + (plist-get talk :bbb-backstage)) + "\">Open backstage BigBlueButton</a></li>" "") + (emacsconf-surround "<li><a href=\"" + (plist-get talk :qa-url) + "\">Open public Q&A</a></li>" "")) :other-files (mapconcat (lambda (s) @@ -373,7 +383,7 @@ :resources (emacsconf-replace-plist-in-string info - "<div class=\"files resources\"><ul>${other-files}${toobnix-info}</ul></div>")))) + "<div class=\"files resources\"><ul>${links}${other-files}${toobnix-info}</ul></div>")))) (defun emacsconf-publish-format-public-email (o &optional email) (format "[%s](mailto:%s?subject=%s)" @@ -503,21 +513,16 @@ resources." :format (concat (or (plist-get o :video-time) (plist-get o :time)) - "-min talk" - (if (plist-get o :q-and-a) - (format " followed by %s Q&A%s" - (plist-get o :q-and-a) - (if (eq emacsconf-publishing-phase 'conference) - (format " (%s)" - (if (string-match "live" (plist-get o :q-and-a)) - (if (eq 'after (emacsconf-bbb-status o)) - "done" - (format "<https://emacsconf.org/current/%s/room>" (plist-get o :slug))) - (emacsconf-publish-webchat-link o))) - "")) - "")) + "-min talk; Q&A: " + (pcase (plist-get o :qa-type) + ("none" "ask questions via Etherpad/IRC; we'll e-mail the speaker and post answers on this wiki page after the conference") + ("live" "BigBlueButton conference room") + ("pad" "Etherpad") + ("irc" "IRC") + (_ (plist-get o :qa-type))) + (emacsconf-surround " <" (plist-get o :qa-url) ">" "")) :pad-info - (if emacsconf-publish-include-pads + (if (and emacsconf-publish-include-pads (not (string= (plist-get o :qa-type) "etherpad"))) (format "Etherpad: <https://pad.emacsconf.org/%s-%s> \n" emacsconf-year (plist-get o :slug)) "") :irc-info @@ -1105,7 +1110,18 @@ Use FILES as the file list, or look in the cache directory." (directory-files emacsconf-cache-dir)))) (defun emacsconf-sum (field talks) - (apply '+ (seq-map (lambda (talk) (string-to-number (or (plist-get talk field) "0"))) talks))) + (apply '+ (seq-map (lambda (talk) + (string-to-number + (or + (if (listp field) + (car + (seq-keep + (lambda (f) + (plist-get talk f)) + field)) + (plist-get talk field)) + "0"))) + talks))) (defun emacsconf-publish-backstage-org-on-state-change (talk) (save-window-excursion @@ -1120,102 +1136,64 @@ Use FILES as the file list, or look in the cache directory." (when (member org-state '("WAITING_FOR_PREREC" "TO_ASSIGN" "TO_CAPTION" "TO_STREAM")) (emacsconf-publish-backstage-index))))) -(defun emacsconf-publish-backstage-processing (by-status files) - (let ((list (append - (assoc-default "TO_PROCESS" by-status) - (assoc-default "PROCESSING" by-status) - (assoc-default "TO_AUTOCAP" by-status)))) - (format "<h1>%s talk(s) being processed (%d minutes)</h1>Not ready for captioning yet, but they will be eventually<ul class=\"videos\">%s</ul>" - (length list) - (emacsconf-sum :video-time list) - (mapconcat - (lambda (f) - (setq f (append - f - (list :extra - (if (plist-get f :caption-note) (concat "<div class=\"caption-note\">" (plist-get f :caption-note) "</div>") "") - :files - (emacsconf-publish-talk-files f files)))) - (format "<li><a name=\"%s\"></a><strong><a href=\"%s\">%s</a></strong><br />%s (id:%s)<br />%s</li>" - (plist-get f :slug) - (plist-get f :absolute-url) - (plist-get f :title) - (plist-get f :speakers) - (plist-get f :slug) - (emacsconf-publish-index-card f))) - list - "\n")))) - (defun emacsconf-publish-backstage-to-assign (by-status files) - (let ((list (assoc-default "TO_ASSIGN" by-status))) - (format "<h1>%s talk(s) to be captioned, waiting for volunteers (%d minutes)</h1><p>You can e-mail <a href=\"mailto:sacha@sachachua.com\">sacha@sachachua.com</a> to call dibs on editing the captions for one of these talks. We use OpenAI Whisper to provide auto-generated VTT that you can use as a starting point, but you can also write the captions from scratch if you like. The starting point for the main video ends in --main.vtt. If you're writing the captions from scratch, you can choose to include timing information, or we can probably figure them out afterwards with a forced alignment tool. More info: <a href=\"https://emacsconf.org/captioning/\">captioning tips</a></p><ul class=\"videos\">%s</ul>" - (length list) - (emacsconf-sum :video-time list) - (mapconcat - (lambda (f) - (setq f (append - f - (list :extra - (if (plist-get f :caption-note) (concat "<div class=\"caption-note\">" (plist-get f :caption-note) "</div>") "") - :files - (emacsconf-publish-talk-files f files)))) - (format "<li><a name=\"%s\"></a><strong><a href=\"%s\">%s</a></strong><br />%s (id:%s)<br />%s</li>" - (plist-get f :slug) - (plist-get f :absolute-url) - (plist-get f :title) - (plist-get f :speakers) - (plist-get f :slug) - (emacsconf-publish-index-card f))) - list - "\n")))) + (emacsconf-publish-backstage-list + (assoc-default "TO_ASSIGN" by-status) + files + "to be captioned, waiting for volunteers" + "<p>You can e-mail <a href=\"mailto:sacha@sachachua.com\">sacha@sachachua.com</a> to call dibs on editing the captions for one of these talks. We use OpenAI Whisper to provide auto-generated VTT that you can use as a starting point, but you can also write the captions from scratch if you like. The starting point for the main video ends in --main.vtt. If you're writing the captions from scratch, you can choose to include timing information, or we can probably figure them out afterwards with a forced alignment tool. More info: <a href=\"https://emacsconf.org/captioning/\">captioning tips</a></p>" + (lambda (f) + (append + f + (list :extra + (if (plist-get f :caption-note) (concat "<div class=\"caption-note\">" (plist-get f :caption-note) "</div>") "") + :files + (emacsconf-publish-talk-files f files)))))) (defun emacsconf-publish-backstage-to-caption (by-status files) + (emacsconf-publish-backstage-list + (assoc-default "TO_CAPTION" by-status) + files + "being captioned" + "People are working on these ones, yay! <a href=\"https://emacsconf.org/captioning\">Captioning process/tips</a>" + (lambda (f) + (append + f + (list :extra + (concat "<div class=\"caption-note\">" + (emacsconf-surround "Being captioned by " (plist-get f :captioner) " " "") + (emacsconf-surround "Note: " (plist-get f :caption-note) "" "") + "</div>") + :files + (emacsconf-publish-talk-files f files)))))) + +(defun emacsconf-publish-backstage-list (talks files header-description &optional description modify-func) + "Display a list of TALKS. +Use the files listed in FILES. +Start the header with HEADER-DESCRIPTION. +If MODIFY-FUNC is specified, use it to modify the talk." (format - "<h1>%d talk(s) being captioned (%s minutes)</h1>People are working on these ones, yay!<ul>%s</ul>" - (length (assoc-default "TO_CAPTION" by-status)) - (emacsconf-sum :video-time (assoc-default "TO_CAPTION" by-status)) - (mapconcat - (lambda (f) - (setq f (append - f - (list :extra - (concat "<div class=\"caption-note\">" - (emacsconf-surround "Being captioned by " (plist-get f :captioner) " " "") - (emacsconf-surround "Note: " (plist-get f :caption-note) "" "") - "</div>") - :files - (emacsconf-publish-talk-files f files)))) - (format "<li><a name=\"%s\"></a><strong><a href=\"%s%s\">%s</a></strong><br />%s (id:%s)<br />%s</li>" - (plist-get f :slug) - emacsconf-base-url - (plist-get f :url) - (plist-get f :title) - (plist-get f :speakers-with-pronouns) - (plist-get f :slug) - (emacsconf-publish-index-card f))) - (assoc-default "TO_CAPTION" by-status) - "\n"))) - -(defun emacsconf-publish-backstage-to-stream (by-status files) - (format - "<h1>%d captioned talk(s) ready for enjoyment (%d minutes)</h1><ol class=\"videos\">%s</ol>" - (length (assoc-default "TO_STREAM" by-status)) - (emacsconf-sum :video-time (assoc-default "TO_STREAM" by-status)) - (mapconcat (lambda (f) - (format "<li><a name=\"%s\"></a><strong><a href=\"%s%s\">%s</a></strong><br />%s (id:%s)<br />%s</li>" - (plist-get f :slug) - emacsconf-base-url - (plist-get f :url) - (plist-get f :title) - (plist-get f :speakers-with-pronouns) - (plist-get f :slug) - (emacsconf-publish-index-card (append f - (list :extra - (concat "Captioned by " (plist-get f :captioner)) - :files (emacsconf-publish-talk-files f files)))))) - (assoc-default "TO_STREAM" by-status) "\n"))) + "<h1>%d talk(s) %s (%d minutes)</h1>%s<ol class=\"videos\">%s</ol>" + (length talks) + header-description + (emacsconf-sum '(:video-time :time) talks) + (or description "") + (mapconcat (lambda (f) + (format "<li><a name=\"%s\"></a><strong><a href=\"%s%s\">%s</a></strong><br />%s (id:%s)<br />%s</li>" + (plist-get f :slug) + emacsconf-base-url + (plist-get f :url) + (plist-get f :title) + (plist-get f :speakers-with-pronouns) + (plist-get f :slug) + (emacsconf-publish-index-card + (if (functionp modify-func) + (funcall modify-func f) + f)))) + talks "\n"))) (defun emacsconf-publish-backstage-index (&optional filename) + "Render the backstage index to FILENAME." (interactive) (setq filename (or filename (expand-file-name "index.html" emacsconf-backstage-dir))) (let ((info (or emacsconf-schedule-draft (emacsconf-publish-prepare-for-display (emacsconf-get-talk-info))))) @@ -1223,7 +1201,8 @@ Use FILES as the file list, or look in the cache directory." (let* ((talks (mapcar (lambda (o) (append - (list :captions-edited t) o)) + (list :captions-edited t + :backstage t) o)) (seq-filter (lambda (o) (plist-get o :speakers)) (emacsconf-active-talks (emacsconf-filter-talks info))))) (by-status (seq-group-by (lambda (o) (plist-get o :status)) talks)) @@ -1259,7 +1238,7 @@ Use FILES as the file list, or look in the cache directory." "TO_ASSIGN (waiting for captioning volunteers)" status) (length (assoc-default status by-status)) - (emacsconf-sum :video-time (assoc-default status by-status)) + (emacsconf-sum '(:video-time :time) (assoc-default status by-status)) (mapconcat (lambda (o) (format "<a href=\"#%s\">%s</a>%s" (plist-get o :slug) (plist-get o :slug) @@ -1267,17 +1246,31 @@ Use FILES as the file list, or look in the cache directory." (assoc-default status by-status) ", "))) (pcase emacsconf-backstage-phase - ('prerec '("PROCESSING" "TO_ASSIGN" "TO_CAPTION" "TO_STREAM")) + ('prerec '("WAITING_FOR_PREREC" "PROCESSING" "TO_ASSIGN" "TO_CAPTION" "TO_STREAM")) ('harvest '("TO_ARCHIVE" "TO_REVIEW_QA" "TO_INDEX_QA" "TO_CAPTION_QA"))) "") "</ul>" (pcase emacsconf-backstage-phase ('prerec (concat - (emacsconf-publish-backstage-processing by-status files) + (emacsconf-publish-backstage-list + (append + (assoc-default "TO_PROCESS" by-status) + (assoc-default "PROCESSING" by-status) + (assoc-default "TO_AUTOCAP" by-status)) + files + "being processed" + "Not ready for captioning yet, but they will be eventually") (emacsconf-publish-backstage-to-assign by-status files) (emacsconf-publish-backstage-to-caption by-status files) - (emacsconf-publish-backstage-to-stream by-status files))) + (emacsconf-publish-backstage-list + (assoc-default "TO_STREAM" by-status) + files + "ready to be streamed") + (emacsconf-publish-backstage-list + (assoc-default "WAITING_FOR_PREREC" by-status) files + "we're waiting for" + "Speakers might submit these, do them live, or cancel the talks."))) ('harvest (let ((stages '(("TO_REVIEW_QA" . @@ -1720,6 +1713,16 @@ ${include} (save-buffer))) (browse-url-of-file "pad-template.html")) +(defun emacsconf-publish-format-files-as-playlist (playlist-name files) + (format "#EXTM3U\n#PLAYLIST: %s\n#EXTALB: %s\n#EXTGENRE: Speech\n%s" + playlist-name playlist-name + (mapconcat + (lambda (file) + (format "#EXTINF:-1,%s\n%s\n" + file + file)) + files + ""))) (defun emacsconf-publish-playlist (filename playlist-name talks &optional base-url) (with-temp-file filename @@ -1747,6 +1750,7 @@ ${include} ""))))) (defun emacsconf-get-preferred-video (file-prefix &optional files) + (when (listp file-prefix) (setq file-prefix (plist-get file-prefix :file-prefix))) (or (car (mapcar @@ -1763,11 +1767,13 @@ ${include} (expand-file-name (concat file-prefix "--" suffix ".webm") emacsconf-cache-dir)) '("main" "captioned" "normalized" "reencoded" "compressed" "original"))) - (car (directory-files emacsconf-cache-dir - nil - (concat (regexp-quote file-prefix) - ".*\\." - (regexp-opt emacsconf-media-extensions)))))) + (car + (seq-remove (lambda (o) (string-match "--intro" o)) + (directory-files emacsconf-cache-dir + nil + (concat (regexp-quote file-prefix) + ".*\\." + (regexp-opt emacsconf-media-extensions))))))) (defun emacsconf-check-video-formats () (interactive) @@ -1862,10 +1868,9 @@ This video is available under the terms of the Creative Commons Attribution-Shar emacsconf-cache-dir))) (when (emacsconf-captions-edited-p caption-file) (org-entry-put (point) "CAPTIONS_EDITED" "1")))) - (unless (plist-get talk :video-duration) - (setq duration (/ (compile-media-get-file-duration-ms video-file) 1000)) - (org-entry-put (point) "VIDEO_DURATION" (format-seconds "%h:%z%.2m:%.2s" duration)) - (org-entry-put (point) "VIDEO_TIME" (number-to-string (ceiling (/ duration 60)))))) + (setq duration (/ (compile-media-get-file-duration-ms video-file) 1000)) + (org-entry-put (point) "VIDEO_DURATION" (format-seconds "%h:%z%.2m:%.2s" duration)) + (org-entry-put (point) "VIDEO_TIME" (number-to-string (ceiling (/ duration 60))))) (when qa-file (org-entry-put (point) "QA_VIDEO_FILE" (file-name-nondirectory qa-file)) (org-entry-put (point) "QA_VIDEO_FILE_SIZE" (file-size-human-readable (file-attribute-size (file-attributes qa-file)))) |