作为一点背景,我有一个负责视频上传的端点。我想要做的是将视频文件复制到请求的临时位置,并启动异步任务(ffmpeg shell进程)以在后台转码该视频,以便我的端点可以及时返回200,并且响应不会等待ffmpeg完成对该视频的转码。
这是我的控制器代码。
def create(conn, %{"file" => file ... })
uuid = Video.uuid()
tmp_path = Application.get_env(:myapp, :video_tmp_path) <> "/" <> uuid
:ok = File.cp(file.path, tmp_path)
VideoService.process(tmp_path, final_path)
VideoService的内部如下所示。
defmodule MyApp.Services do
defmodule VideoService do
def process(tmp_path, final_path) do
Task.start_link fn ->
System.cmd("ffmpeg", ["-i", tmp_path, final_path, "-hide_banner"])
File.rm(tmp_path)
end
end
end
end
我遇到的问题是,无论如何,System.cmd("ffmpeg")
调用都会在VideoService
之后执行,有时System.cmd
调用甚至不会启动{ {1}}进程。我在这里做错了吗?我需要的是一种从控制器/服务在后台旋转此ffmpeg
shell进程的方法,并在视频上传时响应200。提前感谢您的帮助。我是elixir / OTP的新手,所以我确定我做的事情很愚蠢。
我也随机看到以下错误
ffmpeg
答案 0 :(得分:2)
感谢mudasobwa和Dogbert的帮助回答了这个问题。我跟着this guide找到了一个独立的主管,并按照他们的建议在我的凤凰堆中运行。这样做的要点是在lib/myapp.ex
添加一行,创建一个像这样的主管
supervisor(Task.Supervisor, [[name: MyApp.TaskSupervisor]])
然后,当您想要以该主管作为父项运行任务时,您可以运行
Task.Supervisor.start_child(MyApp.TaskSupervisor, fn -> do_stuff() end)
就我而言,do_stuff涉及产生ffmpeg进程并进行一些文件清理。这里的基本想法是,你正在以Supervisor作为父母进行这项工作,这样即使请求退出并且该过程终止,你的主管仍然活着并且很好,因为当你的应用程序启动时它总是在运行。