OpenBSD FAQ - Multimedia [FAQ Index]



Enabling Audio Recording

For privacy reasons, audio recording is disabled by default in OpenBSD. The kern.audio.record sysctl may be used to enable it.
# sysctl kern.audio.record=1
# echo kern.audio.record=1 >> /etc/sysctl.conf

Configuring Audio Hardware

Each sound card model has its own set of controls. Some have no controls at all; others have a hundred or more. Running mixerctl(8) as root will list all of the controls and current settings.

Not every option of every audio chip necessarily reaches the outside world. There may be, for example, more outputs listed than are physically connected. The controls of an audio device may be labeled differently. Usually the controls have a meaningful label, but sometimes one must simply try different settings to see what effect each control has.

Here's a list of controls to consider:

Mute and Level controls - Even if the main controls seem to be properly set, there might be multiple mute or level controls in the signal path. In the example below, the device has a master recording level and a microphone gain control:

record.adc-0:1=248,248
record.adc-0:1_source=mic
inputs.mic=85,85
External Amplifier Power-Down (EAPD) - This switch is typically used for power saving in laptops and may need to be set to get an output signal:
outputs.spkr_eapd=on
Recording Source - Some devices have multiple microphone inputs. Examples of such controls:
record.source=mic
record.adc-0:1_source=mic
To make the changes take effect on each reboot, edit the /etc/mixerctl.conf file. For example:
record.adc-0:1_source=mic
inputs.mic=85,85

Adjusting Audio Levels

The sndioctl(1) utility is used to manipulate audio controls as a regular user. Running it with no arguments will list all the controls and current settings.

The output.level control is always present. It either corresponds to a hardware control or is emulated in software.

Using a USB Audio Interface

An example of a USB audio interface in a dmesg output might look like this:
uaudio0 at uhub2 port 1 configuration 1 interface 1 "ABC C-Media USB Audio Device" rev 1.10/1.00 addr 2
uaudio0: class v1, full-speed, sync, channels: 2 play, 1 rec, 8 ctls
audio1 at uaudio0
On most systems, the first audio device is the internal sound card. A USB audio device then becomes the second one when connected. In the default sndiod(8) configuration, both devices are known to programs as snd/0 (the default) and snd/1 respectively and may be used independently. Programs set up to use snd/1 will use the USB device.

sndiod(8) may be configured to make snd/0 correspond to the USB device if it's connected or to the internal one when it's not:

# rcctl set sndiod flags -f rsnd/0 -F rsnd/1
# rcctl restart sndiod
When the server opens the device, it will first try the USB one. If it's not present, the internal one is used instead. If the USB device is disconnected, sndiod attempts to continue operation using the internal sound card. If the USB device is connected again, sndiod will see it the next time it attempts to open the device. To force sndiod to switch between devices, reload the server:
# rcctl reload sndiod

Playing Audio

OpenBSD comes with aucat(1), a program able to play uncompressed WAV, AIFF and AU files. It can be used in very simple cases or to test playback:

$ aucat -i filename.wav
There are many other players available as packages that support other audio formats.

Recording Audio

Once recording is enabled with the kern.audio.record sysctl, aucat(1) can be used for recording uncompressed WAV, AIFF and AU files.
$ aucat -o file.wav
The above command will start the recording of a file in WAV format. Press CTRL+C to finish the recording.

To play the file back, run:

$ aucat -i file.wav
If recording seemed to work, but playback of the recording was silent or not what was expected, the mixer probably needs some configuration. Make sure that you select the right source to record from and that it is unmuted.

If needed, the resulting WAV file could be compressed with the appropriate program from the ports tree. Alternatively, ports like sox, ffmpeg, or audacity can be used to record, process and compress audio files.

Recording a Monitor Mix of All Audio Playback

A monitoring stream records combined audio output from all playback devices, allowing you to duplicate or save anything going through the audio subsystem. This feature can be useful for screencasts or any kind of live audio mixing.

Create the monitor sub-device mon for sndiod(8) by using:

# rcctl set sndiod flags -s default -m play,mon -s mon
# rcctl restart sndiod
Configure your program to record audio from the snd/0.mon device, for instance:
$ aucat -f snd/0.mon -o file.wav
At this point, whatever your system plays is recorded in file.wav.

Lowering Audio Latency

Latency is the time between when a program takes the decision to play a sample and when the user hears the sample. Since audio data is always buffered, this delay is proportional to the audio buffer size. The following values are recommended: The smaller the audio buffers are (to achieve low latency), the larger the probability to overrun/underrun is. Buffer overruns/underruns result in stuttering of the sound.

sndiod(8) imposes a minimum latency on all audio applications, and the default latency is 160ms. If you plan to use applications that require a lower latency, use the -b option to select the desired latency (expressed in number of frames). For instance, at 48000 samples/second, 50ms latency corresponds to:

48000 samples/second × 0.050 seconds = 2400 samples
Then do:
# rcctl set sndiod flags -b2400

Does low latency improve audio-video synchronization?

No, synchronizing audio to video doesn't require low latency. Synchronization problems are often caused by the software itself. Forcing the application to use smaller buffers (by starting sndiod(8) in low latency mode) may hide the actual problem in some cases, and give the feeling that the software works better, but obviously the right thing to do is to start searching for the corresponding bug.

Using Remote Audio Hardware

sndiod(8) can be configured to accept connections from the network, allowing other machines to use the sound card as well. On the remote system with the sound card, run:
# rcctl set sndiod flags -L-
On the local system, configure your program to use snd@hostname/0, where "hostname" is the address of the remote system. The AUDIODEVICE environment variable could be set to the above value to make the remote sound card the default audio device.

Any system able to connect to TCP port 11025 of the remote host will be able to use the audio device. For privacy reasons, only one user from one system may have connections to it at a given time. If multiple systems have to use the audio device simultaneously, the sndio(7) authorization cookie must be the same. For instance, copy your ~/.sndio/cookie to all accounts that may use the audio device.

To avoid glitches, TCP traffic on port 11025 could be prioritized with the packet filter. With the default configuration, sndiod will consume around 200kB/s of network bandwidth.

Choosing the Default Audio Device

The default audio device is selected with the AUDIODEVICE environment variable. If it's not set, snd/0 is used, which is the first audio device managed by sndiod(8). The most flexible way of choosing the default device is to export AUDIODEVICE, possibly in the user's login profile.

Another way to change the default audio output device is to make the desired device the first device managed by sndiod(8). For example, to use an external DAC rather than your motherboard's onboard audio, just change sndiod(8)'s startup flags to use that device:

# rcctl set sndiod flags -f rsnd/1
# rcctl restart sndiod
This would make the second audio device (rsnd/1) the default.

Debugging Audio Problems

If you do not hear anything when playing audio, it's possible there is a mixer control turned to low or simply muted. See this section for configuring the mixer. Please unmute all inputs and outputs before reporting a problem.

If you believe your device should be working, but for whatever reason isn't, then it's time for a little debugging. The following steps can determine if data is being processed by the DAC.

# cat > /dev/audio0 < /dev/zero &
[1] 9926
# audioctl play.{bytes,errors}
play.bytes=3312000
play.errors=0
# audioctl play.{bytes,errors}
play.bytes=7065600
play.errors=0
# audioctl play.{bytes,errors}
play.bytes=9379200
play.errors=0
# kill %1
# fg %1
cat > /dev/audio0 < /dev/zero
Terminated
Here we see that the processed data count play.bytes increases each time we check, so data is flowing. We also see that the device has not underrun any samples (play.errors). That's good too.

Note that even if you had speakers plugged in when running the above test, you should not have heard anything. The test sends zeros to the device, which is silence for all currently supported default encodings.

Since we know the device can process data, it's a good idea to check the mixer settings again. Make sure all outputs and all inputs are unmuted and are at a reasonable level.

If you are still having problems at this point, it's probably time to file a bug report. Besides the normal bug report information such as a full dmesg and description of the problem, please also include the default output of mixerctl -v and the output of the above test for DAC processing.

Using MIDI Instruments

The Musical Instrument Digital Interface (MIDI) protocol provides a standardized and efficient means to represent musical performance information as electronic data. MIDI data contains only instructions needed by a synthesizer to play the sounds, rather than the actual sounds.

To play MIDI data, a synthesizer connected to a MIDI port of the machine is required. Similarly, to record a MIDI data a MIDI instrument is required (such as a MIDI keyboard). Advanced MIDI instruments may contain multiple subparts (synthesizers, keyboards, control surfaces, etc...). They appear as multiple MIDI ports on OpenBSD.

When you already have OpenBSD running, look for MIDI ports in the output of the dmesg(8) command. An example of MIDI ports in a dmesg output is:

umidi0 at uhub2 port 2 configuration 1 interface 0 "Roland Roland XV-2020" rev 1.10/1.00 addr 2
midi0 at umidi0: <USB MIDI I/F>
umidi1 at uhub1 port 2 configuration 1 interface 1 "Evolution Electronics Ltd. USB Keystation 61es" rev 1.00/1.25 addr 3
midi1 at umidi1: <USB MIDI I/F>
It shows two midi(4) drivers attached, known by programs as: The output of the keyboard can be connected to the input of the synthesizer as follows:
$ midicat -q midi/0 -q midi/1
Now you can hear what you're playing on the MIDI keyboard on the synthesizer.

The sndiod(8) server exposes MIDI thru ports, allowing programs to send each other MIDI data. For instance, if you have no hardware synthesizer connected, you could start a software one (like the audio/fluidsynth port) and then use it as MIDI output:

$ midicat -q midi/0 -q midithru/0

Using a Webcam

Supported Hardware

Most webcams today work according to the USB Video Class (UVC) specification, which is supported by the uvideo(4) device driver and attaches to the video(4) device. The manpage lists some supported devices, but there is a good chance that other devices work as well. For example, webcams in Lenovo Thinkpad laptops do usually work.

A supported webcam (or other video device) shows up in dmesg like this:

uvideo0 at uhub0 port 8 configuration 1 interface 0 "Azurewave Integrated Camera" rev 2.01/69.05 addr 10
video0 at uvideo0
uvideo1 at uhub0 port 8 configuration 1 interface 2 "Azurewave Integrated Camera" rev 2.01/69.05 addr 10
video1 at uvideo1

You see that an uvideo device was detected and has been attached to video0. This device will be accessible through /dev/video0.

Modern laptops sometimes attach a second video device, which is the infrared camera for face recognition. The second camera does not produce a usable video stream.

You can find the usable camera with the video(1) command:

$ video -q -f /dev/video0
video device /dev/video0:
  encodings: yuy2
  frame sizes (width x height, in pixels) and rates (in frames per second):
        320x180: 30
        320x240: 30
        352x288: 30
        424x240: 30
        640x360: 30
        640x480: 30
        848x480: 20
        960x540: 15
        1280x720: 10
  controls: brightness, contrast, saturation, hue, gamma, sharpness, white_balance_temperature

$ video -q -f /dev/video1
video: /dev/video1 has no usable YUV encodings

The usable camera device shows supported resolutions and framerates. Note that the framerates only apply to the uncompressed YUY2 stream. More on that in Recording a webcam stream.

Using a webcam as user

To use the webcam as regular user, you need to change the device permissions. Only root is allowed to access video devices by default.

# chown $USER /dev/video0

Recording a webcam stream

This section uses ffplay and ffmpeg from graphics/ffmpeg. To find out what your camera is capable of, run the following command:

$ ffplay -f v4l2 -list_formats all -i /dev/video0
[...]
[video4linux2,v4l2 @ 0x921f8420800] Raw       : yuyv422 : YUYV : 640x480 320x180 320x240 352x288 424x240 640x360 848x480 960x540 1280x720
[video4linux2,v4l2 @ 0x921f8420800] Compressed:   mjpeg : MJPEG : 1280x720 320x180 320x240 352x288 424x240 640x360 640x480 848x480 960x540

At the end of the output, you'll find two lines similiar to the two above.

The first line shows resolutions supported in the uncompressed YUYV format. The frame rates in this format can be very low.

The second line shows the supported MJPEG compressed video resolutions, which deliver much higher framerates (usually 30fps or 60fps).

Now try to play the webcam stream. Choose one of the MJPEG resolutions and run:

$ ffplay -f v4l2 -input_format mjpeg -video_size 1280x720 -i /dev/video0
[...]
Input #0, video4linux2,v4l2, from '/dev/video0':B sq=    0B f=0/0
  Duration: N/A, start: 1599377893.546533, bitrate: N/A
    Stream #0:0: Video: mjpeg (Baseline), yuvj422p(pc, bt470bg/unknown/unknown), 1280x720, 30 fps, 30 tbr, 1000k tbn, 1000k tbc
The webcam stream should be displayed. Ffplay also shows the used resolution and the framerate (fps) used.

If this works, you can go ahead and record the video with ffmpeg:

$ ffmpeg -f v4l2 -input_format mjpeg -video_size 1280x720 -i /dev/video0 ~/video.mkv
End the recording with "q". You have now recorded your stream to file ~/video.mkv.

Controlling webcam settings

Webcams usually have brightness, contrast and other controls. video(1) allows you to alter these settings.

First find out which supported controls your camera has:

$ video -c
brightness=128
contrast=32
saturation=64
hue=0
gamma=120
sharpness=3
white_balance_temperature=auto

You can change for example the brightness setting to 200:

$ video brightness=200
brightness: 128 -> 200

If you would like to reset all settings to their defaults, you can do so with:

$ video -d
$ video -c
brightness=128
contrast=32
saturation=64
hue=0
gamma=120
sharpness=3
white_balance_temperature=auto

Some settings, like the white_balance_temperature support automatic adjustments. You can set them to a fixed value or set them to "auto", which lets the camera decide and use whatever value it thinks is best.

Access webcam in chromium

Chromium has access to /dev/video by default. To allow Chromium to access other video devices, you need to add the device paths to /etc/chromium/unveil.main and /etc/chromium/unveil.utility_video

Access webcam in firefox

Firefox has access to /dev/video and /dev/video0 by default. To allow Firefox to access other video devices, you need to add the device paths to /etc/firefox/unveil.main.