A Bash/Python script for watching your latest video feeds from your TinyTinyRSS instance using mpv.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
taha@asks2 5cc9bf78c9 Sort order now "newest first" instead of "default". Closes #2. 2 months ago
.gitignore Created branch for public sharing of this project. This branch 10 months ago
LICENSE Created branch for public sharing of this project. This branch 10 months ago
README.md Cleaned up formatting of list in README 10 months ago
requirements.txt Sort order now "newest first" instead of "default". Closes #2. 2 months ago
setup-project.sh Sort order now "newest first" instead of "default". Closes #2. 2 months ago
ttrss-video-mpv.Rproj Created branch for public sharing of this project. This branch 10 months ago
ttrss-video-mpv.code-workspace Created branch for public sharing of this project. This branch 10 months ago
ttrss-video-mpv.desktop.example Created branch for public sharing of this project. This branch 10 months ago
ttrss-video-mpv.py Sort order now "newest first" instead of "default". Closes #2. 2 months ago
ttrss-video-mpv.sh Sort order now "newest first" instead of "default". Closes #2. 2 months ago


➡️ See my blog post for some background


A small bash/Python script that fetches your latest unread video feeds from a specific feed category in your TinyTinyRSS account and plays them in mpv and also marks the feed articles as read in TTRSS, one by one as you watch them.

Installation and config

Clone this repo and enter its directory

git clone https://codeberg.org/taha/ttrss-video-mpv.git
cd ttrss-video-mpv

Create a Python venv and install the ttrss-python library and its dependencies using the shell script I've prepared for that


Now make sure you reset the variables in ttrss-video-mpv.sh to your own values.

And with that, feel free to run the bash script:


You will be prompted for your TTRSS account password (either via Password Store or as a bash prompt) and then you should see mpv text output in the terminal immediately followed by the first video opening in mpv.

To stop the bash script and all playback, kill the terminal (close it, or Ctrl-c in the terminal).

To mark a video as read and skip to the next video in the list, close the playing video window (for example by using the mpv shortcut q, or otherwise close the window).

Integration with GNOME/KDE/others desktop entries (optional, but advisable)

An example .desktop file has been included in this repo.
Make sure to replace the nonsense paths with the path to where you cloned this project.

Note that the TryExec line will hide the desktop entry from your menu if the file it points to does not exist or if the file it points to is not executable.

Integration with i3 window manager (optional)

We can make use of the fact that we set the --x11-name=<string> argument to mpv in our Python script, and add no_focus [instance="<string>"] to our i3 config file to ensure that the mpv window does not keep taking keyboard/mouse focus every time a new video starts.

By setting the x11-name (corresponds to the first part of WM_CLASS, which you can inspect using xprop) we make sure that any i3 rules we set only affect the mpv windows playing our TTRSS videos, and not any other mpv instances.

While we are at it, we could also set these mpv windows to open at a specific position and with a predefined size, so all together:

no_focus [instance="<string>"]
for_window [instance="ttrss-video-mpv"] floating enable, resize set 840 500, sticky enable, move position 1380 700

NOTE! (excerpt from the i3 manual):

When using multiple commands, separate them by using a , (a comma) instead of a semicolon. Criteria apply only until the next semicolon, so if you use a semicolon to separate commands, only the first one will be executed for the matched window(s).

Also, you will of course have to adjust the size and position coordinates to suit your monitor.

Notes during development

Some notes I recorded while putting this together. My machine: Ubuntu 18.04.5, Python 3.6.9, pip 20.2.3, i3 4.19, rofi 1.6.0.

I chose to use Python venv rather than pyenv or virtualenv, since it appears to be the new default.

I had to pip3 install wheel before installing the ttrss module, otherwise the latter failed with invalid command bdist_wheel.

Here's a list of the methods the ttrss-python.client command makes available (thanks to autocomplete in IPython):

>>> client.
client.assign_label(             client.get_pref(                 client.share_to_published(
client.catchup_feed(             client.get_unread_count(         client.sid
client.get_articles(             client.http_auth                 client.subscribe(
client.get_categories(           client.logged_in(                client.toggle_unread(
client.get_feed_count(           client.login(                    client.unsubscribe(
client.get_feed_tree(            client.logout(                   client.update_daemon_running(
client.get_feeds(                client.mark_read(                client.update_feed(
client.get_headlines(            client.mark_unread(              client.url
client.get_headlines_for_label(  client.password                  client.user
client.get_labels(               client.refresh_article(          

To create/update the requirements file:

pip freeze > requirements.txt

To exit the Python venv: deactivate.

This project would not have been possible without the fantastic ttrss-python library by Markus Wilk. Thank you, Markus!

I also found a Gist that integrates TRSS with Calibre, which seems to contain its own custom-made TTRSS Python code.

I did test to use umpv instead of mpv. Here's my notes:

  • pressing Enter did move down the playlist, but the playlist naturally contained only the previously played videos (so all videos in a session where still there in the playlist, which was nice),
  • volume was still reset in mpv with every new video (same as without umpv),
  • the big drawback was that starting another ./ttrss-video-mpv.sh instance while the first was still running (easy enough to do, by mistake or otherwise), caused the second instance to just add videos to the current umpv playlist without playing them, meaning our loop in the Python script would run through every video fetched from TTRSS and mark them as read. I considered this very dangerous behaviour in combination with this script, and thus opted to stay with vanilla mpv.