werfog Ответов: 1

Как поймать видео выход


Всем привет.
Я попробовал следующие строки:

Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = "ffmpeg";
p.StartInfo.Arguments = " -h ";
p = Process.Start(p.StartInfo);
this.textBox1.Text = p.StandardOutput.ReadToEnd();
this.textBox1.Update();
p.WaitForExit();


В этом случае все выглядит нормально и текстовое поле имеет выход ffmpeg.exe.
Но в случае реальной работы:
p.StartInfo.Arguments = " -i input.avi -y output.ts ";

Я вижу только пустое текстовое поле, хотя преобразование было завершено и output.ts был создан.

Заранее спасибо.

Pablo Aliskevicius

Каков результат выполнения команды в окне консоли?
Что произойдет, если вы снова вызовете ReadToEnd() после WaitForExit()?

werfog

1. я не знаю, как добавить картинку к моему ответу. Текст из консоли

C:\Users\aaa\Documents\Visual Studio 2010\Projects\C#\VisualFFmpeg_1\bin\Debug>f
fmpeg.exe -я ... E:\input.avi -у E:\output.ts
ffmpeg версия N-46055-g5f0105b Copyright (c) 2000-2012 разработчики FFmpeg
построен 26 октября 2012 года 17:51:52 с gcc 4.7.2 (GCC)
настройки: опции --Enable-GPL с опцией --enable-версия_3 помощью --disable-pthreads не опцией --enable-недомерок
име-cpudetect опцией --enable-AviSynth с опцией --enable-bzlib опцией --enable-frei0r опцией --enable-OSD меню -
-enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libfreetype --enab
Ле-libgsm опцией --enable-libmp3lame опцией --enable-libnut опцией --enable-libopenjpeg опцией --enable-либо
гной опцией --enable-librtmp опцией --enable-libschroedinger опцией --enable-libspeex опцией --enable-libtheo
РА опцией --enable-libutvideo опцией --enable-собран libvo-aacenc опцией --enable-собран libvo-amrwbenc опцией --enable-ли
bvorbis опцией --enable-libvpx опцией --enable-поддержкой libx264 опцией --enable-libxavs опцией --enable-libxvid --Ена
ble-zlib
libavutil 52. 0.100 / 52. 0.100
libavcodec 54. 69.100 / 54. 69.100
libavformat 54. 35.100 / 54. 35.100
libavdevice 54. 3.100 / 54. 3.100
libavfilter 3. 20.106 / 3. 20.106
libswscale 2. 1.101 / 2. 1.101
libswresample 0. 16.100 / 0. 16.100
libpostproc 52. 1.100 / 52. 1.100
Вход #0, avi, from 'E:\input.avi':
Метаданные:
кодировщик : Lavf51.12.1
Продолжительность: 00:01:00.13, начало: 0.000000, битрейт: 4218 кб/с
Поток #0:0: видео: mpeg4 (простой профиль) (xvid / 0x64697678), yuv420p, 640
x360 [SAR 1:1 DAR 16:9], 29.97 tbr, 29.97 tbn, 29.97 tbc
Поток #0:1: Аудио: mp3 (U[0][0][0] / 0x0055), 44100 Гц, стерео, s16, 128 Кб

Выход #0, mpegts, to 'E:\output.ts':
Метаданные:
кодер : Lavf54.35.100
Поток #0:0: видео: mpeg2video, yuv420p, 640x360 [SAR 1:1 DAR 16:9], q=2-31,
200 кб/с, 90k tbn, 29.97 tbc
Поток #0:1: аудио: mp2, 44100 Гц, стерео, s16, 128 кб/с
Отображение потока:
Поток #0:0 -> #0:0 (mpeg4 -> mpeg2video)
Поток #0:1 -> #0:1 (mp3 -> mp2)
Нажмите [q], чтобы остановиться, [?] для получения помощи
кадр= 227 кадров в секунду=0.0 q=31.0 размер= 999 Кб время=00:00:07.72 битрейт=1059.6 Кбит/
кадр= 476 кадров в секунду=462 q=31.0 размер= 1849kB время=00:00:16.00 битрейт= 946,6 Кбит/
frame= 742 fps=480 q=31.0 size= 2748kB time=00:00:24.85 bitrate= 905.5 kbits/
кадр= 1005 кадров в секунду=488 q=24.8 размер= 3648kB время=00:00:33.66 битрейт= 887.8 Кбит/
рамка= 1272 ФПС=494 м=размер 31.0= 4519kB время=00:00:42.56 битрейт= 869.7 КБ/
рамка= 1526 ФПС=494 м=31.0 размер= 5402kB время=00:00:51.05 битрейт= 866.7 КБ/
кадр= 1790 кадров в секунду=497 q=31.0 размер= 6295kB время=00:00:59.86 битрейт= 861.5 Кбит/
кадр= 1800 кадров в секунду=497 q=31.0 Lsize= 6339kB time=00:01:00.12 битрейт= 863.7 Кбит

видео:аудио 4708kB:940kB подзаголовок:0 глобальные заголовки:0 КБ мультиплексирования накладные 12.233324
%

C:\Users\aaa\Documents\Visual Studio 2010\Projects\C#\VisualFFmpeg_1\bin\Debug>p
потому что
Для продолжения нажмите любую клавишу . . .

2. в текстовом поле больше ничего не отображается.
Спасибо за внимание.

Pablo Aliskevicius

Я предполагаю, что существует какое-то условие гонки: ReadToEnd() может быть вызван до того, как ffmpeg запишет стандартный вывод. Но это всего лишь предположение...
Я поднял этот вопрос в надежде заманить кого-нибудь, кто знает лучше.
Наилучшие пожелания,
Пабло.

werfog

Большое спасибо.
Я написал это в надежде, что кто-то, кто окружил такую проблему и решил ее, может помочь.
Я пытаюсь разобраться с этой проблемой. И я подозреваю, что ответ лежит где-то в квартирной резьбе. Но мне это трудно понять.

1 Ответов

Рейтинг:
9

werfog

Самое лучшее и самое короткое решение было найдено в статье
"Транскодирование видео в стиле YouTube с помощью ffmpeg" , опубликованное Джонатаном Латиги.
Транскодирование видео "в стиле YouTube" с помощью ffmpeg
Он пишет::
"Еще одна проблема возникла при захвате выходных данных из FFMPEG, чтобы получить все метаданные файла. Я создал новый процесс и streamReader, а также захватил стандартный вывод из процесса. Ничего. Оказывается, в FFMPEG нет специальной команды для чтения метаданных из видеофайла, вместо этого эта информация выходит в виде стандартного потока при вызове FFMPEG без указания выходного файла. Как только я переключился с захвата StandardOutput на StandardError, у меня не было никаких проблем."

И это было ключевым фактором для меня. Как я пытался поймать StandardOutput ffmpeg вместо того, чтобы поймать StandardError. Таким образом, я получил все необходимые строки в моем текстовом поле. Наконец, я использовал асинхронное чтение, которое было более подходящим для моей цели. Вот этот код.

try
            {
                Process p = this.process1;
                String input = " -i " + this.listBox2.Text; //  /c ffmpeg.exe // for launching ffmpeg via cmd.exe
                String size = " -s " + this.comboBox1.Text;
                String codec = " -vcodec " + this.comboBox2.Text;
                String encoder = " -vtag " + this.comboBox3.Text;
                String quality = " -qscale " + this.comboBox4.Text;
                String videobr = " -b:v " + this.comboBox4.Text + "k";
                String audiobr = " -ab " + this.comboBox5.Text + "k";
                String output = " -y " + this.textBox2.Text;
                String report = " 2> \"" + this.textBox2.Text + ".log\""; // for launching ffmpeg via cmd.exe and putting output into file
                String s = input + size + codec + encoder + videobr + audiobr + output;// +report;
                String sa = " -h ";// help from ffmpeg
                p.StartInfo.Arguments = s;
                p.Start();

                p.BeginOutputReadLine();
                p.BeginErrorReadLine();
                MessageBox.Show("Waiting for the process to exit....");
                //p.WaitForExit();
                if (p.HasExited) { p.CancelErrorRead(); p.CancelOutputRead(); p.Close(); MessageBox.Show("Closed"); }
            }
            catch (Exception ex)
            {
                MessageBox.Show("1.\n"+ex.Message);
            }

Следующий обработчик ErrorDataReceived.
private void process1_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            this.textBox1.Text += e.Data;
            this.textBox1.Update();
            //MessageBox.Show("4.Error\n" + e.Data);
        }


Вы можете найти несколько дополнительных строк: MessageBoxes и т. д. они предназначены только для отладки.
Так что большое спасибо Джонатану Латиги и 5 звезд за него.
Я рад, если мой опыт пригодится вам.
Наилучшие пожелания.