Skip to main content

Multicam audio sync and director-style auto-edit — align N angles of one event by audio cross-correlation, then cut/PiP them into one MP4. Reversible sidecars, never re-encodes the originals.

Project description

polysync

Multicam audio sync + director-style auto-edit. Align N recordings of the same event by audio cross-correlation, then cut or picture-in-picture them into a single MP4 — driven entirely by who's talking.

What makes it different from "yet another sync tool":

  • Reversible sidecars, never re-encodes the originals. Sync writes a tiny <input>.sync.json next to each file holding a single offset. A 75-min 4K 3-camera shoot is 250+ GB; baking offsets into re-encoded copies would double that and lose quality. Downstream applies the offset with ffmpeg -itsoffset at consume time. Originals are touched read-only, always.
  • Envelope cross-correlation, not raw waveform. Matches the log-energy envelope, which both mics hear regardless of their frequency response — robust even when a second camera's on-board mic sounds nothing like the main one.
  • Clock-drift aware. Cheap recorders drift 5–50 ppm; polysync fits the drift across the recording and reports it separately, so long-form lip-sync can correct it while camera-cut editing can ignore it.
  • Handles the messy real cases. Auto-picks the loudest audio track (pro cameras often leave track 1 dead), partial-coverage clips that only span part of the session, and independent verification of the result.

Install

pip install polysync          # once published
# or, from a checkout:
pip install -e ".[dev]"

Requires Python ≥ 3.9 and ffmpeg / ffprobe on your PATH (brew install ffmpeg, apt install ffmpeg, …). Python deps: numpy, scipy.

Quickstart

# 1. Sync each angle to a reference camera (writes <file>.sync.json sidecars)
polysync sync  CAM_A.mp4 CAM_B.mxf
polysync sync  CAM_A.mp4 CAM_C.mxf

# 2. (optional) Verify the alignment — re-checks residual independently
polysync verify CAM_A.mp4 CAM_B.mxf CAM_B.mxf.sync.json

# 3. Build an auto-edit decision list (who's on screen each second)
polysync edit  CAM_A.mp4 CAM_B.mxf CAM_C.mxf --out edl.json

# 4. Render — hard cuts, or with a picture-in-picture inset
polysync render-cuts edl.json --out final.mp4
polysync render-pip  edl.json --out final.mp4 --pip bottom-right

A clip that only covers part of the session (a Riverside / phone / lavalier recording that started mid-way):

polysync sync REFERENCE.mp4 PARTIAL.m4a --partial

How it consumes the sidecar

delta_seconds is the source's t=0 in the reference's timeline (positive = source starts later). To align by hand:

ffmpeg -itsoffset $(jq -r .delta_seconds CAM_B.mxf.sync.json) -i CAM_B.mxf \
       -i CAM_A.mp4 -filter_complex "[0:v][1:v]hstack" out.mp4

The edit / render-* commands read every sidecar automatically.

Python API

from polysync import compute_sync           # pure-numpy core, unit-testable
from polysync.sync import sync_files         # file → sidecar
from polysync.verify import verify_files
from polysync.edit import build_edl

Status

Beta (0.1). Sync + verify are battle-tested on real Sony FX3/FX6 multicam interview footage; the auto-edit is audio-energy-driven (no face detection). Issues and PRs welcome.

License

MIT © 王建硕 (Jian Shuo Wang)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

polysync-0.2.0.tar.gz (24.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

polysync-0.2.0-py3-none-any.whl (26.3 kB view details)

Uploaded Python 3

File details

Details for the file polysync-0.2.0.tar.gz.

File metadata

  • Download URL: polysync-0.2.0.tar.gz
  • Upload date:
  • Size: 24.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for polysync-0.2.0.tar.gz
Algorithm Hash digest
SHA256 ffba8c0f75c2ce30efd11efdb68e2c8663411ba87ec9379d9ed8630f53225805
MD5 8e4893f10af95b4706e61a4eb940febe
BLAKE2b-256 7531fa5b9018289901c26b4fe8f44ddc46245eb6c2819d51bfa3eb881064716c

See more details on using hashes here.

Provenance

The following attestation bundles were made for polysync-0.2.0.tar.gz:

Publisher: publish.yml on jianshuo/polysync

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file polysync-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: polysync-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 26.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for polysync-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 af4c7bea79cfdf95f448958c66858756d2b6e59825c8e87a55da10d25c8cdd21
MD5 26beed0cbf8ca5259fe8b4ebd96613ac
BLAKE2b-256 b8b73b4b8eaf3f455fe2e0e6200a0000d6b8892e0fd22ed723846413e08a0048

See more details on using hashes here.

Provenance

The following attestation bundles were made for polysync-0.2.0-py3-none-any.whl:

Publisher: publish.yml on jianshuo/polysync

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page