Elixir后台长时间运行任务未完成且偶发崩溃问题求助
实现异步转码的视频上传端点方案
针对你需要实现的异步转码视频上传端点,我整理了一套适配Phoenix框架的实现方案,完全满足你提到的「上传后复制到临时目录、后台启动ffmpeg转码、立即返回200响应」的需求:
核心实现思路
- 接收上传文件后,生成唯一标识并将文件复制到指定临时目录
- 启动独立异步进程执行ffmpeg转码操作,不阻塞当前请求处理
- 立即向客户端返回成功响应,无需等待转码完成
完整控制器代码示例
defmodule MyApp.VideoController do use MyApp.Web, :controller alias MyApp.Video def create(conn, %{"file" => file}) do # 生成唯一UUID作为视频的临时标识 uuid = Video.uuid() # 从应用配置读取临时目录,默认使用系统临时目录下的videos文件夹 temp_dir = Application.get_env(:my_app, :temp_video_storage) || "/tmp/videos" # 确保临时目录存在(不存在则创建) File.mkdir_p!(temp_dir) # 复制上传的原始文件到临时目录,避免原文件被框架自动清理 original_temp_path = Path.join(temp_dir, "#{uuid}_original.mp4") File.cp!(file.path, original_temp_path) # 启动异步任务执行ffmpeg转码 Task.start(fn -> # 定义转码后的输出路径 transcoded_path = Path.join(temp_dir, "#{uuid}_transcoded.mp4") # 执行ffmpeg转码命令,可根据需求调整参数(比如分辨率、码率) {output, exit_code} = System.cmd("ffmpeg", [ "-i", original_temp_path, "-c:v", "libx264", # 使用H.264视频编码 "-crf", "23", # 视频质量参数(值越小质量越高) "-preset", "medium",# 编码速度/压缩比平衡 "-c:a", "aac", # 使用AAC音频编码 "-b:a", "128k", # 音频码率 "-y", # 覆盖已存在的输出文件 transcoded_path ]) # 转码完成后的后续操作示例 if exit_code == 0 do # 转码成功:可以将文件移动到永久存储、更新数据库中视频的状态 # Video.update_transcoding_status(uuid, :completed) # File.rename(transcoded_path, Path.join(permanent_dir, "#{uuid}.mp4")) else # 转码失败:记录错误日志、更新状态为失败 # Logger.error("转码失败,视频ID:#{uuid},错误信息:#{output}") # Video.update_transcoding_status(uuid, :failed) end end) # 立即返回200响应,告知客户端上传成功且转码已启动 conn |> put_status(:ok) |> json(%{ message: "视频上传成功,后台转码已启动", video_id: uuid }) end end
关键细节解释
- 文件复制逻辑:Phoenix会将上传的临时文件存在系统临时目录,且可能在请求结束后清理,所以我们需要主动复制到自定义临时目录,保证转码过程中文件不会丢失。
- 异步任务启动:使用
Task.start/1创建独立进程执行转码,当前控制器进程不会等待转码完成,能快速响应客户端。如果需要更可靠的任务管理(比如失败重试、分布式执行),建议使用Oban这类专业任务队列。 - ffmpeg参数配置:示例中的参数是通用的H.264/AAC转码配置,你可以根据需求调整,比如添加
-s 1920x1080指定1080P分辨率,或者更换编码格式。 - 错误处理:在异步任务中捕获ffmpeg的退出码和输出信息,方便排查转码失败的原因,同时可以更新数据库中视频的状态,让客户端能查询转码进度。
生产环境注意事项
- 资源限制:ffmpeg转码是CPU密集型操作,生产环境中要限制同时运行的转码任务数量,避免服务器资源耗尽。
- 临时文件清理:要定期清理临时目录中的过期文件(比如超过7天的未转码完成文件、转码后的临时文件),可以通过定时任务实现。
- 日志监控:要记录转码任务的执行日志,包括成功和失败的情况,方便运维排查问题。
内容的提问来源于stack exchange,提问作者Kulix
相关产品推荐
相关产品推荐

