Почему ffmpeg никогда не заканчивается при конвертации видео из моего веб-приложения? - PullRequest
4 голосов
/ 28 сентября 2011

Я пытаюсь конвертировать видео, когда пользователь отправляет форму.Кажется, что это нормально, но файл "используется другим процессом", когда я пытаюсь что-то с ним сделать.Похоже, ffmpeg.exe никогда не выходит.Мой код ниже. Есть ли что-то, что я должен сделать по-другому, чтобы процесс освободил файл?Если я запускаю это вручную, он выходит нормально.

internal class ConversionUtility : Utility
{
    public void Convert(string videoFileName)
    {
        var video = new VideoFile(videoFileName);

        if (!video.infoGathered)
            GetVideoInfo(video);

        var Params = string.Format("-y -i \"{0}\" -coder ac -me_method full -me_range 16 -subq 5 -sc_threshold 40 -vcodec libx264 -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -i_qfactor 0.71 -keyint_min 25 -b_strategy 1 -g 250 -r 20 \"{1}\"", video.Path, Path.ChangeExtension(videoFileName,".mp4"));
        //var Params = string.Format("-y -i \"{0}\" -acodec libfaac -ar 44100 -ab 96k -coder ac -me_method full -me_range 16 -subq 5 -sc_threshold 40 -vcodec libx264 -s 1280x544 -b 1600k -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -i_qfactor 0.71 -keyint_min 25 -b_strategy 1 -g 250 -r 20 c:\\output3.mp4", video.Path, videoFileName);
        //var Params = String.Format(" {0} \"{1}\"",this.FFmpegLocation, video.Path);

        var threadStart = new ParameterizedThreadStart(del => RunProcess(Params));
        var thread = new Thread(threadStart);
        thread.Start();            
        //RunProcess(Params);
    }
}

internal class Utility
{
    public string FFmpegLocation { get; set; }        
    private string WorkingPath { get { return Path.GetDirectoryName(FFmpegLocation); } }

    protected string RunProcess(string Parameters)
    {
        //create a process info
        var oInfo = new ProcessStartInfo(this.FFmpegLocation, Parameters)
        {
            UseShellExecute = false,
            CreateNoWindow = true,
            RedirectStandardOutput = true,
            RedirectStandardError = true
        };

        //Create the output and streamreader to get the output
        string output = null; StreamReader srOutput = null;

        //try the process
        try
        {
            //run the process
            Process proc = System.Diagnostics.Process.Start(oInfo);

            proc.WaitForExit();
            //if (!proc.WaitForExit(10000))
            //    proc.Kill();


            //get the output
            srOutput = proc.StandardError;

            //now put it in a string
            output = srOutput.ReadToEnd();

            proc.Close();
        }
        catch (Exception)
        {
            output = string.Empty;
        }
        finally
        {
            //now, if we succeded, close out the streamreader
            if (srOutput != null)
            {
                srOutput.Close();
                srOutput.Dispose();
            }
        }
        return output;
    }

Ответы [ 3 ]

3 голосов
/ 30 сентября 2011

После долгих исследований я наткнулся на этот пост .Что поставило меня на правильный путь.Я прочитал больше о RedirectStandardError и обнаружил, что мне нужно изменить порядок вещей, которые я вызывал.После вызова WaitForExit в конце все заработало как положено.Вот обновленный код:

protected string RunProcess(string Parameters)
{
    //create a process info
    var oInfo = new ProcessStartInfo(this.FFmpegLocation, Parameters)
    {
        UseShellExecute = false,
        CreateNoWindow = true,
        RedirectStandardOutput = true,
        RedirectStandardError = true
    };

    var output = string.Empty;

    try
    {                
        Process process = System.Diagnostics.Process.Start(oInfo);

        output = process.StandardError.ReadToEnd();
        process.WaitForExit();
        process.Close();
    }
    catch (Exception)
    {
        output = string.Empty;
    }                       
    return output;
}
0 голосов
/ 06 декабря 2017

Вы должны всегда читать буферы StandardOutput и StandardError, пока выполняется процесс . Всякий раз, когда буферы достигают своих пределов, процесс будет буквально зависать, пока вы не прочитаете буферы до конца .

FFMpeg постоянно сообщает информацию о конвертации. Каждое обновление информации, которую вы видите в нижней части командной строки, добавляется в буфер StandardOutput, таким образом заполняя буфер. Вероятно, буфер быстро заполняется при конвертации больших файлов.

0 голосов
/ 28 сентября 2011

Имеет ли ваше веб-приложение (удостоверение процесса пула приложений) надлежащие разрешения для того, что делается в потоках процессов, которые вы порождаете?

В прошлом у меня были подобные проблемы, связанные с System.File.Move выполнением потоков процессов, выполняющих ввод-вывод из ASP.NET, что на самом деле является проблемой Win32.

Используйте System.File.Copy или эквивалент Win32, а затем удалите старый файл, если можете. Я предполагаю, что .exe, который вы вызываете (выполняете), не ваш (ваш собственный исходный код, который можно изменить), и вы не можете его изменить.

Вы также можете использовать SysInternals , чтобы увидеть, что может удерживать или блокировать ресурсы.

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