Categories: geek » emacs » yay-emacs

RSS - Atom - Subscribe via email

My Evil Plan for Yay Emacs!

| yay-emacs, emacs, planning

Here's a clip from my 2024-01-21 Yay Emacs livestream about my goals for Yay Emacs and the built-in payoffs that I think will help me keep doing it.

  • 00:00.000: Getting more ideas into blog posts and workflow demos: Now, also, I have an evil plan. My evil plan is that this is a good way for me to get ideas and convert them into blog posts and code and then do the workflow demos, because it's sometimes really difficult to see how to use something from just the code.
  • 00:20.340: I have fun tickling my brain: This process is fun. Tweaking Emacs is fun for me.
  • 00:24.840: I learn from other people's comments, questions: Also, if I do this out loud, other people can help out with questions and comments, like the way that you're all doing now, which is great. Fantastic.
  • 00:35.200: Other people pick up ideas: Of course, those are all very selfish reasons. So I'm hoping other people are getting something out of this too. (Hello, 19 people who are watching, and also for some reason, the hundreds of people who check these videos out afterwards. Great, fantastic.) I'm hoping you pick up some ideas from the crazy things that we like to play with in terms of Emacs.
  • 00:57.440: We bounce ideas around and make lots of progress: My medium-term plan there is then to start seeing how those ideas get transformed when they get bounced off other people and other people bounce ideas back. Because that's one of the fun things about Emacs, right? Everything is so personalizable that seeing how one workflow idea gets transformed into somebody else's life, you learn something from that process. I'm really looking forward to how bouncing ideas around will work here.
  • 01:32.200: More people share more: Especially if we can find little things that make doing things more fun or they make it take less effort–then maybe more people will share more things, and then I get to learn from that also,
  • 01:46.940: Building up an archive: which is fantastic because long term, this can help build up an archive. Then people can go into that archive and find things without necessarily waiting for me. I don't become the bottleneck. People can just go in there and find… "Oh, you remember that time that I saw this interesting idea about SVG highlighting or whatever." You can just go in there and try to find more information.
  • 02:11.640: More people join and thrive in the Emacs community: So that's great. Then ideally, as people find the things that resonate with them, the cool demos that say this text editor can be extended to do audio editing and animation and all that crazy stuff, then more people will come and join and share what they're learning, and then move on to building stuff maybe for themselves and for other people, and then it'll be even more amazing.
  • 02:42.780: I could be a voice in people's heads: And lastly, this is kind of odd, but having listened in the background to so many of the kiddo's current viewing habits, her favorite YouTube channels like J Perm or Cubehead or Tingman for Rubik's cube videos or Eyecraftmc for Minecraft, I'm beginning to appreciate kind of the value of having these mental models of other people in your head. I can imagine how they talk and all that stuff. I am looking forward to watching more Emacs videos, which I haven't done in a while because usually for Emacs News, I'm just skimming through the transcripts super quickly on account of (A), lots of videos and (B), not much time. So this idea of getting other people's voices into your head, or possibly becoming a voice in somebody's head, I think there might be something interesting there. Of course, the buzz these days is, "oh no, AI voice cloning, this is a safety issue and all of that stuff." But I think there are positive uses for this as well, in the sense that… As qzump says, you know, they are like, "I have no Emacs friends and you're speaking to my soul." A lot of us are doing this in isolation. We don't normally meet other people. So the more voices we can have in our heads of actual people who enjoy doing these things, the less weird we feel. Or actually, more like… the more weird we feel, but in a good way, like there's a tribe, right? If sharing more ideas in a multimedia sort of way, like with either audio narration with images or this webcam thing that we're trying (my goodness, I have to actually dress up) helps people build these mental models in their head… Hey, one of the nice things about this webcam thing is I can make hand gestures. Cool, cool. Might be interesting. If, while you're hacking on Emacs, you can imagine me cheering you on and saying, "That's fantastic. Have you thought about writing a blog post about that so that we get that into Planet Emacs Life and, and then into Emacs News? Please share what you're learning." It'll be great. So, yeah, maybe that's a thing. So that's my evil plan for Yay Emacs.
View org source for this post

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

| yay-emacs, 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.

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!

View org source for this post

Yay Emacs 1: EmacsConf 2023 report, SVG animation, Embark, Org Mode links

| yay-emacs, emacs

For this livestream, I experimented with scheduling it for 8:00 AM EST instead of just starting it whenever I could squeeze in the time.1 People dropped by! And asked questions! And suggested interesting things! Wow. This could be fun.

I wrote a bunch of blog posts throughout the week and added lots of little videos to them. It was easy to walk through my recent posts and demonstrate things without worrying about (a) accidentally leaking personal information or (b) flubbing things on camera, since apparently my multitasking abilities are on the way down.2 It felt good to go through them and add some more commentary and highlights while knowing that all the details are there in case people want to do a deeper dive.

Here are the links:

I roughly edited the transcript from Deepgram and I uploaded it to YouTube, fixing some bugs in my Deepgram VTT conversion along the way. I think I like having proper transcripts even for ephemeral stuff like this, since it costs roughly USD 0.21 for the 43-minute video and I can probably figure out how to make editing even faster..

New projects are easier to keep working on when they have immediate personal benefits. It's easy for me to keep doing Emacs News every week because I have so much fun learning about the cool things people are doing with Emacs. I think it'll be easy for me to keep doing Yay Emacs livestreams because not only do I get to capture some workflows and ideas in videos, but other people might even tell me about interesting things that could save me time or open up new possibilities. Also, it's worth building up things I love.

I'm going to try scheduling another stream for next Sunday (Jan 21) at 7:30 AM EST. Maybe I can experiment with sharing my screen with the Surface Book or the W530 and then using that computer to stream. We'll see what that's like!

Footnotes:

1

Thanks to the unpredictability of life with a kiddo, scheduling things has been one of my life goals for a while! <laugh> When I created the event, the kiddo was still in her winter-break habit of sleeping in until 10 or 11, so I figured that I had a little time before I needed to call in for her virtual school at 8:45 AM. Of course, that week she decided to start setting her alarm for 7:59 AM so that she could wake up early and have watching time, and she actually started waking up around that time. So for Friday, I woke up earlier (well, the cat woke got me up even earlier) and packed a little breakfast she could have in the living room (since my computer's on a kitchen cabinet)… and that was the one day she snoozed her alarm clock and sleep in. I've scheduled the next stream for 7:30 AM… and she has announced that she wants to set her alarm for 7:30ish. Hmm.

2

I notice that it can be a little challenging for me to talk and do things at the same time. This is particularly obvious when I'm cubing (brain hiccup at the last step, gotta solve the whole Rubik's cube all over again). It's also why I prefer to record the audio for my presentations separately instead of winging it. =) It could be verbal interference, (very mild, totally expected) age-related cognitive decline (which is a topic I've been meaning to write up my notes on), or my squirrel brain could just have been pretty bad at this all along. Anyway, words or code, sometimes I just gotta pick one. Never mind my laptop's CPU not handling ffmpeg well, my brain's CPU gets high utilization too. That's good, though!

View org source for this post

Quick notes on livestreaming to YouTube with FFmpeg on a Lenovo X230T

| video, youtube, streaming, ffmpeg, yay-emacs

[2024-01-05 Fri]: Updated scripts

Text from the sketch

Quick thoughts on livestreaming

Why:

  • work out loud
  • share tips
  • share more
  • spark conversations
  • (also get questions about things)

Doable with ffmpeg on my X230T:

  • streaming from my laptop
  • lapel mic + system audio,
  • second screen for monitoring

Ideas for next time:

  • Overall notes in Emacs with outline, org-timer timestamped notes; capture to this file
  • Elisp to start/stop the stream → find old code
  • Use the Yeti? Better sound
  • tee to a local recording
  • grab screenshot from SuperNote mirror?

Live streaming info density:

  • High: Emacs News review, package/workflow demo
  • Narrating a blog post to make it a video
  • Categorizing Emacs News, exploring packages
  • Low: Figuring things out

YouTube can do closed captions for livestreams, although accuracy is low. Videos take a while to be ready to download.

Experimenting with working out loud

I wanted to write a report on EmacsConf 2023 so that we could share it with speakers, volunteers, participants, donors, related organizations like the Free Software Foundation, and other communities. I experimented with livestreaming via YouTube while I worked on the conference highlights.

It's a little over an hour long and probably very boring, but it was nice of people to drop by and say hello.

The main parts are:

  • 0:00: reading through other conference reports for inspiration
  • 6:54: writing an overview of the talks
  • 13:10: adding quotes for specific talks
  • 25:00: writing about the overall conference
  • 32:00: squeezing in more highlights
  • 49:00: fiddling with the formatting and the export

It mostly worked out, aside from a brief moment of "uhhh, I'm looking at our private conf.org file on stream". Fortunately, the e-mail addresses that were showed were the public ones.

Technical details

Setup:

  • I set up environment variables and screen resolution:

      # From pacmd list-sources | egrep '^\s+name'
      LAPEL=alsa_input.usb-Jieli_Technology_USB_Composite_Device_433035383239312E-00.mono-fallback #
      YETI=alsa_input.usb-Blue_Microphones_Yeti_Stereo_Microphone_REV8-00.analog-stereo
      SYSTEM=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor
      # MIC=$LAPEL
      # AUDIO_WEIGHTS="1 1"
      MIC=$YETI
      AUDIO_WEIGHTS="0.5 0.5"
      OFFSET=+1920,430
      SIZE=1280x720
      SCREEN=LVDS-1  # from xrandr
      xrandr --output $SCREEN --mode 1280x720
    
  • I switch to a larger size and a light theme. I also turn consult previews off to minimize the risk of leaking data through buffer previews.
    my-emacsconf-prepare-for-screenshots: Set the resolution, change to a light theme, and make the text bigger.
    (defun my-emacsconf-prepare-for-screenshots ()
      (interactive)
      (shell-command "xrandr --output LVDS-1 --mode 1280x720")
      (modus-themes-load-theme 'modus-operandi)
      (my-hl-sexp-update-overlay)
      (set-face-attribute 'default nil :height 170)
      (keycast-mode))
    

Testing:

ffmpeg -f x11grab -video_size $SIZE -i :0.0$OFFSET -y /tmp/test.png; display /tmp/test.png
ffmpeg -f pulse -i $MIC -f pulse -i $SYSTEM -filter_complex amix=inputs=2:weights=$AUDIO_WEIGHTS:duration=longest:normalize=0 -y /tmp/test.mp3; mpv /tmp/test.mp3
DATE=$(date "+%Y-%m-%d-%H-%M-%S")
ffmpeg -f x11grab -framerate 30 -video_size $SIZE -i :0.0$OFFSET -f pulse -i $MIC -f pulse -i $SYSTEM -filter_complex "amix=inputs=2:weights=$AUDIO_WEIGHTS:duration=longest:normalize=0" -c:v libx264 -preset fast -maxrate 690k -bufsize 2000k -g 60 -vf format=yuv420p -c:a aac -b:a 96k -y -flags +global_header "/home/sacha/recordings/$DATE.flv" -f flv

Streaming:

DATE=$(date "+%Y-%m-%d-%H-%M-%S")
ffmpeg -f x11grab -framerate 30 -video_size $SIZE -i :0.0$OFFSET -f pulse -i $MIC -f pulse -i $SYSTEM -filter_complex "amix=inputs=2:weights=$AUDIO_WEIGHTS:duration=longest:normalize=0[audio]" -c:v libx264 -preset fast -maxrate 690k -bufsize 2000k -g 60 -vf format=yuv420p -c:a aac -b:a 96k -y -f tee -map 0:v -map '[audio]' -flags +global_header  "/home/sacha/recordings/$DATE.flv|[f=flv]rtmp://a.rtmp.youtube.com/live2/$YOUTUBE_KEY"

To restore my previous setup:

my-emacsconf-back-to-normal: Go back to a more regular setup.
(defun my-emacsconf-back-to-normal ()
  (interactive)
  (shell-command "xrandr --output LVDS-1 --mode 1366x768")
  (modus-themes-load-theme 'modus-vivendi)
  (my-hl-sexp-update-overlay)
  (set-face-attribute 'default nil :height 115)
  (keycast-mode -1))

Ideas for next steps

I can think of a few workflow tweaks that might be fun:

  • a stream notes buffer on the right side of the screen for context information, timestamped notes to make editing/review easier (maybe using org-timer), etc. I experimented with some streaming-related code in my config, so I can dust that off and see what that's like. I also want to have an org-capture template for it so that I can add notes from anywhere.
  • a quick way to add a screenshot from my Supernote to my Org files

I think I'll try going through an informal presentation or Emacs News as my next livestream experiment, since that's probably higher information density.

View org source for this post