diff options
-rw-r--r-- | emacsconf-extract.el | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/emacsconf-extract.el b/emacsconf-extract.el index bdd5b75..77c8d0b 100644 --- a/emacsconf-extract.el +++ b/emacsconf-extract.el @@ -96,6 +96,179 @@ '("webcams.webm" "metadata.xml" "deskshare.webm" "deskshare.xml" "slides_new.xml" "webcams.opus")))) (emacsconf-prepare-for-display (emacsconf-get-talk-info)))) +(defvar emacsconf-extract-dump-dir "/ssh:orga@res.emacsconf.org#46668:~/current/live0-streams/") +(defun emacsconf-extract-dump-time-from-filename (f) + (when (string-match "\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\)_\\([0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\)" f) + (encode-time + (append + (mapcar (lambda (i) (string-to-number (match-string i f))) (number-sequence 6 1 -1)) + (list nil nil "UTC"))))) +(defun emacsconf-extract-dump-filename (directory input-prefix start-time) + (seq-find + (lambda (f) (time-less-p (emacsconf-extract-dump-time-from-filename f) start-time)) + (nreverse (sort (directory-files (or directory emacsconf-extract-dump-dir) + nil (concat emacsconf-id "-" emacsconf-year "-" + input-prefix ".*\\.webm$")) + 'string<)))) + +;; (emacsconf-extract-dump-filename emacsconf-extract-dump-dir "dev" (emacsconf-extract-time-or-offset-to-time "2022-12-04 11:30")) +;; emacsconf-2021-main_2021-11-20_15-31-16.webm hmm, this might be GMT +(defun emacsconf-extract-dump-ffmpeg-command (input-file start-time end-time output-file &optional compress-command) + (when (stringp start-time) (setq start-time (emacsconf-extract-time-or-offset-to-time start-time))) + (when (stringp end-time) (setq end-time (emacsconf-extract-time-or-offset-to-time end-time))) + (let* ((target-file-start (emacsconf-extract-dump-time-from-filename input-file)) + (dump-args (emacsconf-extract-dump-ffmpeg-seek-and-filename + input-file + (- (time-to-seconds start-time) + (time-to-seconds target-file-start)) + (- (time-to-seconds end-time) + (time-to-seconds target-file-start))))) + (if compress-command + (format "ffmpeg -y %s -c copy %s; %s %s &" + dump-args + output-file + compress-command + output-file) + (format "ffmpeg -y %s -c copy %s" + dump-args + output-file)))) +;; (emacsconf-extract-dump-ffmpeg-command (emacsconf-extract-dump-filename emacsconf-extract-dump-dir "dev" (emacsconf-extract-time-or-offset-to-time "2022-12-04T11:30:00")) "2022-12-04T11:30:00" "2022-12-04T13:00:00" "rms.webm") + +;; output-prefix +;; (format-time-string "%Y-%m-%d_%H-%M-%S" start-time t) +(defun emacsconf-extract-dump-get-command (input-prefix start-time end-time filename) + (interactive) + (setq start-time (emacsconf-extract-time-or-offset-to-time start-time)) + (setq end-time (emacsconf-extract-time-or-offset-to-time end-time)) + (format "ssh conf -- %s; scp conf:~/emacsconf-2021-stream-dumps/%s %s" + (shell-quote-argument + (format "cd %s; sudo %s" + "~/emacsconf-2021-stream-dumps/" + (emacsconf-extract-dump-ffmpeg-command + (emacsconf-extract-dump-filename emacsconf-extract-dump-dir input-prefix start-time) + start-time end-time + (concat "output/" filename)))) + (concat "output/" filename) + filename)) + +;; todo timezones +(defun emacsconf-extract-time-or-offset-to-time (input) + (cond ((numberp input) + (seconds-to-time (+ (time-to-seconds (current-time)) + (* input 60)))) + ((listp input) input) + ((stringp input) (date-to-time (if (string-match "[-Z+]" input) input (concat input emacsconf-timezone-offset)))) + ((string-match " " input) + (org-read-date t t input)) + (t (seconds-to-time (+ (time-to-seconds (current-time)) + (* (string-to-number input) 60)))))) + +(defun emacsconf-extract-dump-ffmpeg-seek-and-filename (filename start-seconds to-seconds) + "Return seek and input file argument." + (if (> start-seconds 30) + (format "-ss %f -i %s -ss %f -to %f" (- start-seconds 30) filename 30 (- to-seconds start-seconds -30)) + (format "-i %s -ss %f -to %f" filename start-seconds to-seconds))) + +(defun emacsconf-extract-dump-get (track start-time end-time output-prefix) + (interactive (list (emacsconf-complete-track) + (read-string "Start: ") + (read-string "End: ") + (read-string "Output prefix: "))) + (let ((result + (emacsconf-extract-dump-get-command + (concat emacsconf-id "-" emacsconf-year "-" (plist-get track :id)) + (emacsconf-extract-time-or-offset-to-time start-time) + (emacsconf-extract-time-or-offset-to-time end-time) + (concat output-prefix (format-time-string "%Y-%m-%d_%H-%M-%S" (emacsconf-extract-time-or-offset-to-time start-time) t) ".webm")))) + (when (called-interactively-p 'any) + (kill-new result)) + result)) + +(defun emacsconf-extract-dump-refine (filename starting-ts ending-ts) + (interactive + (list (read-file-name "Input: " nil (conf-latest-file ".") t) + (read-string "Start timestamp: ") + (read-string "End timestamp: "))) + (let ((result + (format "ffmpeg -y %s -c copy %s" + () + starting-ts filename + starting-ts ending-ts (expand-file-name (concat "trimmed-" (file-name-nondirectory filename)) + (file-name-directory filename))))) + (when (called-interactively-p 'any) + (kill-new result)) + result)) + +(defvar emacsconf-extract-qa-caption-length 50) + +(defun emacsconf-extract-qa-from-assemblyai-sentences (file) + (let ((data + (with-temp-buffer + (insert-file-contents file) + (json-parse-buffer))) + last-speaker) + (subed-create-file + (concat (file-name-sans-extension file) ".vtt") + (mapcar + (lambda (sent) + (let* ((words (mapconcat + (lambda (w) + (propertize (gethash "text" w) + 'start (gethash "start" w) + 'end (gethash "end" w) + 'confidence (gethash "confidence" w))) + (get-hash "words" sent) + " ")) + (reflowed (emacsconf-split-text-based-on-heuristics + words + emacsconf-extract-qa-caption-length))) + (seq-map-indexed + (lambda (line index) + (list + + ) + ) + ) + (list + nil + (gethash "start" sent) + (gethash "end" sent) + (if (string= (or last-speaker "") (gethash "speaker" sent)) + words + (format "[Speaker %s]: %s" (gethash "speaker" sent) (gethash "text" sent))) + (if (string= (or last-speaker "") (gethash "speaker" sent)) + nil + (setq last-speaker (gethash "speaker" sent)) + (emacsconf-surround "NOTE Speaker " (gethash "speaker" sent) "\n\n" nil))))) + (gethash "sentences" data))))) +;; (emacsconf-extract-qa-from-assemblyai-sentences "~/proj/emacsconf/rms/sentences") + +(defun emacsconf-extract-copy-pad () + (interactive) + (let ((slug (emacsconf-get-slug-from-string (file-name-base (buffer-file-name)))) + (delimiter "\\\\-\\\\-\\\\-\\\\-\\\\-") + notes + questions) + (goto-char (point-min)) + (when (re-search-forward "Notes, discussions, links, feedback:" nil t) + (forward-line 1) + (setq notes (string-trim (buffer-substring (point) (if (re-search-forward delimiter nil t) (match-beginning 0) (point-max)))))) + (when (re-search-forward "Questions and answers go here:" nil t) + (forward-line 1) + (setq questions (string-trim (buffer-substring (point) (if (re-search-forward delimiter nil t) (match-beginning 0) (point-max)))))) + (find-file (expand-file-name (concat slug ".md") (expand-file-name "talks" (expand-file-name emacsconf-year emacsconf-directory)))) + (goto-char (point-min)) + (if (re-search-forward "^# Discussion\n\n" nil t) + nil + (re-search-forward "-after)" nil t) + (forward-line -1) + (insert "# Discussion\n\n")) + (save-excursion + (unless (string= (or notes "") "") + (insert "## Notes\n\n" notes "\n\n")) + (unless (string= (or questions "") "") + (insert "## Questions and answers\n\n" questions "\n\n")) + ))) (provide 'emacsconf-extract) ;;; emacsconf-extract.el ends here |