11

I'm attempting to use ffmpeg (compiled on Windows with Cygwin) in a C# program, by using the Process class to spawn an ffmpeg instance. However, I've hit a rather odd bug that doesn't make much sense.

When I run ffmpeg directly from a shell (be it Cygwin's bash, PowerShell, cmd), ffmpeg can properly decode and reencode files without any issues:

PS C:\audio> ffmpeg -i .\sound1.wav -acodec libvorbis -f ogg abc.ogg
ffmpeg version 1.2 Copyright (c) 2000-2013 the FFmpeg developers
  built on Apr  8 2013 15:10:40 with gcc 4.5.3 (GCC)
  configuration: --disable-encoder=vorbis --enable-libvorbis
  libavutil      52. 18.100 / 52. 18.100
  libavcodec     54. 92.100 / 54. 92.100
  libavformat    54. 63.104 / 54. 63.104
  libavdevice    54.  3.103 / 54.  3.103
  libavfilter     3. 42.103 /  3. 42.103
  libswscale      2.  2.100 /  2.  2.100
  libswresample   0. 17.102 /  0. 17.102
[wav @ 0x800538a0] max_analyze_duration 5000000 reached at 5015510 microseconds
Guessed Channel Layout for  Input Stream #0.0 : stereo
Input #0, wav, from '.\sound1.wav':
  Metadata:
    encoder         : Lavf54.63.104
  Duration: 00:00:05.76, bitrate: 1411 kb/s
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, stereo, s16, 1411 kb/s
Output #0, ogg, to 'abc.ogg':
  Metadata:
    encoder         : Lavf54.63.104
    Stream #0:0: Audio: vorbis, 44100 Hz, stereo, fltp
Stream mapping:
  Stream #0:0 -> #0:0 (pcm_s16le -> libvorbis)
Press [q] to stop, [?] for help
size=      55kB time=00:00:05.74 bitrate=  78.5kbits/s
video:0kB audio:51kB subtitle:0 global headers:4kB muxing overhead 0.817473%

The file plays fine, and I can encode to WAV or any other format I like. However, when I call ffmpeg from C# with the following code:

string tempfile = Path.GetTempFileName();
FileStream tempfilestr = File.OpenWrite(tempfile);
input.CopyTo(tempfilestr);

ProcessStartInfo pstart = new ProcessStartInfo("ffmpeg", string.Format("-i \"{0}\" -v verbose -y -f wav -", tempfile));
pstart.CreateNoWindow = true;
pstart.ErrorDialog = false;
pstart.RedirectStandardOutput = true;
pstart.RedirectStandardError = true;
pstart.UseShellExecute = false;


Process proc = new Process();
proc.StartInfo = pstart;
proc.Start();
StreamReader stdout = proc.StandardOutput;
StreamReader stderr = proc.StandardError;

outtempfilestr = File.OpenRead(outtempfile);
MemoryStream output = new MemoryStream();

stdout.BaseStream.CopyTo(output);

try {
    proc.Kill();
}
catch(InvalidOperationException) { }
catch(Win32Exception) { }

File.Delete(tempfile);

return output.ToArray();

This randomly produces errors in the output:

ffmpeg version 1.2 Copyright (c) 2000-2013 the FFmpeg developers
  built on Apr  8 2013 15:10:40 with gcc 4.5.3 (GCC)
  configuration: --disable-encoder=vorbis --enable-libvorbis
  libavutil      52. 18.100 / 52. 18.100
  libavcodec     54. 92.100 / 54. 92.100
  libavformat    54. 63.104 / 54. 63.104
  libavdevice    54.  3.103 / 54.  3.103
  libavfilter     3. 42.103 /  3. 42.103
  libswscale      2.  2.100 /  2.  2.100
  libswresample   0. 17.102 /  0. 17.102
[wav @ 0x80053860] parser not found for codec pcm_s16le, packets or times may be invalid.
    Last message repeated 1 times
[wav @ 0x80053860] max_analyze_duration 5000000 reached at 5015510 microseconds
Guessed Channel Layout for  Input Stream #0.0 : stereo
Input #0, wav, from 'C:\Users\Bevin\AppData\Local\Temp\tmp1CCE.tmp':
  Duration: 00:00:05.20, bitrate: 1411 kb/s
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, stereo, s16, 1411 kb/s
[graph 0 input from stream 0:0 @ 0x8011f320] tb:1/44100 samplefmt:s16 samplerate:44100 chlayout:0x3
Output #0, wav, to 'pipe:':
  Metadata:
    ISFT            : Lavf54.63.104
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, stereo, s16, 1411 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (pcm_s16le -> pcm_s16le)
Press [q] to stop, [?] for help
Multiple frames in a packet from stream 0
[pcm_s16le @ 0x8005c160] Invalid PCM packet, data has size 3 but at least a size of 4 was expected
Error while decoding stream #0:0: Invalid data found when processing input
No more output streams to write to, finishing.
size=     896kB time=00:00:05.20 bitrate=1411.3kbits/s    
video:0kB audio:896kB subtitle:0 global headers:0kB muxing overhead 0.008719%

Note that these errors don't always occur. Sometimes they happen for certain files, sometimes they don't. I've tried various combinations of stream redirects and temp files, none of them work. I've also verified the integrity of the temp files, and it all checks out. I've even extracted the temp file before it was deleted, and decoded it in shell without a hitch.

Any ideas?

Edit: I've tried running ffmpeg from a shell script that's run through C#. It gives the same issues. Compiling ffmpeg via MinGW gives the same issue as well.

3
  • have you tried setting the correct working directory? When you ran an application from the shell the shell path (mostly applications directory) is used as the working directory, when you run it from .net the working directory specified is the directory of YOUR .net application Commented Apr 10, 2013 at 10:33
  • @Gam Erix - The file paths passed to ffmpeg are absolute, so I don't think there's any problem on that end. Commented Apr 10, 2013 at 11:08
  • @Bevin How you tried compiling ffmpeg with statically linked libraries? Maybe that'll help with this issue. Additionally, ffmpeg might be looking for the codec (or libavcodec) under the working directory. Can you try setting the working directory (Environment.CurrentDirectory) just before the proc.Start() call? Commented Apr 17, 2013 at 20:16

1 Answer 1

17
+25

It's because of the way you are passing the arguments. Do this:

Process process = new Process();
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.FileName = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) +
                        @"\bin\ffmpeg.exe";

process.StartInfo.Arguments = "-i .\sound1.wav -acodec libvorbis -f ogg abc.ogg";


process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();

This works perfect.

Sign up to request clarification or add additional context in comments.

2 Comments

I agree with Omid and if something you want to work out, you have to use escape character for all special characters..
Shouldn't there be needed literal string or escape the backslash when assigning the argument, i.e., .\sound1.wav would error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.