:BADGE: [[https://melpa.org/#/elfeed-tube][file:https://melpa.org/packages/elfeed-tube-badge.svg]] :END:
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:
([[https://i.imgur.com/nFK0n3m.png][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 [[https://www.youtube.com/watch?v=oHfAht9uTx8][this video]] by Protesilaos Stavrou.
Contents :TOC:
[[#features][Features]]
[[#transcripts-that-are][Transcripts that are...]]
[[#setup][Setup]]
[[#usage][Usage]]
[[#customization][Customization]]
[[#faq][FAQ]]
[[#limitations][Limitations]]
[[#planned-features][Planned features]]
[[#alternatives][Alternatives]]
[[#acknowledgments][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.
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:
[[https://i.imgur.com/TUn4xmb.jpeg][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:
** "Live" With MPV integration (optional), you can seek to any time in the video by clicking at the corresponding text in your buffer:
You can jump in Emacs to the current video position with =elfeed-tube-mpv-where= (~C-c C-w~):
Finally, you can also follow along with the video in Emacs:
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:
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!
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 [[https://github.com/oantolin/embark][Embark]] to collect the (non-Youtube, non-sponsor) links and open them in a browser:
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 [[https://github.com/melpa/melpa#usage][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:
Dependencies (automatically installed):
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)))
** TODO 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)
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:
https://user-images.githubusercontent.com/8607532/172195966-33089c16-57b1-4bbc-9bcc-71ac3d4338bc.mp4
(Finding the feeds is also asynchronous)
Examples (=RET= means pressing return):
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:
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~ |
** 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
** 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.
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][(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
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
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 [[https://github.com/ottokart/punctuator2][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 [[https://github.com/gRastello/ytel][ytel]] with [[https://github.com/xFA25E/ytel-show][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
Acknowledgments
Chris Wellons for writing [[https://github.com/skeeto/elfeed][Elfeed]], the best feed reader I've used.
Chris Wellons for also writing [[https://github.com/skeeto/emacs-aio][emacs-aio]], the async wrapper for Emacs. It writes callbacks for me so I never have to.
Ajay Ramachandran for writing and running [[https://github.com/ajayyy/SponsorBlock][Sponsorblock]]
The kind folks maintaining [[https://invidious.io/][Invidious]] instances, [[https://youtube-dl.org/][youtube-dl]] and [[https://github.com/yt-dlp/yt-dlp/][yt-dlp]]
COMMENT Notes
** TODO Fix persistence bug It disappears from the index first, then from the content store when =elfeed-db-gc= runs.
TODO Specify what data to fetch per feed instead of globally. TODO 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.)
TODO Support for Youtube's official API TODO Re-punctuating auto-generated captions Using a [[https://github.com/ottokart/punctuator2][punctuator2]] web service
TODO Backfill Youtube feeds TODO Download features [0/3] :PROPERTIES: :COOKIE_DATA: todo recursive :END: *** TODO Download button?
** DONE Chapter extraction CLOSED: [2022-06-18 Sat 23:07] From the descriptions.
** DONE =imenu= support [2/2] CLOSED: [2022-06-18 Sat 22:58] Headings:
** Local