v145 · Web APIs · WebRTC · demo
RTP Clock Converter
The RTP 90 kHz video clock is central to synchronisation and quality analysis. Convert an rtpTimestamp from VideoFrame.metadata() to wall-clock time, compute inter-frame deltas, and use the frame-drop detector below — which flags any gap greater than 1.5× the expected frame interval.
Chrome 145:
VideoFrame.metadata().rtpTimestamp is now populated for frames received via WebRTC. The 90 kHz RTP clock is standard for video (RFC 3550); audio uses 48 kHz or 8 kHz depending on codec.
Enter an RTP timestamp and frame rate · convert to time · then simulate a frame sequence and inject a drop
Time since origin
—
rtpTimestamp ÷ 90000
Inter-frame delta
—
current − previous timestamp
Delta as seconds
—
delta ÷ 90000
Expected interval
—
90000 ÷ fps
Drop detected?
—
delta > 1.5 × expected?
Frame sequence simulator
Fps:
#rtpTimestampdeltasecsstatus
No frames yet — click "+ Frame"
RTP 90 kHz clock — key formulas
time_s = rtpTimestamp / 90000 — convert to seconds (video clock)interval_ticks = 90000 / fps — expected ticks per frame (30fps → 3000)delta = ts_current − ts_previous — ticks between consecutive framesframes_skipped = round(delta / interval) − 1 — dropped frame countdrop_detected = delta > interval * 1.5 — flag conditionwrap = ts > 2^32 → ts - 2^32 — RTP timestamps wrap at 32-bit boundary// Chrome 145: read rtpTimestamp from VideoFrame.metadata()
const processor = new MediaStreamTrackProcessor({ track: videoTrack });
const reader = processor.readable.getReader();
const FPS = 30;
const EXPECTED_INTERVAL = 90000 / FPS; // 3000 ticks at 30fps
let prevRtp = null;
while (true) {
const { value: frame, done } = await reader.read();
if (done) break;
const { rtpTimestamp } = frame.metadata();
if (prevRtp !== null) {
const delta = rtpTimestamp - prevRtp; // handles wrap-around carefully in real code
const dropped = delta > EXPECTED_INTERVAL * 1.5;
if (dropped) {
const skipped = Math.round(delta / EXPECTED_INTERVAL) - 1;
console.warn(`Dropped ${skipped} frame(s) at rtpTimestamp=${rtpTimestamp}`);
}
}
prevRtp = rtpTimestamp;
frame.close();
}