Take (Game) Screenshots On Linux Every X Minutes In Python

Almost four years ago, I explained how I automated taking screenshots of video games on Windows. I integrated this code into a GUI two years later to simplify starting and stopping the capture. It was not a pretty application, but it did the job. Since I resurrected my Linux experiment a while ago, gaming on Linux and even the general day-to-day use of Linux have caught up to the point where it is a serious contender for daily driving. Therefore, I was looking for a way to automate taking a screenshot while I am gaming on Linux. My previous approach would not work since it relied on Windows’ infamous WinAPI, and Wine wasn’t something I wanted to dabble with for something so small.

My initial idea was to use a Wayland API to do something low-level. It seems like this is impossible by design in the name of security. I want to substantiate this with links to official statements or documentation. However, I could only find user messages in various forums and SO-like services saying precisely what I just did, but without providing a source.

The most viable solution I found was using DBus and calling into the XDG Desktop Portal to capture the screen. From my understanding, the desktop environment’s compositor implements this specification and serves the request, e.g., Gnome’s Mutter.

The solution I present here is based on this StackOverflow response. All of the credit goes to that user. I added a bit of context and explanation in this blog post. Note that this is not a DBus tutorial, although I implicitly tackle some core concepts when explaining the code. I would direct you to the Freedesktop tutorial on DBus for a high-level overview. I am not a DBus specialist, and some aspects still elude me.

The complete example code is in my GitHub repository. I only show the bare minimum here for the explanations.

Read More »

Write ID3 mp3 Tags, Cover Art with Python and eyed3

In March 2019, I wrote about using Python with the "pytaglib" library to read and modify audio files’ metadata. This solution worked nicely for what I needed at the time, but as I rewrote my WAV-to-MP3 conversion in Python, I found that it lacked support for adding cover art to the files. After a bit of research, I found eyed3. It also comes with a nice side-effect: it does not require installation of the Taglib C++ library.

Installation is simple.

pip install eyeD3

Additionally, on Windows, you need this, too:

pip install python-magic-bin

For more details, visit the installation guide. Like my old pytaglib post, I will keep this one short and only show code samples for the most relevant tasks.

Before you do anything, import the eyed3 library, of course.

import eyed3

Load a file.

song = eyed3.load(file)

If the file does not yet have any tags, you must create them before setting any metadata.

if not song.tag:
    song.initTag()

Note that this erases existing tags, so only call that if you start from scratch. Now you are ready to set the individual tags or read them if you need them.

song.tag.artist = "Behemoth"
song.tag.album = "The Satanist"
song.tag.genre = "Black Metal"
song.tag.recording_date = 2014
song.tag.track_num = 4
song.tag.title = "Ora pro nobis Lucifer"

The important piece for me, write cover art.

with open(cover_art_filename, "rb") as cover_art:
    song.tag.images.set(3, cover_art.read(), "image/jpeg")

The value 3 indicates that the front cover shall be set. See the documentation for other values. If you are an iTunes user, then select 0 for "Other". iTunes does not seem to like "Front Cover" 🙄.

You may run into a warning message like the following if you use genre names not defined in the ID3 specification.

eyed3.id3:WARNING: Non standard genre name

You do not need to worry about that. If it annoys you, add the following line to your code. eyed3 still writes the tag without any issue.

eyed3.log.setLevel("ERROR")

Using TagLib with pytaglib in Python

I tend to write a lot of background to paint a picture why I’m doing things, so I’ll try to keep it short for to move on to the code quickly.

I have a digital music collection that was sorted by the first letter of the artist (A, B, C etc.) and then the artist and underneath that the albums. While that is good to find things, it’s not optimal for listening in my car (via USB stick). Sometimes I find myself wanting to listen to all of Melodic Death Metal on shuffle play. My car doesn’t support this like iTunes, with its internal music library, which is why I wanted to group artists and albums by genre. Since I didn’t plan to do this all manually, I opted to write some scripts in Python.

The code is available on GitHub. If you have suggestions for improvements, please comment or create a pull request. I’m not a Python pro, so I’m sure there’s some room to make it better.

Read More »