Calculate a multicam clip sync offset from audio spikes
Synchronizing multicamera footage becomes straightforward when both recordings contain the same sharp sound, such as a clap, slate, or drum hit.
Run — free
Enter the detected timestamp of that shared audio spike in the first camera clip and its timestamp in the second clip. The calculator subtracts the second timestamp from the reference timestamp and returns the exact placement offset, plus a clear instruction to delay or advance the second clip. It validates both values and rejects negative timestamps before producing a result.
Choose one unmistakable shared audio spike
Start by identifying the same acoustic event in both camera recordings. A production slate, hand clap, balloon pop, or other short transient works well because its waveform has a steep, recognizable peak. Zoom into each clip's audio waveform and note the timestamp at the same point on that peak, using seconds and decimals when your editor provides subsecond precision. Treat the first camera as the reference timeline: its spike timestamp is the point that the second recording must ultimately match. Enter that value as the first clip spike and enter the matching event from the other recording as the second clip spike. Do not compare different claps or nearby beats, because even a mathematically exact offset cannot repair mismatched source events. The calculator expects timestamps measured from the beginning of each source clip, not existing timeline positions after trims or edits. If a clip has already been trimmed destructively, use the timestamp relative to the trimmed source or restore the original media before measuring. Both timestamps must be zero or greater; a negative timestamp indicates an invalid measurement and is rejected rather than silently interpreted.
Read the offset with the correct sign
The calculation is reference spike time minus second clip spike time. This sign convention describes where the beginning of the second clip belongs on the first clip's timeline. A positive offset means the common sound occurs earlier inside the second clip than it does in the reference, so delay the second clip by the returned number of seconds. A negative offset means the sound occurs later inside the second clip, so advance that clip: its source beginning would sit before the reference timeline origin by the absolute value of the result. A zero result means the detected spikes already share the same source-relative timestamp. The adjustment field restates this interpretation as delay_second_clip, advance_second_clip, or already_aligned, which helps automated editing pipelines avoid reversing the sign. The returned offset is rounded only beyond twelve decimal places to suppress ordinary floating-point residue while preserving practical frame and sample precision. For a frame-based editor, convert seconds to frames using the project's actual timeline frame rate, then inspect the waveform after placement. Keep the seconds value when the editor supports subframe audio positioning, because audio sample accuracy can be finer than a video frame.
Apply and verify the synchronization
Place the first camera clip at the desired reference position, then apply the returned offset to the second clip's start. For a positive value, move the second clip later by exactly that duration. For a negative value, move it earlier by the magnitude of the value; if the timeline cannot extend before zero, shift both clips later by enough time while preserving their relative separation. After placement, play the common event and inspect the two waveforms at high zoom. Their transient peaks should coincide, and muting either track should not reveal a doubled clap or short echo. This calculation solves a constant start-time displacement, which is the usual requirement for cameras that recorded continuously from one shared event. It does not measure clock drift, variable playback speed, dropped frames, differing sample rates, or cuts made inside either clip. For long recordings, verify another shared sound near the end. If the opening spike aligns but the later event does not, correct drift with an appropriate time-stretch or synchronization workflow rather than changing this start offset. Keep the original spike timestamps with the edit notes so the placement can be reproduced, audited, or applied again to proxy and high-resolution media.
What you can do with it
Synchronize an interview shoot
Align a second camera angle to the main camera using the slate clap recorded by both microphones.
Build a multicamera concert timeline
Use a sharp shared drum hit to calculate the start placement of a roaming camera against the reference recording.
Automate proxy relinking preparation
Store a deterministic seconds offset that an editing script can reuse when arranging matching source clips.
FAQ
What does the offset mean?
It is the first clip spike timestamp minus the second clip spike timestamp. Positive means delay the second clip; negative means advance it.
What happens if a timestamp is negative?
The request fails with an invalid input error because a detected event cannot occur before the beginning of its source clip.
Can I enter fractional seconds?
Yes. Decimal seconds preserve subframe or audio-sample precision when that precision is available from your detection workflow.
Does this correct synchronization drift?
No. It calculates one constant placement offset. Use another shared event later in the recordings to test for clock or speed drift.
How much does an API calculation cost?
Each API request costs $0.002. The calculation uses no network services and is deterministic.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/video/multi-cam-sync-offset \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"first_clip_spike_seconds":12.48,"second_clip_spike_seconds":9.73}'const res = await fetch("https://api.kit.forhosting.com/video/multi-cam-sync-offset", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"first_clip_spike_seconds": 12.48,
"second_clip_spike_seconds": 9.73
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/video/multi-cam-sync-offset",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"first_clip_spike_seconds": 12.48,
"second_clip_spike_seconds": 9.73
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/video/multi-cam-sync-offset", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"first_clip_spike_seconds":12.48,"second_clip_spike_seconds":9.73}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"first_clip_spike_seconds":12.48,"second_clip_spike_seconds":9.73}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/video/multi-cam-sync-offset", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"first_clip_spike_seconds": 12.48,
"second_clip_spike_seconds": 9.73
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "video.multi_cam_sync_offset",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 500 |
max_minutes | 60 |
max_megapixels | 3.9 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |