问题
This is actually related to another question I had that was already answered. That question is here: Redirecting stdout of one process object to stdin of another
My issue is (I think) that the program who is getting the input should exit before the program outputting. Here is the bash equivalent of what I'm doing: tccat -i /dev/sr0 -T 1 | ffmpeg -i - -r 1 -t 1 -s 96x72 -ss 5 /tmp/wsmanage/preview_tmp/test\%03d.jpg
This just uses a program called tccat to read the first title of a dvd. That gets output to ffmpeg, which is going to create an output file at 1 frame per second that is 1 second long in .jpg format. As soon as it outputs its frame (or two) it exists. This works fine.
The following code, however, does not. I get scads of "Printing line to ffmpeg", whereas the command line version exits in just over a second. Then, it just stops printing after 30 or 40 seconds or so. FFmpeg never exits, and my program never continues.
I'm I doing this right?
Process tccatProcess = new Process();
tccatProcess.StartInfo.FileName = "tccat";
tccatProcess.StartInfo.Arguments = String.Format("-i {0} -T {1}", devNode, title);
tccatProcess.StartInfo.UseShellExecute = false;
tccatProcess.StartInfo.RedirectStandardOutput = true;
Process ffmpegProcess = new Process();
string bashSafePreviewTemplate = slasher.bashSlash(previewTempDir + "/test%03d.jpg");
ffmpegProcess.StartInfo.FileName = "ffmpeg";
ffmpegProcess.StartInfo.Arguments = String.Format("-i - -r 1 -t 1 -s {1}x{2} -ss {3} {0}",
bashSafePreviewTemplate, width, height, timePosition);
ffmpegProcess.StartInfo.UseShellExecute = false;
ffmpegProcess.StartInfo.RedirectStandardInput = true;
try{
tccatProcess.Start();
ffmpegProcess.Start();
StreamReader tccatOutput = tccatProcess.StandardOutput;
StreamWriter ffmpegInput = ffmpegProcess.StandardInput;
string line;
while(!ffmpegProcess.HasExited)
{
ffmpegProcess.Refresh();
if((line = tccatOutput.ReadLine()) != null)
{
Console.WriteLine("Printing line to ffmpeg");
Console.Out.Flush();
ffmpegInput.WriteLine(line);
ffmpegInput.Flush();
}
}
Console.WriteLine("Closing tccat");
Console.Out.Flush();
tccatProcess.Close();
Console.WriteLine("Tccat closed");
Console.Out.Flush();
}catch(Exception e){
//uninteresting log code
return false;
}
回答1:
Doesn't tccat output binary data since you're working with video and images? If so shouldn't you be reading/writing to the input/output streams directly rather than wrapping them in a text reader?
If so you want to be using Can i put binary in stdin? C#
回答2:
For anyone who wants to do something similar, here is the new version with KeeperOfTheSoul's advice applied:
Process tccatProcess = new Process();
tccatProcess.StartInfo.FileName = "tccat";
tccatProcess.StartInfo.Arguments = String.Format("-i {0} -T {1}", devNode, title);
tccatProcess.StartInfo.UseShellExecute = false;
tccatProcess.StartInfo.RedirectStandardOutput = true;
Process ffmpegProcess = new Process();
string bashSafePreviewTemplate = slasher.bashSlash(previewTempDir + "/test%03d.jpg");
ffmpegProcess.StartInfo.FileName = "ffmpeg";
ffmpegProcess.StartInfo.Arguments = String.Format("-i - -r 1 -t 1 -s {1}x{2} -ss {3} {0}",
bashSafePreviewTemplate, width, height, timePosition);
ffmpegProcess.StartInfo.UseShellExecute = false;
ffmpegProcess.StartInfo.RedirectStandardInput = true;
Console.WriteLine("tccat command: {0} {1}", tccatProcess.StartInfo.FileName, tccatProcess.StartInfo.Arguments);
Console.WriteLine("ffmpeg command: {0} {1}", ffmpegProcess.StartInfo.FileName, ffmpegProcess.StartInfo.Arguments);
//return true;
try{
tccatProcess.Start();
ffmpegProcess.Start();
BinaryReader tccatOutput = new BinaryReader(tccatProcess.StandardOutput.BaseStream);
BinaryWriter ffmpegInput = new BinaryWriter(ffmpegProcess.StandardInput.BaseStream);
int buffSize = 4096;
byte[] buff = new byte[buffSize];
while(!ffmpegProcess.HasExited)
{
ffmpegProcess.Refresh();
buff = tccatOutput.ReadBytes(buffSize);
ffmpegInput.Write(buff);
ffmpegInput.Flush();
}
tccatProcess.Kill();
tccatProcess.Close();
ffmpegProcess.Close();
}catch(Exception e){
//uninteresting log code
return false;
}
来源:https://stackoverflow.com/questions/1373387/redirecting-stdin-and-stdout-where-stdin-closes-first