C# 调用Ffmpeg录制视频流实践
调用Ffmpeg命令行工具录制视频流(以flv >> mp4为例):
.\ffmpeg.exe -i "https://···:···/remote.flv" .\···\local.mp4
针对两种需求:
- 用户指定录制时间
- 用户手动终止录制
针对需求1,可以通过参数实现
https://ffmpeg.org/ffmpeg.html#Main-options
-t duration
在 -i 之前使用,可以限制从数据源读取数据的持续时间
例如,希望录制30s的视频可以:
.\ffmpeg.exe -i "https://···:···/remote.flv" -t 00:00:30 .\···\local.mp4
其他的time duaring格式可以参照https://ffmpeg.org/ffmpeg-utils.html#date-syntax
而对于需求2,则需要手动结束转码程序,以在windows terminal中运行转码命令为例,经过测试:
- 直接关闭窗口
- 输入:q
- 输入:Ctrl+C
录制的视频可以正常播放。 - 直接结束进程
视频无法打开。
创建ffmpeg进程,将pid存入字典
// uid >> ffmpeg process id private static ConcurrentDictionary<string, int> ffmpegs = new ConcurrentDictionary<string,int>(); [HttpPost] public string StartRecordJob(args ...) { const string ffmpegPath = "c:/···/ffmpeg.exe"; var output = @"c:/···/local.mp4"; var cmdStr = $@"-i ""{url}"" {output} -y"; var startInfo = new ProcessStartInfo { FileName = ffmpegPath, Arguments = cmdStr, // 不调用Shell执行 UseShellExecute = false, CreateNoWindow = true, }; var rp = Process.Start(startInfo); var uid = Regex.Replace(Convert.ToBase64String(Guid.NewGuid().ToByteArray()), "[/+=]", ""); var ok = rp != null && ffmpegs.TryAdd(uid, rp.Id); return $"{uid}"; }
在另一个请求中,根据ffmpeg任务的uid,获取进程id,对其进行操作
我的做法是,向进程发送退出(Ctrl+C)命令,以下做法依赖windows环境
https://blog.codetitans.pl/post/sending-ctrl-c-signal-to-another-application-on-windows/
[DllImport("kernel32.dll", SetLastError = true)] static extern bool AttachConsole(uint dwProcessId); [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] static extern bool FreeConsole(); [DllImport("kernel32.dll")] static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate handler, bool add); // Delegate type to be used as the Handler Routine for SCCH delegate Boolean ConsoleCtrlDelegate(CtrlTypes type); // Enumerated type for the control messages sent to the handler routine enum CtrlTypes : uint { CTRL_C_EVENT = 0, CTRL_BREAK_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT = 5, CTRL_SHUTDOWN_EVENT } [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId); public static void StopProgram(uint pid) { // It's impossible to be attached to 2 consoles at the same time, // so release the current one. FreeConsole(); // This does not require the console window to be visible. if (AttachConsole(pid)) { // Disable Ctrl-C handling for our program SetConsoleCtrlHandler(null, true); GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0); // Must wait here. If we don't and re-enable Ctrl-C // handling below too fast, we might terminate ourselves. Thread.Sleep(2000); FreeConsole(); // Re-enable Ctrl-C handling or any subsequently started // programs will inherit the disabled state. SetConsoleCtrlHandler(null, false); } } [HttpDelete] public string StopRecordJob(string uid) { try { threads.TryGetValue(uid, out var p); StopProgram((uint)p); return "true"; } catch (Exception e) { ··· return "not found:"+ p; } }
还有一种做法是将startInfo中的 UseShellExecute
设为 true
,WindowStyle
设为 ProcessWindowStyle.Minimized
。
这样可以通过:
Process.CloseMainWindow()
来结束进程,这种方式的问题是会弹出一个窗口。
站外博客地址:https://blog.yuhang.ch
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南