AWS Lambda中MoviePy调用FFmpeg写入文件报错求助
解决AWS Lambda中MoviePy合并音频视频时的只读文件系统错误
问题概述
在AWS Lambda中使用ElevenLabs生成语音,再通过MoviePy将语音添加到视频开头时,触发以下错误:
[ERROR] OSError: [Errno 32] Broken pipe
MoviePy error: FFMPEG encountered the following error while writing file xxxTEMP_MPY_wvf_snd.mp4:
b'xxxTEMP_MPY_wvf_snd.mp4: Read-only file system\n'
核心原因是MoviePy默认将临时音频文件写入Lambda的只读工作目录(/var/task),即便手动设置了TMPDIR=/tmp,部分内部逻辑仍会使用默认临时路径。
解决方案
1. 强制指定MoviePy临时目录到/tmp
导入MoviePy模块后,显式修改临时目录配置,确保所有临时文件都写入Lambda唯一可写的/tmp目录。
2. 修正S3上传路径
原代码中upload_key包含/tmp前缀,会导致S3存储路径出现不必要的tmp文件夹,需移除该前缀。
3. 手动释放媒体资源
Lambda环境资源有限,处理完视频后手动关闭所有Clip对象,避免资源泄漏。
修改后的完整代码
import json import boto3 import uuid import requests import os import moviepy.config as config from moviepy.editor import VideoFileClip, CompositeAudioClip, AudioFileClip # 强制设置MoviePy临时目录到/tmp config.change_settings({"TEMP_DIR": "/tmp"}) os.environ['TMPDIR'] = '/tmp' def text_to_speech_with_elevenlabs(text, api_key): url = "https://api.elevenlabs.io/v1/text-to-speech/Lx6D7XYCyKMECIXTTYg2" payload = { "model_id": "eleven_multilingual_v2", "text": text, "voice_settings": { "stability": 0.5, "similarity_boost": 0.75, "style": 0, "clarity": 0.75 } } headers = { "xi-api-key": api_key, "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers, stream=True) if response.status_code == 200: return response.content else: raise Exception(f"ElevenLabs API request failed: {response.status_code} {response.text}") def download_audio(audio_content, filename): with open(filename, 'wb') as f: f.write(audio_content) def lambda_handler(event, context): api_key = "x" bucket_name = "video-projects-t" unique_id = str(uuid.uuid4()) s3 = boto3.client('s3') first_name = event['first_name'] last_name = event['last_name'] text = f"some words bla bla, {first_name} {last_name}." audio_content = text_to_speech_with_elevenlabs(text, api_key) tts_audio_path = f"/tmp/{unique_id}_tts.mp3" download_audio(audio_content, tts_audio_path) original_video_key = "Video2.mp4" original_video_path = f"/tmp/{unique_id}_original.mp4" output_video_path = f"/tmp/{unique_id}_processed_video.mp4" # 修正S3上传key,去掉/tmp前缀 upload_key = f"{unique_id}_processed_video.mp4" s3.download_file(bucket_name, original_video_key, original_video_path) video_clip = VideoFileClip(original_video_path) tts_audio_clip = AudioFileClip(tts_audio_path) final_audio = CompositeAudioClip([video_clip.audio, tts_audio_clip.set_start(0)]) final_video = video_clip.set_audio(final_audio) # 显式指定临时音频文件路径到/tmp final_video.write_videofile( output_video_path, codec="libx264", audio_codec="aac", temp_audiofile=f"/tmp/{unique_id}_temp_audio.mp4", remove_temp=True ) s3.upload_file(output_video_path, bucket_name, upload_key) # 手动关闭所有Clip,释放资源 video_clip.close() tts_audio_clip.close() final_video.close() video_url = f"https://{bucket_name}.s3.amazonaws.com/{upload_key}" return { 'statusCode': 200, 'body': json.dumps(video_url) }
关键修改说明
- 新增
config.change_settings({"TEMP_DIR": "/tmp"}):强制MoviePy将所有临时文件写入/tmp,彻底解决只读文件系统问题。 - 修正
upload_key:移除/tmp前缀,避免S3中生成多余的层级目录。 - 在
write_videofile中显式指定temp_audiofile路径:进一步确保临时音频文件写入/tmp,增强兼容性。 - 添加Clip关闭操作:释放Lambda环境中的媒体资源,避免后续执行出现资源不足问题。
内容的提问来源于stack exchange,提问作者zemarkhos
相关产品推荐
相关产品推荐

