snapshot of https://github.com/jitsi/jitsi-videobridge.git @ fcbf741c646bc237d2ed85a1e86910532532b831 (2026-09-15)
Some checks failed
Java CI with Maven / Java 17 (push) Failing after 7m2s
Java CI with Maven / Java 21 (push) Failing after 5m0s

This commit is contained in:
upstream-mirror
2026-09-15 16:12:38 +05:00
commit e1257b7a05
647 changed files with 110946 additions and 0 deletions

203
resources/timeseries-cli.py Executable file
View File

@@ -0,0 +1,203 @@
#!/usr/bin/env python
import argparse
import pandas as pd
import matplotlib.pyplot as plt
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
def read_json(fname):
df = pd.read_json(fname, lines=True, convert_dates=['time'], date_unit='ms')
df['conference_id'] = df['conf_name'] + df['conf_creation_time_ms'].astype(str)
return df
def show(args):
df = read_json(args.infile)
print('series: {}'.format(df['series'].unique()))
print('conferences: {}'.format(df['conf_name'].unique()))
print('endpoints: {}'.format(df['endpoint_id'].unique()))
def vp8_inspect(df):
if args.ssrc:
df = df[df['rtp.ssrc'] == args.ssrc]
if args.endpoint:
df = df[df['endpoint_id'] == args.endpoint]
if args.conference:
df = df[df['conf_name'] == args.conference]
df['time_delta'] = df['time'] - df['time'].shift(1)
df['rtp.seq_delta'] = df['rtp.seq'] - df['rtp.seq'].shift(1)
df['vp8.pictureid_delta'] = df['vp8.pictureid'] - df['vp8.pictureid'].shift(1)
df['vp8.timestamp_delta'] = df['rtp.timestamp'] - df['rtp.timestamp'].shift(1)
print(df)
def vp8_verify(df):
# tl0picidx monotonically increases
# if the timestamp changes, then the pictureid changes
# if the pictureid changes, then the timestamp changes
# the timestamp delta needs to be proportional to the pictureid delta
# there can't be big gaps in the sequence numbers
# the webrtc pacer outputs packets every 10ms
pass
def plot_endpoint(df, series, endpoint_id, remote_endpoint_id):
df = df[df['endpoint_id'] == endpoint_id]
if remote_endpoint_id:
df = df[df['remote_endpoint_id'] == remote_endpoint_id]
fig = plt.figure()
fig.suptitle('Endpoint: {}'.format(endpoint_id))
ax_bitrate = fig.subplots(1, sharex=True)
ax_bitrate.set_xlabel('time')
ax_bitrate.set_ylabel('bitrate (bps)')
if 'calculated_rate' in series:
df_rates = df['series' == 'calculated_rate']
# make sure we're plotting a single remote endpoint.
remote_endpoints = df_rates['remote_endpoint_id'].unique()
if len(remote_endpoints) > 1:
raise Exception('specify a --remote-endpoint {}'.format(remote_endpoints))
for i in range(9):
encoding_quality = str(i)
if encoding_quality in df_rates.columns:
ax_bitrate.plot(df_rates['time'],
df_rates[encoding_quality],
label=encoding_quality)
df_series = df['series'].unique()
if 'sent_padding' in series and 'sent_padding' in df_series:
df_padding = df[df['series'] == 'sent_padding']
ax_bitrate.plot(
df_padding['time'],
df_padding['padding_bps'] + df_padding['total_target_bps'],
label='target + padding',
marker='^',
markersize=4,
linestyle='None')
if 'new_bwe' in series and 'new_bwe' in df_series:
df_bwe = df[df['series'] == 'new_bwe']
ax_bitrate.plot(df_bwe['time'],
df_bwe['bitrate_bps'],
label='estimate',
drawstyle='steps-post')
if 'did_update' in series and 'did_update' in df_series:
df_update = df[df['series'] == 'did_update']
ax_bitrate.plot(df_update['time'],
df_update['total_target_bps'],
label='target',
drawstyle='steps-post')
ax_bitrate.plot(df_update['time'],
df_update['total_ideal_bps'],
label='ideal',
drawstyle='steps-post')
if 'in_pkt' in series and 'in_pkt' in df_series:
df_pkt = df[df['series'] == 'in_pkt']
if len(df_pkt['rbe_id'].unique()) is not 1:
raise Exception('There cannot be multiple remote bitrate estimators')
df_sz = pd.DataFrame(
{'bits': df_pkt['pkt_sz_bytes'] * 8, 'time': df_pkt['time']})
df_rate = df_sz.resample('1S', on='time').sum()
ax_bitrate.plot(df_rate.index, df_rate['bits'], label='sent')
# todo include rtt and packet loss
ax_bitrate.legend()
def plot(args):
df = read_json(args.infile)
endpoint_ids = [args.endpoint_id] if args.endpoint_id else df['endpoint_id'].unique()
for endpoint_id in endpoint_ids:
plot_endpoint(df, args.series, endpoint_id, args.remote_endpoint_id)
plt.show()
def check_endpoint(df, endpoint_id):
# if a property is violated (for example property 3):
# zgrep 7d2b7ecf data/4/series.json.gz| grep did_update | jq '. | select(.bwe_bps >= .total_ideal_bps) | select(.total_target_idx < .total_ideal_idx)' | less -S
df_update = df[df['series'] == 'did_update']
if not len(df_update):
return
# property 1: check if ideal <= estimate => target == ideal
mask_1 = df_update['bwe_bps'] >= df_update['total_ideal_bps']
mask_2 = df_update['total_target_idx'] < df_update['total_ideal_idx']
mask_3 = df_update['total_ideal_bps'] != 0
mask_4 = df_update['total_target_bps'] != 0
assert not len(df_update[mask_1 & mask_2 & mask_3 & mask_4]), '{} is not sending as much as it should.'.format(endpoint_id)
# property 2: check that the target never exceeds the ideal
mask_5 = (df_update['total_ideal_bps'] - df_update['total_target_bps']) < 0
assert not len(df_update[mask_5]), '{} has a target bitrate that exceeds the ideal bitrate.'.format(endpoint_id)
# property 3: make sure that we are calculating bitrate for encodings
# disabled for now as it's a legitimate case, being video muted, for example
#mask_6 = df_update['total_ideal_bps'] > 0
#assert len(df_update[mask_6]), '{} never computed an ideal bitrate.'.format(endpoint_id)
#mask_7 = df_update['total_target_bps'] > 0
#assert len(df_update[mask_7]), '{} never computed a target bitrate.'.format(endpoint_id)
# property 4: check that the target never exceeds the estimate
# disabled for now as can happen and still be correct because we never suspend the on-stage participant
# mask_8 = (df_update['bwe_bps'] - df_update['total_target_bps']) < 0
# assert not len(df_update[mask_8]), '{} has a target bitrate that exceeds the bandwidth estimation.'.format(endpoint_id)
def check_conference(df, conference_id):
endpoint_ids = [args.endpoint_id] if args.endpoint_id else df['endpoint_id'].unique()
for endpoint_id in endpoint_ids:
check_endpoint(df[df['endpoint_id'] == endpoint_id], endpoint_id)
def check(args):
df = read_json(args.infile)
conference_ids = [args.conference_id] if args.conference_id else df['conference_id'].unique()
for conference_id in conference_ids:
check_conference(df[df['conference_id'] == conference_id], conference_id)
if "__main__" == __name__:
parser = argparse.ArgumentParser()
parser.add_argument('infile', type=argparse.FileType('r'))
subparsers = parser.add_subparsers()
parser_show = subparsers.add_parser('show')
parser_show.set_defaults(func=show)
parser_plot = subparsers.add_parser('plot')
parser_plot.add_argument(
'--series', nargs='+', choices=[
'did_update', 'new_bwe', 'sent_padding', 'calculated_rate'],
default='did_update new_bwe sent_padding in_pkt')
parser_plot.add_argument('--endpoint-id')
parser_plot.add_argument('--remote-endpoint-id')
parser_plot.set_defaults(func=plot)
parser_check = subparsers.add_parser('check')
parser_check.add_argument('--endpoint-id')
parser_check.add_argument('--conference-id')
parser_check.set_defaults(func=check)
args = parser.parse_args()
args.func(args)