# A Dirty Hack to Enable Acceptable Sway WM Screen Recording



# TL;DR
https://gist.github.com/Spirotot/9eb68d7e1ea4984c3afa3ef28e2c046d
# Background
I've been running the [Wayland](https://wayland.freedesktop.org/) display server on my XPS 9550 for a while now, using [sway](http://swaywm.org/), the drop-in replacement for the [i3 window manager](https://i3wm.org). One of the significant changes you'll notice moving to Wayland from [X](https://www.x.org/wiki/) is that "regular" screen capture tools[^1] don't work. This is due to Wayland's security architecture; applications are [no longer allowed access to the full frame buffer](https://en.wikipedia.org/wiki/Wayland_(display_server_protocol)#Comparison_with_other_window_systems). In other words, apps can't see what other apps are displaying unless they get special permission from the window manager. Because there is apparently no standardized screenshot/screen recording API to be used across different window managers, each window manager is effectively responsible for developing and including their own screenshot/screen-recording tool. Sway's screenshot & screen recording tool is called [swaygrab](https://github.com/SirCmpwn/sway/tree/master/swaygrab).

# Recording with **swaygrab**

## Screen Recording

It's really easy. I typically just use the following command to get a high-quality recording:

```bash
swaygrab -c -o [display] [output].mkv
```

The `-c` means "capture" a display continuously; without it, `swaygrab` will just take a screenshot.

If you're wondering what to use for `[display]`, you can list the displays that Sway sees by running `swaymsg -t get_outputs`.[^2]

I'll leave it up to you to decide what to call your `.mkv` file.

## Audio Recording
You might also be interested in capturing audio while you're doing this. `swaygrab` does not capture audio, so my recommendation would be to use `arecord` from the [`alsamixer`](http://alsa.opensrc.org/Alsamixer) audio driver package.

```bash
arecord -f cd -D [device] [output].wav
```

The `-f cd` argument is a present for 16-bit, 44100khz, stereo quality. `-D [device]` specifies the recording device -- you can list available devices by running `arecord -l`, which will spit out something like the following:

```
**** List of CAPTURE Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC3266 Analog [ALC3266 Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
```

To use that device, then your argument would be `-D hw:0,0`. The first `0` specifies the card, and the second `0` specifies the subdevice.

# The Dirty Hack

If you've recorded your screen _and_ audio, you'll notice that the resulting output files are of differing lengths -- this is what I was talking about in the **Background**. The `.wav` audio file you recorded will be the right length... but your `.mkv` video file will come up short, often around 50% of the length of the `.wav` file. This is no good. And even if they were the same length, it'd still be nice to have the audio and video embedded into one media file so you can easily share/upload the video.

First thing to do is calculate the length of the `.wav` and `.mkv` in seconds. Then, divide the longer length (should be the `.wav`'s length) by the shorter length (the `.mkv`'s length); you should end up with a floating-point number between ~1.5 and ~2.5, although this may vary greatly. We'll call this number the `[multiplier]`. We'll use the `[multiplier]` to "stretch" the length of the `.mkv` file to match that of the `.wav` file:

```bash
ffmpeg -i [input_mkv] -filter:v "setpts=[multiplier]*PTS" -preset ultrafast [output].mkv
```

`[input_mkv]` is actually the original, too-short `.mkv` you already created. `[output].mkv` is the new, proper-length `.mkv` the preceding command will create.

Now, we just need to squash our new `.mkv` and our original `.wav` into one media file, which can be done with the following command:

```bash
ffmpeg -i [input_mkv] -i [input_wav] -c:v copy -c:a aac [output].mkv
```

In this case, `[input_mkv]` is the newer, proper-length `.mkv`, and `[input_wav]` is the audio you recorded. The `-c:v copy` tells `ffmpeg` to just keep the current video format/bitrate/etc., and the `-c:a aac` tells `ffmpeg` to convert the `.wav` audio to the compressed AAC format for the final `[output].mkv` file.

# Conclusion & Automation!

So was that confusing and poorly explained, or what? Probably... Fortunately, I love writing crappy Bash scripts, and so I've turned all of the information here into a script you can download and run yourself. It has the added bonus of automatically starting & stopping the screen and audio recording simultaneously!

<script src="https://gist.github.com/Spirotot/9eb68d7e1ea4984c3afa3ef28e2c046d.js"></script>

[^1]: If you _are_ still using X, [shutter](http://shutter-project.org/) is by far my personal favorite screenshot tool, and [recordMyDesktop](http://recordmydesktop.sourceforge.net/about.php) is definitely my favorite screen recording tool.
[^2]: Lots of other good Sway info here, especially if you have a HiDPI (i.e. 4k) display: https://github.com/SirCmpwn/sway/wiki


