Yay Emacs!

Stream notes

CANCELLED FOR NOW - experimenting with minimal screen time during the day since that seems to make the kiddo's life easier, so I don't get to have screentime too

Watch previous videos at at https://youtube.com/@sachactube/live - iCalendar file - RSS

Overall goals

2024-01-20-04 My Evil Plan for Yay Emacs! #EvilPlan #planning #emacs #YayEmacs.png

I want to work out loud so that:

  • I can get more stuff out of my head and into code/videos/blog posts
  • people can pick up ideas from things I might overlook
  • I can learn from people's ideas and suggestions

I want to share my notes file so that:

  • people who join mid-way can catch up
  • people can copy-and-paste instead of trying to re-type
  • people can chime in with things they want me to explore

CANCELLED Yay Emacs! 2024-02-11

Past livestreams

Ideas for future sessions

debugging   YayEmacs

@sachac re: the stream comment, I haven't done much debugging in Emacs via its debugger – or it's not a natural part of my elisp flow – so seeing that at the end made me think about debugging wins as potential "Yay emacs" moments.

https://mastodon.social/@charliemac/111794178311111100

*

:CREATED: [2024-01-21 Sun 09:04]

TODO Clip evil plans from 2024-01-21 Yay Emacs   YayEmacs

TODO Transcribe 2024-01-21 Yay Emacs   YayEmacs

SOMEDAY iCalendar Export (The Org Manual)   YayEmacs emacs

Refiling   YayEmacs

refile for navigation refile to current file refile to a subset

news refiling

Workflow

Process

  • Download: yt-dlp –prefer-free-formats $URL

TODO automatically determine the VTT from the filename

SOMEDAY @matthewstott3493 4 minutes ago Fantastic job on your live streams! Loving the faces and themes (ef-themes?), it is highly legible! Would recommend Prot's spacious-mode and some buffers [5:16 the line wrapping would look better with fill-paragraph. Presentation mode might be beneficial unless you are demonstrating. Using a variable pitch face on non-code buffers would be nice. Would prefer 1080p but am guessing you find 720p to be less of an impact on your hardware and streaming. Can you document your setup for recording and live streaming? am sure you learned a lot over the last couple of Emacs Conferences.   YayEmacs workflow

Youtube comment

TODO switch to command log mode since keycast isn't seen in my modeline   YayEmacs workflow

TODO consider refresh for OBS web source   YayEmacs workflow

TODO Get the audio clip about evil plans for Yay Emacs and turn it into an animated blog post   YayEmacs toclip workflow

TODO Figure out how to get live caption text   YayEmacs workflow

Options:

  • Send phone screen through quick OCR for once-in-a-while copies
  • See if I can stream the 608/708 embedded captions from YouTube's autocaptions
  • Use Deepgram's streaming API

SOMEDAY Send URL to Youtube chat   YayEmacs workflow

Figure out how to properly show EMMS track info

Update the category description

(let ((time (my-org-closest-future-time)))
  (with-temp-file "~/proj/static-blog/_data/term-descriptions/yay-emacs.html"
    (insert
     (format
      "<div>The next stream is on %s.
<a href=\"https://yayemacs.com\">Find details and watch here.</a></div>

<iframe width=\"560\" height=\"315\" src=\"https://www.youtube-nocookie.com/embed/live_stream?channel=UClT2UAbC6j7TqOWurVhkuHQ\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen></iframe>"
      (format-time-string "%a %Y-%m-%d %-H:%M %Z (%z)"
                          (org-timestamp-to-time
                           (org-timestamp-from-string
                            time)))))))

DONE Yay Emacs: Using elisp: links in Org Mode to note the time and display messages on stream   YayEmacs org

I like adding chapters to my videos so that people can jump to sections. I can figure out the sections by reading the transcript, adding NOTE comments, and extracting the times for those with my-youtube-copy-chapters. It could be nice to capture the times on the fly. org-timer could let me insert relative timestamps, but I think it might need some tweaking to synchronize that with when the stream starts according to YouTube. I've set up a capture, too, so I can take notes with timestamps.

It turns out that I don't have a lot of mental bandwidth when I'm on stream, so it's hard to remember keyboard shortcuts. (Maybe if I practise using the hydra I set up…) Fortunately, Org Mode's elisp: link type makes it easy to set up executable shortcuts. For example, I can add links like [[elisp:my-stream-message-link][TODO]] to my livestream plans like this:

2024-01-20-elisp-links.svg
Figure 1: Shortcuts with elisp: links

I can then click on the links or use C-c C-o (org-open-link-at-point) to run the function. When I follow the TODO link in the first item, Emacs displays a clock and a message based on the rest of the line after the link.

2024-01-20-message.svg
Figure 2: Displaying a clock and a message

In the background, the code also sets the description of the link to the wall-clock time.

2024-01-20-time.svg
Figure 3: Link description updated with the time

If I start the livestream with a clock displayed on screen, I can use that to translate wall-clock times to relative time offsets. I'll probably figure out some Elisp to translate the times automatically at some point, maybe based on something like org-timer-change-times-in-region.

I figured it might be fun to add a QR code automatically if we detect a URL, taking advantage of that qrencode package I started playing around with. That way, people might be able to just scan it off the screen.

2024-01-20-qr.svg
Figure 4: With a QR code

You can also use elisp: links for more complicated Emacs Lisp functions, like this: elisp:(progn ... ...).

Here's the code that makes it happen. It's based on emacsconf-stream.el.

(defvar my-stream-message-buffer "*Yay Emacs*")
(defvar my-stream-message-timer nil)

(defun my-stream-message-link ()
  (interactive)
  (save-excursion
    (when (and (derived-mode-p 'org-mode)
               (eq (org-element-type (org-element-context)) 'link))
      (my-stream-update-todo-description-with-time)
      (goto-char (org-element-end (org-element-context)))
      (my-stream-message (org-export-string-as (buffer-substring (point) (line-end-position)) 'ascii t)))))
(defun my-stream-update-todo-description-with-time ()
  (when (and (derived-mode-p 'org-mode)
             (eq (org-element-type (org-element-context)) 'link))
    (my-org-update-link-description (format-time-string "%-I:%M:%S %p"))))

(defun my-stream-message (&optional message)
  (interactive "MMessage: ")
  ;; update the description of the link at point to be the current time, if any
  (switch-to-buffer (get-buffer-create my-stream-message-buffer))
  (erase-buffer)
  (delete-other-windows)
  (when (string= message "") (setq message nil))
  (face-remap-add-relative 'default :height 200)
  (insert
   "Yay Emacs! - Sacha Chua (sacha@sachachua.com)\n"
   (propertize
    "date"
    'stream-time (lambda () (format-time-string "%Y-%m-%d %H:%M:%S %Z (%z)")))
   "\n\n"
   message)
  ;; has a URL? Let's QR encode it!
  (when-let ((url (save-excursion
                    (when (re-search-backward ffap-url-regexp nil t)
                      (thing-at-point-url-at-point)))))
    (insert (propertize (qrencode url) 'face '(:height 50)) "\n"))
  (insert  "\nYayEmacs.com\n")
  (when (timerp my-stream-message-timer) (cancel-timer my-stream-message-timer))
  (my-stream-update-time)
  (setq my-stream-message-timer (run-at-time t 1 #'my-stream-update-time))
  (goto-char (point-min)))

(defun my-stream-update-time ()
  "Update the displayed time."
  (if (get-buffer my-stream-message-buffer)
      (when (get-buffer-window my-stream-message-buffer)
        (with-current-buffer my-stream-message-buffer
          (save-excursion
            (goto-char (point-min))
            (let (match)
              (while (setq match (text-property-search-forward 'stream-time))
                (goto-char (prop-match-beginning match))
                (add-text-properties
                 (prop-match-beginning match)
                 (prop-match-end match)
                 (list 'display
                       (funcall (get-text-property
                                 (prop-match-beginning match)
                                 'stream-time))))
                (goto-char (prop-match-end match)))))))
    (when (timerp my-stream-message-timer)
      (cancel-timer my-stream-message-timer))))

Let's see if that makes it easy enough for me to remember to actually do it!

TODO Make alternate timezone org files

  • Like the way we did it in EmacsConf
  • General-purpose way to translate all the times? Do I need to execute all the code, though?

SOMEDAY Tweak stream page theme, add hook   YayEmacs

SOMEDAY Stream page, timezone versions, just use Syncthing   YayEmacs

Schedule for current one Schedule for next one Timezone links Previous livestreams

Back to top | E-mail me