You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 18:14:49