AWS Lambda中使用FFmpeg剪切HLS生成MP4遇SIGSEGV错误求助
问题
在AWS Lambda中使用FFmpeg将存储桶公开URL的HLS流剪切为MP4,输出保存到tmp.mp4后上传至存储桶。本地执行FFmpeg命令正常(耗时≤3秒,输出文件<1MB),但运行Node.js代码时出现SIGSEGV错误,以下是代码及错误日志:
代码
import path from 'path'; import { execSync } from 'child_process'; import fs from 'fs'; export const handler = async (event) => { try { const { m3u8, offset, duration, signedURL } = event; const clipKey = `clip_output.mp4`; const clipFilePath = path.join('/tmp', clipKey); execSync(`/opt/ffmpeglib/ffmpeg -i ${process.env.URL_CLOUDFLARE}/${m3u8} -ss ${offset} -t ${duration} -c copy -f mp4 ${clipFilePath}`) const fileContent = fs.readFileSync(clipFilePath); const resSign = await fetch(signedURL, { method: "PUT", headers: { "Content-Type": "application/octet-stream", }, body: fileContent, }); if (!resSign.ok) throw new Error(`Failed to upload file to S3: ${resSign.statusText}`); fs.unlinkSync(clipFilePath); return { statusCode: 200, body: JSON.stringify({ message: 'Clip procesado y subido correctamente', clipKey: path.basename(clipFilePath) }), }; } catch (error) { console.error("Error al procesar el clip:", error); return { statusCode: 500, body: JSON.stringify({ error: error.message }), }; } };
错误日志
at genericNodeError (node:internal/errors:984:15) at wrappedFn (node:internal/errors:538:14) at checkExecSyncError (node:child_process:891:11) at execSync (node:child_process:963:15) at Runtime.handler (file:///var/task/index.js:16:3) at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1173:29) { status: null, signal: 'SIGSEGV', output: [ null, <Buffer >, <Buffer 66 66 6d 70 65 67 20 76 65 72 73 69 6f 6e 20 4e 2d 37 31 30 36 34 2d 67 64 35 65 36 30 33 64 64 63 30 2d 73 74 61 74 69 63 20 68 74 74 70 73 3a 2f 2f ... 1194 more bytes> ], pid: 13, stdout: <Buffer >, stderr: <Buffer 66 66 6d 70 65 67 20 76 65 72 73 69 6f 6e 20 4e 2d 37 31 30 36 34 2d 67 64 35 65 36 30 33 64 64 63 30 2d 73 74 61 74 69 63 20 68 74 74 70 73 3a 2f 2f ... 1194 more bytes> } ffmpeg version N-71064-gd5e603ddc0-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2024 the FFmpeg developers built with gcc 8 (Debian 8.3.0-6) configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi --enable-libzimg libavutil 59. 27.100 / 59. 27.100 libavcodec 61. 9.100 / 61. 9.100 libavformat 61. 4.100 / 61. 4.100 libavdevice 61. 2.100 / 61. 2.100 libavfilter 10. 2.102 / 10. 2.102 libswscale 8. 2.100 / 8. 2.100 libswresample 5. 2.100 / 5. 2.100 libpostproc 58. 2.100 / 58. 2.100 END RequestId: 2fc8c51e-66c6-4c74-aa9c-fa10c11207a0 REPORT RequestId: 2fc8c51e-66c6-4c74-aa9c-fa10c11207a0 Duration: 164.82 ms Billed Duration: 165 ms Memory Size: 2048 MB Max Memory Used: 88 MB Init Duration: 185.19 ms
解决方案
SIGSEGV错误通常是FFmpeg二进制与Lambda环境不兼容,或命令执行时资源/参数问题导致的,以下是具体修复步骤:
1. 替换Lambda兼容的FFmpeg二进制
Lambda运行在Amazon Linux 2环境,当前使用的FFmpeg是Debian编译版本,存在兼容性问题。重新下载针对Amazon Linux 2编译的静态FFmpeg版本,替换/opt/ffmpeglib/下的二进制文件。
2. 调整FFmpeg命令参数
- 将
-ss移到输入文件前,FFmpeg会先定位到指定时间点再读取流,减少内存占用:/opt/ffmpeglib/ffmpeg -ss ${offset} -i ${process.env.URL_CLOUDFLARE}/${m3u8} -t ${duration} -c copy -f mp4 -y ${clipFilePath} - 添加
-y参数自动覆盖输出文件,避免文件已存在的错误; - 若
-c copy因HLS编码兼容性报错,改为重新编码(虽耗时增加,但稳定性更高):/opt/ffmpeglib/ffmpeg -ss ${offset} -i ${process.env.URL_CLOUDFLARE}/${m3u8} -t ${duration} -c:v libx264 -c:a aac -f mp4 -y ${clipFilePath}
3. 改用异步执行替代execSync
execSync会阻塞事件循环,且易因Lambda资源限制崩溃,换成exec异步执行并捕获完整错误输出:
import { exec } from 'child_process'; // 替换原execSync代码块 await new Promise((resolve, reject) => { const cmd = `/opt/ffmpeglib/ffmpeg -ss ${offset} -i ${process.env.URL_CLOUDFLARE}/${m3u8} -t ${duration} -c copy -f mp4 -y ${clipFilePath}`; exec(cmd, (error, stdout, stderr) => { if (error) { console.error(`FFmpeg执行错误: ${stderr}`); reject(error); return; } resolve(); }); });
4. 检查Lambda权限与资源配置
- 若Lambda在VPC中,需配置NAT网关或允许出站访问Cloudflare的HLS流;
- 提升Lambda内存到3008MB(对应CPU性能提升),同时延长超时时间到30秒;
- 确认
/tmp目录空间(默认512MB,足够当前场景)。
5. 验证输入参数合法性
确保offset、duration为合法数值,m3u8拼接后是有效URL,避免参数错误导致FFmpeg崩溃。
内容的提问来源于stack exchange,提问作者Bruno Munné
相关产品推荐
相关产品推荐

