樹莓派 3A+ 好好玩︰樂直播 《四》

故爾假借

ReSpeaker 4-Mic Array for Raspberry Pi

Introduction

ReSpeaker 4-Mic Array for Raspberry Pi is a quad-microphone expansion board for Raspberry Pi designed for AI and voice applications. This means that we can build a more powerful and flexible voice product that integrates Amazon Alexa Voice Service, Google Assistant, and so on.

談點

Asoundrc

Why asoundrc?

What is it good for, why do I want one?

Neither the user-side .asoundrc nor the asound.conf configuration files are required for ALSA to work properly. Most applications will work without them. These files are used to allow extra functionality, such as routing and sample-rate conversion, through the alsa-lib layer. The actual reason that most applications will work without these user-side custom config files is that usually a default install of alsa-lib provides a sufficiently capable setup consisting of hierarchical config files (which always make use of the standard .asoundrc format syntax as well), which are specifically capable of supporting certain soundcard brands each. Thus, let’s start with a quick overview of how ALSA config file framework evaluation is composed, globally:

Global view of ALSA config file framework, executive summary

The alsa-lib package (at least on Debian libasound2-data 1.0.27) provides the /usr/share/alsa/alsa.conf file as the main entry point. That file is responsible for including the full list of potential .asoundrc-format-type files on the system. It contains a reference to the ALSA “DATADIR” (Debian: /usr/share/alsa/). It continues by loading the DATADIR’s cards/aliases.conf file: that one defines translation mappings from the kernel driver’s sound card name (as listed at /proc/asound/cards, or aplay -Ll) to a “more detailed” description string. That “more detailed name” of a sound card then gets used to lookup a corresponding card-specific config file at DATADIR/cards/CARD.conf. And THAT card-specific file then attempts to provide a maximally elegant sound setup for its specific card brand, by compensating for various limitations of cards (e.g. use dmix to combat single-stream playback only, or stereo downmix to lessen a mono-output-only restriction). Finally (to support those cases where the standard setup of a soundcard is deficient/lacking, or custom plugin setup is desired), alsa.conf loads a system-global custom settings file /etc/asound.conf and a per-user custom settings file ~/.asoundrc.

So, the objective should be to achieve having the common alsa-lib configuration file framework enhanced by default in the best possible manner for each specific soundcard brand, to avoid the need of creating manually customized config files in all standard cases.

With this global overview done and cared for, let’s have a look at the actual configuration format of alsa-lib files.

……

Further reading

───

!!

─── 《【鼎革‧革鼎】︰ RASPBIAN STRETCH 《六之 H 》

 

承上篇,當看到

2018-12-10 16:28:39,609 [ERROR ] – pylive/ALSACapture.cpp:34
cannot open audio device: default error:No such file or directory

訊息時,一時狐疑莫非 USB MIC 壞掉耶?

察了以後︰

pi@raspberrypi:~ arecord -l **** List of CAPTURE Hardware Devices **** card 1: Device [USB PnP Sound Device], device 0: USB Audio [USB Audio]   Subdevices: 1/1   Subdevice #0: subdevice #0 </pre>    <span style="color: #666699;">分明好好的呦!</span>  <span style="color: #666699;">細究之下,發現新版系統沒有任何 asound 設定檔,故沒有所謂『default』名義,所以需用全名也︰</span> <pre class="lang:default decode:true ">pi@raspberrypi:~ arecord -L
null
    Discard all samples (playback) or generate zero samples (capture)
default:CARD=Device
    USB PnP Sound Device, USB Audio
    Default Audio Device
sysdefault:CARD=Device
    USB PnP Sound Device, USB Audio
    Default Audio Device
front:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    Front speakers
surround21:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    2.1 Surround output to Front and Subwoofer speakers
surround40:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    4.0 Surround output to Front and Rear speakers
surround41:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    4.1 Surround output to Front, Rear and Subwoofer speakers
surround50:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    5.0 Surround output to Front, Center and Rear speakers
surround51:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    5.1 Surround output to Front, Center, Rear and Subwoofer speakers
surround71:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    7.1 Surround output to Front, Center, Side, Rear and Woofer speakers
iec958:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    IEC958 (S/PDIF) Digital Audio Output
dmix:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    Direct sample mixing device
dsnoop:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    Direct sample snooping device
hw:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    Direct hardware device without any conversions
plughw:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    Hardware device with all software conversions

 

因此將 tests.py 內的『audioDev=’default’』改之為

『ausioDev=’default:CARD=1’』︰

pi@raspberrypi:~/pysdk-live/tests cat test-av.py  import os from multiprocessing import Process, Queue from pylive import live from pyuvc import uvc   DEV = '/dev/video0' STREAM_NUM = 4 BASE_RTSP_PORT = 8554 IMG_WIDTH = 1280 IMG_HEIGHT = 720 STREAM_DATA_LIST = []   class Capture:      def __init__(self):         params = {             'width': IMG_WIDTH,             'height': IMG_HEIGHT,             'fps': 30,             'fmt_type': uvc.H264             }         print('Start capture: %s' % DEV)         r = uvc.open(             fd=DEV,             **params             )         if r != 0:             print('Open capture failed, test exit(%d)' % r)             os._exit(0)      def init_stream_list(self):         for _ in range(STREAM_NUM):             STREAM_DATA_LIST.append(Queue())      def start_stream_loop(self):         while 1:             data = uvc.get_frame()             for i in STREAM_DATA_LIST:                 i.put(data)   class Live:      def __init__(self, i):         self._i = i      def _live_loop(self):         data_factory = STREAM_DATA_LIST[self._i]          def callback():             return data_factory.get()          live.start(             url='unicast',             width=IMG_WIDTH,             height=IMG_HEIGHT,             bufferSize=uvc.get_buffer_size(),             callback=callback,             # fd=uvc.get_fd(),             # queueSize=10,             rtspPort=BASE_RTSP_PORT+self._i,             # user='admin',             # passwd='admin',             # audioDev='default',             # audioFreq=44100,             # audioNbChannels=2,             # murl='multicast',             # rtspOverHTTPPort=8080             )      def start_live_loop_thread(self):         print('start live loop process: %d' % self._i)         p = Process(target=self._live_loop)         p.daemon = True         p.start()   def test_multi():     c = Capture()     c.init_stream_list()     for i in range(STREAM_NUM):         Live(i).start_live_loop_thread()     c.start_stream_loop()   def test_base():      def callback():         return uvc.get_frame()      Capture()     live.start(         url='unicast',         width=IMG_WIDTH,         height=IMG_HEIGHT,         bufferSize=uvc.get_buffer_size(),         callback=callback,         # fd=uvc.get_fd(),         # queueSize=10,         rtspPort=8554,         # user='admin',         # passwd='admin',         audioDev='default:CARD=1',         # audioFreq=44100,         # audioNbChannels=2,         # audioFmt='S16_BE',         # murl='multicast',         # rtspOverHTTPPort=8080         )   if __name__ == '__main__':     test_base()     # test_multi() </pre>    <span style="color: #666699;">果然一切 OK 矣☆</span> <pre class="lang:default decode:true ">pi@raspberrypi:~/pysdk-live/tests python3 test-av.py 
Start capture: /dev/video0
PYUVC version: 0.3
frame size: 1280*720
frame rate: 30
fmt type: 875967048
Driver: "bm2835 mmal"
Card: "mmal service 16.1"
Bus: "platform:bcm2835-v4l2"
Version: 1.0
Capabilities: 85200005
Input: 0
V4L2 pixel formats:
0: [0x32315559] 'YU12' (Planar YUV 4:2:0)
1: [0x56595559] 'YUYV' (YUYV 4:2:2)
2: [0x33424752] 'RGB3' (24-bit RGB 8-8-8)
3: [0x4745504A] 'JPEG' (JFIF JPEG)
4: [0x34363248] 'H264' (H.264)
5: [0x47504A4D] 'MJPG' (Motion-JPEG)
6: [0x55595659] 'YVYU' (YVYU 4:2:2)
7: [0x59555956] 'VYUY' (VYUY 4:2:2)
8: [0x59565955] 'UYVY' (UYVY 4:2:2)
9: [0x3231564E] 'NV12' (Y/CbCr 4:2:0)
10: [0x33524742] 'BGR3' (24-bit BGR 8-8-8)
11: [0x32315659] 'YV12' (Planar YVU 4:2:0)
12: [0x3132564E] 'NV21' (Y/CrCb 4:2:0)
13: [0x34524742] 'BGR4' (32-bit BGRA/X 8-8-8-8)
PYLIVE version: 0.3
unicast url: unicast
Number of frame queue(queueSize): 10
rtspPort: 8554
rtspOverHTTPPort: 0
verbose(0,1,2): 0
RTCP expiration timeout in seconds(timeout): 65
repeat config before IDR frame(repeatConfig): 1
audioFreq: 44100
audioNbChannels: 2
audioFmt(default S16_BE): 2018-12-10 16:36:30,827 [NOTICE] - pylive/LibLive.cpp:229
	Create ALSA Source...default:CARD=1
2018-12-10 16:36:30,827 [NOTICE] - pylive/DeviceSource.cpp:63
	begin thread
2018-12-10 16:36:30,827 [NOTICE] - pylive/ALSACapture.cpp:27
	Open ALSA device: "default:CARD=1"
2018-12-10 16:36:30,827 [NOTICE] - pylive/H264_V4l2DeviceSource.cpp:48
	profile-level-id=640028;sprop-parameter-sets=J2QAKKwrQCgC3QDxImo=,KO4CXLA=
2018-12-10 16:36:30,875 [NOTICE] - pylive/ALSACapture.cpp:83
	ALSA device: "default:CARD=1" buffer_size:15052 period_size:940 rate:44100
2018-12-10 16:36:30,876 [NOTICE] - pylive/DeviceSource.cpp:63
	begin thread
2018-12-10 16:36:30,879 [NOTICE] - pylive/LibLive.cpp:98
	Play this stream using the URL "rtsp://192.168.11.12:8554/unicast"