1

I am working on a C# Form tool that will help me convert all of my phone and DSLR video to HEVC, currently, i have a program that uploads the photos and videos to different directories in my home server each time i connect to the WiFi. Once a month or so, i manually convert all the videos, but thought I would automate the process.. I have the Form working perfectly for processing 1 file. but get into trouble when processing a Directory (with possible sub-directories) all at once..

Sorry, this is long, just want to be thorough. here is the button calls

private void processFile_Click(object sender, EventArgs e)
    {
        OpenFileDialog file = new OpenFileDialog();
        file.InitialDirectory = baseMediaDirectory;
        if (file.ShowDialog() == DialogResult.OK)
        {
            ProcessSinlgeFile(file.FileName);
        }
    }

(above)for one file and (below) for a directory

private void processDirectory_Click(object sender, EventArgs e)
{
    FolderBrowserDialog file = new FolderBrowserDialog();
    file.SelectedPath = baseMediaDirectory;
    if(file.ShowDialog() == DialogResult.OK)
    {
       ProcessDirectoryOfFiles(file.SelectedPath);
    }
}

private void ProcessDirectoryOfFiles(string selectedPath)
    {
        List<string> listOfFiles = GetAllFiles(selectedPath);
        foreach (string s in listOfFiles)
        {
            ProcessSinlgeFile(s);
        }
    }

both ultimately call this method, to do some checks and setup

private void ProcessSinlgeFile(string fileName)
    {

        if (IsAcceptableMediaFile(fileName))
        {
            outputWindow.AppendText("File to Process: " + fileName);
            processMediaFile = 
                new MediaFileWrapper(this.outputWindow, new MediaFile(fileName), new NReco.VideoInfo.FFProbe());
            if (processMediaFile.OkToProcess)
            {
                int initialCRFValue = 15;
                //ultrafast superfast veryfast faster fast medium slow slower veryslow placebo
                string intialSpeed = "veryfast";
                try {

                    ConvertToMPEG(processMediaFile.getFFMPEGCommand(initialCRFValue, intialSpeed), processMediaFile);
                }
                catch
                {
                    // at somepoint, we'll catch a bad file size (or compression)
                    // then change the CRF value and/or compression speed
                }
            }
        }
    }

ultimately I get to this Method and run into trouble.

    private async void ConvertToMPEG(string arguments, MediaFileWrapper processMediaFile)
    {
        startTime = DateTime.Now;
        watch = new Stopwatch();
        watch.Start();
        progressBar1.Minimum = 0;
        progressBar1.Maximum = processMediaFile.GetTotalMilliseconds();

        // Start the child process.
        p = new Process();

        //Setup filename and arguments
        outputWindow.AppendText("ffmpeg " + arguments);
        p.StartInfo.Arguments = arguments;
        p.StartInfo.FileName = "ffmpeg.exe";
        p.StartInfo.UseShellExecute = false;

        // Redirect the output stream of the child process.
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.RedirectStandardInput = true;

        // capture the date for stdout and std error
        // note FFMPEG uses Stderr exclusively
        p.ErrorDataReceived += new DataReceivedEventHandler(ErrorDataReceived);
        p.OutputDataReceived += new DataReceivedEventHandler(OutputDataReceived);

        // Hide Console Window
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

        p.Start();
        p.BeginErrorReadLine();
        p.BeginOutputReadLine();
        await p.WaitForExitAsync();
    }

and WaitForExitAsync is in another class because in can not be in here with a Form

    public static Task WaitForExitAsync(this Process process,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var tcs = new TaskCompletionSource<object>();
        process.EnableRaisingEvents = true;
        process.Exited += (sender, args) => tcs.TrySetResult(null);
        if (cancellationToken != default(CancellationToken))
            cancellationToken.Register(tcs.SetCanceled);

        return tcs.Task;
    }

however, single files work fine, when I call a directory through, it continuously starts processes for each file, trying to run them all at the same time. You can see I tried implementing this process.WaitForExit() asynchronously with no luck.

Community
  • 1
  • 1
wesman
  • 11
  • 4

0 Answers0