Elfeed Tube: Youtube on your terms
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:
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
- Transcripts that are…
- Setup
- Usage
- Customization
- FAQ
- Limitations
- Planned features
- Alternatives
- Acknowledgments
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.
imenu
Navigable with 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 pressingRET
. 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 withbookmark-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 onelfeed-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
- Curl
Dependencies (automatically installed):
For “live” transcripts with elfeed-tube-mpv
:
- mpv: The mpv library for Emacs
- MPV video player and youtube-dl (or yt-dlp)
use-package
Set up with (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)))
use-package
Set up without (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:
Command | Description | Where | suggested key-binding |
---|---|---|---|
elfeed-tube-add-feeds | Find youtube feeds from search queries | Anywhere in Emacs | N/A |
elfeed-tube-fetch | Fetch info for any video | Anywhere in Emacs | N/A |
elfeed-tube-fetch (again) | Fetch video info for Elfeed entry (optional) | Anywhere in Elfeed | F |
elfeed-tube-save | Manually save entry to Elfeed DB (optional) | In an Elfeed entry | C-x C-s |
elfeed-tube-fill-feeds | Back-fill Youtube feed entries | Anywhere in Elfeed | N/A |
elfeed-tube-mpv
commands, for live transcripts
Command | Description | Where | suggested key-binding |
---|---|---|---|
elfeed-tube-mpv | Open video at time or seek video to this time | In an Elfeed entry | mouse-1 , mouse-2 or RET |
elfeed-tube-mpv-where | Jump to current video location in transcript | In an Elfeed entry | C-c C-w |
elfeed-tube-mpv-follow-mode | Continuously track a video playing in MPV | In an Elfeed entry | C-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,
Dislikesand 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
- Elfeed provides only metadata, not full-text search across your entries since it is (almost) a plain text database.
- 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.
- 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.) - Live transcript seeking and tracking can have an error of ±1 second.
- 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
- mpv-sponsorblock for auto-skipping sponsored segments of videos
- auto-save-state for built-in watch-later functionality
- playlist-manager for playlist support
- undo-redo for undo/redoing seeks in MPV
- streamsave for live-saving clips from a video without reencoding.
- youtube-upnext for in-player video recommendations based on the current video. (Youtube’s sidebar, essentially.)
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