I'm trying to graph the bitrate over time for H.264 and VP9 videos by extracting the frame size with ffprobe, but many of the VP9 videos are showing significantly lower bitrate and total size than both the file size would indicate and that ffprobe reports.
Can someone point me in the right direction for finding the missing bytes?
For example:
# 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
Below is what I'm using for validation. Note that the sample videos do not contain audio.
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))