diff options
author | Sacha Chua <sacha@sachachua.com> | 2022-11-07 12:41:13 -0500 |
---|---|---|
committer | Sacha Chua <sacha@sachachua.com> | 2022-11-07 12:41:13 -0500 |
commit | 49361f4252c3b46588d9a17ef8c131550577b89e (patch) | |
tree | e411c79d26b6251d26871f0672e8e203d079510f | |
parent | 9dd9e9bd8876bab7bdae91ef560deb3a74411544 (diff) | |
download | emacsconf-el-49361f4252c3b46588d9a17ef8c131550577b89e.tar.xz emacsconf-el-49361f4252c3b46588d9a17ef8c131550577b89e.zip |
Use paragraph or chapter information
-rw-r--r-- | emacsconf-publish.el | 125 | ||||
-rw-r--r-- | emacsconf.el | 31 |
2 files changed, 106 insertions, 50 deletions
diff --git a/emacsconf-publish.el b/emacsconf-publish.el index 699b5d2..ac910c5 100644 --- a/emacsconf-publish.el +++ b/emacsconf-publish.el @@ -48,7 +48,7 @@ (emacsconf-upcoming-insert-or-update)) (let ((info (emacsconf-get-talk-info))) (emacsconf-generate-before-page talk info) - (emacsconf-generate-after-page talk info) + (emacsconf-publish-after-page talk info) (emacsconf-generate-main-schedule info))) (defun emacsconf-publish-add-talk () @@ -133,7 +133,7 @@ (emacsconf-get-preferred-video (plist-get talk :video-slug) (plist-get talk :files))))) (video (and video-slug - (emacsconf-index-card-video (or (plist-get talk :video-id) "mainVideo") + (emacsconf-index-card-video (or (plist-get talk :video-id) (concat "mainVideo-" (plist-get talk :slug))) video-file talk extensions)))) ;; Add extra information to the talk (setq talk @@ -210,8 +210,9 @@ (emacsconf-make-chapter-strings (expand-file-name (concat video-base "--chapters.vtt") - emacsconf-backstage-dir) - (plist-get talk :track-base-url)))) + emacsconf-cache-dir) + (plist-get talk :track-base-url) + video-id))) (info (append (list @@ -274,7 +275,7 @@ size=\"${video-file-size}\" duration=\"${video-duration}\" other_resources=\"\"\"${other-files}${toobnix-info}\"\"\"]] ${chapter-list} " - "<video controls preload=\"metadata\" poster=\"${poster}\" id=\"${video-id}\"><source src=\"${source-src}\" />${captions}${chapter-track}</video>") + "<video controls preload=\"metadata\" poster=\"${poster}\" id=\"${video-id}\"><source src=\"${source-src}\" />${captions}${chapter-track}</video>${chapter-list}") "The video for \"${title}\" will be posted here when available. You can also subscribe to the <a href=\"https://lists.gnu.org/mailman/listinfo/emacsconf-discuss\">emacsconf-discuss mailing list</a> for updates.")) :resources (emacsconf-replace-plist-in-string @@ -370,11 +371,11 @@ resources." (emacsconf-index-card (append (list :public 1 - :video-id "qanda" + :video-id (concat "qanda-" (plist-get o :slug)) :toobnix-url nil :video-file (expand-file-name (concat (file-name-sans-extension (plist-get o :video-slug)) "--answers.webm") - emacsconf-cache-directory)) + emacsconf-cache-dir)) o) (list "--answers.vtt" "--answers--chapters.vtt" "--answers--compressed32.webm"))) ""))) @@ -448,13 +449,28 @@ ${pad-info}${status-info}${schedule-info}\n" (plist-get talk :public-email) "emacsconf-org-private@gnu.org")))) -(defun emacsconf-generate-before-page (talk &optional info) +(defun emacsconf-publish-captions-in-wiki (talk) + "Copy the captions file." + (interactive (list (emacsconf-complete-talk-info))) + (unless (file-directory-p (expand-file-name "captions" (expand-file-name emacsconf-year emacsconf-directory))) + (make-directory (expand-file-name "captions" (expand-file-name emacsconf-year emacsconf-directory)))) + (let ((filename (expand-file-name (concat (plist-get talk :video-slug) "--main.vtt") + (expand-file-name "captions" (expand-file-name emacsconf-year emacsconf-directory)))) + (cached-file (expand-file-name (concat (plist-get talk :video-slug) "--main.vtt") emacsconf-cache-dir))) + (when (and (file-exists-p cached-file) + (or + (not (file-exists-p filename)) + (file-newer-than-file-p cached-file filename))) + (copy-file cached-file filename t)))) + +(defun emacsconf-publish-before-page (talk &optional info) "Info included before the abstract." - (interactive (list (emacsconf-get-talk-info-for-subtree))) + (interactive (list (emacsconf-complete-talk-info))) (setq info (or info (emacsconf-get-talk-info))) + (when (plist-get talk :public) (emacsconf-publish-captions-in-wiki talk)) (with-temp-file (expand-file-name (format "%s-before.md" (plist-get talk :slug)) (expand-file-name "info" (expand-file-name emacsconf-year emacsconf-directory))) - (insert "<!-- Automatically generated by emacsconf-generate-before-page -->\n") + (insert "<!-- Automatically generated by emacsconf-publish-before-page -->\n") (when (eq emacsconf-publishing-phase 'schedule) (insert "\n" (format "<div class=\"schedule-in-context schedule-svg-container\" data-slug=\"%s\">\n" (plist-get talk :slug)) @@ -489,20 +505,60 @@ ${pad-info}${status-info}${schedule-info}\n" (emacsconf-format-talk-schedule-info talk) "\n")) ;; Contact information ;; (insert "\n\n" (emacsconf-format-email-questions-and-comments talk) "\n") - (insert "<!-- End of emacsconf-generate-before-page -->"))) + (insert "<!-- End of emacsconf-publish-before-page -->"))) + +(defun emacsconf-format-transcript (talk) + "Format the transcript for TALK, adding paragraph markers when possible." + (require 'subed) + (let* ((paragraphs (expand-file-name + (concat (plist-get talk :video-slug) "--main--paragraphs.vtt") + emacsconf-cache-dir)) + (chapters (expand-file-name + (concat (plist-get talk :video-slug) "--main--chapters.vtt") + emacsconf-cache-dir)) + (subtitles + (subed-parse-file (expand-file-name + (concat (plist-get talk :video-slug) "--main.vtt") + emacsconf-cache-dir))) + (pars (or + (subed-parse-file paragraphs) + (subed-parse-file chapters)))) + (if subtitles + (concat "<a name=\"transcript\"></a> +# Transcript -(defun emacsconf-generate-after-page (talk &optional info) +" + (mapconcat (lambda (sub) + (let ((msecs (elt sub 1))) + (format "[[!template %stext=\"%s\" start=\"%s\" video=\"mainVideo-%s\" id=\"subtitle\"]]" + (if (and pars (>= msecs (elt (car pars) 1))) + (progn + (while (and pars (>= (elt sub 1) (elt (car pars) 1))) + (setq pars (cdr pars))) + "new=\"1\" ") + "") + (replace-regexp-in-string "\"" """ (elt sub 3)) + (concat (format-seconds "%02h:%02m:%02s" (/ (floor msecs) 1000)) + "." (format "%03d" (mod (floor msecs) 1000))) + (plist-get talk :slug)))) + subtitles "\n") + " + +") + ""))) + +(defun emacsconf-publish-after-page (talk &optional info) "Info included before the abstract." - (interactive (list (emacsconf-get-talk-info-for-subtree))) - (setq info (or info (emacsconf-get-talk-info))) + (interactive (list (emacsconf-complete-talk-info))) ;; Contact information (with-temp-file (expand-file-name (format "%s-after.md" (plist-get talk :slug)) (expand-file-name "info" (expand-file-name emacsconf-year emacsconf-directory))) (insert - "<!-- Automatically generated by emacsconf-generate-after-page -->\n" + "<!-- Automatically generated by emacsconf-publish-after-page -->\n" "\n\n" + (if (plist-get talk :public) (emacsconf-format-transcript talk) "") (emacsconf-format-email-questions-and-comments talk) "\n" - "\n\n<!-- End of emacsconf-generate-after-page -->\n"))) + "\n\n<!-- End of emacsconf-publish-after-page -->\n"))) (defun emacsconf-sort-by-track-then-schedule (a b) ;; Gen,Dev; then by time @@ -514,6 +570,7 @@ ${pad-info}${status-info}${schedule-info}\n" ((time-less-p (plist-get a :start-time) (plist-get b :start-time)) t) (t nil))) + (defun emacsconf-generate-nav-pages (&optional talks) (interactive (list (emacsconf-active-talks @@ -557,8 +614,8 @@ Back to the [[talks]] \n" (sort (emacsconf-filter-talks info) #'emacsconf-sort-by-scheduled)))) (emacsconf-generate-nav-pages talks) (mapc (lambda (o) - (emacsconf-generate-before-page o talks) - (emacsconf-generate-after-page o talks)) + (emacsconf-publish-before-page o talks) + (emacsconf-publish-after-page o talks)) talks)))) (defun emacsconf-publish-before-pages (&optional info) @@ -569,7 +626,7 @@ Back to the [[talks]] \n" (sort (emacsconf-filter-talks info) #'emacsconf-sort-by-scheduled))) (emacsconf-publish-with-wiki-change (mapc (lambda (o) - (emacsconf-generate-before-page o info)) + (emacsconf-publish-before-page o info)) info))) (defun emacsconf-generate-talks-page (emacsconf-info) @@ -859,7 +916,7 @@ Entries are sorted chronologically, with different tracks interleaved." (assoc-default "TO_PROCESS" by-status) (assoc-default "PROCESSING" by-status) (assoc-default "TO_AUTOCAP" by-status)))) - (format "<h1>%s talk(s) to be captioned (%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. This year, we're experimenting with using OpenAI Whisper to provide auto-generated VTT that you can use as a starting point. 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: <a href=\"https://emacsconf.org/captioning/\">captioning tips</a></p><ul class=\"videos\">%s</ul>" + (format "<h1>%s talk(s) to be captioned (%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. This year, we're experimenting with using OpenAI Whisper to provide auto-generated VTT that you can use as a starting point. 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: <a href=\"https://media.emacsconf.org/2022/backstage/editing-captions.html\">Editing captions</a>, <a href=\"https://emacsconf.org/captioning/\">captioning tips</a></p><ul class=\"videos\">%s</ul>" (length list) (emacsconf-sum :video-time list) (mapconcat @@ -960,7 +1017,7 @@ Entries are sorted chronologically, with different tracks interleaved." (append (list :public 1 - :video-id "qanda" + :video-id (concat "qanda-" (plist-get o :slug)) :toobnix-url nil :video-file (expand-file-name @@ -1014,7 +1071,7 @@ Entries are sorted chronologically, with different tracks interleaved." (list :public 1 :base-url (concat emacsconf-media-base-url (plist-get f :conf-year) "/") - :video-id "qanda" + :video-id (concat "qanda-" (plist-get f :slug)) :track-base-url (format "/%s/captions/" (plist-get f :conf-year)) :video-file (expand-file-name @@ -1026,22 +1083,24 @@ Entries are sorted chronologically, with different tracks interleaved." info "\n")) "</ol>"))) -(defun emacsconf-make-chapter-strings (filename track-base-url) - (when (file-exists-p filename) - (let ((chapters (with-temp-buffer - (insert-file-contents filename) - (subed--init "vtt") - (subed-subtitle-list)))) +(defun emacsconf-make-chapter-strings (filename track-base-url &optional target) + (let ((chapters (subed-parse-file filename))) + (when chapters (list :track (format "<track kind=\"chapters\" label=\"Chapters\" src=\"%s\"\" />" (concat (or track-base-url "") (file-name-nondirectory filename))) - :md (subed-convert--chapters chapters) - :html (format "<ol class=\"chapters\">\n%s\n</ol>" + :md (mapconcat (lambda (chapter) + (concat + (format-seconds "%.2h:%z%.2m:%.2s" (floor (/ (elt chapter 1) 1000))) + " " + (elt chapter 3) + "\n")) + chapters) + :html (format "<pre data-target=\"%s\" class=\"chapters\">\n%s\n</ol>" + (or target "") (mapconcat (lambda (chapter) - (format "<li data-start=\"%.3f\" data-stop=\"%.3f\">%s %s</li>" - (/ (elt chapter 1) 1000.0) - (/ (elt chapter 2) 1000.0) + (format "%s %s" (format-seconds "%.2h:%z%.2m:%.2s" (floor (/ (elt chapter 1) 1000))) (elt chapter 3))) chapters diff --git a/emacsconf.el b/emacsconf.el index 4443f7e..8e4c4e1 100644 --- a/emacsconf.el +++ b/emacsconf.el @@ -131,9 +131,13 @@ (defun emacsconf-upload-to-backstage () (interactive) - (copy-file (buffer-file-name) (expand-file-name (file-name-nondirectory (buffer-file-name)) - emacsconf-backstage-dir) - t)) + (mapc (lambda (file) + (copy-file file (expand-file-name (file-name-nondirectory file) + emacsconf-backstage-dir) + t)) + (or (dired-get-marked-files) + (list (buffer-file-name))))) + (defun emacsconf-get-srv2-and-upload-to-backstage (talk) (interactive (list (emacsconf-complete-talk-info (seq-filter (lambda (o) (plist-get o :youtube-url)) (emacsconf-get-talk-info))))) (let ((filename (make-temp-file nil nil "srv2")) @@ -145,21 +149,13 @@ (emacsconf-upload-to-backstage-and-rename talk "main--srt"))))) (defun emacsconf-upload-to-backstage-and-rename (talk filename) - (interactive (let ((talk (emacsconf-complete-talk-info)) - (base (file-name-base (buffer-file-name)))) - (list - talk - (if (and (not current-prefix-arg) - (string-match (concat "^" (regexp-quote (plist-get talk :video-slug)) "--\\([a-z]+\\)") - base)) - (match-string 1 base) - (read-string (format "Filename (%s): " base) - nil nil - base))))) + (interactive (list (emacsconf-complete-talk-info) + (read-string "Filename: "))) (copy-file (buffer-file-name) (expand-file-name (concat (plist-get talk :video-slug) - "--" - filename + (if (string= filename "") + "" + (concat "--" filename)) "." (file-name-extension (buffer-file-name))) emacsconf-backstage-dir) @@ -311,6 +307,7 @@ (defvar emacsconf-status-types '(("WAITING_FOR_PREREC" . "Waiting for video from speaker") ("TO_PROCESS" . "Processing uploaded video") + ("PROCESSING" . "Processing uploaded video") ("TO_AUTOCAP" . "Processing uploaded video") ("TO_ASSIGN" . "Waiting for a caption volunteer") ("TO_CAPTION" . "Processing uploaded video") @@ -1016,7 +1013,7 @@ Filter by TRACK if given. Use INFO as the list of talks." (defun emacsconf-bbb-status (talk) (let ((states '((open . "OPEN_Q UNSTREAMED_Q") - (before . "TODO TO_REVIEW TO_ACCEPT WAITING_FOR_PREREC TO_PROCESS TO_AUTOCAP TO_ASSIGN TO_CAPTION TO_STREAM PLAYING CLOSED_Q") + (before . "TODO TO_REVIEW TO_ACCEPT WAITING_FOR_PREREC TO_PROCESS PROCESSING TO_AUTOCAP TO_ASSIGN TO_CAPTION TO_STREAM PLAYING CLOSED_Q") (after . "TO_ARCHIVE TO_EXTRACT TO_FOLLOW_UP DONE")))) (if (string-match "live" (or (plist-get talk :q-and-a) "")) (or (car (seq-find (lambda (state) |