This question has already been solved
You
Hi,
I am running 3 threads that each start an ffmpeg process to extract 3 snapshots form a video file.
I need to be able to call this method multiple times, with different video files.
It writes the three snapshots to the system.
However If I try to delete these files using File.Delete, it throws an exception.
Here is the code:
namespace runFFmpeg
{
public struct ThreadData
{
public string time;
public string inputFilename;
public string outputFilename;
}
/// <summary>
/// Description of MyClass.
/// </summary>
public class FfmpegBitmapCapture
{
private string output1;
private string output2;
private string pathToFfmpg = "..\\..\\lib\\ffmpeg.exe";
private SnapshotItem[] snapshotItems = new SnapshotItem[3];
private TimeSpan executionTime;
public SnapshotItem[] SnapshotItems
{
get { return snapshotItems; }
}
public TimeSpan ExecutionTime
{
get { return this.executionTime;}
}
public FfmpegBitmapCapture(string filename, int percentFirst, int percentSecond, int percentThird)
{
GetSnapshotTimes(percentFirst,percentSecond,percentThird,filename);
SmallLogger.SmallLogger.LogMessageToFile("ffmpeg: filename " + filename);
ThreadData tdStart = new ThreadData();
tdStart.inputFilename = filename;
tdStart.outputFilename = this.GetTempPath() + "vidLib_snapshot[1].jpg";
tdStart.time = snapshotItems[0].Time.ToString();
Thread startThread = new Thread(new ParameterizedThreadStart(ExtractSnapshot));
ThreadData tdMiddle = new ThreadData();
tdMiddle.inputFilename = filename;
tdMiddle.outputFilename = this.GetTempPath() + "vidLib_snapshot[2].jpg";
tdMiddle.time = snapshotItems[1].Time.ToString();
Thread middleThread = new Thread(new ParameterizedThreadStart(ExtractSnapshot));
ThreadData tdEnd = new ThreadData();
tdEnd.inputFilename = filename;
tdEnd.outputFilename = this.GetTempPath() + "vidLib_snapshot[3].jpg";
tdEnd.time = snapshotItems[2].Time.ToString();
Thread endThread = new Thread(new ParameterizedThreadStart(ExtractSnapshot));
DateTime startTime = DateTime.Now;
startThread.Start(tdStart);
middleThread.Start(tdMiddle);
endThread.Start(tdEnd);
startThread.Join();
middleThread.Join();
endThread.Join();
this.snapshotItems[0].Thumbnail = new Bitmap(tdStart.outputFilename);
this.snapshotItems[1].Thumbnail = new Bitmap(tdMiddle.outputFilename);
this.snapshotItems[2].Thumbnail = new Bitmap(tdEnd.outputFilename);
try
{
File.Delete(tdStart.outputFilename);
File.Delete(tdMiddle.outputFilename);
File.Delete(tdEnd.outputFilename);
}
catch(Exception ex)
{
System.Console.Out.WriteLine(ex);
}
DateTime stopTime = DateTime.Now;
this.executionTime = stopTime - startTime;
}
void ExtractSnapshot(object threadData)
{
ThreadData td = (ThreadData)threadData;
string outFileName = td.outputFilename;
//from http://dotnetperls.com/process-redirect-standard-output
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = this.pathToFfmpg;
start.Arguments = "-i \"" + td.inputFilename + "\" -r 1 -f mjpeg -vframes 1 -ss " + td.time + " -y " + outFileName;
//start.Arguments = "-h";
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
start.CreateNoWindow = true;
//using(Process process = Process.Start(start))
//{
Process process = new Process();
process.StartInfo = start;
process.Start();
using(StreamReader reader = process.StandardOutput)
{
output1 = reader.ReadToEnd();
}
using (StreamReader reader2 = process.StandardError)
{
output2 = reader2.ReadToEnd();
}
process.WaitForExit();
process.Close();
//}
}
private string GetTempPath()
{
string path = System.Environment.GetEnvironmentVariable("TEMP");
if (!path.EndsWith("\\")) path += "\\";
return path;
}
private void GetSnapshotTimes(int percentFirst,
int percentMiddle,
int percentLast,
string filename)
{
string outputList;
TimeSpan middle;
TimeSpan end;
TimeSpan begin;
ProcessStartInfo start = new ProcessStartInfo();
//start.FileName = "C:\\Users\\daddy\\Downloads\\ffmpeg-latest\\bin\\ffmpeg.exe";
start.FileName = this.pathToFfmpg;
start.Arguments = "-i \"" + filename + "\"";
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
start.CreateNoWindow = true;
using(Process process = Process.Start(start))
{
using (StreamReader reader2 = process.StandardError)
{
outputList = reader2.ReadToEnd();
}
process.WaitForExit();
}
Regex regex = new Regex("Duration: +(?<dur>\\d\\d:\\d\\d:\\d\\d.\\d+)");
Match m = regex.Match(outputList);
if(m.Success)
{
TimeSpan OneSecond = TimeSpan.Parse("00:00:01.00");
long OneseconTicks = OneSecond.Ticks;
string duration = m.Groups["dur"].Value;
TimeSpan ts = TimeSpan.Parse(duration);
long durTicks = ts.Ticks;
if(durTicks <= OneseconTicks){
begin = TimeSpan.FromTicks((long)((double)durTicks * 0.05));
end = begin;
middle = begin;
}
else
{
middle = TimeSpan.FromTicks((long)((double)durTicks * ((double)percentMiddle)/100.0));
end = TimeSpan.FromTicks((long)((double)durTicks * ((double)percentLast)/100.0));
begin = TimeSpan.FromTicks((long)((double)durTicks * ((double)percentFirst)/100.0));
}
this.snapshotItems[0].Time = begin;
this.snapshotItems[1].Time = middle;
this.snapshotItems[2].Time = end;
}
}
}
}
Regards,
John
Hi, I am running 3 threads that each start an ffmpeg process to extract 3 snapshots form a video file. I need to be able to call this method multiple times, with different video files. It writes the three snapshots to the system. However If I try to delete these files using File.Delete, it throws an exception.
Here is the code:
namespace runFFmpeg { public struct ThreadData { public string time; public string inputFilename; public string outputFilename; } /// <summary> /// Description of MyClass. /// </summary> public class FfmpegBitmapCapture { private string output1; private string output2; private string pathToFfmpg = "..\\..\\lib\\ffmpeg.exe"; private SnapshotItem[] snapshotItems = new SnapshotItem[3]; private TimeSpan executionTime; public SnapshotItem[] SnapshotItems { get { return snapshotItems; } } public TimeSpan ExecutionTime { get { return this.executionTime;} } public FfmpegBitmapCapture(string filename, int percentFirst, int percentSecond, int percentThird) { GetSnapshotTimes(percentFirst,percentSecond,percentThird,filename); SmallLogger.SmallLogger.LogMessageToFile("ffmpeg: filename " + filename); ThreadData tdStart = new ThreadData(); tdStart.inputFilename = filename; tdStart.outputFilename = this.GetTempPath() + "vidLib_snapshot[1].jpg"; tdStart.time = snapshotItems[0].Time.ToString(); Thread startThread = new Thread(new ParameterizedThreadStart(ExtractSnapshot)); ThreadData tdMiddle = new ThreadData(); tdMiddle.inputFilename = filename; tdMiddle.outputFilename = this.GetTempPath() + "vidLib_snapshot[2].jpg"; tdMiddle.time = snapshotItems[1].Time.ToString(); Thread middleThread = new Thread(new ParameterizedThreadStart(ExtractSnapshot)); ThreadData tdEnd = new ThreadData(); tdEnd.inputFilename = filename; tdEnd.outputFilename = this.GetTempPath() + "vidLib_snapshot[3].jpg"; tdEnd.time = snapshotItems[2].Time.ToString(); Thread endThread = new Thread(new ParameterizedThreadStart(ExtractSnapshot)); DateTime startTime = DateTime.Now; startThread.Start(tdStart); middleThread.Start(tdMiddle); endThread.Start(tdEnd); startThread.Join(); middleThread.Join(); endThread.Join(); this.snapshotItems[0].Thumbnail = new Bitmap(tdStart.outputFilename); this.snapshotItems[1].Thumbnail = new Bitmap(tdMiddle.outputFilename); this.snapshotItems[2].Thumbnail = new Bitmap(tdEnd.outputFilename); try { File.Delete(tdStart.outputFilename); File.Delete(tdMiddle.outputFilename); File.Delete(tdEnd.outputFilename); } catch(Exception ex) { System.Console.Out.WriteLine(ex); } DateTime stopTime = DateTime.Now; this.executionTime = stopTime - startTime; } void ExtractSnapshot(object threadData) { ThreadData td = (ThreadData)threadData; string outFileName = td.outputFilename; //from http://dotnetperls.com/process-redirect-standard-output ProcessStartInfo start = new ProcessStartInfo(); start.FileName = this.pathToFfmpg; start.Arguments = "-i \"" + td.inputFilename + "\" -r 1 -f mjpeg -vframes 1 -ss " + td.time + " -y " + outFileName; //start.Arguments = "-h"; start.UseShellExecute = false; start.RedirectStandardOutput = true; start.RedirectStandardError = true; start.CreateNoWindow = true; //using(Process process = Process.Start(start)) //{ Process process = new Process(); process.StartInfo = start; process.Start(); using(StreamReader reader = process.StandardOutput) { output1 = reader.ReadToEnd(); } using (StreamReader reader2 = process.StandardError) { output2 = reader2.ReadToEnd(); } process.WaitForExit(); process.Close(); //} } private string GetTempPath() { string path = System.Environment.GetEnvironmentVariable("TEMP"); if (!path.EndsWith("\\")) path += "\\"; return path; } private void GetSnapshotTimes(int percentFirst, int percentMiddle, int percentLast, string filename) { string outputList; TimeSpan middle; TimeSpan end; TimeSpan begin; ProcessStartInfo start = new ProcessStartInfo(); //start.FileName = "C:\\Users\\daddy\\Downloads\\ffmpeg-latest\\bin\\ffmpeg.exe"; start.FileName = this.pathToFfmpg; start.Arguments = "-i \"" + filename + "\""; start.UseShellExecute = false; start.RedirectStandardOutput = true; start.RedirectStandardError = true; start.CreateNoWindow = true; using(Process process = Process.Start(start)) { using (StreamReader reader2 = process.StandardError) { outputList = reader2.ReadToEnd(); } process.WaitForExit(); } Regex regex = new Regex("Duration: +(?<dur>\\d\\d:\\d\\d:\\d\\d.\\d+)"); Match m = regex.Match(outputList); if(m.Success) { TimeSpan OneSecond = TimeSpan.Parse("00:00:01.00"); long OneseconTicks = OneSecond.Ticks; string duration = m.Groups["dur"].Value; TimeSpan ts = TimeSpan.Parse(duration); long durTicks = ts.Ticks; if(durTicks <= OneseconTicks){ begin = TimeSpan.FromTicks((long)((double)durTicks * 0.05)); end = begin; middle = begin; } else { middle = TimeSpan.FromTicks((long)((double)durTicks * ((double)percentMiddle)/100.0)); end = TimeSpan.FromTicks((long)((double)durTicks * ((double)percentLast)/100.0)); begin = TimeSpan.FromTicks((long)((double)durTicks * ((double)percentFirst)/100.0)); } this.snapshotItems[0].Time = begin; this.snapshotItems[1].Time = middle; this.snapshotItems[2].Time = end; } } } }Regards, John
OK, I fixed the problem myself.
I found that the lines, such as:
this.snapshotItems[0].Thumbnail = new Bitmap(tdStart.outputFilename);
lock the bitmap files that have been written out.
I changed these lines to:
using(Bitmap bm = new Bitmap(dStart.outputFilename))
{
this.snapshotItems[0].Thumbnail = bm;
} This closes and disposes of the Bitmap, and I can then delete the file.
I am sure there are other solutions, any help appreciated.
John