Индикатор выполнения кодирования видео ffmpeg
Когда я запускаю преобразование в браузере, оно просто показывает пустое пространство. Только после конвертации загрузится страница.
Пожалуйста, предложите, как реализовать индикатор выполнения, который показывает прогресс пользователя при конвертации видео.
У меня есть это в моем сценарии PHP
exec("ffmpeg -i filename.flv -sameq -ab 128 -s 640x480 filename.mp4");
Итак, как мне изменить этот скрипт, чтобы получить информацию о прогрессе даже в файл или непосредственно как вывод на странице. Пожалуйста, кто-нибудь может дать мне полный сценарий / код, чтобы объяснить это подробно. Потому что я думаю, что я не могу получить полные ответы, и поэтому я не понимаю, что делать с этим
5 ответов
javascript должен сказать php начать конвертацию [1], а затем сделать [2]...
[1] php: начать преобразование и записать статус в текстовый файл - пример синтаксиса:
exec("ffmpeg -i path/to/input.mov path/to/output.flv 1>path/to/output.txt 2>&1");
Для второй части нам нужно просто JavaScript, чтобы прочитать файл. В следующем примере используется dojo.request для AJAX, но вы также можете использовать jQuery, vanilla или что-то еще:
[2] js: захватить прогресс из файла:
var _progress = function(i){
i++;
// THIS MUST BE THE PATH OF THE .txt FILE SPECIFIED IN [1] :
var logfile = 'path/to/output.txt';
/* (example requires dojo) */
request.post(logfile).then( function(content){
// AJAX success
var duration = 0, time = 0, progress = 0;
var result = {};
// get duration of source
var matches = (content) ? content.match(/Duration: (.*?), start:/) : [];
if( matches.length>0 ){
var rawDuration = matches[1];
// convert rawDuration from 00:00:00.00 to seconds.
var ar = rawDuration.split(":").reverse();
duration = parseFloat(ar[0]);
if (ar[1]) duration += parseInt(ar[1]) * 60;
if (ar[2]) duration += parseInt(ar[2]) * 60 * 60;
// get the time
matches = content.match(/time=(.*?) bitrate/g);
console.log( matches );
if( matches.length>0 ){
var rawTime = matches.pop();
// needed if there is more than one match
if (lang.isArray(rawTime)){
rawTime = rawTime.pop().replace('time=','').replace(' bitrate','');
} else {
rawTime = rawTime.replace('time=','').replace(' bitrate','');
}
// convert rawTime from 00:00:00.00 to seconds.
ar = rawTime.split(":").reverse();
time = parseFloat(ar[0]);
if (ar[1]) time += parseInt(ar[1]) * 60;
if (ar[2]) time += parseInt(ar[2]) * 60 * 60;
//calculate the progress
progress = Math.round((time/duration) * 100);
}
result.status = 200;
result.duration = duration;
result.current = time;
result.progress = progress;
console.log(result);
/* UPDATE YOUR PROGRESSBAR HERE with above values ... */
if(progress==0 && i>20){
// TODO err - giving up after 8 sec. no progress - handle progress errors here
console.log('{"status":-400, "error":"there is no progress while we tried to encode the video" }');
return;
} else if(progress<100){
setTimeout(function(){ _progress(i); }, 400);
}
} else if( content.indexOf('Permission denied') > -1) {
// TODO - err - ffmpeg is not executable ...
console.log('{"status":-400, "error":"ffmpeg : Permission denied, either for ffmpeg or upload location ..." }');
}
},
function(err){
// AJAX error
if(i<20){
// retry
setTimeout(function(){ _progress(0); }, 400);
} else {
console.log('{"status":-400, "error":"there is no progress while we tried to encode the video" }');
console.log( err );
}
return;
});
}
setTimeout(function(){ _progress(0); }, 800);
Это можно сделать, хотя было бы неплохо использовать более простой индикатор ajax для небольших файлов, но для больших файлов>50–80 МБ вы можете сделать это:
Вы можете прочитать возвращаемые значения FFMPEG через PHP. ffmpeg (последние несколько строк) возвращает это:
Press [q] to stop encoding
frame= 1850 fps=115 q=31.0 Lsize= 5789kB time=74.00 bitrate= 640.8kbits/s
video:5135kB audio:580kB
Время =74.00 - это текущее время файла (НЕ время выполнения). Вы можете использовать некоторое регулярное выражение для анализа этого значения, а с помощью некоторой математики вы можете получить процент завершенного бара.
Если вы не знаете длительность файла. FFMPEG первые несколько строк возвращает это:
Input #0, flv, from 'cf_video_3728.flv':
Duration: 00:01:14.13, start: 0.000000, bitrate: 864 kb/s
Вы можете проанализировать продолжительность и получить общее время.
Надеюсь это поможет.
Если вы используете PHP-FFMpeg, они добавили функцию on, которую вы можете прослушивать для прогресса и выполнять обратный вызов. Вы настраиваете его в своем контейнере видео формата так:
$format = new Format\Video\X264();
$format->on('progress', function ($video, $format, $percentage) {
echo "$percentage % transcoded";
});
Более подробную информацию можно найти в документации https://github.com/PHP-FFMpeg/PHP-FFMpeg
Я не верю, что это возможно.
Проблема в том, что вам нужен ваш PHP
скрипт, чтобы быть в курсе текущего ffmpeg
статус обработки. Если вы делаете ffmpeg
преобразование через командную строку, он отображает прогресс для пользователя, но у вас нет доступа к этому потоку вывода, когда вы порождаете ffmpeg
используя команды в PHP, как exec
,
Вместо того, чтобы пытаться показать пользователю настоящий "индикатор прогресса", я предлагаю вместо этого просто включить индикатор ожидания на странице. Вы можете найти много изображений для этой цели или сгенерировать их с помощью таких инструментов, как http://ajaxload.info/.
Возможно, вам будет интересно почитать о COMET.
Это метод программирования, который позволяет передавать информацию с сервера в браузер без необходимости запрашивать ее у браузера.
Вот статья, объясняющая, как реализовать это с помощью PHP с помощью скрытого iframe.
http://www.zeitoun.net/articles/comet_and_php/start
Возможно, вы могли бы использовать это в сочетании с предоставленным Стьюи ответом относительно чтения возвращаемых значений из ffmpeg.