webman中需用ffprobe提取视频元数据:先通过uploadfile->moveto()保存临时文件,再调用shell_exec()执行ffprobe命令(需escapeshellarg()处理路径、校验权限),清洗后存duration/width/height等标准化字段,异步处理避免阻塞。

Webman里怎么接收视频文件并提取元数据
Webman 默认不自动解析 multipart/form-data 中的视频文件元数据,$_FILES 只提供基础上传信息(路径、大小、类型),真正要拿到时长、分辨率、码率、编码格式这些,得靠外部工具。别指望 getimagesize() 或 exif_read_data() —— 它们对 MP4/AVI/MOV 基本无效。
实操建议:
- 用
move_uploaded_file()先把临时文件存到可读写的临时目录(比如runtime/upload_tmp/),注意 Webman 的$request->file()返回的是UploadFile对象,调用->moveTo($path)更安全 - 用
ffprobe(FFmpeg 工具集的一部分)命令行提取元数据,PHP 调用shell_exec()或proc_open(),返回 JSON 格式最方便解析 - 必须校验
ffprobe是否存在且有执行权限,否则会静默失败;建议在项目启动时用which ffprobe检查一次并记录日志 - 视频路径含空格或中文时,
shell_exec()里务必用escapeshellarg()包裹,否则命令直接崩
为什么用 ffprobe 而不是 PHP 扩展(如 php-ffmpeg)
php-ffmpeg 是个封装库,底层仍调用 ffprobe 和 ffmpeg,但 Webman 是常驻内存进程(基于 Workerman),PHP 扩展在长时间运行中容易出现资源泄漏或内存不释放,尤其高频上传场景下,Ffmpeg\FFMpeg 实例反复 new 容易撑爆内存。
更稳的做法是:只用 PHP 做“调度”,把解析逻辑交给独立进程。好处包括:
-
ffprobe启动快、无状态、单次执行完就退出,不污染 Webman 主进程 - 便于横向扩展:后续可把元数据解析抽成独立微服务,用 HTTP 或消息队列接活
- 避免因视频损坏导致 PHP 进程卡死(
ffprobe自身健壮,超时可设-v quiet -show_entries精简输出,再配合timeout 10s控制最长耗时)
Webman 中处理大视频上传的坑
用户上传 500MB+ 视频时,常见报错是 Request Entity Too Large 或请求直接中断,这不是 PHP 层面的问题,而是 Webman 前置的 Nginx 或 Swoole 配置限制。
必须同步检查三处:
- Nginx:确认
client_max_body_size(比如设为2G),且proxy_buffering off关闭缓冲,否则大文件会卡在代理层 - Swoole:修改
config/bootstrap.php中HttpServer的upload_max_filesize和post_max_size参数(单位是字节),例如'upload_max_filesize' => 2 * 1024 * 1024 * 1024 - Webman 自身:
app/middleware/UploadMiddleware.php里别写死ini_set('upload_max_filesize', '2M')这类覆盖逻辑,它对 Swoole 不生效,纯干扰项
另外,前端上传建议加断点续传(如用 web-upload 库分片),Webman 接口按 identify + chunk_index + total_chunks 存临时分片,全部收齐再合并、触发 ffprobe 解析 —— 这样即使上传中途断网也不用重来。
提取到的元数据怎么存和用
别把 ffprobe 输出的原始 JSON 直接入库。字段太多、嵌套深、部分字段(如 tags)内容不可控,直接存会污染结构、查询慢、还容易被注入。
推荐做法是清洗后存固定字段:
- 必存:
duration(秒,float)、width/height(int)、codec_name(如h264)、bit_rate(int,单位 bit/s)、rotate(int,用于播放器自动翻转) - 选存:
has_audio(bool)、frame_rate(string,如"25/1",入库前转成 float)、creation_time(datetime,优先取format.tags.creation_time,没有则 fallback 到文件 mtime) - 绝对不要存:
streams[].tags全部内容、format.tags.encoder(广告嫌疑大)、任意未定义字段
清洗逻辑建议封装成一个独立 Service 类(如 VideoMetadataParser),输入是 ffprobe -v quiet -print_format json -show_format -show_streams 的输出,输出是标准化数组。这样以后换解析工具(比如用 mediainfo --Output=JSON)也只需改一个地方。
元数据提取耗时明显(尤其 4K 视频可能 2–5 秒),千万别在上传接口里同步等结果再返回成功。应该先返回 {status: "processing", task_id: "xxx"},后台用 Webman 的 Timer::tick() 或投递到 Redis 队列异步处理,完成后回调或轮询更新状态。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











