Skip to content

karthink/elfeed-tube

Repository files navigation

Elfeed Tube: Youtube on your terms

https://melpa.org/packages/elfeed-tube-badge.svg

Elfeed Tube is an Emacs package for a richer, interactive, noise-free and fully text-capable interface to your Youtube subscriptions and playlists using Elfeed, the RSS feed reader for Emacs. Think of it as supercharging Elfeed, or perhaps a taste of what the RSS/Atom protocol could have become today if it had continue to evolve.

Elfeed Tube adds video descriptions, metadata and “live” transcripts (see below) for all Youtube video entries in Elfeed. Here is what a video entry looks like:

(Higher quality version)

Here is the same Youtube video entry in Elfeed without Elfeed Tube:

Elfeed Tube is useful for any Youtube RSS feed, but it works particularly well for channels/playlists with longer form videos, podcasts, technical talks and lectures. For an introduction to Elfeed and RSS feeds, see this video by Protesilaos Stavrou.

Contents

Features

Fully asynchronous updates

Like Elfeed, Elfeed Tube fetches all data asynchronously. Emacs will not block. (This gets top billing because I know the pain.)

Description and other metadata

Elfeed Tube adds the video duration, thumbnail, video description and chapters to each Youtube entry in Elfeed. These elements can be turned off individually or tweaked to your liking.

For example, you may prefer to avoid including video descriptions because they often have linkspam, or prefer larger thumbnails.

Transcripts that are…

Youtube transcripts, including auto-generated ones, are automatically downloaded in your language of choice, formatted and displayed in your Elfeed buffers:

Noise-free (No Ad reads)

There are no sponsor reads, ads or promotions in the transcript. These are automatically recognized and either greyed out or hidden from view. Here’s an Ad read section that you now don’t have to read:

Here is a more extensive version.

You can turn this feature off, or add more recognized sections to the strike-list, like intros and outros.

Interactive

Clicking on a transcript segment opens the video at that time in your browser or video player of choice:

You can also move your cursor there and press return (RET). The tool-tip provides more help.

Navigable with imenu

Video chapters, when available, are included as headings in the transcript. The entry can be navigated through imenu. Here I jump between descriptions of different movies in this video:

chapter-imenu-demo.mp4

“Live”

With MPV integration (optional), you can seek to any time in the video by clicking at the corresponding text in your buffer:

seek-to-time-1.mp4

You can jump in Emacs to the current video position with elfeed-tube-mpv-where (C-c C-w):

jump-to-playing-1.mp4

Finally, you can also follow along with the video in Emacs:

follow-mode-4.mp4

To do this, turn on elfeed-tube-mpv-follow-mode (C-c C-f). When this mode is active you can pause video playback with SPC. Clicking on any segment in the transcript will still seek to that point.

You can combine elfeed-tube-mpv-follow-mode with other Emacs buffer modes, like Emacs’ follow-mode that shows a contiguous buffer in two windows:

follow-mode-3-.4.mp4

This feature does not lock up Emacs. You can work in a different window while tracking updates in this one.

Archivable and retrievable

The information fetched by Elfeed Tube, including the transcripts (with timing information) is associated with the feed and stored in your Elfeed database like any other text entry. You can bookmark it in Emacs, refer to it in your other notes and so on.

The Elfeed database is plain text, optionally gzipped. You can be sure that it will be readable decades from now.

Searchable and Org-linkable (It’s just an Emacs buffer)

You can text search your transcripts, Org-link them, quote from them, etc. Tagging support, date-oriented and metadata-based search is included as part of Elfeed.

When transcripts are available in some form, which is most of the time, they can be your primary entry and reference point for the video. This works especially well with technical content, tutorials, talks and podcasts.

NOTE: It would be fantastic to be able to search for caption text across your entire Elfeed database instead of inside an entry, but Elfeed does not (yet) support full-text search. You’ll have to search for entries by supported fields instead, through a combination of the entry date range, tags, entry title and channel name etc.

Putting it together

Combined with the text manipulation capabilities of Emacs, you can combine these features into a very accessible video interface. You can handle video partially like you handle text:

  • Narrow the buffer to just occurrences of a phrase in the transcript, then jump between where they appear. In this example I use consult-focus-lines to show only lines mentioning “Ramanujan”, then jump through these points in the video by pressing RET. Full-text video search!
    demo-focus-lines-1.mp4

    This search missed one mention (which was spelled “ramonogen”), but Youtube’s auto-generated captions do a surprisingly good job of capturing most common English words. Videos with uploaded captions (most talks/technical videos) don’t have this problem.

  • The simpler version: Want to jump to where in the episode you heard a podcast host talking about Tunisian history? Search the buffer for Tunisia using Isearch in Emacs, then press RET.
  • Youtube video descriptions for technical videos often have useful links or references. Here I use Embark to collect the (non-Youtube, non-sponsor) links and open them in a browser:
    demo-desc-links-1-.2.mp4

    This works in regular Elfeed too, of course, but for Youtube videos this is much more pleasant than hunting for the tiny “more…” dropdown in the web browser.

  • Watching a lecture or a long video and need a break? Jump to the currently playing position in the transcript with elfeed-tube-mpv-where (C-c C-w), then bookmark the buffer (bookmark-set, C-x r m) and quit Emacs. You can pick up right where you left off in both the transcript and video with bookmark-jump (C-x r b).
  • Want to focus playback to a certain part of the transcript? Narrow the buffer (C-x n n) to the region you want and turn on elfeed-tube-mpv-follow-mode.

Setup

Elfeed Tube is available on MELPA. After adding MELPA to your package archives, you can install it by running M-x package-install⮐ elfeed-tube in Emacs, or by running the below use-package block(s).

MPV integration with the live transcripts is provided separately as elfeed-tube-mpv, you can install it with M-x package-install⮐ elfeed-tube-mpv.

Requirements:

  • Emacs 27.1 or newer with JSON support
  • Curl

Dependencies (automatically installed):

  • Elfeed, the feed reader for Emacs.
  • aio, the async-IO library for Emacs.

For “live” transcripts with elfeed-tube-mpv:

Set up with use-package

(use-package elfeed-tube
  :ensure t ;; or :straight t
  :after elfeed
  :demand t
  :config
  ;; (setq elfeed-tube-auto-save-p nil) ; default value
  ;; (setq elfeed-tube-auto-fetch-p t)  ; default value
  (elfeed-tube-setup)

  :bind (:map elfeed-show-mode-map
         ("F" . elfeed-tube-fetch)
         ([remap save-buffer] . elfeed-tube-save)
         :map elfeed-search-mode-map
         ("F" . elfeed-tube-fetch)
         ([remap save-buffer] . elfeed-tube-save)))

If you want “live” captions and better MPV support:

(use-package elfeed-tube-mpv
  :ensure t ;; or :straight t
  :bind (:map elfeed-show-mode-map
              ("C-c C-f" . elfeed-tube-mpv-follow-mode)
              ("C-c C-w" . elfeed-tube-mpv-where)))

Set up without use-package

(require 'elfeed-tube)
(elfeed-tube-setup)
(define-key elfeed-show-mode-map (kbd "F") 'elfeed-tube-fetch)
(define-key elfeed-show-mode-map [remap save-buffer] 'elfeed-tube-save)
(define-key elfeed-search-mode-map (kbd "F") 'elfeed-tube-fetch)
(define-key elfeed-search-mode-map [remap save-buffer] 'elfeed-tube-save))

If you want “live” captions and better MPV support:

(require 'elfeed-tube-mpv)
(define-key elfeed-show-mode-map (kbd "C-c C-f") 'elfeed-tube-mpv-follow-mode)
(define-key elfeed-show-mode-map (kbd "C-c C-w") 'elfeed-tube-mpv-where)

Usage

If you are already subscribed to Youtube RSS feeds using Elfeed, you can skip to Step II.

Elfeed Tube tries its best to work out of the box with no set up, but Step I below is unavoidable if you’re starting fresh.

Step I: Add Youtube subscriptions to Elfeed

Fortunately, Youtube still provides RSS feeds for channels and playlists. Unfortunately, Youtube doesn’t make it easy to find them.

Elfeed Tube provides a helper function: M-x elfeed-tube-add-feeds to find the RSS feeds (asynchronously) for channels or playlists. When given one ore more Youtube video/playlist/channel URLs or plain text search terms, it will:

  • Find the corresponding feeds and display a summary you can confirm
  • Add the feeds to your list of elfeed-feeds.
add-feeds-demo-1.mp4

(Finding the feeds is also asynchronous)

Examples (RET means pressing return):

  • M-x elfeed-tube-add-feeds RET cgp grey, julia computing, https://www.youtube.com/playlist?list=PLZdCLR02grLqSy15ALLAZDU6LGpAJDrAQ RET
  • M-x elfeed-tube-add-feeds RET https://www.youtube.com/watch?v=6etTERFUlUI RET

Queries are separated by Emacs’ crm-separator, which is comma (,) by default. Be warned: URLs are safer, plain text queries might find the wrong channels!

When called noninteractively, it can accept a list of URLs or queries:

(elfeed-tube-add-feeds '("veritasium"
                         "https://www.youtube.com/playlist?list=PLEoMzSkcN8oMc34dTjyFmTUWbXTKrNfZA"
                         "quanta magazine"
                         "julia computing"
                         "https://www.youtube.com/watch?v=bSVfItpvG5Q"
                         "https://youtu.be/7CM7Ef-dPWQ"
                         "tom scott"))

See the docstring for more options.

Other ways to find feeds

You can use a web service like https://rssbox.herokuapp.com/, or look in the HTML of a Youtube channel page if you like your web browser’s element inspector!

Step II: Use Elfeed as usual

That’s it. Assuming you’ve run (elfeed-tube-setup), included in the above use-package block, there’s nothing else to do.

If you’re new to Elfeed, you can start with M-x elfeed.

In case the fetch for a Youtube entry fails you can call M-x elfeed-tube-fetch with a prefix argument (C-u F or C-u M-x elfeed-tube-fetch) to force a refetch.

(Optional) Back-fill YouTube feeds

While Elfeed is a vault, Youtube RSS feeds only contain the last 15 videos from a channel. So you will only collect entries for videos from a little before when you subscribe to a channel’s feed.

Elfeed Tube provides a command to add all historical entries for Youtube feeds to Elfeed. Call elfeed-tube-fill-feeds in an Elfeed search or entry buffer to fetch all entries for the feed at point. You can do this for many feeds at once by selecting a region of entries.

(Optional) For “Live” captions with MPV

For a “live” connection between the transcript and MPV:

  • Ensure the mpv library is installed (M-x package-install mpv). Without it, you can still open videos at transcript locations in MPV but it will not be “live”.
  • Start playback by clicking anywhere in the transcript.
  • To seek to a text segment click there or press RET.
  • To jump to the current location in the transcript, use elfeed-tube-mpv-where (C-c C-w).
  • To track a video continuously, turn on elfeed-tube-mpv-follow-mode (C-c C-f). You can continue to work in a different window.

Additionally, playback with “live” transcripts will behave as expected with buffer narrowing.

(Optional) View entries instead of auto-saving them

Not all Youtube videos contain gems of wisdom, to put it mildly. You may thus want to only view video information instead of adding it directly to the Elfeed database. This is especially salient since there’s no (user-facing) way to delete items in Elfeed.

To do this you can set

(setq elfeed-tube-auto-save-p nil) ;This is the default value

Now Youtube entries you view will feature a [*NOT SAVED*] marker:

The fetched info will be cached for this Emacs session. Entries that you deem useful (such as the handy Guix tutorial in the above entry) can be added to your Elfeed database by clicking on this marker, or with your save-buffer keybinding (typically C-x C-s):

You can change the marker style through elfeed-tube-save-indicator if you’d like a more subdued indicator.

(Optional) Fetch manually

Finally, you can also disable auto-fetching data and call M-x elfeed-tube-fetch (bound to F) from an Elfeed Search or Show buffer to fetch selectively. To do this, set

(setq elfeed-tube-auto-fetch-p nil)

M-x elfeed-tube-fetch will fetch info for all Youtube entries in a selected region in an Elfeed Search buffer.

You can independently control auto/manual fetching of info and auto/manual saving of info to the Elfeed database.

(Optional) Elfeed Tube for any video

You can call elfeed-tube-fetch outside of Elfeed to read an abritrary Youtube video URL (not just feed entries) and produce an Elfeed-like entry buffer for it with description, other metadata and live transcripts etc. Essentially you can use Elfeed Tube as a Youtube viewer. This feature is currently experimental.

Commands summary

elfeed-tube commands:

CommandDescriptionWheresuggested key-binding
elfeed-tube-add-feedsFind youtube feeds from search queriesAnywhere in EmacsN/A
elfeed-tube-fetchFetch info for any videoAnywhere in EmacsN/A
elfeed-tube-fetch (again)Fetch video info for Elfeed entry (optional)Anywhere in ElfeedF
elfeed-tube-saveManually save entry to Elfeed DB (optional)In an Elfeed entryC-x C-s
elfeed-tube-fill-feedsBack-fill Youtube feed entriesAnywhere in ElfeedN/A

elfeed-tube-mpv commands, for live transcripts

CommandDescriptionWheresuggested key-binding
elfeed-tube-mpvOpen video at time or seek video to this timeIn an Elfeed entrymouse-1, mouse-2 or RET
elfeed-tube-mpv-whereJump to current video location in transcriptIn an Elfeed entryC-c C-w
elfeed-tube-mpv-follow-modeContinuously track a video playing in MPVIn an Elfeed entryC-c C-f

Customization

Elfeed Tube has opinionated defaults but is fully configurable through the Customize interface (M-x customize). Here are some examples:

Disabling fields

Customize elfeed-tube-fields. To show only the duration and captions but no description, thumbnail or chapter locations:

;; Other options:  thumbnail, description, chapters
(setq elfeed-tube-fields '(duration captions))

Customizing fields

Thumbnails

Control the size with elfeed-tube-thumbnail-size.

Captions

Languages

elfeed-tube-captions-languages: Language preference. The first available matching transcript will be fetched:

;; Arabic or English or auto generated English captions
(setq elfeed-tube-captions-languages
      '("ar" "en" "english (auto generated)"))

Sponsored segments

  • elfeed-tube-captions-sblock-p controls whether sponsored segments of videos are de-emphasized in the transcript.
  • elfeed-tube-captions-faces: Faces to use for different types of transcript segments.

Persistence

Set the boolean elfeed-tube-auto-save-p to t to automatically save fetched information to the Elfeed database.

The boolean elfeed-tube-save-indicator controls the style of indicator used to indicate unsaved content.

FAQ

Do I need a Youtube API key to use this?

Not as of right now, it should Just Work.

Where does Elfeed Tube fetch data from?

It combines information from a number of sources:

  • Scraping the Youtube video page
  • Invidious instances that provide an API (dynamically found)
  • The Sponsorblock API for crowd-sourced Ad segment identification

Yes, this does mean that the fetcher code is going to need updating often. Them’s the breaks.

Can I use the transcripts feature without installing Elfeed?

Not at present. Elfeed Tube depends on Elfeed to do a lot of the lifting.

However you can use it with any Youtube video, see: (Optional) Elfeed Tube for any video. If you’re interested in creating a stand alone package for this please go ahead.

What about these Youtube features?

No support is currently planned for

  • Search
  • Video recommendations
  • Comments
  • Likes, Dislikes and views

Elfeed Tube is not a Youtube client for Emacs.

Instead, it plays to the strengths of RSS: to provide you with a regular digest of self-curated content in a more accessible way than otherwise possible. So search is not planned (see alternatives).

Video recommendations are sometimes useful for discovery, but in their current form they’re designed primarily to keep you watching Youtube and often end in rabbit-holeing and doom spirals. Helping myself avoid these behaviors is an explicit goal of Elfeed Tube!

The top comments are occasionally useful, especially on technical videos. I might add support for these in the future, although none is planned as of now.

Limitations

  1. Elfeed provides only metadata, not full-text search across your entries since it is (almost) a plain text database.
  2. There is no (user-facing) way to delete entries from an Elfeed database, so curate wisely! Note that my Elfeed database has about 32,000 entries across 272 feeds and it’s very snappy so far.
  3. Only one MPV instance can be connected to a live transcript in an Emacs session at a time. This is a limitation of the mpv library. (You can spawn as many “non-live” instances as you want.)
  4. Live transcript seeking and tracking can have an error of ±1 second.
  5. Fetches can occasionally fail. If this happens you may need to call M-x elfeed-tube-fetch manually on an entry or selection of entries.

Planned features

  • [ ] Specify what data to fetch per feed instead of globally.
  • [ ] Elfeed search keyword for video duration: (“=crafters <25min” should return videos in the Elfeed DB from the “System Crafters” Youtube channel feed that are under 25 minutes long, etc.)
  • [ ] Support for Youtube’s official API
  • [ ] Re-punctuating auto-generated captions using a punctuator2 web service
  • [ ] url-retrieve support so Curl isn’t required
  • [ ] Backporting to Emacs 26.x

Alternatives

  • If you are looking for a Youtube client for Emacs, with full search, comments, view counts and video recommendations, check out ytel with ytel-show.
  • Not an alternative but a nice complement to Elfeed Tube: Lua scripts for MPV can offer a superior Youtube watching experience than anything in the browser. Check out

    The full list of scripts is overwhelming!

Acknowledgments

  • Chris Wellons for writing Elfeed, the best feed reader I’ve used.
  • Chris Wellons for also writing emacs-aio, the async wrapper for Emacs. It writes callbacks for me so I never have to.
  • Ajay Ramachandran for writing and running Sponsorblock
  • The kind folks maintaining Invidious instances, youtube-dl and yt-dlp