我试图通过使用 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))