tomaszzmuda / Xabe.FFmpeg

.NET Standard wrapper for FFmpeg. It allows to process media without know how FFmpeg works, and can be used to pass customized arguments to FFmpeg from dotnet core application.
https://xabe.net/product/xabe_ffmpeg/
Other
715 stars 128 forks source link

ffmpeg and ffprobe Paths get overriden with empty values after the first constructor #470

Open cnd-jan-luebben opened 11 months ago

cnd-jan-luebben commented 11 months ago

When we upload multiple videos for conversion and use this library in parallel the path sometimes is not found

Xabe.FFmpeg.Exceptions.FFmpegNotFoundException: 'Cannot find FFmpeg in PATH. This package needs installed FFmpeg. Please add it to your PATH variable or specify path to DIRECTORY with FFmpeg executables in FFmpeg.ExecutablesPath' in FFmpeg.cs - private void ValidateExecutables()

I have traced this problem back to the paths for FFmpeg and FFprobe that seem to be for some reason be overriden with empty values.

I created the following testcase for myself:

  var videoBasePath = "C:\\path-to-folder\\";
  var videos = new string[]
  {
      "video1.mp4",
      "video2.mkv",
      "video3.mkv",
  };

  var result = Parallel.For(0, videos.Length, async (i) =>
  {
      var converter = new Converter();
      var video = videos[i];
      var output = string.Join(".", (videoBasePath + "result\\" + videos[i]).Split(".")[..^1]) + ".m3u8";
      var conversion = await FFmpeg.Conversions.FromSnippet.Convert(videoBasePath + videos[i], output);      

      var result = await conversion.Start();
      Console.WriteLine(i + " Done");
  });

Then i added the following override checks to the setters of FFfmpegPath and FFprobePath in FFmpeg.cs (in probepath with _ffprobePath):

private set
{
    lock (_ffmpegPathLock)
    {
        if ((value == null || value.Length == 0) && _ffmpegPath != null && _ffmpegPath.Length > 0)
        {
            Console.WriteLine("tried path override on ffmpeg");
            return;
        }

        _ffmpegPath = value;
    }
}

With the return commented out the console output is e.g. the following:

Constructor (log in ctor of FFmpeg.cs)
Constructor (log in ctor of FFmpeg.cs)
Constructor (log in ctor of FFmpeg.cs)
tried path override on ffprobe
tried path override on ffmpeg

and then the application crashes with the mentioned exception (note: the progress seems to be random, sometimes it even works despite the overrides (also sometimes there are less override calls than secondary constructor calls))

Keeping the return gives the following console output and sucessfully completes the task:

Constructor (log in ctor of FFmpeg.cs)
Constructor (log in ctor of FFmpeg.cs)
Constructor (log in ctor of FFmpeg.cs)
tried path override on ffprobe
tried path override on ffmpeg
tried path override on ffprobe
tried path override on ffmpeg
Constructor (log in ctor of FFmpeg.cs)
tried path override on ffprobe
tried path override on ffmpeg
Constructor (log in ctor of FFmpeg.cs)
tried path override on ffprobe
tried path override on ffmpeg
Constructor (log in ctor of FFmpeg.cs)
tried path override on ffprobe
tried path override on ffmpeg
2 Done
1 Done
0 Done

It seems that the path gets overriden with empty values after the first constructor except for some seemingly random timing based cases.

Is it possible to add a check like mentioned above to the paths or, if the deletion is required for other functions, what is the way to prevent the paths from being overridden?

Ps. #388 might be the same underlying problem.