为什么 ffmpeg 在从我的网络应用程序转换视频时永远不会完成?
我试图在用户提交表单时转换视频。它似乎转换正常,但当我尝试用它做任何事情时,文件“正在被另一个进程使用”。看起来 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;
}
I am trying to convert a video when the user submits a form. It seems to convert ok but the file "is being used by another proccess" when I try to do anything with it. It looks like ffmpeg.exe never exits. My code is below is there anything I should be doing different to allow the process to release the file? If I run this manually it exits fine.
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
经过大量研究后,我发现了这个 帖子。这让我走上了正确的道路。我阅读了有关 RedirectStandardError 的更多信息,发现我需要改变我打电话的顺序。最后调用
WaitForExit
后,一切都按预期进行。这是更新后的代码:After a good bit of research I came across this post. Which set me on the right track. I read more about RedirectStandardError and found I needed to change the order I was calling things. After calling
WaitForExit
at the end everything worked as expected. Here is the updated code:您应该在进程运行时始终读取 StandardOutput 和 StandardError 缓冲区。每当缓冲区达到其限制时,该进程就会挂起,直到您读取缓冲区结束。
FFMpeg 不断报告有关转换的信息。您在命令提示符底部看到的信息的每次更新都会添加到标准输出缓冲区,从而填满缓冲区。转换大文件时,缓冲区可能会很快填满。
You should always read the StandardOutput and the StandardError buffers while the process is running. Whenever the buffers reach their limits, the process will literally hang until you read the buffers to end.
FFMpeg constantly reports information about the conversion. Every update of the information you see in the bottom of the Command Prompt is added to the StandardOutput buffer, thus filling up the buffer. The buffer is likely to fill up quickly when converting large files.
您的 Web 应用程序(应用程序池进程标识)是否具有在您生成的进程线程中执行的操作的适当权限?
我过去曾遇到过与从 ASP.NET 运行进程线程执行 IO 的
System.File.Move
相关的问题,这实际上是一个 Win32 问题。使用 System.File.Copy 或 Win32 等效项,然后删除旧文件(如果可以)。我的猜测是您调用(执行)的 .exe 不是您的(您自己的源代码可以修改)并且您无法更改它。
您还可以使用 SysInternals 查看可能占用或阻止资源的内容。
Does your web application(app pool process identity) have the proper permissions for what's being done in the process threads you are spawning?
I have had issues like this in the past related to
System.File.Move
running Process Threads doing IO from ASP.NET, which is really a Win32 issue under the hood.Use
System.File.Copy
or the Win32 equivalent and then delete the old file if you can. My guess is the .exe you are calling out(executing) to isn't yours(your own source code to be able to modify) and you can't change it.You can also use SysInternals to see what may be holding on to or blocking resources.