Voice-Chat between two OpenBSD Hosts

With the recent developments made in the OpenBSD sound architecture (many thanks to Jacob Meuser and the other OpenBSD developers who have done all this hard work), it is possible (and quite easy) to setup a two-way voice chatting between two OpenBSD machines using nothing more than the aucat(1) and ssh(1), which are both in the base installation. Not only is it easy, but it's quite usable; you are able to voice chat with telephone-quality sound and a ≤ 1 second delay.

Requirements

In the examples below, we'll be working with two users: user ryan on the machine tarski and user neal on the machine montague will be voice-chatting. The following are required:

  • Both users will need ssh(1) access to each others machines. Specifically: user ryan needs to be able to login on montague (I'll assume the login name is the same), and user neal needs to be able to login on tarski (also assuming the login name is the same).
  • Both machines (tarski and montague) need OpenBSD version 4.4 or greater installed.
  • Fully read the FAQ entry § 13.4 Can I use OpenBSD to record audio samples.
  • Fully read the man page aucat(1).

Setting it Up

The rough idea is simple, although there is some setup and the exact commands are slightly different (mostly to avoid high latency). User ryan does the following from tarski:

         ryan@tarski> aucat -l
         ryan@tarski> aucat -o - | ssh ryan@montague aucat -i -

and neal does the following from montague:

         neal@montague> aucat -l
         neal@montague> aucat -o - | ssh neal@tarski aucat -i -

There's some setup, however, regarding running aucat(1) in server mode and allowing other users to bind to that server instance.

When using aucat by default, it will “dominate” your audio hardware, in such a way that any other applications will be denied access to the audio devices in /dev/*. Using the setup above, however, two distinct users will need access to the hardware through aucat(1), and you have to “trick” aucat(1) into allowing this access. This is done in the following manner...

When aucat(1) is run in server-mode (i.e. aucat -l) it will create the socket /tmp/aucat-USERID/default where USERID is the user-id (from /etc/passwd) of the user invoking the aucat -l command. Any subsequent instances of aucat(1) by that user will not bind to the audio hardware directly, but rather use this socket and the server instance of aucat(1) listening on this socket will multiplex those instances. Other users, however, will not be allowed to bind to this socket, because their instances of aucat(1) will try to bind to a socket in /tmp/aucat-OtherUSERID/default rather than the one that already exists. To trick these other instances of aucat(1), you simply open-up the permissions on the /tmp/aucat-USERID directory and create a symbolic-link to that directory for the other user. Specifically, using the ryan/neal example, above...

  • As user ryan on tarski do the following
                ryan@tarski> RyanUID=`id -ur ryan`
                ryan@tarski> NealUID=`id -ur neal`
                ryan@tarski> aucat -l
                ryan@tarski> cd /tmp/
                ryan@tarski> chmod 755 aucat-$RyanUID
                ryan@tarski> ln -s aucat-$RyanUID aucat-$NealUID
  • Do the same thing as user neal on montague, only reverse...
                neal@montague> NealUID=`id -ur neal`
                neal@montague> RyanUID=`id -ur ryan`
                neal@montague> aucat -l
                neal@montague> cd /tmp/
                neal@montague> chmod 755 aucat-$NealUID
                neal@montague> ln -s aucat-$NealUID aucat-$RyanUID

After this, each user can simply do the following...
First, user ryan on tarski establishes their connection with:

         ryan@tarski> aucat -o - | ssh ryan@montague aucat -i -

Then, user neal on montague establishes their connection with:

         neal@montague> aucat -o - | ssh neal@tarski aucat -i -

While the above will work, you may notice stuttering and a high-delay (5-10 seconds) with the audio. Playing with the -b and -r options to aucat(1) will help. We found that the following produces telephone-quality audio with a ≤ 1 second delay

         ryan@tarski> aucat -b 1 -r 11000 -o - \
            | ssh ryan@montague aucat -b 1 -r 11000 -i -

and

         neal@montague> aucat -b 1 -r 11000 -o - \
            | ssh neal@tarski aucat -b 1 -r 11000 -i -

Tweaking

The following greatly helps...

  • Having a microphone!
  • Increasing microphone input volume on both ends via
             prompt> mixerctl inputs.mic=255,255