如何用Python通过二进制流获取视频的元数据(播放时长、分辨率等信息)?

网上一些获取媒体元数据的库如 moviepy,mutagen 等都是通过文件路径名作为输入. 把 bytes 存为文件然后再通过 filename 作为输入这样多此一举,还会占用磁盘 IO

如何像 PIL Image.open(io.BytesIO(file.body)) 这样直接读 bytes 数据就能获取元数据信息呢?


如何用Python通过二进制流获取视频的元数据(播放时长、分辨率等信息)?
6 回复

h264 手动解析 pps 和 sps


用Python获取视频元数据,一个直接的方法是使用ffmpeg-python库,它封装了FFmpeg的功能。如果没装,先pip install ffmpeg-python。下面这个例子从二进制流中读取视频文件并提取关键信息:

import ffmpeg
import io

def get_video_metadata_from_bytes(video_bytes):
    """
    从二进制数据中获取视频元数据。
    
    参数:
        video_bytes: 视频文件的二进制数据 (bytes)
    
    返回:
        包含时长、分辨率等信息的字典
    """
    # 将字节数据包装成类文件对象
    input_stream = io.BytesIO(video_bytes)
    
    try:
        # 使用ffmpeg.probe分析视频流
        probe = ffmpeg.probe(
            'pipe:0',  # 从标准输入读取
            format='mp4',  # 根据实际情况调整格式
            cmd='ffprobe'  # 确保ffprobe在系统路径中
        )
        
        # 获取视频流信息(通常第一个视频流)
        video_stream = next(
            (stream for stream in probe['streams'] if stream['codec_type'] == 'video'),
            None
        )
        
        if video_stream is None:
            return {"error": "未找到视频流"}
        
        # 提取关键信息
        metadata = {
            "duration": float(video_stream.get('duration', 0)),  # 时长(秒)
            "width": int(video_stream.get('width', 0)),          # 宽度
            "height": int(video_stream.get('height', 0)),        # 高度
            "codec": video_stream.get('codec_name', 'unknown'),  # 编码格式
            "bit_rate": video_stream.get('bit_rate', 'N/A'),     # 比特率
            "frame_rate": eval(video_stream.get('avg_frame_rate', '0/1'))  # 帧率
        }
        
        return metadata
        
    except ffmpeg.Error as e:
        return {"error": f"FFmpeg错误: {e.stderr.decode()}"}
    except Exception as e:
        return {"error": f"处理失败: {str(e)}"}

# 使用示例
if __name__ == "__main__":
    # 模拟从文件读取二进制数据
    with open('example.mp4', 'rb') as f:
        video_data = f.read()
    
    # 获取元数据
    result = get_video_metadata_from_bytes(video_data)
    print("视频元数据:", result)

关键点说明:

  1. 二进制流处理:通过io.BytesIO将字节数据转换为类文件对象,FFmpeg可以从标准输入(pipe:0)读取。
  2. 格式指定format参数需要根据实际视频格式调整(如mp4、avi、mov等)。
  3. 帧率计算avg_frame_rate返回字符串格式的分数(如"30/1"),用eval()转换为浮点数。
  4. 错误处理:FFmpeg可能因格式不支持或损坏文件而失败,需要适当捕获异常。

替代方案:如果不想依赖FFmpeg,可以用moviepypip install moviepy),它更简单但功能稍少:

from moviepy.editor import VideoFileClip
import io

def get_metadata_moviepy(video_bytes):
    with io.BytesIO(video_bytes) as buffer:
        buffer.write(video_bytes)
        buffer.seek(0)
        with VideoFileClip(buffer) as video:
            return {
                "duration": video.duration,
                "size": video.size,  # (width, height)
                "fps": video.fps
            }

总结:用ffmpeg-python处理二进制流最可靠。

这工作量也太大啦吧, 而且不止是 mp4 媒体文件有可能是 ogg, avi 等多种格式.感觉应该会有现成的轮子啊. 我一直没找到. 看 stackoverflow 也有人在问 https://stackoverflow.com/questions/17340292/python-get-media-file-metadata-from-byte-array

libmediainfo,有包括 Python 在内的多种语言的 API binding

看了下 pymediainfo 这个库,也是只有通过文件名来读取 : (
pymediainfo.MediaInfo.parse(“xxx.mp4”)

这个需求没必要用 python 去实现,直接通过 shell 调用获取到数据就行了,本地的用 ffmpeg,网络的用 ffprobe

回到顶部