AWS Lambda无法将音频上传至S3问题排查求助
问题分析与修复方案
核心问题1:S3上传逻辑错误(39B无效文件)
你调用s3.put_object时,直接把字符串路径'/tmp/'+ file_name传给Body参数,这会把路径字符串本身作为文件内容上传,而非读取目标音频文件。这就是为什么文件只有39B——那只是路径字符串的长度,完全不是音频数据。
核心问题2:pytube下载路径使用错误
YoutubeAudioDownload函数中,audio.download()的参数应该是目录路径,但你传的是带文件名的完整路径(比如/tmp/xxx.mp4)。pytube会把这个路径当成目录名尝试创建,然后用视频默认标题作为文件名下载,导致后续找不到你预期的目标文件,甚至触发隐藏错误。
核心问题3:Lambda超时配置不足
YouTube音频下载需要一定时间,Lambda默认超时仅3秒,稍大的音频文件必然会超时。需要在Lambda控制台将超时时间调整为1分钟以上(比如5分钟,可根据实际文件大小灵活设置)。
修复后的完整代码
import json from pytube import YouTube import boto3 def lambda_handler(event, context): video_url = event['url'] # 用视频ID生成合法文件名(避免URL中的特殊字符,比直接截取URL更可靠) file_name = f"{video_url.split('=')[-1]}.mp4" BUCKET_NAME = 'my_bucket_name' def youtube_audio_download(video_url, save_dir, save_filename): try: video = YouTube(video_url) audio = video.streams.filter(only_audio=True).first() # 明确指定输出目录和自定义文件名 audio.download(output_path=save_dir, filename=save_filename) print("音频下载成功") except Exception as e: print(f"下载失败: {str(e)}") raise # 抛出异常让上层统一处理 try: # 下载到Lambda临时目录/tmp,指定目标文件名 youtube_audio_download(video_url, '/tmp', file_name) # 读取本地文件并上传到S3 s3 = boto3.client('s3') with open(f'/tmp/{file_name}', 'rb') as audio_file: response = s3.put_object( Body=audio_file, Bucket=BUCKET_NAME, Key=file_name, ContentType='audio/mp4' ) print(f"S3上传响应: {response}") return { 'statusCode': 200, 'body': json.dumps('MP4音频文件上传成功') } except Exception as e: print(f"执行错误: {str(e)}") return { 'statusCode': 500, 'body': json.dumps(f"上传失败: {str(e)}") }
额外优化建议
- 文件名合法性:避免直接用URL截取生成文件名,URL中的
/、&等字符会导致S3路径或本地文件操作异常,用视频ID作为文件名更安全。 - Lambda资源配置:将Lambda内存调高到512MB或1GB,Lambda的内存与CPU、网络带宽正相关,更高内存能加快下载和上传速度。
- 异常细化处理:针对pytube可能出现的网络超时、视频权限限制等异常单独捕获,方便快速定位问题。
内容的提问来源于stack exchange,提问作者Gregi
相关产品推荐
相关产品推荐

