0

我试图通过使用 ffprobe 提取帧大小来绘制 H.264 和 VP9 视频随时间变化的比特率,但许多 VP9 视频显示的比特率和总大小明显低于文件大小和 ffprobe 报告的大小.

有人可以指出我找到丢失字节的正确方向吗?

例如:

# The extracted values and the ffprobe values are very close for mp4
Video Codec: h264
Video Bitrate: 0.668869
Frame Bitrate: 0.665552571931
Video Size: 6381536.0
Frame Total Size: 6349891

# The extracted values and the ffprobe values are very different for some vp9 videos
Video Codec: vp9
Video Bitrate: 0.600966
Frame Bitrate: 0.375144984531
Video Size: 5730519.0
Frame Total Size: 3577195

以下是我用于验证的内容。请注意,示例视频不包含音频。

import subprocess
import json

def export_video_info(video_id):
    proc = subprocess.Popen(['ffprobe',
        '-v', 'quiet', '-print_format', 
        'json', '-show_format',
        '-show_streams', '-show_frames',
        video_id
        ],
        stdout=subprocess.PIPE,
    )
    return proc.communicate()[0]

# Example video:  https://www.youtube.com/watch?v=g_OdgCrnzYo
# youtube-dl --id -f 135 https://www.youtube.com/watch?v=g_OdgCrnzYo
# youtube-dl --id -f 244 https://www.youtube.com/watch?v=g_OdgCrnzYo
video_list = ['g_OdgCrnzYo.mp4', 'g_OdgCrnzYo.webm']

'''
Format for every frame: 

    {
        "media_type": "video",
        "key_frame": 0,
        "pkt_pts": 84484,
        "pkt_pts_time": "84.484000",
        "pkt_dts": 84484,
        "pkt_dts_time": "84.484000",
        "best_effort_timestamp": 84484,
        "best_effort_timestamp_time": "84.484000",
        "pkt_duration": 33,
        "pkt_duration_time": "0.033000",
        "pkt_pos": "7103361",
        "pkt_size": "28",
        "width": 854,
        "height": 480,
        "pix_fmt": "yuv420p",
        "sample_aspect_ratio": "1:1",
        "pict_type": "P",
        "coded_picture_number": 0,
        "display_picture_number": 0,
        "interlaced_frame": 0,
        "top_field_first": 0,
        "repeat_pict": 0
    },
'''


# NOTE: videos do not include audio
for video in video_list:
    output = json.loads(export_video_info(video))
    ff_bitrate = float(output['format']['bit_rate']) / 10**6
    ff_duration = float(output['format']['duration'])
    ff_codec = output['streams'][0]['codec_name']
    ff_size = float(output['format']['size'])
    frame_size_sum = 0
    for val, items in enumerate(output['frames']):
        if output['frames'][val]['media_type'] == 'video': 
            frame_size_sum += int(output['frames'][val]['pkt_size'])

    frame_bitrate = frame_size_sum / ff_duration * 8 / 10**6
    print('Video Codec: {}\nVideo Bitrate: {}\nFrame Bitrate: {}\nVideo Size: {}\nFrame Total Size: {}\n\n'.format(ff_codec, ff_bitrate, frame_bitrate, ff_size, frame_size_sum))
4

0 回答 0