Как изменить вывод на экран от ffmpeg.exe в Perl? - PullRequest
1 голос
/ 19 августа 2010

Я хочу, чтобы на экране отображался только вывод постоянно обновляемой информации о времени при системном вызове ffmpeg.exe.

Я придумал следующий скрипт:

use Capture::Tiny qw/capture/;
use threads;
use threads::shared;

my $stderr :shared;
my $thread1 = threads->create(\&ffmpeg);
my $threads = threads->create(\&time_info,$thread1);
$threads->join();

sub ffmpeg {
    ($stdout, $stderr) = capture {
    system "ffmpeg -i source_video.flv -vcodec wmv2 -acodec wmav2 output_video.wmv";
    };
}

sub time_info {
    while(1){
        $|=1;
        $stderr =~ m{time=(\d+\.\d+)}msg;
        print $1,"\n";
        sleep(1);
    }
}

Я знаю, что скрипт глючит. Но мой текущий вопрос: почему подпрограмма time_info не работает одновременно с подпрограммой ffmpeg? Кажется, он запускается только после завершения функции ffmpeg. И когда подпрограмма ffmpeg завершится, подпрограмма time_info выдаст мне что-то вроде следующего:

3.28
7.56
11.64
15.80
20.88
25.76
30.84
35.88
40.76
45.80
50.88
55.88
60.88
65.88
71.08
76.32
79.46
3.28
7.56

Здесь 79,46 - это продолжительность видео.

Есть указатели? Спасибо, как всегда :)

Обновление:

Спасибо @daxim за то, что отправили меня на правильный путь. Теперь, используя pump from IPC: Run, я создал следующий скрипт, который все еще глючит, но в основном может делать то, что мне нужно, то есть подавлять вывод из ffmpeg и отображать индикатор выполнения видеосвязи.

use strict;
use warnings;
use IPC::Run qw(start pump);
use Term::ProgressBar;

my @cmd = qw(ffmpeg -i source_video.flv -vcodec wmv2 -acodec wmav2 output_video.wmv);

my ($in, $out, $err);

my $harness = start \@cmd, \$in, \$out, \$err;

#Captures the duration of the video...
#Converts hh:mm:ss format to seconds only
pump $harness until ($err =~ m{time=(\d+\.\d+)}msg);
$err =~ m{Duration: (\d+:\d+:\d+\.\d+)}ms;
my $duration = $1;
my ($h, $m, $s) = split /:/, $duration;
$duration = $h * 3600 + $m * 60 + $s;


my $progress = Term::ProgressBar->new ({count => $duration});

#Builds an infinite loop...
#Stops at intervals to print progress information
while(1){
    pump $harness until ($err =~ m{time=(\d+\.\d+)}msg);
    my $so_far = $1;
    $progress->update ($so_far);
    last if ( $duration - $so_far <= 0.5);
    }

1 Ответ

1 голос
/ 19 августа 2010

Вы видите это, потому что capture заполняет переменные только после завершения блока. Если вы хотите прочитать дочерний вывод по кусочкам, используйте pump из IPC::Run.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...