Alsa: audio loopbacks (o cómo capturar el audio que reproduzco)

Arco

Llevaba ya mucho tiempo sin escribir por aquí algo... y para desengrasarme un poco voy con una recetilla muy simple pero que puede ser de mucha utilidad: supongamos que entras en una página que reproduce audio mediante streaming y que quieres capturar ese audio. Si abres un programa de captura comprobarás que no se captura ese sonido... necesitamos algún tipo de tarjeta "virtual" que nos permita capturar lo que reproduce, esto es: audio loopback.

Instalando (quick'n'dirty)

Los señores de ALSA crearon hace tiempo un modulito que permitía justamente esto, el aloop, pero lamentáblemente no se compila por defecto, esto hace que distribuciones como Debian no lo traigan de serie, por tanto, nuestro primer paso es compilar el modulito.

Empezamos descargándonos el archivo alsa-drivers de ALSA FTP (el link es FTP pero el drupal lo cambia a HTTP porque es muy listo). Lo suyo sería que fuese el de la misma versión que tengamos en nuestro sistema. Si no sabéis qué versión usáis, ejecutad lo siguiente:
$ cat /proc/asound/version
Advanced Linux Sound Architecture Driver Version 1.0.16.

De todas formas, yo tengo la versión 1.0.16 y me he instalado el módulo en su versión 1.0.17 (porque era la que tenía a mano) y no he tenido warnings ni nada por el estilo...

Una vez descargado, descomprimimos y compilamos:
$ unp alsa-driver-1.0.16.tar.bz2
$ ./configure --with-cards=loopback --with-sequencer=yes
$ make

Ahora podríamos hacer un make install pero yo no lo hago por una sencilla razón: instala más módulos de los estrictamente necesarios. Para no "tocar" más de lo necesario hago lo siguiente (como root):
# cp drivers/snd-aloop.ko /lib/modules/$(uname -r)/kernel/sound/drivers/
# depmod -ae

Y ya está... ahora a saber cómo usarlo...

Instalando(Debian way)

[TO-DO]

Usando aloop

Lo primero es cargar el módulo:
# modprobe snd-aloop

Ahora configuramos la tarjeta (realmente este paso no es necesario para ciertas aplicaciones: las que usen alsa-lib, pero nunca está de más), para ello debemos saber qué tarjetas tenemos funcionando (esto ya lo podemos hacer como usuario):
$ cat /proc/asound/cards
0 [A5451 ]: ALI5451 - ALI 5451
ALI 5451 at 0x8400, irq 9
1 [pcsp ]: PC-Speaker - pcsp
Internal PC-Speaker at port 0x61
2 [Loopback ]: Loopback - Loopback
Loopback 1

Como podemos ver, la tarjeta virtual Loopback es la 2, esto nos permite escribir lo siguiente en el archivo ~/.asoundrc (si no existe lo creáis) y añadimos lo siguiente:

pcm.aloop {
	type hw
	card 2
}

ctl.aloop {
	type hw
	card 2
}

Con esto ya tenemos listos dos canales PCM, que en este caso serían (en nomenclatura ALSA): hw2,0 y hw2,1. Lo que reproduzcamos por uno de ellos, lo podremos capturar por el otro, lo único que hay que tener en cuenta es que el formato de captura debe coincidir con el del audio que se está reproduciendo.

Si queréis un ejemplo podéis hacer lo siguiente: capturamos uno de los extremos del loopback:
$ arecord -D hw:2,1 -c 2 test.wav

Y ahora podemos reproducir cualquier archivo (en estéreo, puesto que estamos capturando 2 canales), seleccionando dispositivo de reproducción hw:2,0:
$ aplay -D hw:2,0 music.wav

Y ya está.... así de fácil! Smiling

Rizando el rizo: múltiples tarjetas loopbacks

Bien, ya sabemos crear una tarjeta virtual con sus 8 subcanales PCM listos (si, no lo he comentado antes, pero mezcla hasta 8 canales), pero... ¿qué pasa si queremos más de una tarjeta loopback?. La solución es fácil: al cargar el módulo podemos especificar cuántas tarjetas virtuales queremos (hasta un máximo de ocho):
# rmmod snd-aloop
# modprobe snd-aloop index=2,3 enable=1,1 pcm_substreams=4

En el ejemplo anterior primero descargamos el módulo y después lo volvemos a cargar de la siguiente manera:

  • index: índices de las nuevas tarjetas a crear, esto es: las tarjetas loopback serán hw:2.x y hw:3.x.
  • enable: tarjetas virtuales a habilitar. Un 0 la deja deshabilitada y un 1 la activa (realmente no se para que sirve esto ya que no entiendo porqué alguien va a crear una tarjeta virtual que no pueda usar. Simplemente poned tantos unos como tarjetas vayáis a añadir).
  • pcm_substreams: número de subcanales que tendrá cada tarjeta virtual. En este caso serán 4 subcanales por tarjeta.

Enlaces

Aunque está un poco anticuada... la página de aloop module puede ser útil...

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

No me funciona :(

Tienes enlazado "ALSA FTP" como http y no funciona, deberías poner ftp://

Muy interesante esta receta, pero en Ubuntu Hardy me daba un error al hacer el make porque dice:
"alsa-driver-1.0.16/utils/patch-alsa: 24: patch: not found"

Esto es porque no tenía instalado patch, pero durante unos segundos me he quedado confuso hasta que me he dado cuenta de que no se refería al archivo "patch-alsa", si no al paquete "patch". Por defecto Ubuntu no instala "build-essential" y no lo había hecho antes.

Bueno, ya lo he hecho y he intentado reproducir en totem un vídeo y capturar el audio en Audacity, pero a pesar de que me aparecen los dispositivos, no graba nada.

A mi el loopback me lo pone como 1:

$ cat /proc/asound/cards
0 [Intel ]: HDA-Intel - HDA Intel
HDA Intel at 0xfc300000 irq 22
1 [Loopback ]: Loopback - Loopback
Loopback 1

Así que he puesto:

pcm.aloop {
type hw
card 1
}

ctl.aloop {
type hw
card 1
}

En Audacity me aparecen en dispositivos de grabación:
OSS: /dev/dsp1
ALSA: Loopback: Loopback PCM (hw:1,0)
ALSA: Loopback: Loopback PCM (hw:1,1)
ALSA: aloop
ALSA: default

Da igual el que use, no graba nada.

¿qué hago mal?

Imagen de int-0

Gracias por tus correcciones

El problema que tienes me ocurrió a mi y no es realmente un problema, símplemente que no entendimos bien cómo funciona el invento.

Debes capturar del siguiente dispositivo:

ALSA: Loopback: Loopback PCM (hw:1,1)

Pero cuando configures el dispositivo de reproducción de los otros programas, no debes seleccionar la tarjeta por defecto (en tu caso la HDA-Intel) sino que debes elegir la Loopback también, esto es:

ALSA: Loopback: Loopback PCM (hw:1,0)

Entonces verás que la captura ya se realiza correctamente Eye-wink.

Si el programa no te deja cambiar el dispositivo de reproducción, quizás lo puedas hacer en el gnome-sound-properties. Si así tampoco te funciona, puedes indicar a ALSA que tu tarjeta de reproducción por defecto es otra, para ello modifica el ~/.asoundrc añadiendo lo siguiente:

pcm.!default {
	type hw
	card 1
}

Eso indica a ALSA que la tarjeta por defecto es la 1 y no la 0.

De todas formas lo ideal sería que la reproducción fuese transparente, esto es, añadir opciones al ~/.asoundrc para que reproduzca por dos tarjetas a la vez: la nuestra por defecto y la loopback. Eso está en proceso. Sticking out tongue

------------------------------------------------------------
$ python -c "print 'VG9udG8gZWwgcXVlIGxvIGxlYSA6KQ==\n'.decode('base64')"
------------------------------------------------------------

sigue sin funcionar

Si configuro el xmms para que use hw:1,0 como salida, no se escucha nada (según entiendo eso es norma), el problema que al poner el audacity en hw:1,1 y darle a "grabar" me sale un error mientras abría el dispositivo de sonido. Si en cambio en el xmms pongo cualquier otra tarjetay en audacity la hw:1,1 el error no aparece, el programa empieza a grabar pero solo captura silencio.

¿alguna idea?

F.

Imagen de int-0

Comprueba la configuración de reproducción/captura

No se si lo digo por la receta, pero es importante (de hecho obligatorio) que la configuración del formato de audo de captura sea la misma que la configurada en la reproducción, es decir: si estás reproduciendo a 44000kHz, estéreo (2 canales) y formato 16BIT_LE (16 bits little endian), así es como debes configurar al audacity en la captura. De lo contrario obtendrás un error tal que "no se pudo abrir el dispositivo".

También puedes probar a poner primero el audacity a capturar; al hacer esto el loopback se configura con el formato de audio de captura. Después pones a reproducir el XMMS (configurando su salida con el mismo formato).

------------------------------------------------------------
$ python -c "print 'VG9udG8gZWwgcXVlIGxvIGxlYSA6KQ==\n'.decode('base64')"
------------------------------------------------------------

Ya me funciona, pero claro,

Ya me funciona, pero claro, la solución buena es lo que dices de usar los dos interfaces, porque si no, no oyes lo que estás grabando. Otra cosa es que hay que ejecutar el "modprobe snd-aloop" cada vez que arrancas, porque al reiniciar se descarga el loopback.

La solución de poner pcm.!default funciona bien, pero lógicamente deja de sonar todo, así que hay que ponerlo para grabar y luego quitarlo. El único reproductor de vídeo que he encontrado que funciona sin editar ~/.asoundrc, es mplayer.

Desde luego que hay otras formas de sacar el track de audio de un vídeo, pero algunas veces, por ejemplo con el navegador que ponías de ejemplo, es bastante tedioso.

Hay otra forma bastante interesante de hacer esto, usando Jack (http://jackaudio.org/faq), aunque claro, la aplicación que uses debe soportar Jack.

mas simple.. te vas al

mas simple..
te vas al alsamixer(ncurses) , le das F4, grabación y elijes de entrada Mix o Mix mono, y grabas lo que suena.

Imagen de int-0

Ciertamente...

...no has entendido nada sobre la receta. Tu "micro-receta" explica cómo cambiar el volumen de captura... ya me dirás en qué se parece eso en capturar, por ejemplo, lo que reproduces desde totem, o desde el navegador, etc. Si pulsando F4 en alsamixer (que el de texto no es ncurse, por cierto) consigues capturar en un WAV lo que reproduzcas desde el firefox (por ejemplo) entonces enhorabuena...

------------------------------------------------------------
$ python -c "print 'VG9udG8gZWwgcXVlIGxvIGxlYSA6KQ==\n'.decode('base64')"
------------------------------------------------------------