我正在尝试在用户提交表单时转换视频。它似乎转换正常,但当我尝试用它做任何事情时,文件“被另一个进程使用”。看起来ffmpeg.exe永远不会退出。我的代码在下面是否有任何我应该做的不同以允许进程释放文件?如果我手动运行它会退出。
internal class ConversionUtility : Utility
{
public void Convert(string videoFileName)
{
var video = new VideoFile(videoFileName);
if (!video.infoGathered)
GetVideoInfo(video);
var Params = string.Format("-y -i \"{0}\" -coder ac -me_method full -me_range 16 -subq 5 -sc_threshold 40 -vcodec libx264 -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -i_qfactor 0.71 -keyint_min 25 -b_strategy 1 -g 250 -r 20 \"{1}\"", video.Path, Path.ChangeExtension(videoFileName,".mp4"));
//var Params = string.Format("-y -i \"{0}\" -acodec libfaac -ar 44100 -ab 96k -coder ac -me_method full -me_range 16 -subq 5 -sc_threshold 40 -vcodec libx264 -s 1280x544 -b 1600k -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -i_qfactor 0.71 -keyint_min 25 -b_strategy 1 -g 250 -r 20 c:\\output3.mp4", video.Path, videoFileName);
//var Params = String.Format(" {0} \"{1}\"",this.FFmpegLocation, video.Path);
var threadStart = new ParameterizedThreadStart(del => RunProcess(Params));
var thread = new Thread(threadStart);
thread.Start();
//RunProcess(Params);
}
}
internal class Utility
{
public string FFmpegLocation { get; set; }
private string WorkingPath { get { return Path.GetDirectoryName(FFmpegLocation); } }
protected string RunProcess(string Parameters)
{
//create a process info
var oInfo = new ProcessStartInfo(this.FFmpegLocation, Parameters)
{
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
//Create the output and streamreader to get the output
string output = null; StreamReader srOutput = null;
//try the process
try
{
//run the process
Process proc = System.Diagnostics.Process.Start(oInfo);
proc.WaitForExit();
//if (!proc.WaitForExit(10000))
// proc.Kill();
//get the output
srOutput = proc.StandardError;
//now put it in a string
output = srOutput.ReadToEnd();
proc.Close();
}
catch (Exception)
{
output = string.Empty;
}
finally
{
//now, if we succeded, close out the streamreader
if (srOutput != null)
{
srOutput.Close();
srOutput.Dispose();
}
}
return output;
}
答案 0 :(得分:3)
经过一番研究后,我发现了post。这让我走上正轨。我阅读了更多关于RedirectStandardError的内容,发现我需要改变我调用的顺序。在最后调用WaitForExit
后,一切都按预期工作。这是更新的代码:
protected string RunProcess(string Parameters)
{
//create a process info
var oInfo = new ProcessStartInfo(this.FFmpegLocation, Parameters)
{
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
var output = string.Empty;
try
{
Process process = System.Diagnostics.Process.Start(oInfo);
output = process.StandardError.ReadToEnd();
process.WaitForExit();
process.Close();
}
catch (Exception)
{
output = string.Empty;
}
return output;
}
答案 1 :(得分:0)
您的Web应用程序(应用程序池进程标识)是否对您正在生成的进程线程中执行的操作具有适当的权限?
过去我遇到过与System.File.Move
运行进程线程从ASP.NET做IO的问题有关的问题,这实际上是一个Win32问题。
使用System.File.Copy
或Win32等效项,然后删除旧文件(如果可以)。我的猜测是你调用(执行)的.exe不是你的(你自己的源代码能够修改),你不能改变它。
您还可以使用SysInternals查看可能持有或阻止资源的内容。
答案 2 :(得分:0)
您应该在进程运行时始终读取StandardOutput和StandardError缓冲区。每当缓冲区达到极限时,该过程将逐渐挂起,直到您阅读缓冲区结束。
FFMpeg会不断报告有关转化的信息。您在命令提示符底部看到的每次更新信息都会添加到StandardOutput缓冲区,从而填满缓冲区。转换大文件时,缓冲区可能会很快填满。