Skip to main content

av-drift-detector (Python)

Measure audio/video sync to a fraction of a millisecond, frame by frame.

Python bindings to av-drift-detector, the Rust library behind the av-drift command. Generate a test video whose every frame, and every frame's worth of audio, carries its own frame number. Play it through whatever you want to test (an encoder, a streaming pipeline, a TV, a video call), record the result, and measure how far the sound has drifted from the picture at every frame.

import av_drift_detector as avd

avd.generate("sync.mp4", fps="29.97", duration=10, audio_offset=0.040)
# ... play sync.mp4 through the system under test and record it as captured.mp4 ...
report = avd.analyze("captured.mp4")
print(report["summary"]["mean_ms"])  # positive means the audio is late

Install

pip install av-drift-detector

Python 3.11 or later. Wheels cover macOS (Apple silicon and Intel), Linux (x64 and arm64, manylinux) and Windows (x64); elsewhere pip builds from source, which needs Rust.

Reading and writing files runs the ffmpeg and ffprobe programs, so install FFmpeg 5.1 or later (brew install ffmpeg, sudo apt install ffmpeg, winget install Gyan.FFmpeg) and keep them on your PATH, or set AV_DRIFT_FFMPEG and AV_DRIFT_FFPROBE to their paths. Writing H.264 needs an FFmpeg with libx264, as those packages have. The in-memory functions below don't need FFmpeg.

Files

  • generate(output, *, fps="30", duration=10.0, width=1280, height=720, sample_rate=48000, video_codec="h264", audio_codec="aac", audio_offset=0.0, music=True, on_progress=None) writes a test video and returns a summary. audio_offset (seconds) deliberately delays the audio; negative makes it early. music plays a tune under the tones that doesn't affect analysis. on_progress(frames_done, frames_total) is called about once a percent. FFV1 video and PCM audio need .mov or .mkv.
  • analyze(path, *, offset=0.0, duration=None, fps=None, use_qr=True, capture="auto") measures every frame of a capture. offset and duration choose a window in seconds, and capture is "auto", "file" (a digital copy) or "camera" (a phone filming a screen).

Reports are the dicts av-drift analyze --json writes (format), typed as DriftReport, so json.dump(report, f) saves the CLI's format:

s = report["summary"]
print(f"{s['mean_ms']:+.2f} ms ± {s['stddev_ms']:.2f}, skew {s['skew_ppm']:+.1f} ppm")
for f in report["frames"]:
    if f["status"] == "ok":
        print(f["time"], f["video_frame"], f["drift_ms"])

Frames and audio from elsewhere

If you already have decoded frames and audio (a capture card, WebRTC, a camera), measure them without files:

reader = avd.StampReader()
for time, luma in my_frames():           # 8-bit luma (Y) planes: bytes, numpy uint8, ...
    reader.read(luma, width, height, time)

audio = {"sample_rate": 48_000, "start_time": t0, "samples": mono_float32}  # array("f"), numpy float32, ...
report = avd.analyze_frames(reader.finish(), audio, width=width, height=height)

Frame times and start_time must be on the same clock, in seconds.

  • StampReader(*, try_qr=True) reads the frames of one capture in order. read(luma, width, height, time, stride=None, *, exposure=None, readout=None) returns the frame ({"time", "stamp", "qr_located", "exposure", "readout"}); finish() returns every frame read, with any that could only be identified from later frames filled in. It follows the QR code from frame to frame, which is faster than reading each frame alone, and it reads pictures a camera caught while the screen switched frames, measuring how far through the switch each was (the stamp's blend). Use it for camera footage. For a camera, time is when the picture's top row began its exposure, as phones' camera APIs record it; if the camera reports each frame's exposure time and rolling-shutter readout (seconds), pass them too, and a camera locked to the pattern's rate is timed to a millisecond or two.
  • read_frame(luma, width, height, stride=None, *, try_qr=True) reads one frame's stamp (barcode, then QR code), or returns None.
  • PatternRenderer(*, fps="30", width=1280, height=720, sample_rate=48000, duration=None).render(frame_id) draws a test-pattern frame as luma bytes. With duration (seconds), the info line shows the file's length.
  • synthesize_audio(count, *, fps="30", sample_rate=48000, delay=0.0, start=0, music=True) makes the test audio as an array("f"), with the music unless music is false.

Errors raise AvDriftError. Slow calls release the GIL, so they run in parallel from threads.

More

The repository has the guides: measuring with a camera, the test pattern specification, and how the analysis works. Licensed under the BSD-2-Clause Plus Patent License.

Metadata

Release files for av-drift-detector 0.6.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for av-drift-detector 0.6.1
File Size Uploaded Provenance Actions
av_drift_detector-0.6.1.tar.gz 164.8 kB With provenance Details for av_drift_detector-0.6.1.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for av-drift-detector 0.6.1
File Actions
av_drift_detector-0.6.1-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details for av_drift_detector-0.6.1-cp311-abi3-win_amd64.whl
av_drift_detector-0.6.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 abi3 Linux glibc 2.17+ x86-64 Details for av_drift_detector-0.6.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
av_drift_detector-0.6.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.11 abi3 Linux glibc 2.17+ ARM64 Details for av_drift_detector-0.6.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
av_drift_detector-0.6.1-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details for av_drift_detector-0.6.1-cp311-abi3-macosx_11_0_arm64.whl
av_drift_detector-0.6.1-cp311-abi3-macosx_10_12_x86_64.whl CPython 3.11 abi3 macOS 10.12+ x86-64 Details for av_drift_detector-0.6.1-cp311-abi3-macosx_10_12_x86_64.whl

Total release size: 5.5 MB

Release files / av_drift_detector-0.6.1.tar.gz

Download URL av_drift_detector-0.6.1.tar.gz
Size 164.8 kB
Tags Source
SHA-256 checksum
How to use checksums
a3c3ec936a90461d3016f6d3da622a2b0a832e2e01736132266c37ee827b64c0
BLAKE2b-256 checksum
How to use checksums
4f7efbe5c1b2949c1e73e880f72c7d3f201f09fd0a4a57874303a9715a209220
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / av_drift_detector-0.6.1-cp311-abi3-win_amd64.whl

Download URL av_drift_detector-0.6.1-cp311-abi3-win_amd64.whl
Size 996.9 kB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
a486c7d8387e26cf19399d942f5e37cbafd4ee630edb913216e79c19507a19a5
BLAKE2b-256 checksum
How to use checksums
e3fe4db07696348292b0b9d6289fa586fcd58198bbf043a33959a497e513dec5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / av_drift_detector-0.6.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL av_drift_detector-0.6.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 1.2 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
26f6bda0c3a5ee566b1f47dafef61299c3167c02574aa0824f1cce1d90b4aac7
BLAKE2b-256 checksum
How to use checksums
316e30cee109a7f66b0cd1026c250ffd4185ed608f0391771bd338832390c34d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / av_drift_detector-0.6.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL av_drift_detector-0.6.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 1.0 MB
Tags CPython 3.11 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
3f026e30a277cedefda4abeb97a00441cff02f925ef5aa2fe3c4679f07cef4a2
BLAKE2b-256 checksum
How to use checksums
b0968e0ea6aad8c3869e20417ac9c008ed930c396259b6726b448a543401f36c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / av_drift_detector-0.6.1-cp311-abi3-macosx_11_0_arm64.whl

Download URL av_drift_detector-0.6.1-cp311-abi3-macosx_11_0_arm64.whl
Size 951.6 kB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a2f00921c8e7d1d6a79191b2d35e3e5eb3c5129109983246e266d60dcd027534
BLAKE2b-256 checksum
How to use checksums
3145b56993133a9a297cc80c9668bac59f4b0637ea24c5ac560d4dc577c0a7e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / av_drift_detector-0.6.1-cp311-abi3-macosx_10_12_x86_64.whl

Download URL av_drift_detector-0.6.1-cp311-abi3-macosx_10_12_x86_64.whl
Size 1.1 MB
Tags CPython 3.11 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
933d0381c17c80f67e77fa7437156a7683ccc90d38a71622ce368b82f96338b0
BLAKE2b-256 checksum
How to use checksums
81609182d4111b13f53b2ce6c96d78d1e2867bac93d0ec7c99aac4592ab1afb6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Security for av-drift-detector 0.6.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 6 files in this release have been uploaded with provenance metadata.

Select from 6 files

Attestation for av_drift_detector-0.6.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page