Bawiłem się z tym przez kilka dni. Pomogło mi to "ffmpegprogress", ale bardzo ciężko było pracować z moją konfiguracją i trudno było odczytać kod.
W celu wykazania postępu ffmpeg trzeba wykonać następujące czynności:
- uruchomić polecenie ffmpeg od PHP bez niego czekając na odpowiedź (dla mnie, to była najtrudniejsza część)
- powiedz ffmpeg, aby wysłać wynik do pliku
- z przedniego końca (AJAX, Flash, cokolwiek) uderzył bezpośrednio w ten plik lub plik php, który może wyciągnąć postęp z wyjścia ffmpeg.
Oto jak rozwiązać każdą część:
1. mam następujący pomysł z "ffmpegprogress". Oto, co zrobił: jeden plik PHP wywołuje inny przez gniazdo http. Drugi faktycznie uruchamia "exec", a pierwszy plik po prostu się rozłącza. Dla mnie jego wdrożenie było zbyt skomplikowane. Używał "fsockopen". Lubię CURL.Więc oto co zrobiłem:
$url = "http://".$_SERVER["HTTP_HOST"]."/path/to/exec/exec.php";
curl_setopt($curlH, CURLOPT_URL, $url);
$postData = "&cmd=".urlencode($cmd);
$postData .= "&outFile=".urlencode("path/to/output.txt");
curl_setopt($curlH, CURLOPT_POST, TRUE);
curl_setopt($curlH, CURLOPT_POSTFIELDS, $postData);
curl_setopt($curlH, CURLOPT_RETURNTRANSFER, TRUE);
// # this is the key!
curl_setopt($curlH, CURLOPT_TIMEOUT, 1);
$result = curl_exec($curlH);
Ustawianie CURLOPT_TIMEOUT do 1 oznacza, że będzie czekać 1 sekundy na odpowiedź. Korzystnie byłoby to niższe. Istnieje również CURLOPT_TIMEOUT_MS, który trwa milisekundy, ale nie zadziałał on dla mnie.
Po 1 sekundzie CURL rozłącza się, ale polecenie exec nadal działa. Część 1 rozwiązana.
BTW - Kilka osób sugerowało użycie polecenia "nohup" w tym celu. Ale wydawało się, że to nie działa dla mnie.
* RÓWNIEŻ! Posiadanie pliku php na serwerze, który może wykonywać kod bezpośrednio w linii poleceń, jest oczywistym zagrożeniem bezpieczeństwa. Powinieneś mieć hasło lub kodować dane dotyczące postów w jakiś sposób.
2. Powyższy skrypt "exec.php" musi również informować ffmpeg o wyprowadzeniu do pliku. Oto kod, który:
exec("ffmpeg -i path/to/input.mov path/to/output.flv 1> path/to/output.txt 2>&1");
Uwaga "1> ścieżka/do/output.txt 2> & 1". Nie jestem ekspertem od linii poleceń, ale z tego co mogę powiedzieć, ta linia mówi: "wyślij normalne wyjście do tego pliku, I wyślij błędy w to samo miejsce". Sprawdź ten adres URL, aby uzyskać więcej informacji: http://tldp.org/LDP/abs/html/io-redirection.html
3. Z przodu wywołaj skrypt php, podając lokalizację pliku output.txt. Ten plik php następnie wyciągnie postęp z pliku tekstowego. Oto, jak to zrobiłem:
// # get duration of source
preg_match("/Duration: (.*?), start:/", $content, $matches);
$rawDuration = $matches[1];
// # rawDuration is in 00:00:00.00 format. This converts it to seconds.
$ar = array_reverse(explode(":", $rawDuration));
$duration = floatval($ar[0]);
if (!empty($ar[1])) $duration += intval($ar[1]) * 60;
if (!empty($ar[2])) $duration += intval($ar[2]) * 60 * 60;
// # get the current time
preg_match_all("/time=(.*?) bitrate/", $content, $matches);
$last = array_pop($matches);
// # this is needed if there is more than one match
if (is_array($last)) {
$last = array_pop($last);
}
$curTime = floatval($last);
// # finally, progress is easy
$progress = $curTime/$duration;
Mam nadzieję, że to komuś pomaga.
Ale dlaczego użyć pliku tekstowego? musi być lepszy sposób. Czy nie musiałbyś tworzyć nowego pliku tekstowego dla każdego przesłania? – Scarface