Registrare con Fedora usando ffpmeg
Sono speaker in una web radio (per vostra info https://www.radiocittaperta.it,ogni lunedì) e quello che sto cercando di ottenere è qualcosa che:
- Crea un podcast per ogni trasmissione, data l’ora di inizio e di fine
- Consenta allo speaker di avviare e interrompere manualmente una registrazione della trasmissione
- Abilita lo speaker a scegliere se sovrascrivere o meno la registrazione automatica
- Caricare sul sito web il podcast
- Crea la pagina con il podcast
Questi sono compiti abbastanza complicati da svolgere per una singola risorsa IT, ma Roma non è stata costruita in un giorno. Questo post riguarda la registrazione dello streaming audio dalla linea di input della scheda audio collegata, utilizzando una pagina Web per avviare e interrompere la registrazione. Prima di tutto la radio ha due computer con Fedora, sono configurati come gemelli, solo per ridondanza. Nell’installazione di apache ho installato anche un’installazione base di wordpress, questo mi dà le funzionalità di un CMS (accesso utente, password persa, gestione dei plugin) in modo da concentrarmi solo sui requisiti. Ho creato un plugin wordpress con un semplice pulsante frontend: Start --> Stop
Il comportamento segue questo percorso https://trac.ffmpeg.org/wiki/PHP :
- php avvia un record usando ffmpeg in background
- il pid del processo viene salvato nel database
- sul lato client (javascript nel browser) una richiesta ajax controlla se il processo è ancora attivo
- il pulsante di arresto interrompe il processo utilizzando il numero pid (“kill -9 <pid#>”)
Ci sono diversi punti dolenti da tenere in considerazione quando si utilizza questo approccio: ho iniziato con il comando arecord e pipe con la libreria lame per salvare i file mp3, ma sembra che arecord possa essere eseguito solo una volta per risorsa (risorsa = scheda audio) e anche ha un problema che non so perché: si ferma dopo 1h 33m (ref. http://stackoverflow.com/questions/42457839/recording-with-arecord-stops-after-1h-33m-under-fedora-23 ), quindi sono passato a ffmpeg. L’utente Apache non è stato in grado di utilizzare l’audio. Questa è una limitazione sulla maggior parte della distribuzione, ho dovuto aggiungere l’utente apache ai gruppi: audio,pulse,pulse-access e ho aggiunto anche gruppi video (non so se è necessario) comando è: usermod -a -G video,audio,pulse,pulse-access apache
Un altro punto dolente su Fedora era SELinux. SELinux è un’utility abilitata per impostazione predefinita, per gestire le policy di sicurezza. Esistono diversi modi per aggirare questo problema: indagare e impostare la politica perfetta per le cartelle (molte di esse sono cartelle di memoria condivisa), impostare SELinux in modo che sia più permissivo, disabilitare SELinux. Non voglio dirti la soluzione perfetta, l’ho disabilitata, ma non voglio che tu lo faccia, è una situazione legata alla sicurezza e un ripristino dopo un disastro di sicurezza è qualcosa che davvero non vuoi . La classe wrapper ffmpeg che ho scritto è
<?php
include_once 'Executer.php';
/**
* Description of FfmpegWrapper
* * @author mbarsocchi */ class FfmpegWrapper {
public function startRecord($mountpoint = null, $name, $timeToRun = null) {
$timeStringToRun = "";
$filename = $name . ".mp3";
if ($timeToRun != null) {
$timeStringToRun = "-t " . $timeToRun;
} $command = "/usr/bin/ffmpeg -y -f pulse -i alsa_input.usb-Focusrite_Scarlett_Solo_USB-00.analog-stereo -loglevel fatal " . $timeStringToRun . " -c:a libmp3lame -b:a 192k " . dirname(__FILE__) . DIRECTORY_SEPARATOR . "ripped" . DIRECTORY_SEPARATOR . $filename . " </dev/null";
$exec = new Executer();
$exec->execute($command, true);
$res['retcode'] = $exec->getRetCode();
$res['output'] = $exec->getOutput();
$res['pid'] = $exec->getPid();
return $res;
}
public function stopRecord($pid) {
$exec = new Executer();
$exec->stopPid($pid);
$res['retcode'] = $exec->getRetCode();
$res['output'] = $exec->getOutput();
return $res;
}
}Executer è una classe di supporto che avvolge il comando shell_exec. Questa classe è anche in grado di ottenere flag background=true o background=false. Quando viene impostato background=true, il pid del processo viene salvato nel DB con alcune informazioni aggiuntive, nel mio caso le informazioni aggiuntive sono il nome dell'mp3 registrato. Per fermare la registrazione, ho usato brutalmente un Kill -9 <pid>. So di poter reindirizzare std-in in un file e usarlo come file-socket per inviare il comando [q] a ffmpeg (ffmpeg è uno strumento interattivo, quindi puoi inviare il comando mentre lavori, q sta per "esci") . Puoi anche scegliere una soluzione più elegante, io uso questa perché non voglio scherzare con i file lasciati... e cose del genere. Nella pagina ajax chiama un endpoint per recuperare il processo in esecuzione, se è presente un processo live, la pagina ha il pulsante STOP con una chiamata asincrona a un endpoint che chiama:
FfmpegWrapper:: stopRecord(<pid>)
In caso contrario, il pulsante è START. Questa soluzione funziona molto bene per le mie esigenze e spero che questo post ti aiuti in una soluzione simile.