summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--emacsconf-publish.el125
-rw-r--r--emacsconf.el31
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 "\"" "&quot;" (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)