Python Lambda从S3加载.mov视频读取StreamingBody报错如何解决
问题根因
两个报错本质都是混淆了二进制数据和文本数据的处理逻辑:
'utf-8' codec can't decode byte错误:.mov是二进制格式文件,不是UTF-8编码的文本,你调用.read().decode()强行把二进制字节流按文本规则解析,必然触发编码错误。所有图片、视频、压缩包这类非文本文件,都不能直接用文本编码解码成字符串。endswith first arg must be bytes or a tuple of bytes, not str错误:这个是参数类型传错导致的,常见触发场景有三个:一是把读取到的视频字节内容当成文件路径传给了视频处理库,库内部做后缀判断时拿到字节而非路径字符串就会抛错;二是读写文件时混用了文本模式和二进制模式;三是构造内存流后调用处理接口时,没有给接口提供正确的格式后缀标识,接口做后缀校验时参数类型不匹配。
正确实现代码
Lambda环境下处理S3上的.mov视频,根据你后续用的视频处理库是否支持内存流,分两种写法,核心是不要对二进制字节流做文本转码,IO操作明确指定二进制模式:
import json import urllib.parse import boto3 import os from io import BytesIO # 按需导入你用的视频处理库,比如opencv、moviepy # import cv2 # import numpy as np # from moviepy.editor import VideoFileClip print('Loading function') s3 = boto3.client('s3') def lambda_handler(event, context): bucket = os.environ['SOURCE_BUCKET_NAME'] key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8') try: s3_resp = s3.get_object(Bucket=bucket, Key=key) # 直接读取二进制字节,绝对不要调用decode()转字符串 video_bytes = s3_resp['Body'].read() # --- 写法1:内存流处理,适合小视频、库支持类文件对象入参的场景 --- video_stream = BytesIO(video_bytes) # moviepy 读内存流示例,传带.mov后缀的虚拟文件名帮库识别格式 # clip = VideoFileClip(video_stream, audio=True) # opencv 读内存流示例 # img_array = np.asarray(bytearray(video_bytes), dtype=np.uint8) # cap = cv2.VideoCapture(img_array, cv2.CAP_FFMPEG) # --- 写法2:落地到临时目录处理,适合大视频、库只支持本地文件路径的场景 --- # Lambda只有/tmp目录可写,默认512M,可在配置里最高调到10G local_file_path = f"/tmp/{os.path.basename(key)}" # 写二进制文件必须指定wb模式,不能用默认的w文本模式 with open(local_file_path, "wb") as f: f.write(video_bytes) # 之后直接传本地路径给处理库即可 # cap = cv2.VideoCapture(local_file_path) return { "statusCode": 200, "body": json.dumps("video load success") } except Exception as e: print(e) print(f'Error getting object {key} from bucket {bucket}. Make sure they exist and your bucket is in the same region as this function.') raise e
注意事项
- Lambda内存配置必须大于你要处理的单视频大小,如果用内存流处理,还要预留出视频处理库运行的内存占用,否则会触发OOM被强杀。
- 所有二进制文件的读写操作,都要显式指定
rb(读二进制)、wb(写二进制)模式,不要用默认的文本模式,否则Python会自动做编码转换,损坏视频文件内容。 - 大部分视频处理库会根据文件后缀判断封装格式,不管是传内存流还是本地文件,都要保证文件名后缀和实际格式一致(这里是.mov),否则容易触发格式识别错误。
- 大体积视频不建议直接全量读到内存处理,优先落地到/tmp目录,或者用分块读取的方式处理,避免超出Lambda内存限制。
内容的提问来源于stack exchange,提问作者munkaboo
相关产品推荐
相关产品推荐

