viernes, 29 de diciembre de 2017

Grabación de audio en concursos (FFMPEG)


El, a mi juicio, principal concurso del calendario, el CQ WW, pone como requisito que las estaciones que lideren una determinada categoría, incluso a nivel continental (sección XII.C de las reglas), debe estar en condiciones de entregar a los organizadores registros de audio sobre la totalidad de la participación. Si no se entregan los registros el comité organizador puede aplicar una serie de medidas que pueden llegar incluso a la descalificación. Materia seria si las hay, y de hecho han descalificado estaciones por ese motivo en ediciones anteriores.

Que sepa es el único concurso importante del calendario internacional que tiene éste requisito, pero no sería de extrañar que otros concursos adopten medidas similares.
La medida se inscribe en el conjunto de iniciativas que los organizadores instrumentan para evaluar conductas que pudieran ser consideradas como fraudulentas. Es mucho lo que se puede debatir al respecto y poco lo que se puede lograr con ello.
Por eso, construyendo mi estación concursera decidí abordar éste requerimiento como uno mas para la estación viendo como se puede instrumentar de la mejor forma.
En los foros concurseros se dá como solución al problema utilizar el programa Audacity, pero algunas pruebas me permitieron encontrar que no cumple con algunos de los requerimientos, en particular la posibilidad de arrancarlo sin interacción mediante el procesador de comandos con un script batch.
Mi primer intento fue recurrir a algún dispositivo externo, pero para sorpresa de nadie no tengo ninguno adecuado. Algunos grabadores viejos, ya largamente mas allá de su vida útil, tenían la dificultad de una operación totalmente manual, cintas (¡cassettes!) que duran entre 60 y 90 minutos y la integración con los canales de audio. No hay una forma simple de referenciar cronológicamente las grabaciones tampoco, el primer intento fué entonces rápidamente abandonado.
El segundo intento fue revisar las opciones en dispositivos un poco mas modernos basados en estado sólido, una revisión rápida me permitió concluir que los dispositivos a mano tenían capacidad de muy poco tiempo y requerirían una interfaz compleja para controlar (sincronizar) la grabación y bajar los archivos que se pudieran ir generando.

El tercer intento fue, ya mas adecuado al resto de la estación utilizar una placa embebida Raspberry PI con ese propósito, la RBPI tiene capacidad de manejar audio, capacidad de red para eventualmente grabar los archivos en algun server de mi red y enorme cantidad de software disponible para el ambiente Linux. Justamente investigando el software disponible me topé con el paquete denominado FFMPEG que es una plataforma realmente enorme para manipular (crear, editar, transmitir, mezclar, transformar) imágenes y sonidos. El único problema que restaba solucionar era en ese punto como sincronizar la operación del programa con el resto de la configuración de concurso, por supuesto que se puede manejar un esquema RPC para ello, o un script con algun esquema de control via TCP/IP de otra índole. Pero no deja de ser un poco complicado y el volumen necesario es un poco mucho para una RBPI.

La solución estaba a la vista todo el tiempo, FFMPEG también tiene una versión para Windows, donde puede ser invocada desde un archivo batch con los argumentos apropiados para definir formatos, canales de entrada y canales de salida. Simplemente puede ser lanzado por el mismo script batch que lanza todos los programas de la configuración de concursos, incluyendo apagarlo cuando se apaga el logger (¿descanso?¿reboot?).
Dado que hay que proporcionar lo que escucha cada oido es necesario, en una configuración SO2R como la mia grabar los dos receptores, por lo que tengo una instancia corriendo de FFMPEG por cada canal como hilos separados. El llamado luce de la siguiente forma:

@ffmpeg -f dshow -y -t 00:01:00 -i audio="%AUDIO%" "%outfile%"

La variable AUDIO tiene el nombre del canal de entrada y la variable OUTFILE el archivo de salida donde se grabará el resultado.  Para saber el nombre de los canales de entrada puede usarse el comando

@ffmpeg -list_devices true -f dshow -i dummy

Con estos argumentos el programa graba por espacio de un minuto y finaliza, eso está hecho así para poder "cerrar" el archivo, mientras está grabando el archivo de salida está "abierto" y en caso de interrumpirse súbitamente la ejecución (corte de energía, colgada de la máquina, etc) no se podría recuperar lo que estuvo grabando. Uno no quiere grabar horas y perderlo por un accidente. ¿Porque un minuto? Bueno eso es arbitrario, puede usarse un período mayor, ¿2 minutos? ¿5 minutos?.
El mismo script que llama cuando termina revisa si está activo el logger y en caso de estarlo vuelve a llamar a FFMPEG por otro minuto, de no estarlo termina la ejecución.
Para que en cada ejecución no "pise" la anterior el nombre del archivo se genera en cada ciclo basado en la hora, es relativamente sencillo:

@Set outfile=.\AUDIOLOG_%CALLSIGN%_%CONTEST%_%RIG%_%date:~-2,2%%date:~-7,2%%date:~-10,2%_%time:~-11,2%%time:~-8,2%%time:~-5,2%%time:~-2,2%.mp3

Por lo que los archivos toman un nombre del estilo

AUDIOLOG_LU7DID_CQWW_R1_17122817020456.mp3

Los que se van almacenando en algún directorio que resulte conveniente, desde donde pueden ser respaldados periódicamente o pueden directamente ser grabados en un server remoto. En caso de algún accidente el peor problema es perder el último minuto en que el problema ocurrió.
Si bien se pueden optimizar los valores de grabado, cosa que seguramente seguiré explorando, toma aproximadamente 1 MByte/Minuto, o sea 2 MByte/minuto para los dos canales; para todo un concurso que puede durar 30 horas serán unos 3.6 GBytes de información al finalizar el concurso repartidas en unos 3600 archivos; no es poco, pero tampoco es una cifra que no se pueda manejar en una PC mas o menos actualizada. En caso que fueran requeridos se puede mandar un .ZIP con todos los archivos via espacio en la nube (DropBox o OneDrive por ejemplo).
Una forma de reducir drásticamente el tamaño de los archivos grabados es reducir el "samplerate" al cual se toma el audio:

@ffmpeg -f dshow -ar %SAMPLERATE% -y -t 00:01:00 -i audio="%AUDIO%" "%outfile%"

utilizando previamente

@Set SAMPLERATE=11025

En este caso los archivos generados son del orden de 300 KBytes por minuto, lo que requiere para todo el concurso y dos canales aproximadamente 1 GByte, lo que es un número mas accesible para máquinas pequeñas.

No hay comentarios:

Publicar un comentario