php上传后必须用ffmpeg转采样率,不能用gd或file_get_contents;需先move_uploaded_file(),再执行ffmpeg -i in -ar 44100 -ac 2 -b:a 128k -y out,捕获stderr并校验return_code、输出文件完整性。

PHP上传后用ffmpeg转采样率,别碰原生GD或file_get_contents
PHP本身不处理音频采样率转换,move_uploaded_file()只是把文件挪到服务器,后续必须调用外部工具。常见错误是试图用getimagesize()或fopen()读取音频头来“改采样率”——这只会破坏文件,根本无效。
- 必须依赖
ffmpeg命令行工具,PHP只负责拼命令、执行、检查返回码 - 确保服务器已安装ffmpeg且PHP能执行:运行
shell_exec('which ffmpeg')应返回路径 - 上传后的临时文件(
$_FILES['audio']['tmp_name'])不能直接传给ffmpeg做输入?不行——需先move_uploaded_file()到可读写目录,再作为ffmpeg输入 - 输出路径必须带明确扩展名(如
.mp3或.wav),否则ffmpeg可能推断失败或静默报错
用ffmpeg -ar 强制指定采样率,-ac 和 -b:a 通常要同步调整
仅加-ar 44100不够。原始音频若为单声道、低码率,强制重采样后可能失真或播放异常。关键参数要成套配:
-
-ar 44100:目标采样率(常用44100或48000) -
-ac 2:统一转为双声道(避免某些播放器对单声道MP3兼容差) -
-b:a 128k:音频码率,和采样率匹配(44.1kHz下128k常见;若原文件是96k,强行拉到128k无意义,反而增大体积) -
-y:覆盖输出文件,避免因文件存在导致ffmpeg退出码非0
完整示例命令:ffmpeg -i /path/in.wav -ar 44100 -ac 2 -b:a 128k -y /path/out.mp3
exec()执行时务必捕获错误,ffmpeg静默失败很常见
很多PHP脚本只写exec($cmd),但ffmpeg遇到不支持编码、权限不足、磁盘满等情况,往往不输出stderr,exec()返回空数组,误判为成功。
- 用
exec($cmd . ' 2>&1', $output, $return_code)捕获全部输出 - 检查
$return_code !== 0,而非只看$output是否为空 - 典型错误信息如
Unsupported codec for output stream #0.0或Permission denied必须记录到日志,不能只echo给用户 - 注意:禁用
safe_mode(已废弃)或disable_functions中是否禁了exec、shell_exec
Web环境要注意超时、大文件和并发限制
音频文件常几MB到上百MB,PHP默认max_execution_time=30,ffmpeg转码很容易超时;同时Nginx/Apache也有请求体大小和超时限制。
- PHP侧:转码前设
set_time_limit(300)(5分钟),并确认upload_max_filesize和post_max_size足够(如64M) - Nginx侧:检查
client_max_body_size和fastcgi_read_timeout(至少设为300) - 不要在HTTP请求内直接跑长时ffmpeg——考虑写入队列,用后台进程或定时任务处理,避免用户等待或连接中断
- 转码完成前,别删原始上传文件;输出文件生成后,用
is_file()和filesize()双重校验是否写完,防止截断
采样率转换不是“改个头就能用”,ffmpeg的输入解码器、输出编码器、重采样引擎三者耦合紧密,一个参数不匹配就可能输出无声文件或无法播放的损坏流。实际部署时,先拿几个典型格式(MP3/FLAC/M4A/WAV)各跑一遍,比对着ffprobe输出检查sample_rate和codec_type更可靠。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











