Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Record Sound on Ubuntu Docker Image

Tags:

I would like record audio with ffmpeg when I capture my screen. The error I'm getting when using alsa is that is that my image does not have a sound card -f alsa -ac 2 -i hw:0

Here is how to reproduce on a fresh version of Ubuntu

Start a session in a new ubuntu docker image.

docker pull ubuntu
docker run -it --rm ubuntu

Setup alsa (Advanced Linux Sound Architecture)

apt-get update
apt-get install alsa-utils

List the sound cards

aplay -l
# aplay: device_list:268: no soundcards found...

And playing this sound will fail because this image doesn't have any sound cards

sudo aplay /usr/share/sounds/alsa/Front_Center.wav
like image 942
Daniel Rasmuson Avatar asked Apr 09 '17 23:04

Daniel Rasmuson


2 Answers

EDIT: after reading first comment to BMitch about not needing to play out to local computer

Im recommanding to use pulseaudio since its userspace code and no kernel modules are needed. It would seem unlikely to me that alsa would work for docker (though I could be wrong)

If I do this:

apt-get update
apt-get install pulseaudio socat
apt-get install alsa-utils
apt-get install ffmpeg

# Start the pulseaudio server
pulseaudio -D --exit-idle-time=-1

# Load the virtual sink and set it as default
pacmd load-module module-virtual-sink sink_name=v1
pacmd set-default-sink v1

# set the monitor of v1 sink to be the default source
pacmd set-default-source v1.monitor

# Start the ffmpeg capture to an audio file
ffmpeg -f pulse -i default out.mp3

then in a separate terminal

paplay /usr/share/sounds/alsa/Front_Center.wav

The audio of the WAV file is captured by ffmpeg and appears in the out.mp3

I dont really know what your X setup looks like but if you can get the audio going to pulseaudio, then ffmpeg will capture the audio without needing a real sound card

Original Answer: if you want the audio to get to the Mac OS sound card

I originally got to this page cos I was trying to get the playback of audio from within the VM to the Mac OS. But if you dont care about getting it out the VM, then the following is overly complicated. Im leaving it here though as this idea was why i ended up here

It is possible to use pulseaudio within the VM to play back a WAV file to the physical sound card. Im using docker 17.03.1-ce on Mac OS Sierra and have used brew to install sox. This setup also requires socat to be installed on the VM but someone with more pulseaduio knowledge (or if i get more time) should be able to remove this part i think

The strategy is to use paplay to play the wav file through pulseaudio and have pulseaudio send the audio out over the network on a port you published at start up of the VM. On the Mac-side, you'll connect to this published port and send the data through sox to the Mac.

1. MAC: pull and run image with published port

    docker pull ubuntu
    docker run -it --rm -p 127.0.0.1:3000:3000 ubuntu

2. VM: update and install the require packages

    apt-get update
    apt-get install pulseaudio socat
    apt-get install alsa-utils

Im only installing alsa-utils for the wav file, so you could remove this

3. VM: start the pulseaudio server

    pulseaudio -D --exit-idle-time=-1

This tell the server to fork to the background and not to exit based on inactivity

4. VM: create a "sink" for pulseaudio

The sink is where pulseaudio will send the audio data in a specific format:

    pacmd load-module module-pipe-sink file=/dev/audio format=s16 rate=44100 channels=2

This will send the audio to the file /dev/audio in signed 16-bit 2-channel at 44100Hz.

5. VM: Attach file to the network

This file now needs to be "attached" to the network, socat is used to create a listening socket at the published address (NOTE: there is no authentication here) that is ready to send the audio when the Mac-side connects

    socat file:/dev/audio tcp-listen:3000

6. MAC: read data from network into sox

On the Mac-side, we now need to connect to this port and send the detail, via sox, to the audio driver:

    nc 127.0.0.1 3000 | sox -traw -r44100 -b16 -c2 -e signed-integer - -d

the mac has netcat (nc) by default so Im using this here to connect to the published port and then pipe the data to sox, with flags to sox to match the values set in the "load-module" statement above.

7. VM: Play!

Finally, using paplay from the pulseaudio package the WAV file can be played:

    paplay /usr/share/sounds/alsa/Front_Center.wav

8. MAC: Listen! On the mac side you should now here the audio and be able to see the output from sox which includes a small level meter and this should move:

    $ nc 127.0.0.1 3000 | sox -traw -r44100 -b16 -c2 -e signed-integer - -d
    -: (raw)

     File Size: 0
      Encoding: Signed PCM
      Channels: 2 @ 16-bit
    Samplerate: 44100Hz
    Replaygain: off
      Duration: unknown

    In:0.00% 00:00:06.78 [00:00:00.00] Out:299k  [      |      ]        Clip:0

Doing the reverse (ie sending the Mac audio to pulseaudio on the VM) should also be possible with a similar, though backwards, setup (module-pipe-source?)

I haven't tested this against the commands on the ffmpeg page as I have no X server.

like image 182
spacepickle Avatar answered Oct 04 '22 18:10

spacepickle


I think the key is on docker run command to map device into the container. Try this:

docker run -ti --rm \
    -v /dev/snd:/dev/snd \
    --lxc-conf='lxc.cgroup.devices.allow = c 116:* rwm' \
    myContainer sh -c "echo run something"`

Extracted from here. On this link there are more options if this doesn't work for you. Check it out!

like image 30
OscarAkaElvis Avatar answered Oct 04 '22 20:10

OscarAkaElvis