My thoughts on Slackware, life and everything

Tag: video (Page 1 of 2)

Slackware Cloud Server Series, Episode 3: Video Conferencing

Hi all!
This is already the third episode in a series of articles I am writing about using Slackware as your private/personal ‘cloud server’. Time flies when you’re having fun.
We’re still waiting for Slackware 15.0 and in the meantime, I thought I’d speed up the release of my article on Video Conferencing. My initial plan was to release one article per week after Slackware 15 had been made available. The latter still did not happen (unstuck in time again?) but then I realized, an article about Docker and another about Keykloak still won’t give you something tangible and productive to run and use. So here is Episode 3, a couple of days earlier than planned, to spend your lazy sunday on: create your own video conferencing platform.
Episodes 4 and 5 won’t be far off, since I have already written those as well.

Check out the list below which shows past, present and future episodes in the series, if the article has already been written you’ll be able to click on the subject.
The first episode also contains an introduction with some more detail about what you can expect.

  • Episode 1: Managing your Docker Infrastructure
  • Episode 2: Identity and Access management (IAM)
  • Episode 3 (this article): Video Conferencing
    Setting up Jitsi Meet – the Open Source video conferencing platform. This makes us independent of cloud conferencing services like MS Teams, Zoom or Google Meet. The Jitsi login is offloaded to our Keycloak IAM provider.

    • Jitsi Meet on Docker
    • Preamble
    • Initial Configuration
    • Adding Etherpad integration
    • Creating application directories
    • Starting Jitsi Meet
    • Considerations about the “.env” file
    • Upgrading Docker-Jitsi-Meet
    • Apache reverse proxy setup
    • Fixing Etherpad integration
    • Network troubleshooting
    • Creating internal Jitsi accounts
    • Connecting Jitsi and Keycloak
      • Adding jitsi-keycloak
      • Configuration of jitsi-keycloak in the Keycloak Admin console
      • Remaining configuration done in jitsi-keycloak
    • Configure docker-jitsi-meet for use of jitsi-keycloak
    • Firing up the bbq
    • Thanks
    • Attribution
  • Episode 4: Productivity Platform
  • Episode 5: Collaborative document editing
  • Episode 6: Etherpad with Whiteboard
  • Episode 7: Decentralized Social Media
  • Episode X: Docker Registry

Secure Video Conferencing

Actually, my original interest in Docker was raised in the beginning of 2020 when the Corona pandemic was new, everybody was afraid and people were sent home to continue work and school activities from there.
One of the major challenges for people was to stay connected. Zoom went from a fairly obscure program to a hugely popular video conferencing platform in no time at all (until severe security flaws made a fair-sized dent in its reputation); Microsoft positioned its Teams platform as the successor of Skype but targets mostly corporate users; Google Hangouts became Google Meet and is nowadays the video conferencing platform of choice for all corporations that have not yet been caught in the Microsoft vendor lock-in.
None of these conferencing platforms are open source and all of them are fully cloud-hosted and are inseparable from privacy concerns. In addition, un-paid use of these platforms imposes some levels of limitation to the size and quality of your meetings. As a user, you do not have control at all.

Enter Jitsi, whose Jitsi Meet platform is available for everybody to use online for free and without restrictions. Not just free, but Open Source, end-to-end encrypted communication and you can host the complete infrastructure on hardware that you own and control.
People do not even have to create an account in order to participate – the organizer can share a URL with everyone who (s)he wants to join a session.

Jitsi is not as widely known as Zoom, and that is a pity. Therefore this Episode in my Slackware Cloud Server series will focus on getting Jitsi Meet up and running on your server, and we will let login be handled by the Keycloak Identity and Access Management (IAM) tool which we have learnt to setup in the previous Episode.

In early 2020, when it became clear that our Slackware coreteam member Alphageek (Erik Jan Tromp) would not stay with us for long due to a terminal illness, I went looking for a private video conferencing platform for our Slackware team and found Jitsi Meet.
I had no success in getting it to work on my Slackware server unfortunately. Jitsi Meet is a complex product made of several independent pieces of software which need to be configured ‘just right‘ to make them work together properly. I failed. I was not able to make it work in time to let alphageek use it.
But I also noticed that Jitsi Meet was offered as a Docker-based solution. That was the start of a learning process full of blood sweat & tears which culminated in this article series.

With this article I hope to give you a jump-start in getting your personal video conferencing platform up and running. I will focus on the basic required functionality but I will leave some of the more advanced scenarios for you to investigate: session recording; automatic subtitling of spoken word; integrating VOIP telephony; to name a few.

Jitsi Meet on Docker

Docker-Jitsi-Meet is a Jitsi Github project which uses Docker Compose to create a fully integrated Jitsi application stack which works out of the box. All internal container-to-container configurations are pre-configured.

As you can see from the picture below, the only network ports that need to be accessible from the outside are the HTTPS port (TCP port 443) of your webserver, UDP port 10000 for the WebRTC (video) connections and optionally (not discussed in my article) UDP port range 20000 – 20050 for allowing VOIP telephones to take part in Jitsi meetings.

These ports need to be opened in your server firewall.

Installing docker-jitsi-meet is relatively straight-forward if you go the quick-start page and follow the instructions to the letter. Integrating Jitsi with Keycloak involves using a connector which is not part of either programs; I will show you how to connect them all.

You will be running all of this in Docker containers eventually, but there’s stuff to download, edit and create first. I did not say it was trivial…

Preamble

For the sake of this instruction, I will use the hostname “https://meet.darkstar.lan” as the URL where users will connect to their conferences; The server’s public IP address will be “10.10.10.10“.
Furthermore, “https://sso.meet.darkstar.lan” will be the URL for the connector between Jitsi and Keycloak and “https://sso.darkstar.lan/auth” is the Keycloak base URL (see Episode 2 for how we did the Keycloak setup).

Setting up your domain (which will hopefully be something else than “darkstar.lan”…) with new hostnames and then setting up web servers for the hostnames in that domain is an exercise left to the reader. Before continuing, please ensure that your equivalents for the following two hosts have a web server running. They don’t have to serve any content yet but we will add some blocks of configuration to their VirtualHost definitions during the steps outlined in the remainder of this article:

  • meet.darkstar.lan
  • sso.meet.darkstar.lan

I expect that your Keycloak application is already running at your own real-life equivalent of https://sso.darkstar.lan/auth .

Using a  Let’s Encrypt SSL certificate to provide encrypted connections (HTTPS) to your webserver is documented in an earlier blog article.

Note that I am talking about webserver “hosts” but in fact, all of these are just virtual webservers running on the same machine, at the same IP address, served by the same Apache httpd program, but with different DNS entries. There is no need at all for multiple computers when setting up your Slackware Cloud server.

Initial Configuration

Download and extract the tarball of the latest stable release: https://github.com/jitsi/docker-jitsi-meet/releases/latest into the “/usr/local/” directory. Basically any directory will do but I am already backing up /usr/local so the Jitsi stuff will automatically be taken into backup with all the rest.
At the moment of writing, the latest stable version number is ‘6826‘. Which means, after extracting the tarball we do:

cd /usr/local/docker-jitsi-meet-stable-6826/

A Jitsi Meet container stack for Docker Compose is defined in the file “docker-compose.yml” which you find in this directory.
In addition to this YAML file, the ‘docker-compose‘ program parses a file named “.env” if it exists in the same directory. Its content is used to initialize the container environment. You can for instance store passwords and other secrets in “.env” but also all the configuration variables that define how your stack will function.
Docker-Jitsi-Meet ships an example environment file containing every configurable option, but mostly commented-out.

Configuration:

We start with creating a configuration file “.env” from the example file “env.example“:

$ cp -i env.example .env

And then edit the “.env” file to define our desired configuration.

First of all,

  • Change “CONFIG=~/.jitsi-meet-cfg” to “CONFIG=/usr/share/docker/data/jitsi-meet-cfg” because I do not want application data in my user’s or root’s homedirectory.

Then the ones that are easy to understand:

  • Change “HTTP_PORT=8000” to "HTTP_PORT=8440” because port 8000 is used by far too many applications. Port 8440 is what we will use again in the reverse proxy configuration.
  • Change “TZ=UTC” to “TZ=Europe/Amsterdam” or whatever timezone your server is in.
  • Change “#PUBLIC_URL=https://meet.example.com” to “PUBLIC_URL=https://meet.darkstar.lan/” i.e. change it to the URL where you want people to connect. The connections will be handled by your Apache httpd server who will manage the traffic back and forth between Jitsi container and the client.
  • Change “#DOCKER_HOST_ADDRESS=192.168.1.1” to “DOCKER_HOST_ADDRESS=10.10.10.10” where of course “10.10.10.10” needs to be replaced by your server’s actual public Internet IP address.

Other settings that I would explicitly enable but their commented-out values are the default values anyway (matter of taste, it avoids getting bitten by a future change in application default settings):

  • ENABLE_LOBBY=1“; “ENABLE_PREJOIN_PAGE=1“; “ENABLE_WELCOME_PAGE=1“; “ENABLE_BREAKOUT_ROOMS=1“; “ENABLE_NOISY_MIC_DETECTION=1“.

IPv6 Network consideration:

  • Change “#ENABLE_IPV6=1” to “ENABLE_IPV6=0” if your Docker installation has ipv6 disabled. This is a requirement if your host server would have ipv6 disabled.
    You can find out whether ipv6 is disabled in Docker, because in that case the file “/etc/docker/daemon.json” will contain this statement:

    { "ipv6": false }

Connection encryption:

  • Change “#DISABLE_HTTPS=1” to “DISABLE_HTTPS=1“. We disable HTTPS in the container because we will again use Apache http reverse proxy to handle encryption.
  • Change “#ENABLE_LETSENCRYPT=1” to “ENABLE_LETSENCRYPT=0” because we do not want the container to handle automatic certificate renewals – it’s just too much of a hassle on a server where you already run a webserver on ports 80 and 443. Our Apache reverse proxy is equipped with a Let’s Encrypt SSL certificate and I want to handle SSL certificate renewals centrally – on the host.

Authentication:

The authentication will be offloaded to Keycloak using JSON Web Tokens aka ‘JWT‘ for the inter-process communication. The following variables in “.env” need to be changed:

  • #ENABLE_AUTH=1” should become “ENABLE_AUTH=1
  • #ENABLE_GUESTS=1” should become “ENABLE_GUESTS=1
  • #AUTH_TYPE=internal” should become “AUTH_TYPE=jwt
  • TOKEN_AUTH_URL=https://auth.meet.example.com/{room}” should become “TOKEN_AUTH_URL=https://sso.meet.darkstar.lan/{room}
  • #JWT_APP_ID=my_jitsi_app_id” should become “JWT_APP_ID=jitsi
  • #JWT_APP_SECRET=my_jitsi_app_secret” should become “JWT_APP_SECRET=NmjPGpn+NjTe7oQUV9YqfaXiBULcsxYj

Actually, to avoid confusion: my proposed value of “JWT_APP_SECRET" (the string “NmjPGpn+NjTe7oQUV9YqfaXiBULcsxYj”) is a value which you will be generating yourself a few sections further down. It is a string which is used by two applications to establish mutual trust in their intercommunication.

We will re-visit the meaning and values of JWT_APP_ID and JWT_APP_SECRET in a moment.

When our modifications to the “.env” file are complete, we run a script which will fill the values for all PASSWORD variables with random strings (this can be done at any time really):

$ ./gen-passwords.sh

Adding Etherpad integration

Etherpad is an online editor for real-time collaboration. The Docker version of Jitsi Meet is able to integrate Etherpad into your video conferences. I am going to show you how to run Etherpad on your Slackware Cloud server and integrate collaborative editing into your video meetings.

The git checkout of ‘docker-jitsi-meet‘ into /usr/local/docker-jitsi-meet-stable-6826/will have given you not only a docker-compose.yml file which starts Jitsi and its related containers, but also a file etherpad.yml. This is a Docker Compose file which starts an Etherpad container and connects it to the Jitsi Meet container stack.
FYI: you can use Docker Compose to process multiple YAML files in one command-line instead of implicitly processing only the ‘docker-compose.yml’ file (which happens if you do not explicitly mention the YAML filename in a “-f” parameter).
For instance if you wanted to start Jitsi and Etherpad together, you would use a command like this, using two “-f” parameters to specify the two YAML files:

# docker-compose -f docker-compose.yml -f etherpad.yml up -d

But I found out the hard way that this is risky.
Because sometime in the future you may want to bring that container stack down, for instance to upgrade Jitsi Meet to the latest version. If you forget that you had actually started two stacks (I consider the ‘etherpad.yml’ as the source for a second stack ) and you simply run “docker-compose down” in the directory… then only the Jitsi Meet stack will be brought down and Etherpad will happily keep running.
To protect myself from my future self, I have copied the content of ‘etherpad.yml‘ and added it to the bottom of ‘docker-compose.yml‘, so that I can simply run:

# docker-compose up -d

I leave it up to you to pick either scenario. Whatever works best for you.

Now on to the stuff that needs fixing because the standard configuration will not result in a working Etherpad integration.
First of all, add a “ports” configuration to expose the Etherpad port outside of the container. This is how that looks in the YAML file:

# Etherpad: real-time collaborative document editing
etherpad:
    image: etherpad/etherpad:1.8.6
    restart: ${RESTART_POLICY}
    ports:
        - '127.0.0.1:9001:9001'
    environment:
        - TITLE=${ETHERPAD_TITLE}
        - DEFAULT_PAD_TEXT=${ETHERPAD_DEFAULT_PAD_TEXT}
        - SKIN_NAME=${ETHERPAD_SKIN_NAME}
        - SKIN_VARIANTS=${ETHERPAD_SKIN_VARIANTS}
networks:
    meet.jitsi:
        aliases:
            - etherpad.meet.jitsi

You will also have to edit the “.env” file a bit more. Look for the ETHERPAD related variables and set them like so:

# Set etherpad-lite URL in docker local network (uncomment to enable)
ETHERPAD_URL_BASE=http://etherpad.meet.jitsi:9001
# Set etherpad-lite public URL, including /p/ pad path fragment (uncomment to enable)
ETHERPAD_PUBLIC_URL=https://meet.darkstar.lan/pad/p/
# Name your etherpad instance!
ETHERPAD_TITLE=Slackware EtherPad Chat
# The default text of a pad
ETHERPAD_DEFAULT_PAD_TEXT="Welcome to Slackware Web Chat!\n\n"

The most important setting is highlighted in green: “https://meet.darkstar.lan/pad/p/” . This is the external URL where we will expose our Etherpad. Since the Docker container exposes Etherpad only at the localhost address “127.0.0.1:9001” we need to setup yet another Apache reverse proxy. See the section “Apache reverse proxy setup” below.
There is one potential snag and you have to consider the implications: in the above proposed setup we expose Etherpad in the “/pad/” subdirectory of our Jitsi Meet server. But the Jitsi conference rooms also are exposed as a subdirectory, but then without the trailing slash. Which means everything will work just fine as long as nobody decides to call her conference room “pad” – that can lead to unexpected side effects. You could remedy that by choosing a more complex string than “/pad/” for Etherpad, or else setup a separate web host (for instance “etherpad.darkstar.lan“) just for Etherpad.

In any case, with all the preliminaries taken care of, you can continue with the next sections of the article.
Note: After starting the containers, you will have to do one last edit in the configuration of Jitsi Meet to actually make Etherpad available in your videomeetings. See the section “Fixing Etherpad integration” below.

I am still investigating the integration of Keycloak authentication with Etherpad. Once I am sure I have a working setup, I will do a write-up on the subject in a future article in this series. In the meantime, you need to realize that your Etherpad is publicly accessible.

Creating application directories

The various Docker containers that make up Docker-Jitsi-Meet need to write data which should persist across reboots. The “CONFIG” variable in “.env” points to the root of that directory structure and we need to create the empty directory tree manually before firing up the containers.
Using one smart command which will be expanded by Bash to a lot of ‘mkdir‘ commands:

# mkdir -p /usr/share/docker/data/jitsi-meet-cfg/{web/letsencrypt,transcripts,prosody/config,proso
dy/prosody-plugins-custom,jicofo,jvb,jigasi,jibri}

Starting Jitsi Meet

# cd /usr/local/docker-jitsi-meet-stable-*
# docker-compose up -d

With an output that will look somewhat like:

Creating network "docker-jitsi-meet-stable-4548-1_meet.jitsi" with the default driver
Creating docker-jitsi-meet-stable-4548-1_prosody_1 ... done
Creating docker-jitsi-meet-stable-4548-1_web_1 ... done
Creating docker-jitsi-meet-stable-4548-1_jicofo_1 ...
Creating docker-jitsi-meet-stable-4548-1_jvb_1 ...
...
Pulling web (jitsi/web:stable-4548-1)...
stable-4548-1: Pulling from jitsi/web
b248fa9f6d2a: Pull complete
173b15edefe3: Pull complete
3242417dae3a: Pull complete
331e7c5436be: Pull complete
6418fea5411e: Pull complete
0123aaecd2d8: Pull complete
bd0655288f32: Pull complete
f2905e1ad808: Pull complete
8bcc7f5a0af7: Pull complete
20878400e460: Extracting [====================================> ]
84.67MB/114.9MBB
..... etcetera

And that’s it. Our Jitsi Meet video conferencing platform is up and running.
But it is not yet accessible: we still need to connect the container stack to the outside world. This is achieved by adding an Apache httpd reverse proxy between our Docker stack and the users. See below!

 

Considerations about the “.env” file

Note that the “.env” file is only used the very first time ‘docker-compose‘ starts up your docker-jitsi-meet container stack, in order to  populate /usr/share/docker/data/jitsi-meet-cfg/ and its subdirectories.

After that initial start of the docker-jitsi-meet container stack you can tweak your setup by editing files in the /usr/share/docker/data/jitsi-meet-cfg/ directory tree, since these directories are mounted inside the various containers that make up Docker-Jitsi-Meet.
But if you ever edit that “.env” file again… you need to remove and re-create the directories below /usr/share/docker/data/jitsi-meet-cfg/ and restart the container stack.

NOTE: ‘docker-compose stop‘ stops all containers in the stack which was originally created by the ‘docker-compose up -d‘ command. Using ‘down‘ instead of ‘stop‘ will additionally remove containers and networks as defined in the Compose file(s). After using ‘down‘ you would have to use ‘up -d‘ instead of ‘start‘ to bring the stack back online.

This is how you deal with “.env” configuration changes:

# cd /usr/local/docker-jitsi-meet-stable-*
# docker-compose stop
# vi .env
# ... make your changes
# rm -rf /usr/share/docker/data/jitsi-meet-cfg/
# mkdir -p /usr/share/docker/data/jitsi-meet-cfg/{web/letsencrypt,transcripts,prosody/config,prosody/prosody-plugins-custom,jicofo,jvb,jigasi,jibri}
# docker-compose start

Upgrading Docker-Jitsi-Meet

You don’t need to follow the above process if you want to upgrade Docker-Jitsi-Meet to the latest stable release as part of life cycle management, but with an un-changed.env” file. In such a case, you simply execute:

# cd /usr/local/docker-jitsi-meet-stable-*
# docker-compose down
# docker-compose pull
# docker-compose up -d

Apache reverse proxy setup

We need to connect the users of our Jitsi and Etherpad services to the containers. Since these containers are exposed by Docker only at the loopback address (127.0.0.1 aka localhost) we use the Apache httpd’s ‘reverse proxy‘ feature.

These three blocks of text need to be added to the VirtualHost definition for your “meet.darkstar.lan” webserver so that it can act as a reverse proxy and connects your users to the Docker Jitsi Meet and Etherpad containers:

Generic block:

SSLProxyEngine on
RequestHeader set X-Forwarded-Proto "https"
ProxyTimeout 900
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
Options FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all

Specific to Jitsi Meet:

<Location />
    ProxyPass http://127.0.0.1:8440/
    ProxyPassReverse http://127.0.0.1:8440/
</Location>
# Do not forget WebSocket proxy:
RewriteEngine on
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule ^/?(.*) "ws://127.0.0.1:8440/$1" [P,L]

And specific to Etherpad:

<Location /pad/>
    ProxyPass http://127.0.0.1:9001/ retry=0 timeout=30
    ProxyPassReverse http://127.0.0.1:9001/
    AddOutputFilterByType SUBSTITUTE text/html
    Substitute "s|meet.darkstar.lan/|meet.darkstar.lan/pad/|i" 
</Location>
<Location pad/socket.io>
    # This is needed to handle websocket transport through the proxy, since
    # etherpad does not use a specific sub-folder, such as /ws/
    # to handle this kind of traffic.
    RewriteEngine On
    RewriteCond %{QUERY_STRING} transport=websocket [NC]
    RewriteRule /(.*) ws://127.0.0.1:9001/socket.io/$1 [P,L]
    ProxyPass http://127.0.0.1:9001/socket.io retry=0 timeout=30
    ProxyPassReverse http://127.0.0.1:9001/socket.io
    AddOutputFilterByType SUBSTITUTE text/html
    Substitute "s|meet.darkstar.lan/|meet.darkstar.lan/pad/|i" 
</Location>

In “127.0.0.1:8440” you will recognize the TCP port 8440 which we configured for the Jitsi container in the “.env" file earlier. The “127.0.0.1:9001” corresponds to the port 9001 which we exposed explicitly in the ‘docker-compose.yml‘ file for the Etherpad service.

After adding this reverse proxy configuration and restarting Apache httpd. your video conference server will be publicly accessible at https://meet.darkstar.nl/ .

Fixing Etherpad integration

I told you earlier that you needed to make a final edit after the Jitsi Meet stack is up & running to fix the Etherpad integration.
Open the stack’s global config file “/opt/jitsi-meet-cfg/web/config.js” in your editor and look for this section of text:

// If set, add a "Open shared document" link to the bottom right menu that
// will open an etherpad document.
// etherpad_base: 'https://meet.darkstar.lan/pad/p/',

You need to un-comment the last line so that this section looks like:

// If set, add a "Open shared document" link to the bottom right menu that
// will open an etherpad document.
etherpad_base: 'https://meet.darkstar.lan/pad/p/',

It’s a long-standing bug apparently.
Now, when you join a Jitsi Meeting, the menu which opens when you click the three-dots “more actions” menu in the bar at the bottom of your screen, will contain an item “Open shared document“:

If you select this, your video will be replaced by an Etherpad “pad” with the name of your Jitsi meeting room.

Externally i.e. outside of the Jitsi videomeeting, your Etherpad ‘pad‘ will be available as “https://meet.darkstar.lan/pad/p/jitsiroom” where “jitsiroom” is the name you gave your Jitsi videomeeting aka ‘room‘. This means that people outside of your videomeeting can still collaborate with you in real-time.

Network troubleshooting

Docker’s own dynamic management of iptables chains and rulesets will be thwarted if you decide to restart your host firewall. The custom Docker chains disappear and the docker daemon gets confused. If you get these errors in logfiles when starting the Docker-Jitsi-Meet containers, simply restart the docker daemon itself (/etc/rc.d/rc.docker restart):

> driver failed programming external connectivity on endpoint docker-jitsi-meet
> iptables failed
> iptables: No chain/target/match by that name

Creating internal Jitsi accounts

Just for reference, in case you want to play with Jitsi before integrating it with Keycloak.
Internal Jitsi users must be created with the “prosodyctl” utility in the prosody container.

In order to run that command, you need to first start a shell in the corresponding container – and you need to do this from within the extracted tarball directory “/usr/local/docker-jitsi-meet-stable-*“:

# cd /usr/local/docker-jitsi-meet-stable-*
# docker-compose exec prosody /bin/bash

Once you are at the prompt of that shell in the container, run the following command to create a user:

> prosodyctl --config /config/prosody.cfg.lua register TheDesiredUsername meet.jitsi TheDesiredPassword

Note that the command produces no output. Example for a new user ‘alien‘:

> prosodyctl --config /config/prosody.cfg.lua register alien meet.jitsi WelcomeBOB!

Now user “alien” will be able to login to Jitsi Meet and start a video conference.

Connecting Jitsi and Keycloak

The goal is of course to move to a Single Sign On solution instead of using local accounts. Jitsi supports JWT Tokens which it should get from a OAuth/OpenID provider. We have Keycloak lined up for that, since it supports OAuth, OpenID, SAML and more.

Adding jitsi-keycloak

Using Keycloak as OAuth provider for Jitsi Meet is not directly possible, since unfortunately Keycloak’s JWT token is not 100% compatible with Jitsi. So a ‘middleware‘ is needed, and jitsi-keycloak fills that gap.

We will download the middleware from their git repository and setup a local directory below “/usr/share/docker/data” where we have been storing configurations for all our applications so far. All we are going to use from that repository checkout is the Docker Compose file you can find in there. The actual ‘jitsi-keycloak‘ middleware will eventually be running as yet another Docker container.

# cd /usr/local/
# git clone https://github.com/d3473r/jitsi-keycloak jitsi-keycloak
# mkdir -p /usr/share/docker/data/jitsi-keycloak/config
# cp ./jitsi-keycloak/example/docker-compose.yml /usr/share/docker/data/jitsi-keycloak/

Edit our working copy ‘/usr/share/docker/data/jitsi-keycloak/docker-compose.yml‘ to provide the correct environment variables for our instances of our already running Jitsi and Keycloak containers:

# --- start ---
version: '3'

services:
    jitsi-keycloak:
    image: d3473r/jitsi-keycloak
    container_name: jisi-keycloak
    hostname: jisi-keycloak
    restart: always
environment:
    JITSI_SECRET: NmjPGpn+NjTe7oQUV9YqfaXiBULcsxYj
    DEFAULT_ROOM: welcome
    JITSI_URL: https://meet.darkstar.lan/
    JITSI_SUB: meet.darkstar.lan
volumes:
    - /usr/share/docker/data/jitsi-keycloak/config:/config
ports:
    - "3000:3000"
networks:
    keycloak0.lan:
    ipv4_address: 172.20.0.6
aliases:
    - jitsi-keycloak.keycloak0.lan

networks:
    keycloak0.lan
    external: true
# --- end ---

The string value for the JITSI_SECRET variable needs to be the same string we used in the definition of the Jitsi container earlier, where the variable is called JWT_APP_SECRET.

Hint: in Bash you can create a random 32 character string like this:

$ cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1
BySOoKBDIC1NWfeYpktvexJIqOAcAMEt

If you have nodejs installed, generate a random ‘secret’ string using this ‘node’ command:

$ node -e "console.log(require('crypto').randomBytes(24).toString('base64'));"
NmjPGpn+NjTe7oQUV9YqfaXiBULcsxYj

Configuration of jitsi-keycloak in the Keycloak Admin console

Point your browser to the Keycloak Admin console https://sso.darkstar.lan/auth/admin/ to start the configuration process.

Add a public openid-connect client in the ‘foundation‘ Keycloak realm (the realm where you created your users in the previous Episode of this article series):

  • Select ‘foundation‘ realm; click on ‘Clients‘ and then click ‘Create‘ button.
    • Client ID‘ = “jitsi
    • Client Protocol‘ = “openid-connect” (the default)
    • Save.
  • Also in ‘Settings‘, allow this app from Keycloak.
    Our Jitsi-keycloak container is running on https://sso.meet.darkstar.lan . Therefore we add

    • Valid Redirect URIs‘ = https://sso.meet.darkstar.lan/*
    • Web Origins‘ = https://sso.meet.darkstar.lan
    • Save.
  • Go to ‘Installation‘ tab to download the ‘keycloak.json‘ file for this new client:
    • Format Option‘ = “Keycloak OIDC JSON”
    • Click ‘Download‘ which downloads a file “keycloak.json” with the following content:
# ---
{
    "realm": "foundation",
    "auth-server-url": "https://sso.darkstar.lan/auth",
    "ssl-required": "external",
    "resource": "jitsi",
    "public-client": true,
    "confidential-port": 0
}
# ---

Remaining configuration done in jitsi-keycloak

Back at your server’s shell prompt again, do as follows:

Copy the downloaded “keycloak.json” file into the ‘/config‘ directory of jitsi-keycloak (the container’s /config is exposed in the host filesystem as /usr/share/docker/data/jitsi-keycloak/config).

# cp ~/Download/keycloak.json /usr/share/docker/data/jitsi-keycloak/config/

Start the jitsi-keycloak container in the directory where we have our tailored ‘docker-compose.yml‘ file:

# cd /usr/share/docker/data/jitsi-keycloak
# docker-compose up -d

Once the container is running, we make jitsi-keycloak available at https://sso.meet.darkstar.lan/ using a reverse-proxy setup (jitsi-keycloak will not work in a sub-folder).
Add these reverse proxy lines to your VirtualHost definition of the “sso.meet.darkstar.lan” web site configuration and restart httpd:

# ---
# Reverse proxy to jitsi-keycloak Docker container:
SSLProxyEngine On
SSLProxyCheckPeerCN on
SSLProxyCheckPeerExpire on
RequestHeader set X-Forwarded-Proto: "https"
RequestHeader set X-Forwarded-Port: "443"

<Location />
    AllowOverride None
    Require all granted
    Order allow,deny
    Allow from all
</Location>

ProxyPreserveHost On
ProxyRequests Off
ProxyVia on
ProxyAddHeaders On
AllowEncodedSlashes NoDecode

# Jitsi-keycloak:
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
# ---

Configure docker-jitsi-meet for use of jitsi-keycloak

Actually, you have already done all the correct changes which are needed in the ‘.env‘ file for Docker Compose!
The  docker-jitsi-meet configurations that are relevant for jitsi-keycloak are as follows:

ENABLE_AUTH=1
AUTH_TYPE=jwt
JWT_APP_ID=jitsi
JWT_APP_SECRET=NmjPGpn+NjTe7oQUV9YqfaXiBULcsxYj
# To enable an automatic redirect from Jitsi to the Keycloak login page:
TOKEN_AUTH_URL=https://sso.meet.darkstar.lan/{room}

The values for ‘JWT_APP_SECRET‘ and ‘JITSI_SECRET‘ must be identical, and the value of ‘JWT_APP_ID‘ must be equal to “jitsi“.

Firing up the bbq

With all the prep work completed and the containers are running, we can enjoy the new online video conferencing platform we now operate for friends and family.

So, how does this actually look in practice? I’ll share a couple of screenshots from a Jitsi Meet session that I setup. Look at how cool it looks (and not just because of the screenshot of my den and the Slackware hoodie I am wearing…)

The Jitsi Meet welcome screen:

Device settings:

Joining a meeting:

Logging in via Keycloak SSO, you’ll notice that I have configured 2-Factor Authentication for my account:

After having logged in, I am back at the “join meeting screen” but now with my name written as Keycloak knows it (“Eric Hameleers” instead of “Alien BOB“) and I need to click one more time on the “Join” button.
Then I am participating in the meeting as the moderator.
You’ve probably noticed that I flipped my camera view here. I also added one ‘break-out room‘ to allow for separate discussions to take place outside of the main room:

 

 

And if you are not the moderator but a guest who received the link to this meeting, this is what you’ll see at first:

 

Cool, eh?

Thanks

… again for taking the time to read through another lengthy article. Share your feedback in the comments section below, if you actually implemented Jitsi Meet on your own server.


Attribution

The Docker-Jitsi-Meet architecture image was taken from Jitsi’s github site.

I finally updated my avidemux package

I have an avidemux package in my (restricted) repository.
But… it had not been refreshed since Slackware 14.0 (8 years old now) and its binaries stopped working on Slackware long ago. Looking back at the packaging work I did today, I guess the thing that kept me from updating that Avidemux package was the numerous dependencies that also needed an update (they all were stuck at an old Slackware 14.0 release).

In the midst of a full week of holidays and waiting for my rye/honey sourdough bread dough to ferment, I had plenty time to devote to the creation of a fresh package for  Avidemux 2.8.0. This was recently released; yesterday actually!
And not just avidemux needed some work on its SlackBuild script; I needed to update ageing scripts for aften, faac, faad2, libdca, libfdk-aac, opencore-amr, x264 and xvidcore, and added a x265 package before I could compile avidemux with full support for codecs and plugins.

Based on the imminent (fingers crossed) release of Slackware 15.0 according to Patrick himself, I decided to create these packages only for Slackware-current (soon to become 15.0). I also cleaned out ancient versions of all these packages. They are now removed for Slackware 14.1 and older.
Note that faac and libfdk-aac just like avidemux contain patent-encumbered software (the AAC encoder) and due to that circumstance  the three packages are banished to my ‘restricted repository‘ which is hosted outside the US of A so that the patent trolls won’t bother Pat.

Let me cue you in about Avidemux in case you are not familiar with the program.
It’s a video editor supporting many video formats thanks to the built-in ffmpeg libraries and many plugins. It allows for a decent level of automation through tasks and scripts, and it has a command-line interface next to its Qt5-based graphical user interface.

Some of the 2.8.0 release highlights: Avidemux is now able to convert HDR video to SDR with tone mapping using a variety of methods. The FFV1 encoder has been added again. TrueHD audio tracks can be decoded and are supported for Matroska containers. The internal ffmpeg libraries are the latest 4.4.1 version. It integrates better with pulseaudio in terms of volume adjustments.

In case you are interested in some comparisons between the functionality of Avidemux and its competitors, here are some pointers. In terms of video conversion capability it compares to Handbrake (also in my repository), see here: https://en.wikipedia.org/wiki/Comparison_of_video_converters. When you look at its video cutting and edting qualities on the other hand, Avidemux is better compared with Kdenlive which is included in Slackware as part of KDE Plasma5: https://en.wikipedia.org/wiki/Comparison_of_video_editing_software

FYI… my sourdough bread is out of the oven, and it’s smelling great!

Handbrake reaches 1.0.0 milestone after 13 years of development

handbrake_logoChristmas creates a different focus for the average IT guy, spending time with family instead of computers. It was nice. But it’s over and done now, even though the Christmas tree in the corner of our living room is still on fire (metaphorically speaking).

Tonight I have time to write about the latest Handbrake release. It took the developer team “only” 13 years to reach the stable milestone, 1.0.0. Congratulations are appropriate, because it is great software. But still there’s that nagging thought at the back of my mind… why the fuck is its GUI depending on a recent GTK+3 and therefore almost enforcing the use  of a Gnome-based distro? GTK has always been a moving target, theoretically separate from Gnome but in all honesty, the two are bonded with superglue. I can not compile Handbrake for Slackware 14.1 or older, and this GTK crap does not lend itself for static compilation inside the handbrake package. There now, I vomited a little. Why the fuck did they drop the Qt-based GUI? People can make bad decisions out of habit… this was definitely one.
I think we must be glad that we can compile the GUI for Handbrake 1.0.0 at all on Slackware 14.2.

By the way, compiling the command-line version of Handbrake is possible, even on Slackware 14.1 because that does not require GTK+3 as a dependency (although it depends on a lot of other X libraries on Slackware… i.e. the command-line program is unusable on a headless server without X.Org and friends installed).

Enjoy the new Handbrake!

handbrake-1.0.0

Packages for Slackware 14.2 and -current can be obtained from my “restricted” repository. Handbrake employs some software libraries that are under patent dispute (the MP3 and AAC audio encoders) so I can not host the package on the Slackware server in the US. The regular repository does have a handbrake directory but that hosts only the scripts, sources and patches, not the Slackware packages.

Get them here:

Eric

Setting up Jack Audio in Slackware

Note: this article has been superseded by the (much less complex) instructions in a newer article “Configuring Slackware for use as a DAW“.

If you are using your computer as a Digital Audio Workstation (DAW) then the ALSA sound subsystem is just not up for the task. Musicians and audio professionals prefer to use Jack Audio on Linux. Let me quote from the Jack Audio web site:

What is JACK?

Have you ever wanted to take the audio output of one piece of software and send it to another? How about taking the output of that same program and send it to two others, then record the result in the first program? Or maybe you’re a programmer who writes real-time audio and music applications and who is looking for a cross-platform API that enables not only device sharing but also inter-application audio routing, and is incredibly easy to learn and use? If so, JACK may be what you’ve been looking for.

JACK is system for handling real-time, low latency audio and MIDI.

We “ordinary” users of Slackware don’t usually have a need for Jack. It makes your computer’s sound subsystem more complex, meaning that more things can go wrong (where you end up with distorted or even no sound) and that fixing things requires more knowledge.

However there are cases even for non-musicians to want to install Jack Audio. I am one of them. As I explained in my previous post, I want to record videos of programs running on my desktop, along with the comments I may record through a microphone. When I selected SimpleScreenRecorder as my tool for doing this, I found out that it needs Jack in order to record the audio (but come to think of it… after reading bradpit’s comment in the previous post I realize that there may be a way around Jack – something I will check out soon and report if I find anything worth mentioning).

This article is meant to show you how to install and configure Jack Audio, and how to configure ALSA so that applications will still have sound even if they are unaware of Jack (Jack grabs the computer’s sound hardware and won’t allow ALSA applications to use it).

The article will center around you, being the one behind the physical computer. No system file needs to be changed, all configuration is done in your own home directory, for your use only. If someone else logs in, he or she will not be bothered by Jack and everything will work as before.

 

Installing Jack Audio

In order to install Jack Audio, you need the following packages: jack and qjackctl.

The qjackctl package contains the “de facto” configuration utility for Jack Audio, also called qjackctl. It is a Qt-based graphical program which allows you to configure “several JACK daemon parameters, which are properly saved between sessions, and a way control of the status of the audio server daemon” according to the program description. It also allows you to configure and autoload the patchbay and offers full connection control.

qjackctl_main

Configuring ALSA

The goal is to have a configuration where ALSA applications can access a “audio hardware” device even when the real device is locked by Jack Audio. That way, ALSA applications will not complain about unavailable audio hardware. I will show you how to provide ALSA with such a virtual hardware, and ensure that all sound which goes into that virtual hardware will be picked up by Jack and played through your speakers (hence the phrase “bridged”).

This “virtual hardware” is provided by the ALSA loop driver. When loaded into the kernel, this driver provides a pair of cross-connected devices, forming a full-duplex loopback soundcard.

First: load the kernel module (as root)

# /sbin/modprobe snd-aloop

You should add the above command-line to the file “/etc/rc.d/rc.modules” or to “/etc/rc.d/rc.local” so that the module will be loaded automatically on every boot.

The driver creates 8 independent substreams by default, but we need only two. Therefore you can add the following line to a (new) file called “/etc/modprobe.d/alsaloop.conf”:

options snd-aloop pcm_substreams=2

Next: write an ALSA configuration file which uses the new loopback devices

Create your ~/.asoundrc file as follows – if this file exists in your home directory, please back it up first!

# ------------------------------------------------------
# hardware 0,0 : used for ALSA playback
pcm.loophw00 {
  type hw
  card Loopback
  device 0
  subdevice 0
  format S32_LE
  rate 44100
}

# ------------------------------------------------------
# hardware 0,1 : used for ALSA capture
pcm.loophw01 {
  type hw
  card Loopback
  device 0
  subdevice 1
  format S32_LE
  rate 44100
}

# ------------------------------------------------------
# playback PCM device: using loopback subdevice 0,0
pcm.amix {
  type dmix
  ipc_key 196101
  slave {
    pcm "loophw00"
    buffer_size 8192
    period_size 4096
    periods 2
  }
}

# capture PCM device: using loopback subdevice 0,1
pcm.asnoop {
  type dsnoop
  ipc_key 196102
  slave {
   pcm loophw01
   period_size 4096
   periods 2
  }
}

# ------------------------------------------------------
# software volume
pcm.asoftvol {
  type softvol
  slave.pcm "amix"
  control { name PCM }
  min_dB -51.0
  max_dB   0.0
}

# ======================================================

# ------------------------------------------------------
# duplex device combining our PCM devices defined above
pcm.aduplex {
  type asym
  playback.pcm "asoftvol"
  capture.pcm "loophw01"
  hint {
    description "ALSA->JACK Loop Bridge"
  }
}

# ======================================================

# ------------------------------------------------------
# Mixer control definitions to keep JACK and some other apps happy
ctl.amix {
    type hw
    card Loopback
}

ctl.asnoop {
    type hw
    card Loopback
}

ctl.aduplex {
    type hw
    card Loopback
}

# ======================================================

# ------------------------------------------------------
# for jack alsa_out: looped-back signal at other end
pcm.ploop {
  type hw
  card Loopback
  device 1
  subdevice 1
  format S32_LE
  rate 44100
}

# ------------------------------------------------------
# for jack alsa_in: looped-back signal at other end
pcm.cloop {
  type hw
  card Loopback
  device 1
  subdevice 0
  format S32_LE
  rate 44100
}

# ======================================================

# ------------------------------------------------------
# default device

pcm.!default {
  type plug
  slave.pcm "aduplex"
}

When you save that file, its content will re-define your ALSA configuration with immediate effect. KDE may complain about hardware that was added or went missing, you can ignore that for now.

What these definitions do for ALSA, is to create a new full-duplex PCM device called “pcm.aduplex” with a description (which you will see mentioned in your programs’ ALSA device selectors) of “ALSA->JACK Loop Bridge”. What these definitions also do, is to create additional PCM devices for capture (pcm.cloop) and playback (pcm.ploop) which we will connect Jack to. That way, your ALSA applications are going to pipe their audio into one end of the loopback device and Jack will see this as incoming audio and play it on your speakers.

 You can test your new ~/.asoundrc file even though you will not hear a thing because the new virtual device is not yet connected to a real audio device (we will come to that in the next section). If you run the following command (under your own account – not as root) you should not see any error message:

$ aplay /usr/share/sounds/alsa/Front_Center.wav

Playing WAVE ‘/usr/share/sounds/alsa/Front_Center.wav’ : Signed 16 bit Little Endian, Rate 48000 Hz, Mono

If you see errors instead of the above text, then there is something wrong with the ~/.asoundrc file you just created.

Configuring Jack Audio

You should use qjackctl to configure the jack daemon. Jack installs a D-Bus service which qjackctl will connect to. Qjackctl can launch the daemon by itself or attach to an already running jack daemon (the qjackctl tray icon will be green if it had to start jackd and orange if it connected to an already running jackd).

qjackctl_setup_misc

Qjackctl will write the jack daemon configuration to a file in your homedirectory: ~/.jackdrc .It will write its own configuration to a different file: ~/.config/rncbc.org/QjackCtl.conf

I found out that I needed to have a sampling frequency of 44100 (the Jack default) instead of what musicians usually use (48000) in order to prevent distorted sounds coming from ALSA applications (youtube flash videos!). Whatever frequency you choose, you will need to use the same sampling frequency in ~/.asoundrc (see above) and for jackd.

qjackctl_setup

Using qjackctl, you can easily configure jack to use the soundcard hardware to which your speakers are connected: it shows a list of available devices in a dropdown menu. If you want to construct the jackd command-line manually, the names of all hardware devices can be obtained by running the following command:

$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: NVidia [HDA NVidia], device 0: VT1708S Analog [VT1708S Analog]
  Subdevices: 2/2
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
card 0: NVidia [HDA NVidia], device 1: VT1708S Digital [VT1708S Digital]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

The content of my ~/.jackdrc file looks like this:

/usr/bin/jackd -r -m -dalsa -r44100 -p1024 -n2 -m -H -D -Chw:NVidia -Phw:NVidia

The various jackd parameters all correspond to selections in the qjackctl dialog window.

Now when jack starts, it will still not know what to do with our modified ALSA configuration. A few commands need to be executed to form a bridge between ALSA and Jack using  the loopback driver. This is done most easily by creating a script file (for instance as user root create the file “/usr/local/bin/loop2jack” so that other users of your PC can use it as well) and in that file, add the following:

#!/bin/sh
#
# script loop2jack, located in /usr/local/bin
#
# Start jack if it is not already running:
/usr/bin/jack_control start
# loop client creation
/usr/bin/alsa_out -j ploop -dploop -q 1 2>&1 1> /dev/null &
/usr/bin/alsa_in -j  cloop -dcloop -q 1 2>&1 1> /dev/null &
# give it some time before connecting to system ports
sleep 1
# cloop ports -> jack output ports
/usr/bin/jack_connect cloop:capture_1 system:playback_1
/usr/bin/jack_connect cloop:capture_2 system:playback_2
# system microphone to "ploop" ports
/usr/bin/jack_connect system:capture_1 ploop:playback_1
/usr/bin/jack_connect system:capture_2 ploop:playback_2
# done
exit 0

Don’t forget to make the script executable:

chmod +x /usr/local/bin/loop2jack

This script should to be started after jackd has been started, but if jackd is not yet running, the script will start it for you. You can run it manually to see if there are any errors in your ~/.asoundrc file that you have to fix first. You can use qjackctl to run this script automatically when it starts:

qjackctl_setup_options

In the above screenshot you will also notice how the patchbay definitions are made persistent – I will show why this is important when I get to the section on SimpleScreenRecorder.

 

Starting Jack Audio

You will want to start the  jack daemon before any of your ALSA applications start! The ALSA driver grabs the audio hardware as soon as an application tries to make a sound using ALSA. Desktop Environments like KDE and XFCE have a feature called “session restore” which means that programs which were running when you logged out, will be started again – automatically – when you login again. A program like Skype, or even the startup sounds of your KDE desktop, will prevent Jack from launching properly.

If you are in runlevel 4 (graphical login) then you can start jackd by adding an appropriate command line in the following file: ~/.xprofile

If you are in runlevel 3 then you can start jackd from your normal login, using the file: ~/.profile

For instance, I have added this text to my ~/.xprofile :

# Create the bridge between ALSA applications and JACK output:
/usr/local/bin/loop2jack

… which will solve all timing issues: the loop2jack script will start the Jack daemon if it was not yet running, and it will bridge the ALSA and Jack in- and output channels using our virtual loopback device. This way, qjackctl does not even have to start anything (but we will not change the qjackctl configuration, in case you need to stop and restart Jack during a desktop login session).

 

Caveats

You have to keep in mind that running Jack is now required after making these modifications to your ALSA setup! When Jack is stopped (or not started) your ALSA sound system is no longer bridged to the physical sound card and you’ll hear nothing.

Also note that you may have a system-wide ALSA configuration file “/etc/asound.conf” which may interfere with your setup. Your own ~/.asoundrc definitions are added on top of the definitions in /etc/asound.conf and do not replace them.

 

Reverting this bridged ALSA-Jack setup

Reverting to the original Jack-less configuration is easy.

  1. Stop the Jack daemon using the qjackctl menu, and then stop qjackctl

  2. Remove or rename the file ~/.asoundrc (and restore your backup if you had an earlier version of this file)

  3. Remove or rename the file ~/.jackdrc

  4. Remove the invocation of “/usr/local/bin/loop2jack” from your ~/.xprofile and/or ~/.profile scripts.

The steps (1) and (2) are sufficient to restore the default ALSA behaviour and steps (3) and (4) ensure that Jack will not interfere at next login.

Getting audio into SimpleScreenRecorder (SSR)

In the “connections” window of qjackctl, my computer’s audio layout looks like this when I have started SimpleScreenRecorder (read my earlier post about this video recording tool):

qjackctl_connections_ssr

It’s a fairly simple layout with just a single Jack input client (being SSR) and a single output client (the entry “alsa-jack.jackP5161.0” which is the VLC program playing music).

The connections you see here between Jack’s “monitor” outputs (which were activated by checking the “Monitor” box in qjackctl’s setup dialog) and SSR’s inputs are automatically created when SSR connects to the Jack server. This happens because I defined these connections in qjackctl’s “patchbay” and let them be automatically activated. It seemed to be necessary this way because I could not get the monitor’s output to start inputting into SSR except by creating manual connections everytime.

qjackctl_patchbay_ssr

This is how I was finally able to record videos of (programs running on) my Slackware Linux desktop. Feedback highly appreciated!

Eric

 

A simpler solution (but not as robust)

There is another way to route the audio to and from ALSA-using applications when Jack is the sound server. In http://jackaudio.org/routing_alsa you can see how to use the “ALSA Jack PCM plugin” which creates a new PCM type called “jack”. This is a lot simpler to setup than the above article but it is not as robust and flexible. I used this solution for a little while and was happy with it – until I found out that it will not enable me to record audio with the SimpleScreenRecorder. So I had to abandon it.

You will need my alsa-plugins package for this. This package has two dependencies: jack (naturally) and ffmpeg. Note that if you want to use alsa-plugins and you are running 32-bit software which plays or records audio (think of Skype, Steam games) and you are on a 64-bit Slackware system, then you will additionally need multilib (of course) as well as “compat32” versions of the 32-bit ffmpeg and jack packages.

 

References

These pages have been helpful (most important info in the first link):

A journey into recording sound & video in Slackware

ssr When it comes to audio and sounds in Slackware, we’re happy to have ALSA as the sound subsystem. It works reliably, and has done so ever since it replaced OSS in Slackware all those years ago. In due course ALSA got capable of dynamically mixing multiple sound sources – which is basically what a sound server does, too. We were never plagued with the issues of other distros when they abandoned ALSA for PulseAudio.
When the Arts sound daemon of KDE was deprecated and finally removed with the release of KDE4, Slackware was left without a sound “server” that ran out of the box. We still have ESD, the Enlightened Sound Daemon but that one has limited use because of the wrapper programs it needs.
There are however scenarios where you wish Slackware had some sort of audio server. Until now, the only times when that thought crossed my mind it was related to streaming audio over a network – think of remote desktop sessions and virtual machines. I may write some more about that topic in a future post because I think I have the solution now – read on.

A more immediate need arose when I went looking for software that can record videos of my Slackware desktop – individual program windows and gameplay footage. My son is a huge Minecraft fan and wants to be able to do in Slackware what he already does with Fraps in Windows. My intention is to task him with creating some Slackware “end-user” videos to attract newcomers to the distro 🙂

It turns out that there really is not all that many good desktop video recording software in Linux land. I have tried recordmydesktop and like it well enough (that is how it ended up in Slackware’s “/extra” section) but it does not deliver stellar videos, in particular I don’t think it is suited for recording gameplay. It also produces OGG video only, which is OK since that gives you the only free and open video format and codecs… but I believe this design decision limits my options too much.

I read up on ArsTechnica’s attempts to record gameplay footage on SteamOS. To this day, the ArsTechnica folk have not found a way to record the audio of a game… apparently it is not as easy as you might think, to record OpenGL games. Programs like FFMPEG and VLC are able to record (parts of) your desktop but it is cumbersome and also does not deliver high-quality video with properly synced audio. These programs are not capable of intercepting OpenGL renders either, which limits their use.
So I went looking… and came across GLC, an ALSA & OpenGL recording software for Linux which was inspired by Fraps and Yukon, but it seems mostly abandoned by its author. Then there also is SimpleScreenRecorder, a relatively new piece of work by Maarten Baert. The program uses FFMPEG’s codecs to allow you to record audio and video into any format supported by the locally installed version of ffmpeg. It supports the recording of ALSA sound sources (think of a microphone). The word “simple” in its name only characterizes the ease-of-use, not the featureset! And it has a Qt-based GUI which nicely blends into my KDE desktop. By means of an OpenGL injection library it also supports direct recording of OpenGL renders (read: games). That should produce superior videos compared to merely recording the desktop window (because that produces lower frame rate videos or lower quality).

Unfortunately it turned out that SimpleScreenRecorder was not capable of recording my Slackware desktop’s sound, and therefore game videos are silent.
That is a show stopper… apparently you need a sound server like PulseAudio in order to record the audio as well. I am not prepared to install PulseAudio on Slackware – as you are well aware, this is a personal issue I have with the PA author and the way he writes code. So I investigated further, and found out that the unreleased GIT sources of SimpleScreenRecorder support JACK as a new sound source next to ALSA (and PulseAudio). I built the program from its GIT sources and then went on to learn about JACK Audio Connection Kit. I knew that JACK is primarily used by audio professionals and musicians because of its low-latency core design. But as it goes with versatile programs, it is inherently difficult to grasp its concepts and complex to configure. But I persevered and ultimately found a way to configure JACK on my desktop, and reconfigure my ALSA setup so that all the programs that I use can still emit sound, and SimpleScreenRecorder is now capable of recording video and audio! I put a demo video online which I recorded for the intro sequence from the Metro: Last Light game.

As you can see, the game stutters a bit, but that is not caused by the recording software – it’s my desktop PC which is just not fast enough for the game.

ssr_qtui

My next post will be about how I built and configured JACK, and what I had to change in my ALSA configuration so that for instance Steam games (using SDL for audio) and MineCraft (using OpenAL for audio) would still make sounds.

In the meantime, if you want to try SimpleScreenRecorder, there’s a couple of dependencies you need to install as well. SimpleScreenRecorder was built against ffmpeg (version 2.1 to be precise – please note that upgrades of ffmpeg will usually break a lot of applications that depend on it due to a change in library versions). Also, the package which I released has been built against jack – even if you do not plan on using it, you’ll have to install it… or you can rebuild SimpleScreenRecorder yourself.
If you want to use SimpleScreenRecorder to record 32-bit OpenGL programs (Steam games, WINE based games) and are running a 64-bit Slackware, it will have to be a multilib system and you will have to use the “convertpkg-compat32″ script (part of my compat32-tools package) to convert and install the 32-bits “compat32” versions of the simplescreenrecorder, ffmpeg and jack packages as well as the 64-bit versions.
If you want to try and record a Steam game without the Steam windows being visible (those are also rendered in OpenGL), you’ll definitely have to read these instructions: http://www.maartenbaert.be/simplescreenrecorder/recording-steam-games/#native-steam-for-linux because currently it involves some manual tweaking to get this working (I expect that this will get easier in time). Judging by his Wiki, Maarten is responsive to the users of his program and is able to write meaningful documentation.

Get packages (and sources) here:

Have fun! Eric

« Older posts

© 2024 Alien Pastures

Theme by Anders NorenUp ↑