Manipolazione file audio da command line, alcuni esempi

Della serie “Il potere della Linea di Comando” o anche “May the force (of the Command Line) be with you” vediamo come manipolare file audio da linea di comando tramite le utility che si possono trovare sui sistemi GNU/Linux.

In particolare, i tool utilizzati oggi sono:

  • cuetools: “set of utilities for working with Cue Sheet (cue) and Table of Contents (toc) files“.
  • shntool: “multi-purpose tool for manipulating and analyzing WAV files”
  • vorbis-tools: comandi vari per la generazione e manipolazione di file OGG

Obiettivo: dato un album contenuto in un unico file in formato FLAC e indicizzato tramite un file CUE, generare un file OGG per ogni traccia.

L’operazione è composta da due fasi:

  • Dividere il file FLAC in tanti file, uno per traccia
  • Convertire i file ottenuti in OGG cercando di inserire anche qualche tag estratto dal CUE

Prima proposta di soluzione (semplice ma sbagliata)

Passo (1): Generazione di tanti file WAV uno per traccia dandogli come nome split-trackNN.wav dove NN è il numero della traccia.

$ cuebreakpoints cue_file.cue | shnsplit audio_file.flac

Passo (2): conversione in formato OGG.

$ oggenc *.wav

Per fare tutto con un unico comando è anche possibile dire a shnsplit di effettuare direttamente la conversione in OGG:

$ cuebreakpoints cue_file.cue | shnsplit -o 'cust ext=ogg oggenc - -o %f' audio_file.flac

con questo comando si creano direttamente i file split-trackNN.ogg.

Seconda soluzione (leggermente più complicata, ma migliore)

Un metodo alternativo per leggere il file CUE consiste nel farlo leggere direttamente al comando shnsplit tramite l’opzione -f. In questo modo il comando cuebreakpoints non è più necessario e soprattutto, come vedremo, sarà facile dare ai file generati un nome più significativo.

Il comando è:

$ shnsplit -o 'cust ext=ogg oggenc - -o %f' -f cue_file.cue audio_file.flac

NOTA: Un problema minore di questo modo di lavorare è che, almeno in alcuni casi, viene creato anche un file di indice 00 che contiene un “pre-gap”. Di fatto è un file molto breve senza audio. Non ho trovato un modo per evitare di generarlo, per cui se viene creato va semplicemente cancellato dopo la conversione.

Il grosso vantaggio dell’opzione -f è invece che leggendo il file CUE direttamente è possibile nominare i file che vengono creati in modo automatico utilizzando le informazioni di traccia presenti nel file CUE. L’opzione da utilizzare è -t.

Per esempio per creare i file nel formato NN_-_TrackTitle.ogg (NN = track number) si può utilizzare il seguente comando:

$ shnsplit -o 'cust ext=ogg oggenc - -o %f' -t "%n_-_%t" -f cue_file.cue audio_file.flac

Se si vuole, si può anche utilizzare l’opzione -m per evitare l’uso di caratteri speciali nei nomi di file. Per esempio, per utilizzare il carattere underscore al posto degli spazi si può dare il seguente comando:

$ shnsplit -o 'cust ext=ogg oggenc - -o %f' -t "%n_-_%t" -m \ _ -f cue_file.cue audio_file.flac

Come inserire i tag nei file OGG

Vediamo infine come inserire le informazioni di album e traccia (tag) nei file OGG generati. E’ tutto molto semplice, basta utilizzare il comando cuetag:

$ cuetag cue_file.cue *.ogg

N.B: per evitare di avere errori ricordarsi di cancellare il file pregap di indice 00 eventualmente creato da shnsplit.

Per controllare il valore dei tag inserito nei file OGG si può utilizzare il comando vorbiscomment.

$ vorbiscomment file_ogg.ogg

CREDITS: Siti consultati:

Un potente programma per effettuare backup: rsync

Un ringraziamento preventivo a Matteo, che a suo tempo, in un progetto in cui lavoravamo insieme, si occupò di determinare le migliori opzioni da utilizzare con il comando rsync per l’implementazione delle operazioni descritte in questo articolo.

Una delle utility più interessanti per effettuare copia di file, sincronizzazione di directory e backup nell’ecosistema GNU/Linux è il programma rsync. Come molto spesso capita, dietro l’apparenza banale di una utility command line si nasconde un programma molto potente che laconicamente si autodefinisce “a fast, versatile, remote (and local) file-copying tool“.

In questo articolo si dimostrerà come utilizzare la funzionalità di sincronizzazione tra directory offerta dal programma per copiare il contenuto di una directory in una seconda area. L’applicazione è ovvia: effettuare il backup della prima directory (che nel seguito chiameremo “primaria”) nella seconda (definita “secondaria”).

Per rendere più interessante la dimostrazione supporremo che le due directory risiedano su due PC diversi (ma le stesse operazioni possono essere effettuate anche con le due aree poste sullo stesso PC). Naturalmente occorre che i due PC siano connessi in rete possibilmente senza firewall nel mezzo che potrebbero bloccare le porte necessarie a rsync per lavorare.

La configurazione rsync scelta è quella client-server:

  • lato directory primaria si manterrà il programma in esecuzione come demone (server) pronto a rispondere alle interrogazioni dei client
  • lato directory secondaria si lancerà il comando da linea di comando (client); al termine di ogni sincronizzazione il programma esce.

Nel seguito indicheremo ip_server l’indirizzo IP del server e con ip_client quello del client.

Installazione

Normalmente rsync è già presente di default sulle più diffuse distribuzioni GNU/Linux. Nel caso non fosse presente, installarlo seguendo le procedure standard della distribuzione. Per esempio su Debian/Ubuntu e derivati dare il comando:

sudo apt-get install rsync

Configurazione e startup demone lato server

Per prima cosa definiamo la directory di cui si vuol effettuare il backup. Supponiamo sia /home/user/workarea. Supponiamo che al suo interno sia presente un unico file di nome foo.bar.

Come seconda cosa occorre preparare il file di configurazione per il server rsync. Supponiamo sia /home/user/rsyncd.conf. Nel nostro esempio il suo contenuto deve essere il seguente:

[WorkArea]
path=/home/user/workarea/
log=/home/user/logs/rsyncd.log
max verbosity

A questo punto per lanciare il server il comando da dare è il seguente:


user@host:~$ sudo rsync --daemon --config=/home/user/rsyncd.conf
user@host:~$ _

Se si controlla con il comando ps si vedrà il server in esecuzione.

Sincronizzazione lato client

Prima di effettuare la sincronizzazione vera e propria può essere utile lanciare il comando in modalità “dry-run”: si interroga il server per capire se deve essere effettuata un’operazione di sincronizzazione, cioè se lato server ci sono dei file nuovi o se alcuni file sono stati modificati. Per effettuare l’operazione il comando da dare è il seguente:


user@host:~$ rsync --dry-run -v --force --delete -a --port=873 <ip_server>::WorkArea workarea_backup
created directory workarea_backup
./
foo.bar
sent 36 bytes received 77 bytes 226.00 bytes/sec
total size is 56 speedup is 0.50 (DRY RUN)

Dall’output del comando si capisce che c’è la directory root della workarea modificata e il file foo.bar  modificato. Si capisce anche che verrebbe creata la directory di destinazione del backup, workarea_backup. Vediamo nel dettaglio il significato dei parametri utilizzati:

  • --dry-run: non effettua alcuna operazione, mostra solo le operazioni che verrebbero effettuate se non ci fosse questa opzione
  • -v: aumenta la verbosità delle informazioni mostrate a schermo
  • --force: forza la cancellazione delle directory non più esistenti anche se non vuote
  • --delete: se da server sono stati cancellati dei file ancora presenti nell’area di backup (come risultato di una precedente sincronizzazione), questi vengono cancellati
  • --port=873: cerca il server sulla porta 873 (la porta standard del comando rsync)
  • <ip_server>::WorkArea: indirizzo IP del server e “stanza” del file di configurazione con le informazioni dell’area da sincronizzare
  • workarea_backup: directory locale dove salvare il contenuto della sincronizzazione. Da notare che il contenuto di questa directory viene modificato in modo da rispecchiare il contenuto dell’area sul server, per cui eventuali file estranei verrebbero cancellati.

A questo punto, per effettuare la sincronizzazione ripetere il comando senza l’opzione –dry-run:

user@host:~$ rsync -v --force --delete -a --port=873 <ip_server>::WorkArea workarea_backup
created directory workarea_backup
./
foo.bar
sent 36 bytes received 77 bytes 226.00 bytes/sec
total size is 56 speedup is 0.50 (DRY RUN)

Verificare il contenuto della directory workarea_backup: adesso contiene il file foo.bar presente sul server.

D’ora in avanti, per mantenere aggiornata la directory di backup, basterà ripetere periodicamente il comando sul client.

Bonus track: uso di netcat per controllare lo stato di una porta

Infine un “bonus track” per vedere come lato client si può utilizzare la utility netcat per controllare se il server è attivo. Questo può essere utile soprattutto in script per controllare che il server sia presente prima di inoltrare i comandi visti in precedenza.

Come dice la sua manpage, “The nc (or netcat) utility is used for just about anything under the sun involving TCP or UDP“. In questo caso noi la useremo dal client per controllare che il server rsync sia in esecuzione. La porta su cui sta in ascolto il server rsync è la 873. Il comando netcat da dare per controllare se il server è attivo è il seguente:

user@host:~$ nc -z -n -w 1 <ip_server> 873
user@host:~$ _

Il significato delle opzioni è il seguente:

  • -z: effettua uno scan della porta senza inviare pacchetti
  • -n: non usa DNS
  • -w 1: imposta il timeout di attesa della risposta a 1 secondo

Il comando come spesso capita sulla command line di sistemi GNU/Linux, laconicamente, non scrive niente. Per controllare l’esito dell’interrogazione occorre verificare il valore ritornato dal comando tramite l’analisi della variabile $?. Se il valore di questa variabile è 0 vuol dire che il server è attivo (qualcuno è in ascolto sulla porta 873), altrimenti il server non risponde (nessuno è in ascolto sulla porta 873.

L’analisi della valore di ritorno del comando nc può essere fatto tramite il comando echo:

user@host:~$ echo $?
0
user@host:~$ _

o tramite, per esempio, tramite il seguente snippet di codice bash:

nc -z -n -w 1 <ip_server> 873
if [ $? -eq 0 ]; then
echo "rsync server is running!"
else
echo "rsync server not running"
fi