Esegui un process ffmpeg in background

Sto volendo usare ffmpeg per convertire i video in .flv in php. Attualmente ho questo funzionamento, ma si blocca il browser fino a quando il file viene caricato e non è finito. Ho visto i documenti php su come eseguire un process exec () in background, mentre aggiornavo il process usando il PID restituito. Ecco cosa ho trovato:

//Run linux command in background and return the PID created by the OS function run_in_background($Command, $Priority = 0) { if($Priority) $PID = shell_exec("nohup nice -n $Priority $Command > /dev/null & echo $!"); else $PID = shell_exec("nohup $Command > /dev/null & echo $!"); return($PID); } 

C'è anche un trucco che uso per monitorare se l'attività in background è in esecuzione utilizzando il PID restituito:

 //Verifies if a process is running in linux function is_process_running($PID) { exec("ps $PID", $ProcessState); return(count($ProcessState) >= 2); } 

Suppongo di creare un file .php separato che poi viene eseguito da php cli per eseguire una di queste funzioni? Ho solo bisogno di un piccolo spintone per far funzionare questo e poi posso prenderlo da lì.

Grazie!

Suppongo di creare un file .php separato che poi viene eseguito da php cli per eseguire una di queste funzioni?

Questo è probabilmente il modo in cui lo farei:

  • la pagina web di PHP aggiunge un record nel database per indicare "questo file deve essere elaborato"
    • e visualizza un messaggio all'utente; qualcosa come "il tuo file verrà elaborato presto"
  • In CLI, disporre di un batch per elaborare i nuovi file inseriti
    • per prima cosa, contrassegna un record come "elaborazione"
    • fai la cosa ffmpeg
    • segna il file come "elaborato"
  • E, sulla pagina web, puoi mostrare all'utente in quale stato il suo file è:
    • se non è stato ancora elaborato
    • se è in fase di elaborazione
    • o se è stato elaborato, puoi quindi fornirgli il link al nuovo file video.

Ecco un paio di altri pensieri:

  • Il giorno in cui la tua applicazione diventa più grande, puoi avere:
    • un "web server"
    • molti "server di elaborazione"; nella tua applicazione, è la cosa ffmpeg che richiederà molta CPU, non servendo pagine web; quindi, essere in grado di scalare quella parte è bello (questo è un altro per "bloccare" i file, indicandoli come "elaborazione" in DB: in questo modo, non si avranno più server di elaborazione che tentano di elaborare lo stesso file)
  • Si utilizza PHP dal server Web solo per generare pagine Web, che è il lavoro di un server web
    • L'elaborazione pesante / lunga non è il lavoro di un server web!
    • Il giorno in cui vorresti passare a qualcosa di diverso da PHP per la parte "di elaborazione", sarà più facile.

Il tuo "script di elaborazione" dovrebbe essere avviato each due minuti; puoi usare cron per questo, se sei su una macchina simile a Linux.


Modifica: un po 'più di informazioni, dopo aver visto il commento

Poiché la parte di elaborazione viene eseguita dalla CLI, e non da Apache, non è necessario alcun tipo di manipolazioni "di background": puoi semplicemente usare shell_exec , che restituirà l'intera output del command al tuo script PHP quando è finito, facendo ciò è lavoro.

Per l'utente che guarda la pagina web che dice "elaborazione", sembrerà un'elaborazione in background; e, in un certo senso, lo sarà, poiché l'elaborazione verrà eseguita da un altro processus (forse anche su un'altra macchina).

Ma per te sarà molto più semplice:

  • una pagina web (niente "background")
  • uno script CLI, senza alcuna roba di background.

Lo script di elaborazione potrebbe assomigliare a qualcosa del genere, suppongo:

 // Fetch informations from DB about one file to process // and mark it as "processing" // Those would be fetched / determined from the data you just fetched from DB $in_file = 'in-file.avi'; $out_file = 'out-file.avi'; // Launch the ffmpeg processing command (will probably require more options ^^ ) // The PHP script will wait until it's finished : // No background work // No need for any kind of polling $output = shell_exec('ffmpeg ' . escapeshellarg($in_file) . ' ' . escapeshellarg($out_file)); // File has been processed // Store the "output name" to DB // Mark the record in DB as "processed" 

Davvero più facile di quello che hai pensato, non è vero? 😉
Non preoccuparti più delle cose in sottofondo: l'unica cosa importnte è che lo script di elaborazione viene lanciato regolarmente da crontab.

Spero che questo ti aiuti 🙂

Non è necessario scrivere uno script php separato per fare ciò (anche se in seguito potresti voler implementare una sorta di sistema di accodamento).

Ci sei quasi. L'unico problema è che i blocchi di chiamata shell_exec () aspettano il return della shell. È ansible evitare questo se si reindirizza tutto l'output dal command nella shell per avvizzire un file o / dev / null e lo background dell'attività (con l'operatore &). Quindi il tuo codice diventerebbe:

 //Run linux command in background and return the PID created by the OS function run_in_background($Command, $Priority = 0) { if($Priority) { shell_exec("nohup nice -n $Priority $Command 2> /dev/null > /dev/null &"); } else { shell_exec("nohup $Command 2> /dev/null > /dev/null &"); } } 

Non penso che ci sia un modo per recuperare il PID, sfortunatamente.