在 laravel 中实现视频转码队列,核心做法是利用 queue 组件配合 dispatch() 将耗时的转码任务推入后台执行。你需要定义一个实现了 shouldqueue 接口的 job 类,在其中调用 ffmpeg 等工具处理视频文件,并通过配置 broadcast_driver 和 queue_connection 指定 redis 或数据库作为驱动。这样前端提交上传请求后会立即返回,实际转码由 worker 异步完成,避免阻塞主线程。

如何定义支持队列的转码 Job 类
定义 Job 类时,必须实现 Illuminate\Contracts\Queue\ShouldQueue 接口,并注入依赖如 Storage 门面或具体的路径参数。在 handle() 方法中编写实际的 FFmpeg 命令执行逻辑,确保捕获异常并处理临时文件清理。该类实例化后可通过 VideoTranscodeJob::dispatch($fileId) 触发,Laravel 会自动将其序列化并发送到队列连接中。

namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Storage;
class VideoTranscodeJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $fileId;
public function __construct($fileId)
{
$this->fileId = $fileId;
}
public function handle()
{
$path = Storage::disk('public')->path("videos/{$this->fileId}.mp4");
if (!file_exists($path)) {
return false;
}
$outputPath = Storage::disk('public')->path("transcoded/{$this->fileId}_720p.mp4");
$command = "ffmpeg -i {$path} -vf scale=1280:720 -c:a copy {$outputPath}";
exec($command . ' 2>&1', $output, $returnCode);
if ($returnCode !== 0) {
throw new \Exception("FFmpeg failed for file {$this->fileId}");
}
// 可选:删除原文件以节省空间
// Storage::disk('public')->delete("videos/{$this->fileId}.mp4");
}
}
如何配置队列驱动与启动 Worker
配置阶段需在 .env 文件中设置 QUEUE_CONNECTION=redis 并确保 Redis 服务可用,或者使用 database 驱动进行开发测试。安装 Redis 扩展后,Laravel 会使用 php artisan queue:work 启动监听进程。Worker 从队列中取出 Job 实例并调用其 handle() 方法。若使用数据库驱动,需先运行 php artisan queue:table 生成数据表并迁移。生产环境建议使用 Supervisor 管理 Worker 进程以保证稳定性。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
立即学习“PHP免费学习笔记(深入)”;

# .env 示例配置 BROADCAST_DRIVER=log CACHE_DRIVER=file SESSION_DRIVER=file QUEUE_CONNECTION=redis # 或使用 database 驱动 # QUEUE_CONNECTION=database
当 FFmpeg 命令执行失败时如何处理重试机制
当 handle() 方法抛出异常时,Laravel 队列系统会根据配置自动重试该 Job。默认情况下,如果未指定 tries 属性,Job 会无限重试直到成功或达到最大超时时间。可以通过在 Job 类中定义 public $tries = 3; 来限制重试次数,或定义 public $timeout = 60; 设置单个 Job 的最大执行时间。此外,可以重写 failed() 方法来记录错误日志或发送通知,例如将失败的 fileId 存入数据库以便人工介入。这种机制确保了在网络波动或资源暂时不可用时,转码任务不会直接丢失。


















