PHP视频转MP4:如何处理超大文件避免内存溢出

老敏君_9204

老敏君_9204

2026-08-14

662人浏览

原创

PHP不能直接转MP4,只能调用ffmpeg等外部工具处理;禁用file_get_contents()避免内存溢出,应使用readfile()或fopen()+fpassthru()流式输出大文件,并确保HTTP头正确、moov box前置以支持浏览器播放。

php视频转mp4:如何处理超大文件避免内存溢出

PHP 本身不能“转”出 MP4,它只能调用 ffmpeg 处理原始数据、透传已有 MP4 文件,或协调异步任务。所谓“视频转 MP4”,本质是让 PHP 正确调度外部工具并规避自身内存模型的硬伤——超大文件直接进内存必崩。

为什么 file_get_contents + echo 会炸内存

这是最常踩的坑:把 file_get_contents() 用于几百 MB 甚至几 GB 的视频文件,等同于要求 PHP 在用户空间一次性分配等量物理内存。哪怕服务器有 64GB 内存,PHP 进程也会因 memory_limit(默认通常 128M)被强制终止,报错 Allowed memory size exhausted。

  • 即使你临时用 ini_set('memory_limit', '-1') 关掉限制,也掩盖不了问题本质:PHP 不是为长时大块 I/O 设计的
  • file_get_contents() 返回的是完整字符串,后续任何 str_replace、json_encode 或拼接操作都会触发复制,内存翻倍风险极高
  • Web 服务器(如 Nginx)可能在 PHP 还没吐完数据前就因超时或缓冲区满而切断连接,导致客户端拿到截断的 MP4,无法播放

大 MP4 文件输出必须用流式响应

当你要把一个已存在的大 MP4 文件(比如 4GB 的录制回放)发给前端,核心原则是:不加载、不拼接、不缓存,让数据从磁盘直通 socket。

  • 绝对禁用 file_get_contents() 和 echo,改用 readfile() —— 它内部调用系统 sendfile()(Linux)或 TransmitFile()(Windows),绕过 PHP 用户态内存
  • 若需更细粒度控制(比如加权限校验、分段限速),则用 fopen() + fpassthru():
    $fp = fopen('/path/to/big.mp4', 'rb');
    if ($fp) {
        header('Content-Type: video/mp4');
        header('Content-Length: ' . filesize('/path/to/big.mp4'));
        header('Accept-Ranges: bytes');
        fpassthru($fp);
        fclose($fp);
    }
  • 务必确保 header() 调用前没有任何输出(包括 UTF-8 BOM、空行、echo ''),否则 HTTP 头发送失败,MP4 二进制流开头混入 HTML 字符,文件直接损坏

调用 ffmpeg 生成 MP4 时如何防卡死和溢出

PHP 只是 ffmpeg 的“遥控器”,真正干活的是子进程。如果让它在 Web 请求里干重活,轻则超时白屏,重则 fork 出一堆僵尸 ffmpeg 进程占满 CPU 和内存。

btpanel phpsite 宝塔面板PHP网站
btpanel phpsite 宝塔面板PHP网站

宝塔面板 PHP 网站管理:站点创建、删除、启停、PHP 版本切换、域名管理、SSL证书管理、伪静态管理、数据库管理

下载
  • 永远不要在 $_POST 接收后直接 exec('ffmpeg -i ...');必须移交到后台:写入 Redis 队列 → Worker 进程消费 → 调用 proc_open() 并设置 timeout 和 limit
  • 用 proc_open() 替代 shell_exec(),可捕获 stderr 实时日志,并在超时时 proc_terminate() 强杀子进程,避免孤儿进程堆积
  • 对输入源做预检查:用 finfo_file() 确认上传文件真是视频,用 ffprobe 快速读取时长/码率,拒绝明显异常的输入(如 10GB 但只有 2 秒的“视频”)
  • FFmpeg 命令务必加资源限制参数:-threads 2 控制线程数,-max_muxing_queue_size 1024 防止内存堆积,-y 自动覆盖避免交互阻塞

真正的大文件场景:别让 PHP 碰原始字节

当视频源是摄像头 RTMP 流、分片上传的 50GB 录像包,或需要实时添加水印/字幕时,PHP 就不该再承担“读-处理-写”的角色。它的定位应是任务编排器。

  • 前端分片上传 → 后端仅校验每片 SHA256 + 存入对象存储(如 MinIO/S3)→ 触发异步任务 → Worker 下载分片 → ffmpeg -f concat 合并 + 转码 → 上传结果回对象存储
  • 所有大文件 I/O 操作都交给 C 扩展(如 swoole_file)、系统命令或专用服务(如 FFmpeg HTTP API),PHP 只管发指令、查状态、返回 URL
  • 若必须用 PHP 处理中间数据(如提取关键帧缩略图),优先用 yield 生成器流式产出,而不是 array 累积;用 stream_filter_append() 在读取时就解码/转换,避免全量缓存

最容易被忽略的一点:MP4 的 moov box 必须在文件开头才能被浏览器正常播放。用 ffmpeg 合成时加 -movflags +faststart,否则即使文件生成成功,前端 Blob 创建的 URL 也无法直接 播放——这个细节和内存无关,但会让整个流程“看起来失败”。

php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

php

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2023.09.01

12144

6

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

6941

5

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

2215

5

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

2023.10.23

4428

4

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

2023.10.23

5134

6

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.03

4031

9

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.09

5837

8

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.13

4582

8

sprintf函数用法详解
sprintf函数用法详解

sprintf函数的用法:1、格式化字符串;2、指定输出宽度和精度;3、返回值。更多关于sprintf函数用法详解的内容,大家可以阅读下面的文章。

2023.11.27

12402

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
墨刀帮助中心
墨刀帮助中心

共0课时 | 0人学习

MyEclipse学习中心
MyEclipse学习中心

共0课时 | 0人学习

Apache Subversion 官方手册
Apache Subversion 官方手册

共0课时 | 0人学习