如何优化FFmpeg命令以避免1GB内存的Amazon Linux AMI 2023服务器崩溃?
如何优化FFmpeg命令以避免1GB内存的Amazon Linux AMI 2023服务器崩溃?
看起来你在1GB内存的服务器上用FFmpeg处理高分辨率图片时遇到了内存耗尽导致崩溃的问题,结合你已经做的排查(小图/去掉scale就正常),我给你几个实用的优化方向,先不用急着升级服务器,试试这些:
一、先给FFmpeg命令“瘦个身”,减少不必要的开销
你当前的命令里有些参数可以调整,直接降低内存占用:
- 简化音频相关参数:现在你还没加音频,命令里的
-c:a aac其实是无用的,先去掉它,减少FFmpeg不必要的编码初始化开销。 - 优化缩放滤镜的计算方式:默认的缩放算法(bicubic)内存占用较高,换成更快更省内存的
fast_bilinear,同时加上low_memory标记,修改后的scale滤镜:scale=1344:768:force_original_aspect_ratio=decrease:flags=fast_bilinear+low_memory,pad=1344:768:(ow-iw)/2:(oh-ih)/2 - 限制FFmpeg的内存使用上限:加上
-max_memory 512M参数,强制FFmpeg最多使用512MB内存,避免它把系统内存吃光;另外可以降低缓存大小,加-bufsize 10M减少帧缓存占用。 - 减少线程数:FFmpeg默认会用多线程,1GB内存下多线程反而会增加内存开销,加上
-threads 1限制单线程运行,虽然速度慢一点,但内存占用会显著降低。
调整后的完整命令大概是这样:
ffmpeg -protocol_whitelist file,http,https,tcp,tls,crypto -max_memory 512M -bufsize 10M -threads 1 -f concat -safe 0 -i demux_file.txt -filter_complex "scale=1344:768:force_original_aspect_ratio=decrease:flags=fast_bilinear+low_memory,pad=1344:768:(ow-iw)/2:(oh-ih)/2" -c:v libx264 -pix_fmt yuv420p -crf 18 -movflags +faststart -map 0 -y output.mp4
二、分阶段处理,降低单步内存压力
如果直接优化命令还是不行,那就把“缩放+拼接”拆成两步:
- 先单独处理每张图片:循环遍历demux文件里的图片链接,把每张高分辨率图单独缩放到目标尺寸,保存成临时小图(可以存在本地临时目录):
# 先创建临时目录存处理后的小图 mkdir -p temp_imgs # 遍历demux文件里的图片链接(跳过注释行) while read -r line; do if [[ ! $line =~ ^# ]]; then # 提取图片文件名,生成临时文件名 img_name=$(echo "$line" | sed 's/.*\///') ffmpeg -i "$line" -filter_complex "scale=1344:768:force_original_aspect_ratio=decrease,pad=1344:768:(ow-iw)/2:(oh-ih)/2" -q:v 2 "temp_imgs/$img_name" fi done < demux_file.txt - 生成新的demux文件:指向这些处理好的临时小图:
> new_demux.txt for img in temp_imgs/*; do echo "file '$PWD/$img'" >> new_demux.txt done - 用新的demux文件拼接视频:这时候处理的都是小图,内存占用会低很多:
ffmpeg -f concat -safe 0 -i new_demux.txt -c:v libx264 -pix_fmt yuv420p -crf 18 -movflags +faststart -y output.mp4
处理完后记得删除临时目录:rm -rf temp_imgs new_demux.txt
三、给服务器加个“内存缓冲”——交换分区(Swap)
1GB内存确实比较紧张,你可以给系统加个Swap分区,当物理内存不够时,系统会用磁盘空间临时当内存用,虽然速度会慢一点,但至少不会崩溃。在Amazon Linux 2023上可以这么操作:
# 创建2GB的Swap文件 sudo fallocate -l 2G /swapfile # 设置权限(只有root能访问) sudo chmod 600 /swapfile # 格式化Swap文件 sudo mkswap /swapfile # 启用Swap sudo swapon /swapfile # 设置开机自动挂载Swap echo '/swapfile none swap defaults 0 0' | sudo tee -a /etc/fstab
四、试试硬件加速(如果你的服务器支持)
如果你的AWS实例是带有Intel Quick Sync或者GPU的机型(比如T系列、G系列),可以启用FFmpeg的硬件加速,用GPU来处理缩放和编码,能大幅降低CPU和内存占用。比如Intel实例可以这么改命令:
ffmpeg -protocol_whitelist file,http,https,tcp,tls,crypto -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -f concat -safe 0 -i demux_file.txt -filter_complex "scale_vaapi=1344:768:force_original_aspect_ratio=decrease,pad=1344:768:(ow-iw)/2:(oh-ih)/2" -c:v h264_vaapi -pix_fmt yuv420p -crf 18 -movflags +faststart -map 0 -y output.mp4
注意:如果服务器没有硬件加速支持,这个命令会报错,先确认你的实例是否支持。
最后总结
优先试试调整FFmpeg命令和加Swap分区,这两个操作成本最低;如果还是不行,再用分阶段处理的方式;最后再考虑升级服务器内存。等后面加音频的时候,记得把-shortest加回去,确保视频和音频时长对齐。
备注:内容来源于stack exchange,提问作者threeFatCat




