I am using ffmpeg to capture screen and audio using a C# application. The command I am using to execute ffmpeg as follows:
ffmpeg -f gdigrab -i desktop -f dshow -i audio="Microphone (Realtek High Definition Audio)" -v
codec libx264 output.mp4
Now I want to pause/resume recording and want to control it from the C# application. Is there anyway I can achieve that?
Add Helper class to project as below:
static class Helper
{
public static T[] ToArray<T>(this ICollection collection)
{
var items = new T[collection.Count];
collection.CopyTo(items, 0);
return items;
}
}
Add a class to your project as below:
public static class ProcessExtensions
{
#region Methods
public static void Suspend(this Process process)
{
Action<ProcessThread> suspend = pt =>
{
var threadHandle = NativeMethods.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pt.Id);
if (threadHandle != IntPtr.Zero)
{
try
{
NativeMethods.SuspendThread(threadHandle);
}
finally
{
NativeMethods.CloseHandle(threadHandle);
}
};
};
var threads = process.Threads.ToArray<ProcessThread>();
if (threads.Length > 1)
{
Parallel.ForEach(threads, new ParallelOptions { MaxDegreeOfParallelism = threads.Length }, pt =>
{
suspend(pt);
});
}
else
{
suspend(threads[0]);
}
}
public static void Resume(this Process process)
{
Action<ProcessThread> resume = pt =>
{
var threadHandle = NativeMethods.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pt.Id);
if (threadHandle != IntPtr.Zero)
{
try
{
NativeMethods.ResumeThread(threadHandle);
}
finally
{
NativeMethods.CloseHandle(threadHandle);
}
}
};
var threads = process.Threads.ToArray<ProcessThread>();
if (threads.Length > 1)
{
Parallel.ForEach(threads, new ParallelOptions { MaxDegreeOfParallelism = threads.Length }, pt =>
{
resume(pt);
});
}
else
{
resume(threads[0]);
}
}
#endregion
#region Interop
static class NativeMethods
{
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
public static extern uint SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll")]
public static extern uint ResumeThread(IntPtr hThread);
}
[Flags]
enum ThreadAccess : int
{
TERMINATE = (0x0001),
SUSPEND_RESUME = (0x0002),
GET_CONTEXT = (0x0008),
SET_CONTEXT = (0x0010),
SET_INFORMATION = (0x0020),
QUERY_INFORMATION = (0x0040),
SET_THREAD_TOKEN = (0x0080),
IMPERSONATE = (0x0100),
DIRECT_IMPERSONATION = (0x0200)
}
#endregion
}
Start ffmpeg
as below:
process =new Process();
process.StartInfo.FileName = "ffmpeg";
process.StartInfo.Arguments = "-i foo.VOB blabla.mp4";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
Use process.Suspend();
for Pause and process.Resume();
for Resume. Note that ffmpeg
MUST start from your application. I tested it in windows application and it worked fine.