短视频上传需分片上传并双重校验,转码须异步执行生成多格式版本及封面图,播放应代理控制权限与断点续传,配套CDN加速和回调通知更新状态。

上传环节:安全接收 + 分片支持
ThinkPHP6 默认支持常规文件上传,但短视频往往体积大、网络不稳定,直接单次上传易失败。推荐启用分片上传机制,前端用 WebUploader 或七牛 SDK,后端配合处理分块合并。
关键点:
- 配置 upload_max_filesize 和 post_max_size 至少 512M(php.ini 或 runtime 目录下动态设置)
- 校验必须双重:扩展名白名单(mp4、mov、webm)+ finfo_open() 检测真实 MIME 类型
- 生成唯一存储路径,如 video/{user_id}/{date}/{$md5_hash}.mp4,避免覆盖与猜测访问
- 上传成功后不立即转码,仅写入数据库标记为“待处理”,状态字段如 status = 'uploaded'
转码环节:异步执行 + 多格式输出
TP6 本身不处理视频,需借助 FFmpeg 命令行工具。切忌在 HTTP 请求中同步执行转码,否则页面卡死或超时。应使用队列(如 think-queue + Redis)调度 Worker 异步处理。
典型转码命令(适配 Web 播放):
立即学习“PHP免费学习笔记(深入)”;
ffmpeg -i input.mp4 \ -c:v libx264 -preset medium -b:v 1200k -vf "scale=1280:-2" \ -c:a aac -b:a 128k \ -f mp4 output.mp4
建议同时生成多版本:
- 高清版(1280×720,H.264+MP4):主播放源
- 标清版(640×360,H.264+MP4):弱网备用
- WebM 版(VP9+Opus):现代浏览器节省带宽
- 自动提取首帧为封面图:ffmpeg -i input.mp4 -ss 00:00:01 -vframes 1 cover.jpg
播放环节:权限控制 + 断点续传
视频文件不应放在 public 目录下直连。推荐将原始文件存于 runtime/video/ 或对象存储(OSS/Qiniu),通过 PHP 接口代理播放。
创建 VideoController@play 方法,核心逻辑:
- 验证用户登录态与视频所属权限(如私有视频仅作者/会员可看)
- 读取文件并判断是否含 Range 请求头,支持断点续传(返回 206 状态码)
- 正确设置响应头:Content-Type: video/mp4、Accept-Ranges: bytes、Content-Length 或 Content-Range
- 用 fpassthru() 分段输出,避免内存溢出
前端调用示例:
<video controls> <source src="/video/play?id=123" type="video/mp4"> </video>
配套增强:CDN 加速与回调通知
转码完成后,应自动将结果文件推送到 CDN 或对象存储,再更新数据库中的播放地址字段(如 play_url)。若使用云服务(阿里云 VOD、七牛),可启用上传完成回调(callbackUrl),由 TP6 接收并更新状态,避免轮询。
回调验证要点:
- 校验签名(如七牛的 Authorization header 或阿里云的 Signature 参数)
- 解析回调 body 中的 fileName、size、hash、bucket 等字段
- 匹配本地记录的上传任务,将 status 改为 'processed' 并写入 play_url
- 触发事件(如 VideoProcessed),供其他模块监听(发通知、生成缩略图、更新推荐池)



















