php视频转码使用异步队列处理的核心做法是:web端接收上传后仅生成任务记录并返回,随后通过消息队列(如rabbitmq或redis)将转码指令发送给worker进程执行。这样做能避免http请求超时,提升用户体验,同时利用多进程并行处理提高吞吐量。

如何设计任务状态流转机制
在数据库设计中,需要为每个转码任务维护明确的状态字段,通常包括pending、processing、completed和failed。当用户提交视频时,系统立即创建一条状态为pending的记录并返回任务ID。Worker从队列获取任务后,将状态更新为processing,执行ffmpeg命令。成功后更新为completed并存储结果URL,失败则标记为failed并记录错误信息。这种状态机模式确保了前端轮询或WebSocket推送时的数据一致性。

CREATE TABLE `video_tasks` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) NOT NULL,
`original_url` varchar(500) NOT NULL,
`status` enum('pending','processing','completed','failed') DEFAULT 'pending',
`result_url` varchar(500) DEFAULT NULL,
`error_msg` text DEFAULT NULL,
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Worker进程如何高效执行转码
Worker进程应当采用长驻内存的方式运行,避免每次任务都重新加载框架或初始化数据库连接。推荐使用Swoole或Workerman等协程/多进程框架,或者传统的CLI脚本配合Supervisor管理。在执行ffmpeg时,建议设置合理的超时时间和资源限制,防止单个大文件转码阻塞整个Worker。同时,应实现断点续传或重试机制,以应对网络波动导致的下载失败或转码中断。

// Worker.php
require_once 'vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('video_transcode', false, true, false, false);
$callback = function($msg) {
$data = json_decode($msg->body, true);
$taskId = $data['task_id'];
$inputUrl = $data['input_url'];
// 更新状态为 processing
updateStatus($taskId, 'processing');
try {
$outputPath = '/tmp/output_' . $taskId . '.mp4';
$cmd = sprintf(
'ffmpeg -i %s -c:v libx264 -preset fast -crf 23 %s 2>&1',
escapeshellarg($inputUrl),
escapeshellarg($outputPath)
);
exec($cmd, $output, $returnCode);
if ($returnCode === 0) {
// 上传OSS并更新状态
uploadToOss($outputPath, $taskId);
updateStatus($taskId, 'completed', getOssUrl($taskId));
} else {
updateStatus($taskId, 'failed', 'FFmpeg execution failed');
}
} catch (Exception $e) {
updateStatus($taskId, 'failed', $e->getMessage());
}
$msg->ack();
};
$channel->basic_consume('video_transcode', '', false, false, false, false, $callback);
while (count($channel->callbacks)) {
$channel->wait();
}
如何处理转码过程中的异常与重试
在实际生产环境中,转码任务可能会因为源文件损坏、格式不支持或服务器资源不足而失败。为了增强系统的健壮性,应在Worker中实现指数退避的重试策略。例如,如果ffmpeg返回非零退出码,可以将任务重新推入队列,但增加一个延迟时间,避免立即重试导致资源耗尽。同时,对于超过最大重试次数(如3次)的任务,应自动标记为failed,并触发告警通知管理员介入检查。此外,建议在任务元数据中记录重试次数,以便后续分析和优化。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











