Convert timecode to frame number
Turn a timecode into a frame number and back: 00:01:00:00 at 30 frames per second is frame 1800, counted from zero, so cuts, markers and captions land exactly where they should. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Direction
- To frames
- Framerate
- 30
- Timecode
- 00:01:00:00
- Frames
- 1,800
- Hours
- 0
- Minutes
- 1
- Seconds
- 0
Video editors, colorists, QC operators, and pipeline engineers constantly move between human-readable SMPTE-style timecode and the integer frame counts that NLEs, render farms, and subtitle tools actually index. A single off-by-one error in the frame digit or a framerate mismatch can land a cut on the wrong frame, break an EDL, or shift a caption by a full second. This converter accepts a non-drop HH:MM:SS:FF string plus an integer project framerate and returns the total frame number from zero, or takes a total frame count and rebuilds a zero-padded timecode.
How non-drop timecode maps to a total frame number
Non-drop SMPTE-style timecode labels each frame as hours, minutes, seconds, and a frame digit within the current second. At a constant integer framerate fps, every complete second contributes exactly fps frames, every minute contributes sixty seconds, and every hour contributes three thousand six hundred seconds. The conversion therefore multiplies the wall-clock part of the label by fps and adds the frame digit: frames equals ((hours times three thousand six hundred plus minutes times sixty plus seconds) times fps) plus FF.
Zero-based counting starts at 00:00:00:00 as frame zero, so 00:00:01:00 at thirty frames per second is frame thirty, and 00:01:00:00 at thirty fps is frame one thousand eight hundred. The reverse path peels frames off with integer division and remainder: FF is frames modulo fps, then the remaining whole seconds are split into hours, minutes, and seconds with the usual sixty-based clock. Choose the integer fps that matches your project (twenty-four, twenty-five, thirty, forty-eight, fifty, sixty, and similar) and keep labels consistent across every tool that reads the same media.
Where frame-exact timecode saves the day
Editorial assistants and junior assistants often translate cue sheets and producer notes written in HH:MM:SS:FF into frame numbers for markers, while engineers do the reverse when logging render ranges for a farm that only understands integers. Subtitle and caption pipelines convert in and out points so SRT or VTT cues land on legal frames for the deliverable fps. QC scripts can reject illegal FF values before a package leaves the facility, catching a common paste error that would otherwise pass a string-only validator.
LMS and film-school labs use the free browser path so students practice non-drop arithmetic without installing desktop calculators that disagree on zero-based counting.
What you can do with it
Editorial cue sheets to frame markers
Convert producer notes written as HH:MM:SS:FF into total frame numbers for markers, ranges, and render jobs at a stated project fps.
Caption and QC validation
Reject illegal frame digits (FF ≥ fps) before packaging, and rebuild padded timecode from integer in/out points used by export tools.
FAQ
How do I convert a frame count back to timecode?
The response rebuilds zero-padded HH:MM:SS:FF and the hour, minute, second, and frame components.
What happens if the frame digit is larger than the framerate?
FF must satisfy 0 ≤ FF < framerate; for example 00:00:01:30 is illegal at 24 fps. Invalid input is not billed.
Is this drop-frame or non-drop?
Non-drop only. Semicolons in the input string are accepted as separators, but no NTSC drop-frame skip tables are applied. Use the integer fps of your project.
How many frames are in one minute at 30 frames per second?
One minute is 1800 frames. Counting starts at 00:00:00:00 as frame zero, so 00:00:01:00 is frame 30 and 00:01:00:00 is frame 1800 at that rate.
Which frame rates can I use?
Any whole number from 1 to 240 frames per second, such as 24, 25, 30, 48, 50 or 60. Pick the rate of your project and use the same one in every tool that reads the same media.
Related tools
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/timecode-convert-frames \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"direction":"to_frames","framerate":30,"timecode":"00:01:00:00"}'const res = await fetch("https://api.kit.forhosting.com/video/timecode-convert-frames", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"direction": "to_frames",
"framerate": 30,
"timecode": "00:01:00:00"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/video/timecode-convert-frames",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"direction": "to_frames",
"framerate": 30,
"timecode": "00:01:00:00"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/video/timecode-convert-frames", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"direction":"to_frames","framerate":30,"timecode":"00:01:00:00"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"direction":"to_frames","framerate":30,"timecode":"00:01:00:00"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/video/timecode-convert-frames", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"direction": "to_frames",
"framerate": 30,
"timecode": "00:01:00:00"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "video.timecode_convert_frames",
"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. |
Technical notes
When the frame digit FF is greater than or equal to the framerate the request fails with invalid_input instead of silently wrapping.
How non-drop timecode maps to a total frame number
This endpoint implements that non-drop arithmetic only; it does not apply NTSC drop-frame skip rules for twenty-nine point nine seven, because those rules change the label without changing the underlying frame count formula in the same way.
Input contract, validation rules, and response fields
Framerate must be an integer from one through two hundred forty frames per second. Hours may run from zero through nine thousand nine hundred ninety-nine; minutes and seconds must sit in zero through fifty-nine. The critical editorial rule is enforced on the frame digit: FF must satisfy zero less than or equal to FF and FF strictly less than framerate. On success the body echoes direction and framerate, returns a normalized zero-padded timecode string, the total frames integer, the decomposed hours minutes seconds and frame components, and a short formula string restating the non-drop identity. The reverse with frames one thousand eight hundred and the same fps rebuilds 00:01:00:00. POST a JSON body with direction, framerate, and either timecode or frames. Direction to_frames (aliases frames, tc_to_frames) requires a timecode string HH:MM:SS:FF; colons or semicolons are accepted as separators, but the math is always non-drop. Direction to_timecode (aliases timecode, frames_to_tc) requires a non-negative integer frames field. Example: direction to_frames, framerate thirty, timecode 00:01:00:00 yields frames one thousand eight hundred.
Integration use cases
Classroom and pipeline unit tests
Give students and CI jobs a deterministic non-drop oracle that matches zero-based frame zero at 00:00:00:00 across browser and API.
Technical questions
How do I convert HH:MM:SS:FF to a total frame number?
Send direction to_frames, an integer framerate (fps), and timecode such as 00:01:00:00. The API returns frames = ((H×3600+M×60+S)×fps)+FF with a normalized padded timecode.
What does the timecode to frame number converter cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.