ASP.NET Core mvc 应用程序中的 FFMPEG 录制
Posted
技术标签:
【中文标题】ASP.NET Core mvc 应用程序中的 FFMPEG 录制【英文标题】:FFMPEG recording in ASP.NET Core mvc application 【发布时间】:2020-03-31 16:43:22 【问题描述】:我正在使用 ASP.NET Core 和 ffmpeg 录制实时视频流。当页面收到获取请求时,流应该开始记录并使用 ffmpeg 保存到文件夹。我想让它在访问 stop 端点时干净地关闭 ffmpeg 进程。
不幸的是,在离开 Get 方法后,我无法向标准输入发送“q”。使用 taskkill 需要使用 /F 使 ffmpeg 进程(不是窗口)强制退出并且不能正确保存视频,从而导致文件损坏。
我尝试使用Process.Kill()
,但这也会导致文件损坏。另外,我尝试了Process.CloseMainWindow()
,它有效,但只有当进程作为窗口启动时,我无法在我正在使用的服务器中将进程作为窗口启动。
我已经在下面包含了到目前为止的代码,所以希望有人能引导我走上正确的道路。
using System;
...
using Microsoft.Extensions.Logging;
namespace MyApp.Controllers
[Route("api/[controller]")]
[Authorize]
public class RecordingController : Controller
private readonly ApplicationDbContext _context;
private readonly ILogger<HomeController> _logger;
public RecordingController(ApplicationDbContext context, ILogger<HomeController> logger)
_context = context;
_logger = logger;
[HttpGet]
public async Task<ActionResult> Get()
// Define the os process
var processStartInfo = new ProcessStartInfo()
// ffmpeg arguments
Arguments = "-f mjpeg -i \"https://urlofstream.com/video.gci\" -r 5 \"wwwroot/video.mp4\"",
FileName = "ffmpeg.exe",
UseShellExecute = true
;
var p1 = Process.Start(processStartInfo);
// p1.StandardInput.WriteLineAsync("q"); <-- This works here but not in the Stop method
return Ok(p1.Id);
// GET: api/Recording/stop
[HttpGet("stop/pid")]
public ActionResult Stop(int pid)
Process processes = Process.GetProcessById(pid);
processes.StandardInput.WriteLineAsync("q"); // Does not work, is not able to redirect input
return Ok();
【问题讨论】:
【参考方案1】:我发现了一个解决这个问题的方法,希望可以帮助其他人。解决方案是使用 Singleton 和 ConcurrentDictionary 的组合并写入 StandardInput。您可以写入正在运行的进程的标准输入的唯一方法是,如果您仍然可以访问已启动的进程句柄,并且您无法从控制器内访问它,因此您需要创建一个单例并存储进程在 ConcurrentDictionary 中(非常适合从多个线程进行更新)。
首先我创建了一个记录管理器类。 RecordingManager.cs
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace MyApp.Services
public class RecordingManager
// Key int is the ProcessId. Value process is the running Process
private static ConcurrentDictionary<int, Process> _processes = new ConcurrentDictionary<int, Process>();
public Process Start()
// Define the os process
var processStartInfo = new ProcessStartInfo()
// ffmpeg arguments
Arguments = "-f mjpeg -i https://urlofstream.com/video.gci -r 5 wwwroot/video.mp4",
FileName = "ffmpeg.exe",
RedirectStandardInput = true, // Must be set to true
UseShellExecute = false // Must be set to false
;
Process p = Process.Start(processStartInfo);
// Add the Process to the Dictionary with Key: Process ID and value as the running process
_processes.TryAdd(p1.Id, p);
return p;
private Process GetProcessByPid(int pid)
return _processes.FirstOrDefault(p => p.Key == pid).Value;
public void Stop(int pid)
Process p = GetProcessByPid(pid);
// FFMPEG Expects a q written to the STDIN to stop the process
p.StandardInput.WriteLine("q\n");
_processes.TryRemove(pid, out p);
// Free up resources
p.Close()
接下来,我将单例添加到 ConfigureServices 方法中的 startup.cs 类中
services.AddSingleton<RecordingManager>();
最后,我将单例添加到我的控制器构造函数并在那里调用方法。 RecordingController.cs
namespace MyApp.Controllers
[Route("api/[controller]")]
[Authorize]
public class RecordingController : Controller
private readonly ApplicationDbContext _context;
private readonly ILogger<HomeController> _logger;
private readonly RecordingManager _recordingManager;
public RecordingController(ApplicationDbContext context, ILogger<HomeController> logger, RecordingManager recordingManager)
_context = context;
_logger = logger;
_recordingManager = recordingManager;
[HttpGet]
public async Task<ActionResult> Get()
Process p = _recordingManager.Start();
return Ok(p.Id); // Wouldn't recommend simply returning an Ok Result here. Check for issues
// GET: api/Recording/stop
[HttpGet("stop/pid")]
public ActionResult Stop(int pid)
_recordingManager.Stop(pid);
return Ok(); // Wouldn't recommend simply returning an Ok Result here. Check for issues
【讨论】:
以上是关于ASP.NET Core mvc 应用程序中的 FFMPEG 录制的主要内容,如果未能解决你的问题,请参考以下文章
Asp.Net Core MVC 中的 Request.IsAjaxRequest() 在哪里?
从 ASP.net Core 2 MVC 应用程序中的 appSettings.json 存储/检索 ConnectionString