45

when i do the following command into dos it will work fine

ffmpeg -f image2 -i frame%d.jpg -vcodec mpeg4 -b 800k video.avi

When I try to use the process class in c#, without the arguments, it loads ffmpeg in a console window then dissapears like usual. However, when I try to use the argument as I do above, formatted exactly the same...it doesn't work! ffmpeg still loads, however since the console window closes so fast I cannot determine what the error is :/

Process ffmpeg = new Process();
ffmpeg.StartInfo.FileName = path + "//" + "ffmpeg.exe";
ffmpeg.StartInfo.Arguments = " -f image2 -i frame%d.jpg -vcodec mpeg4 -b 800k video.avi";
ffmpeg.Start();

Any one know why this is? Why would the command work from dos and then fail to work using c# even when the arguments are exactly the same? I've used this method before for many things and never encountered this.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
brux
  • 3,197
  • 10
  • 44
  • 78
  • Are you sure the `FileName` is correct? Shouldn't the slashes be \\ rather then //. – Jason Evans Jul 16 '10 at 19:03
  • 13
    Use System.IO.Path.Combine(path, "ffmpeg.exe") instead. This puts the correct directory separator in the path, if one isn't already there. – Tergiver Jul 16 '10 at 19:05
  • 2
    ye the filename property is correct, like i said mate, the process is actually starting so the file must be found, its the arguments that are failing. I tried concatenating the string and then passing that to the arguments instead of the above, still no joy : – brux Jul 16 '10 at 19:08
  • if i need to convert .caf to .mp3 what shall be the arguments of the process –  Apr 17 '14 at 09:20

5 Answers5

47

Not really a direct answer, but I'd highly recommend using LINQPad for this kind of "exploratory" C# programming.

I have the following as a saved "query" in LINQPad:

var p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c echo Foo && echo Bar";
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.Start();
p.StandardOutput.ReadToEnd().Dump();

Feel free to adapt as needed.

Daniel Pryden
  • 59,486
  • 16
  • 97
  • 135
  • don't forget to add p.StandardError.ReadToEnd().Dump(); for those (rare) apps that write to stderr as well. – Tergiver Jul 16 '10 at 20:06
  • @Tergiver: Except that due to buffeting, calling ReadToEnd on one stream before the other can lead to a deadlock. Sure, it's unlikely to be an issue with most programs, but I figured that, for example code, it's better to leave something out than implement it incorrectly. – Daniel Pryden Jul 16 '10 at 21:02
  • I hadn't ever tried it that way, I asynchronously read both streams when redirecting a process. I see why you would give that simple example instead of a complete (asynchronous) one. – Tergiver Jul 17 '10 at 00:05
34

Try fully qualifying the filenames in the arguments - I notice you're specifying the path in the FileName part, so it's possible that the process is being started elsewhere, then not finding the arguments and causing an error.

If that works, then setting the WorkingDirectory property on the StartInfo may be of use.

Actually, according to the link

The WorkingDirectory property must be set if UserName and Password are provided. If the property is not set, the default working directory is %SYSTEMROOT%\system32.

cristobalito
  • 4,192
  • 1
  • 29
  • 41
  • 2
    thank you, i set the workingdirectory property to match the same path as ffmpeg and works now – brux Jul 16 '10 at 21:23
  • "/k \"c:\\users\\jafar.baltidynamolog\\documents\\visual studio 2010\\Projects\\VideoProjectBilal\\VideoProjectBilal\\bin\\Debug\\ffmpeg.exe\" -i \"C:\\Users\\jafar.baltidynamolog\\Videos\\videos\\SampleVideo_360x240_2mb.mp4\" -i \"C:\\Users\\jafar.baltidynamolog\\Videos\\images\\2.png\" -filter_complex \"overlay=10:10\" \"c:\\users\\jafar.baltidynamolog\\documents\\visual studio 2010\\Projects\\VideoProjectBilal\\VideoProjectBilal\\bin\\Debug\\Output\\SampleVideo_360x240_2mb_Output.mp4\"" I am getting problem in first space. Kindly help – Charlie Nov 30 '15 at 09:05
  • So what's the answer? – Demodave Jan 01 '19 at 16:13
15

Make sure to use full paths, e.g. not only "video.avi" but the full path to that file.

A simple trick for debugging would be to start a command window using cmd /k <command>instead:

string ffmpegPath = Path.Combine(path, "ffmpeg.exe");
string ffmpegParams = @"-f image2 -i frame%d.jpg -vcodec"
    + @" mpeg4 -b 800k C:\myFolder\video.avi"

Process ffmpeg = new Process();
ffmpeg.StartInfo.FileName = "cmd.exe";
ffmpeg.StartInfo.Arguments = "/k " + ffmpegPath + " " + ffmpegParams
ffmpeg.Start();

This will leave the command window open so that you can easily check the output.

Dirk Vollmar
  • 172,527
  • 53
  • 255
  • 316
  • 2
    @0xA3 It really works. The ffmpeg disappear too quick to take a snapshot even I use the process.WaitForExit(10 * 1000)`10(s)`. What does this "/k" actually mean? How did find it? Thanks. – Alston Jun 14 '13 at 10:37
  • @Stallman: `/k` means that the command window is not closed but remains open. You can get all options by calling `cmd.exe /?` on the command prompt. – Dirk Vollmar Jun 14 '13 at 11:57
7

To diagnose better, you can capture the standard output and standard error streams of the external program, in order to see what output was generated and why it might not be running as expected.

Look up:

If you set each of those to true, then you can later call process.StandardOutput.ReadToEnd() and process.StandardError.ReadToEnd() to get the output into string variables, which you can easily inspect under the debugger, or output to trace or your log file.

Chris W. Rea
  • 5,430
  • 41
  • 58
0

Very edge case, but I had to use a program that worked correctly only when I specified

StartInfo = {..., RedirectStandardOutput = true}

Not specifying it would result in an error. There was not even the need to read the output afterward.

Bene Tleilax
  • 190
  • 12