Dá pra gravar áudio da linha de comando? | O Gravador sem Cabeça #1

O Problema
- Eu tenho uma banda (🍪).
- Nós gostamos de nos gravar 🌚, áudio e vídeo.
- Nós temos uma mesa de som velha, com uma interface USB 🎚️.
- Nós temos um netbook velho de um núcleo, 32bits 💻.
- Nós queremos eventualmente gravar multipista com uma interface adicional, ou juntando várias pra fazer mixagens melhores 🎛️.
- Nós temos celulares pra gravar vídeos 📹.
- Eu tenho um aplicativo que comanda câmeras de celulares (android, apenas) 📱.
- Não sabemos se vai funcionar pois o netbook é bem antigo e lento. Sim, já quero inventar antes de testar.
Pois bem. Eu tenho um raspberry pi 3 sobrando 🍓.
Qual é o problema? Nenhum, eu quero inventar alguma coisa 😄.
As idéia
A ideia principal é: Um gravador portátil, simples de usar (pluga a(s) interface(s) e aperta gravar). E por gravar, eu entendo:
- Gravar áudio das interfaces
- Enviar o comando de gravação para as câmeras
Limitações
Se não me engano, temos ALSA (um sistema de áudio do Linux) por padrão no Raspberry Pi OS. Dá até pra agregar interfaces (pegar várias e transformar em uma interface só), mas também dá pra disparar vários processos do arecord (o programa gravador padrão do ALSA) pra gravar áudio de interfaces diferentes ao mesmo tempo, que parece mais simples.
Bom, o raspberry pi não tem tela, nem pretendo colocar. Botões talvez sejam uma boa ideia, mas, pelo menos inicialmente, vou precisar de mais controle, até porque vou estar explorando, né?.
Se não tem tela, não tem interface gráfica. Daria até pra rodar um Reaper e tentar fazer alguma mágica, mas acho que temos soluções mais simples, pelo menos por enquanto. Provavelmente vou pelo caminho de interface web pra comandar por um celular ou tablet.
E daí vem o nome desse projeto. Normalmente chamamos algo que não tem uma interface direta (nesse caso, uma tela) de headless, ou sem cabeça.
Pra acessar a interface web, eu vou precisar conectar no pi num ambiente potencialmente sem rede, então vou ter que sacrificar o WiFi do Pi pra criar um hot spot onde o controlador vai conectar. Não é muito diferente de como as mesas de som digitais funcionam.
Para as câmeras tem o meu projeto citado acima, mas o mais importante é o áudio. Mais importante ainda é:
Dado um Raspberry Pi 3B com uma interface de áudio conectada, eu consigo conectar diretamente nele via WiFi com um tablet e enviar comandos pra gravar áudio?
Protótipo
Vamos lá.
Tenho algumas coisas pra testar.
- Consigo gravar de uma interface de áudio usando arecord?
- Consigo gravar de duas interfaces de áudio simultaneamente usando arecord?
- Consigo usar um serviço web pra disparar a gravação?
- Consigo conectar e enviar os comandos acima diretamente no pi como um hot spot?
Mão na massa
Vamos tentar riscar o primeiro item.
Reinstalei o Pi e pluguei minha interface numa das portas USB. Vamos ver se o ALSA detectou.
Eu sei que existe um comando pra gravar áudio direto da linha de comando, que faz parte da “caixa de ferramentas” do ALSA, chamado arecord.
Bora tentar:
raphaelpaiva@hr:~ $ arecord
Usage: arecord [OPTION]... [FILE]...
-h, --help help
--version print current version
-l, --list-devices list all soundcards and digital audio devices
-L, --list-pcms list device names
-D, --device=NAME select PCM by name
-q, --quiet quiet mode
-t, --file-type TYPE file type (voc, wav, raw or au)
-c, --channels=# channels
-f, --format=FORMAT sample format (case insensitive)
-r, --rate=# sample rate
-d, --duration=# interrupt after # seconds
-s, --samples=# interrupt after # samples per channel
-M, --mmap mmap stream
-N, --nonblock nonblocking mode
-F, --period-time=# distance between interrupts is # microseconds
-B, --buffer-time=# buffer duration is # microseconds
--period-size=# distance between interrupts is # frames
--buffer-size=# buffer duration is # frames
-A, --avail-min=# min available space for wakeup is # microseconds
-R, --start-delay=# delay for automatic PCM start is # microseconds
(relative to buffer size if <= 0)
-T, --stop-delay=# delay for automatic PCM stop is # microseconds from xrun
-v, --verbose show PCM structure and setup (accumulative)
-V, --vumeter=TYPE enable VU meter (TYPE: mono or stereo)
-I, --separate-channels one file for each channel
-i, --interactive allow interactive operation from stdin
-m, --chmap=ch1,ch2,.. Give the channel map to override or follow
--disable-resample disable automatic rate resample
--disable-channels disable automatic channel conversions
--disable-format disable automatic format conversions
--disable-softvol disable software volume control (softvol)
--test-position test ring buffer position
--test-coef=# test coefficient for ring buffer position (default 8)
expression for validation is: coef * (buffer_size / 2)
--test-nowait do not wait for ring buffer - eats whole CPU
--max-file-time=# start another output file when the old file has recorded
for this many seconds
--process-id-file write the process ID here
--use-strftime apply the strftime facility to the output file name
--dump-hw-params dump hw_params of the device
--fatal-errors treat all errors as fatal
Recognized sample formats are: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE IEC958_SUBFRAME_LE IEC958_SUBFRAME_BE MU_LAW A_LAW IMA_ADPCM MPEG GSM S20_LE S20_BE U20_LE U20_BE SPECIAL S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE U18_3BE G723_24 G723_24_1B G723_40 G723_40_1B DSD_U8 DSD_U16_LE DSD_U32_LE DSD_U16_BE DSD_U32_BE
Some of these may not be available on selected hardware
The available format shortcuts are:
-f cd (16 bit little endian, 44100, stereo)
-f cdr (16 bit big endian, 44100, stereo)
-f dat (16 bit little endian, 48000, stereo)
Ele me chamou de burro de forma educada.
Usage: arecord [OPTION]... [FILE]... me diz como usar esse comando. Eu tenho que passar pra ele opções (pelo menos uma) ou arquivos (pelo menos um).
Vamos tentar passar um arquivo qualquer, deve ser o arquivo de destino da gravação.
raphaelpaiva@hr:~ $ arecord opa.wav
arecord: main:830: audio open error: No such file or directory
Ok, erro ao abrir o áudio. Soa até meio estranho. Como no Linux tudo é representado por um arquivo, inclusive a minha interface de áudio, eu suspeito que ele não tenha conseguido abrir o dispositivo de áudio. Talvez tenhamos que informar o arecord de qual interface eu quero gravar. Vai que tem mais de uma.
Da saída ali em cima, onde as opções foram listadas, algumas chamaram minha atenção. A primeira delas foi
-l, --list-devices list all soundcards and digital audio devices
Bora lá tentar passar essa opção então!
raphaelpaiva@hr:~ $ arecord -l
**** List of CAPTURE Hardware Devices ****
card 2: CODEC [USB Audio CODEC], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
Opa! Essa saída significa que ele detectou um dispositivo de saída.
Traduzindo:
card 2: CODEC [USB Audio CODEC], device 0: USB Audio [USB Audio]- Esse dispositivo está na placa número 2 (
card 2). - O nome dessa placa é
CODEC [USB Audio CODEC]. - O dispositivo de saída é o primeiro dispositivo desta placa (
device 0). - O nome dele é
USB Audio [USB Audio].
- Esse dispositivo está na placa número 2 (
Subdevices: 1/1- Ele tem um sub-dispositivo
Subdevice #0: subdevice #0- Este sub-dispositivo é o número 0
Entendeu? Eu também não, mas já deu pra sacar que o ALSA faz referência dos dispositivos por números ou por nomes.
Do manual do ALSA, tem uma outra opção interessante:
-L, --list-pcms
List all PCMs defined
Que diabos é um PCM? É uma sigla pra Pulse-code modulation, ou uma das formas que um computador pode “ouvir”. No contexto do ALSA, PCM é o que vem do seu dispositivo de captura, ou seja, essa opção lista as fontes de áudio disponíveis.
Vou escrever sobre PCM depois, é muito interessante, mas não vale alongar aqui.
raphaelpaiva@hr:~ $ arecord -L
null
Discard all samples (playback) or generate zero samples (capture)
hw:CARD=CODEC,DEV=0
USB Audio CODEC, USB Audio
Direct hardware device without any conversions
plughw:CARD=CODEC,DEV=0
USB Audio CODEC, USB Audio
Hardware device with all software conversions
default:CARD=CODEC
USB Audio CODEC, USB Audio
Default Audio Device
sysdefault:CARD=CODEC
USB Audio CODEC, USB Audio
Default Audio Device
front:CARD=CODEC,DEV=0
USB Audio CODEC, USB Audio
Front output / input
dsnoop:CARD=CODEC,DEV=0
USB Audio CODEC, USB Audio
Direct sample snooping device
Temos um pouco mais de informação dessa opção do arecord. Duas seções saltam aos olhos:
hw:CARD=CODEC,DEV=0
USB Audio CODEC, USB Audio
Direct hardware device without any conversions
plughw:CARD=CODEC,DEV=0
USB Audio CODEC, USB Audio
Hardware device with all software conversions
Parece que temos acesso ao dado direto do hardware com o hw: e acesso ao dado tratado com o plughw:. Que diferença isso faz? Sei lá. Vou chutar que podem rolar umas conversões de formato e taxa de amostragem, mas tem uma outra coisa mais importante:
hw:CARD=CODEC,DEV=0 tem muita cara de ser um identificador de dispositivo. CODEC é o nome da placa que vimos na saída do arecord -l e 0 é o número do dispositivo, então hw:CARD=CODEC,DEV=0 deve significar a fonte de áudio direto do hardware que vem da placa CODEC, dispositivo 0. Da mesma forma, plughw:CARD=CODEC,DEV=0 deve significar a mesma fonte de áudio, mas com conversões de software, seja lá o que isso signifique.
A tradução do resto da saída do arecord -L fica como exercício para o leitor 😄.
Uma terceira opção que chamou atenção foi a seguinte:
-D, --device=NAME select PCM by name
Tá com toda cara que é com essa opção que eu digo qual é a interface que eu quero utilizar. Resta saber se vamos de hw: ou plughw:. Como o plughw: faz conversões, ele parece ser a aposta mais segura.
Vamo lá
raphaelpaiva@hr:~ $ arecord -Dplughw:CARD=CODEC,DEV=0 opa.wav
Recording WAVE 'opa.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
Parece que tá gravando!
Como eu não sabia parar, meti um ctrl+C mesmo (padrão para abortar programas na linha de comando) e vamos ver no que deu.
Se não apareceu o áudio, ouve aí a alegra do nerdola
Parece até o áudio do Yuri Gagarin com essa qualidade tosca. Tudo bem, com 8 bits de resolução e uma taxa de amostragem de 8kHz não dá pra esperar muita coisa.
Vamos ver se dá pra melhorar isso, mas eu estou curioso pra saber o que vem se eu usar o hw:.
raphaelpaiva@hr:~ $ arecord -Dhw:CARD=CODEC,DEV=0 opa.wav
Recording WAVE 'opa.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
arecord: set_params:1343: Sample format non available
Available formats:
- S8
- S16_LE
Opa! Eu gosto de erro assim. Que diz o que eu fiz de errado e ainda diz como consertar:
arecord: set_params:1343: Sample format non available
Available formats:
- S8
- S16_LE
Então eu tenho que especificar o formato da amostra. Lá da primeira saída do programa, dá pra ver como e ainda tem algumas opções interessantes pra controlar a qualidade e duração.
-c, --channels=# channels
-f, --format=FORMAT sample format (case insensitive)
-r, --rate=# sample rate
-d, --duration=# interrupt after # seconds
Vamos mexer só no formato por enquanto, que foi o que ele reclamou.
raphaelpaiva@hr:~ $ arecord -Dhw:CARD=CODEC,DEV=0 -f S16_LE opa.wav
Recording WAVE 'opa.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Mono
Warning: rate is not accurate (requested = 8000Hz, got = 11025Hz)
please, try the plug plugin
Deu um warning, mas gravou. Vou chorar 😭.
Reparou que a qualidade parece bem melhor? Esse foi o salto de 8bits/8000Hz pra 16bits/11025Hz. Brabo.
Vou escrever sobre o que esses número significam, mas calma.
Vamos brincar um pouco com os outros parâmetros.
Eu quero gravar um áudio de 5 segundos, 16bits, 44100Hz e usando todos os 2 canais da interface. Vou plugar minha guitarra no segundo canal e bora ver se vai sair fumaça.
arecord -Dhw:CARD=CODEC,DEV=0 -d 5 -f S16_LE -r 44100 -c 2 opa.wav
Recording WAVE 'opa.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
Ai papai! Emocionado. Ouve aí!.
Conclusão
Dá, hein!
Vimos como gravar áudio de uma interface de áudio via linha de comando usando o ALSA, sistema de som padrão no Raspberry Pi OS.
Na próxima etapa vamos ver se conseguimos gravar de duas interfaces simultaneamente.
Segue o pai!
Dedico esse posto ao nut da minha guitarra que quebrou durante essa gravação. Não coloque si no lugar da mizinha, viu?