📜 ⬆️ ⬇️

Making a media matrix on the knee

Often there is a need to receive an audio signal from a variety of unrelated devices and give the received signal to many unrelated speakers. Many people do this through BiAMP, Kramer media matrixes in conjunction with management through Kramer, Palantir, etc., but this equipment costs money, but money is not always there.

I dare to describe the budget option, which in the basic functionality is not inferior to the products described above. And in terms of management can be more flexible.
The project uses 15 media servers (Windows 7), each of which has its own video sequence displayed on plasmas and projectors, as well as an audio stream accompanying the video series. There are also 3 speakers, to which the audio stream can be output.

A little about the structure.
The video sequence is transmitted from the server room via DVI and VGA signal converters to equipment rendered from the server room at a distance of up to 50 meters. Using the built-in or remote speakers for audio broadcast would result in cacophony and inability to perceive the displayed content. To reproduce the sound, it was decided to divide the 15 media servers into 3 groups and switch the audio signal to 3 different speakers, geographically close to the plasmas and projectors.

Since the sound switching needs to be controlled remotely, it means that you need to switch it somewhere. Physical switching is old and reliable, but we live in the digital age. Therefore, to switch the sound, we will use a number, and to get a digital stream, you need to take it from somewhere.
')
We install virtual audio cable drivers on the computer.
These drivers are a virtual sound card in which you can send the entire sound of the system and remove the sound stream in digital form using programs.

In our case, the usual ffmpeg is used.

To get a list of audio devices, you must run ffmpeg with the following keys:
 C: \ Progs \ ffmpeg \ bin> ffmpeg -list_devices true -f dshow -i dummy
 [dshow @ 00000000020a77e0] DirectShow video devices
 [dshow @ 00000000020a77e0] "Logitech HD Webcam C310"
 [dshow @ 00000000020a77e0] DirectShow audio devices
 [dshow @ 00000000020a77e0] "Microphone (HD Webcam C310)"
 [dshow @ 00000000020a77e0] "CABLE Output (VB-Audio Virtual"


The device from which we will shoot the audio stream will be “CABLE Output (VB-Audio Virtual”.

As a device in which the entire sound of the system will be output will be “CABLE Input (Virtual Audio Cable)”.



Run ffmpeg and broadcast the data to the network.
 C: \ Progs \ ffmpeg \ bin> ffmpeg -re -f dshow -i audio = "CABLE Output (VB-Audio Virtual" -f mp3 udp: //239.1.1.1: 5001
 ffmpeg version N-49610-gc2dd5a1 Copyright (c) 2000-2013 the FFmpeg developers
   built on Feb 5 2013 13:26:02 with gcc 4.7.2 (GCC)
   libavutil 52. 17.101 / 52. 17.101
   libavcodec 54. 91.100 / 54. 91.100
   libavformat 54. 61.104 / 54. 61.104
   libavdevice 54. 3.103 / 54. 3.103
   libavfilter 3. 35.101 / 3. 35.101
   libswscale 2. 2.100 / 2. 2.100
   libswresample 0. 17.102 / 0. 17.102
   libpostproc 52. 2.100 / 52. 2.100
 [dshow @ 00000000024de080] Estimating duration from bitrate, this may be inaccurate
 Guessed Channel Layout for Input Stream # 0.0: stereo
 Input # 0, dshow, from 'audio = CABLE Output (VB-Audio Virtual':
   Duration: N / A, start: 270550.167000, bitrate: 1411 kb / s
     Stream # 0: 0: Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb / s
 Output # 0, mp3, to 'udp: //239.1.1.1: 5001':
   Metadata:
     TSSE: Lavf54.61.104
     Stream # 0: 0: Audio: mp3, 44100 Hz, stereo, s16p
 Stream mapping:
   Stream # 0: 0 -> # 0: 0 (pcm_s16le -> libmp3lame)
 Press [q] to stop [?] For help
 size = 100kB time = 00: 00: 06.37 bitrate = 128.5kbits / s


Anywhere on the network you can listen to this stream with any player (ffplay, vlc, etc.). If you wish, you can change the codec and bitrate.
The basic setting was made, the sound was received, the drivers were replicated on 15 media servers, 15 different streams were received, and now the question is “how to listen and commute.”

From the point of view of saving iron and resources, you can use a single machine with a certain number of audio cards that output sound to the acoustics. Now in the market there are various small-sized USB sound cards. From the point of view of ease of use, cheap cards like CMEDIA are not profitable, because they do not have serial numbers inside, and it’s impossible to determine which card after rebooting to which channel began to work. I used the “Creative SB Play!” Cards that give a pretty good sound and have the ability to identify them in the system.

Since when USB audio is connected, dynamic numbers are assigned to cards, a set of rules was written for devd:

 attach 50 {
         match "device-name" "uaudio [0-9] +";
         match "sernum" "[0-9A-Za-z] +";
         match "mode" "host";
         action "logger USB Audio S / N: $ sernum is attached";
         action "ln -fs / dev /` head -n 1 / tmp / $ device-name.dsp` /dev/$device-name.dsp ";
         action "ln -fs /dev/$device-name.dsp /dev/uaudio.serial.$sernum";
         action "rm /tmp/$device-name.dsp";

         match "device-name" "uaudio [0-9] +";
         match "hubaddr" "[0-9] +";
         match "port" "[0-9] +";
         match "devaddr" "[0-9] +";
         action "echo $ device-name at ugen. $ port. $ devaddr";
         action "ln -fs /dev/$device-name.dsp /dev/uaudio.ugen.$port.$devaddr";

 };

 attach 50 {
         match "device-name" "uaudio [0-9] +";
         match "sernum" "$";
         match "mode" "host";
         action "logger USB Audio without serial number is attached";
         action "ln -fs / dev /` head -n 1 / tmp / $ device-name.dsp` /dev/$device-name.dsp ";
         action "rm /tmp/$device-name.dsp";

         match "device-name" "uaudio [0-9] +";
         match "hubaddr" "[0-9] +";
         match "port" "[0-9] +";
         match "devaddr" "[0-9] +";
         action "echo $ device-name at ugen. $ port. $ devaddr";
         action "ln -fs /dev/$device-name.dsp /dev/uaudio.ugen.$port.$devaddr";

 };

 attach 40 {
         match "device-name" "pcm [0-9] +";
         match "bus" "uaudio [0-9] +";
         action "logger Found $ device-name at $ bus. Saving.";
         action "echo -n $ device-name | sed -E 's / pcm / dsp /' >> /tmp/$bus.dsp";
 };

 detach 40 {
         match "device-name" "uaudio [0-9] +";
         match "bus" "uhub [0-9] +";
         action "logger dropping dsp symlink for $ device-name";
         action "find / dev / -type l -ls | awk '$$ NF ~ /$device-name\./ {print $ (NF-2)}' | xargs rm";
         action "rm -f /dev/$device-name.dsp";
 };

 notify 50 {
         match "type" "DETACH";
         match "mode" "host";
         match "sernum" "[0-9A-Za-z] +";
         action "logger USB Audio S / N: $ sernum detached";
 };


Which forms symlinks on the connected equipment in the form " /dev/uaudio.serial. <SerialNumber> ", as a result, the list of devices looks like this:

 lrwxr-xr-x 1 root wheel 16 May 15 09:27 /dev/uaudio.serial.131014000129 -> /dev/uaudio1.dsp
 lrwxr-xr-x 1 root wheel 16 May 15 09:23 /dev/uaudio.serial.140210000BB2 -> /dev/uaudio0.dsp
 lrwxr-xr-x 1 root wheel 16 May 15 09:23 /dev/uaudio.ugen.5.6 -> /dev/uaudio0.dsp
 lrwxr-xr-x 1 root wheel 16 May 15 09:27 /dev/uaudio.ugen.5.7 -> /dev/uaudio1.dsp
 lrwxr-xr-x 1 root wheel 16 May 15 08:37 /dev/uaudio.ugen.5.8 -> /dev/uaudio2.dsp
 lrwxr-xr-x 1 root wheel 9 May 15 09:23 /dev/uaudio0.dsp -> / dev / dsp6
 lrwxr-xr-x 1 root wheel 9 May 15 09:27 /dev/uaudio1.dsp -> / dev / dsp7
 lrwxr-xr-x 1 root wheel 9 May 15 08:37 /dev/uaudio2.dsp -> / dev / dsp8


That allows you to uniquely identify the card and the speaker system that it serves.

The log also contains information about what is happening.

 May 15 08:35:31 franky zhecka: USB Audio S / N: 131014000129 is attached
 May 15 08:35:36 franky zhecka: Found pcm8 at uaudio2.  Saving.
 May 15 08:35:36 franky kernel: uaudio2: <vendor 0x0d8c Generic USB Audio Device, class 0/0, rev 1.10 / 1.00, addr 8> on usbus5
 May 15 08:35:36 franky kernel: uaudio2: Play: 44100 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 08:35:36 franky kernel: uaudio2: Play: 48000 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 08:35:36 franky kernel: uaudio2: Play: 44100 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 08:35:36 franky kernel: uaudio2: Record: 44100 Hz, 1 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 08:35:36 franky kernel: uaudio2: Record: 48000 Hz, 1 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 08:35:36 franky kernel: uaudio2: Record: 44100 Hz, 1 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 08:35:36 franky kernel: uaudio2: No MIDI sequencer.
 May 15 08:35:36 franky kernel: pcm8: <USB audio> on uaudio2
 May 15 08:35:36 franky kernel: uaudio2: HID volume keys found.
 May 15 08:35:37 franky zhecka: USB Audio without serial number is attached
 May 15 08:37:11 franky zhecka: Dropping dsp symlink for uaudio2
 May 15 08:37:11 franky kernel: uaudio2: at uhub6, port 3, addr 8 (disconnected)
 May 15 08:37:15 franky zhecka: Found pcm8 at uaudio2.  Saving.
 May 15 08:37:15 franky kernel: uaudio2: <vendor 0x0d8c Generic USB Audio Device, class 0/0, rev 1.10 / 1.00, addr 8> on usbus5
 May 15 08:37:15 franky kernel: uaudio2: Play: 44100 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 08:37:15 franky kernel: uaudio2: Play: 48000 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 08:37:15 franky kernel: uaudio2: Play: 44100 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 08:37:15 franky kernel: uaudio2: Record: 44100 Hz, 1 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 08:37:15 franky kernel: uaudio2: Record: 48000 Hz, 1 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 08:37:15 franky kernel: uaudio2: Record: 44100 Hz, 1 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 08:37:15 franky kernel: uaudio2: No MIDI sequencer.
 May 15 08:37:15 franky kernel: pcm8: <USB audio> on uaudio2
 May 15 08:37:15 franky kernel: uaudio2: HID volume keys found.
 May 15 08:37:15 franky zhecka: USB Audio without serial number is attached
 May 15 09:17:56 franky zhecka: USB Audio S / N: 140210000BB2 detached
 May 15 09:17:56 franky kernel: uaudio0: at uhub7, port 2, addr 6 (disconnected)
 May 15 09:17:56 franky zhecka: USB Audio S / N: 140210000BB2 detached
 May 15 09:17:56 franky zhecka: Dropping dsp symlink for uaudio0
 May 15 09:23:36 franky zhecka: Found pcm6 at uaudio0.  Saving.
 May 15 09:23:36 franky kernel: uaudio0: <vendor 0x041e product 0x30d3, class 0/0, rev 1.10 / 1.00, addr 6> on usbus5
 May 15 09:23:36 franky kernel: uaudio0: Play: 44100 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 09:23:36 franky kernel: uaudio0: Play: 48000 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 09:23:36 franky kernel: uaudio0: Play: 44100 Hz, 2 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 09:23:36 franky kernel: uaudio0: Record: 44100 Hz, 1 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 09:23:36 franky kernel: uaudio0: Record: 48000 Hz, 1 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 09:23:36 franky kernel: uaudio0: Record: 44100 Hz, 1 ch, 16-bit S-LE PCM format, 2x8ms buffer.
 May 15 09:23:36 franky kernel: uaudio0: No MIDI sequencer.
 May 15 09:23:36 franky kernel: pcm6: <USB audio> on uaudio0
 May 15 09:23:36 franky kernel: uaudio0: HID volume keys found.
 May 15 09:23:36 franky zhecka: USB Audio S / N: 140210000BB2 is attached
 May 15 09:23:38 franky zhecka: USB Audio S / N: 131014000129 detached
 May 15 09:23:38 franky kernel: uaudio1: at uhub7, port 4, addr 7 (disconnected)
 May 15 09:23:38 franky zhecka: USB Audio S / N: 131014000129 detached
 May 15 09:23:38 franky zhecka: Dropping dsp symlink for uaudio1


We dealt with the cards. Now it's the turn for the reproduction of all this happiness.
Form the playlist.xspf :
 <? xml version = "1.0" encoding = "UTF-8"?>
 <playlist version = "1" xmlns = "http://xspf.org/ns/0/" xmlns: vlc = "http://www.videolan.org/vlc/playlist/ns/0/">
         <title> AudioStreams </ title>
         <trackList>
                 <track>
                         <title> TV 1 </ title>
                         <location> udp: //@239.1.1.1: 5001 </ location>
                         <extension application = "http://www.videolan.org/vlc/playlist/0">
                                 <vlc: id> 1 </ vlc: id>
                                 <vlc: option> input-repeat = -1 </ vlc: option>
                         </ extension>
                 </ track>
                 <track>
                         <title> TV 2 </ title>
                         <location> udp: //@239.1.1.2: 5001 </ location>
                         <extension application = "http://www.videolan.org/vlc/playlist/0">
                                 <vlc: id> 2 </ vlc: id>
                                 <vlc: option> input-repeat = -1 </ vlc: option>
                         </ extension>
                 </ track>
                 <track>
                         <title> TV 3 </ title>
                         <location> udp: //@239.1.1.3: 5001 </ location>
                         <extension application = "http://www.videolan.org/vlc/playlist/0">
                                 <vlc: id> 3 </ vlc: id>
                                 <vlc: option> input-repeat = -1 </ vlc: option>
                         </ extension>
                 </ track>
         </ trackList>
 </ playlist>


Copy the lua vlc tree to / usr / local / www / vlc_http
Playlist put in /usr/local/www/vlc_http/playlists/Playlist.xspf

now run the cvlc package in the following config:
 vlc -vvv --sout-transcode-venc none --network-caching 50 --sout-mux-caching 50 -Aoss --oss-audio-device = / dev / uaudio.serial.131014000129 -I http --http- src = / usr / local / www / vlc_http --http-host = 192.168.5.2 --http-port = 8101 --http-password = mypass1 /usr/local/www/vlc_http/playlists/Playlist.xspf
 vlc -vvv --sout-transcode-venc none --network-caching 50 --sout-mux-caching 50 -Aoss --oss-audio-device = / dev / uaudio.serial.140210000BB2 -I http --http- src = / usr / local / www / vlc_http --http-host = 192.168.5.2 --http-port = 8102 --http-password = mypass1 /usr/local/www/vlc_http/playlists/Playlist.xspf


Next thing is small. Take examples from the http vlc controllers and make your own control pages. Fortunately there is a solid jquery and javascript.
In the main tree of the web server, we form a page where we integrate the controls of each of the streaming players in the iframe and open the case through the phone or tablet. The rest of the control logic is written in html and is not very complex.
Since we are not tied to the sources of sound, it gives great flexibility in the management of sound streams. It is possible to output the same stream for any acoustics from any media server, it is possible to swap streams, etc.

Now back to the USB audio cards, we still have microphone inputs to which we can produce sound from physical devices such as players, phones, microphones, etc. To connect to the microphone input line outputs from the players, you need to collect a simple voltage divider. Article on Habré again there. The incoming signal from the microphone input is also brought into the stream and broadcasts either to localhost or to the network.

Something like that. There will be questions - write.

Source: https://habr.com/ru/post/222905/


All Articles