🎬 Introduction: The Challenge of Video Annotation (Why Frame-by-Frame Labeling Burns Out Teams)
Video annotation is one of the most time-consuming tasks in data labeling: it's not just about the sheer number of frames — it demands sustained high attention and consistently applied standards. The traditional approach requires frame-by-frame annotation. A 1-minute video at 30fps contains 1,800 frames. If the task involves detection or tracking boxes, many teams experience noticeable fatigue within 30–90 minutes, and consistency degrades (box tightness, category boundaries, occlusion rules) in ways that become uncontrollable.
Today we introduce a more "engineering-oriented" approach: breaking "video annotation" into "frame extraction + keyframe labeling + automatic propagation + quality control". The core idea is: don't pay for information redundancy — focus human effort on where "changes happen or decisions are needed."
This workflow applies to most "video → training dataset" tasks, including but not limited to:
- Object detection: bbox + class (e.g., vehicles/pedestrians/balls)
- Instance segmentation: mask + class (e.g., extracting products/people)
- Keypoints/pose: keypoints + visibility (e.g., body pose, hand keypoints)
- Tracking/behavior: track ID + state (e.g., cross-frame object consistency, anomaly event start/end)
Think of it as a reusable data production pipeline:
Video → Preprocessing (segmenting/stabilizing/deduplication) → Frame extraction (fixed/change-based/keyframe) → Keyframe labeling (human+AI)
→ Automatic propagation (interpolation/tracking/propagation) → QC (sampling+rules+consistency) → Export (YOLO/COCO/VOC…)
🎯 Challenges of Video Annotation (And How They Manifest in Projects)
Pain Points of the Traditional Approach
Problem 1: Massive workload
- 1-minute video = 1,800 frames (30fps)
- Frame-by-frame labeling is extremely time-consuming
- Costs are very high
More critically: frame count grows linearly, but management costs grow exponentially — once you start frame-by-frame, every labeling rule (occlusion, truncation, overlap, hard cases) must be "repeatedly enforced" across massive frames, easily generating extensive rework.
The most common manifestations in projects are:
- Uncontrollable timelines: Initially estimated at "30 seconds per frame," eventually becoming "2–5 minutes per frame + multiple QC rounds"
- Annotation debt accumulation: Starting work before rules are clearly defined, then needing to roll back and redo when guidelines change
- Capacity bottlenecks: More people create more chaos, and management and recovery costs keep rising
Problem 2: Redundant labeling
- Adjacent frames have similar content
- Massive duplicate work
- Low efficiency
In most scenarios (surveillance, dashcam, sports broadcast), dozens or even hundreds of consecutive frames differ very little. Frame-by-frame labeling turns "temporal continuity" into human repetitive labor, instead of letting algorithms leverage that continuity.
Redundant labeling also introduces a hidden problem: standard drift for the same object across frames. For example, you draw a tight box in frame 1, but by frame 100 fatigue leads to a looser box. During training, the model learns "boundary uncertainty," ultimately affecting localization precision and recall.
Problem 3: High time cost
- Requires prolonged concentration
- Fatigue sets in easily
- Error rates increase
Common consequences include:
- Missed labels: Targets that appear briefly are easily missed (e.g., a 0.2-second pedestrian/ball/gesture).
- Box drift: Bounding box positions gradually deviate across adjacent frames (fatigue-induced "casual boxing").
- Category drift: The same target gets labeled as different classes at different time points.
Problem 4: Hard cases cluster and explode (frame-by-frame amplifies "few hard cases" into "massive rework") The frames that truly need human decisions in a video are usually few: occlusion, overlap, glare, motion blur, strong perspective, small targets, rapid camera movement. A frame-by-frame strategy causes hard cases to be encountered repeatedly, leading to:
- Skyrocketing rule explanation costs (everyone has to "think it through again")
- Skyrocketing QC pressure (hard case error rates are significantly higher than normal frames)
Problem 5: Cross-person/cross-day consistency is hard Even the same annotator, coming back the next day to review yesterday's data, may show inconsistencies in "box tightness/occlusion judgment." Solving this usually doesn't rely on "trying harder," but on:
- Writing guidelines as executable checklist items (that can automatically detect issues)
- Accumulating hard cases into example images and rules (reducing subjective interpretation)
- Concentrating human effort on keyframes (reducing fatigue and repetition)
💡 Solution: Video-to-Frame + AI Assistance
Method 1: Intelligent Frame Extraction (Filtering Out Redundant Frames)
Principle:
- Extract keyframes from video
- Avoid redundant labeling
- Improve efficiency
Think of "frame extraction" as a form of sampling: we don't aim to keep every frame, but rather to retain sufficient information at an acceptable cost. As long as downstream training/evaluation metrics aren't affected, sampling is a net gain.
Here's a very practical criterion: If the "target position/appearance change" between consecutive frames is small enough that it wouldn't change the labeling decision, then those frames have low marginal value for training. Conversely, "change points" have extremely high learning value for the model (entry/exit, occlusion, pose switch, key action moments).
Extraction Strategies:
-
Fixed-interval extraction
- Extract 1 frame every N frames
- Simple and straightforward
- Suitable for uniformly changing scenes
Applicable scenarios: Stable camera, smooth target movement, fixed action rhythm. Pros: Low implementation cost, high controllability. Cons: Easy to miss "sudden event frames" (sudden entry, sudden occlusion, rapid turns).
Practical parameter suggestions:
- Express sampling density in fps: e.g., 2fps/5fps (more intuitive and comparable than "every N frames")
- Validate fps with small samples: Compare 1fps vs 5fps for the same duration, evaluating metrics and hard case performance (small targets/occlusion/fast motion)
-
Change detection extraction
- Detect inter-frame changes
- Extract only when changes occur
- Suitable for static scenes
Applicable scenarios: Mostly static with occasional key changes (security, retail stores, warehouses). Common implementation approaches (from easy to hard):
- Pixel difference/histogram difference: Fast, but sensitive to lighting changes
- Structural Similarity (SSIM): More robust, but slightly heavier computation
- Optical flow/motion intensity: Captures motion, but requires more computation and tuning Key point: Change detection isn't about being "smarter" — it's about concentrating the labeling budget on when changes happen.
Common pitfalls (recommended to avoid in advance):
- Lighting flicker/auto-exposure can cause "false change detection," leading to over-dense frame extraction
- Camera shake causes large-area pixel changes — consider stabilization first, or use "motion region ratio" instead of full-frame differencing
- Subtitles/watermarks scrolling can interfere with change detection — best to crop fixed regions before detection
-
Keyframe extraction
- Extract key action frames
- Reduce redundancy
- Suitable for action scenes
Applicable scenarios: Action decomposition, pose, sports, industrial operation workflows. If you have prior knowledge (e.g., "takeoff/landing," "raise hand/lower hand," "grasp/release"), keyframe extraction can dramatically reduce labeling volume while improving sample diversity.
Common implementation paths (from easy to hard):
- Rules/thresholds: Velocity peaks, acceleration peaks, body keypoint change thresholds
- Shot/scene segmentation: Shot boundary / scene change (suitable for videos with obvious content transitions)
- Lightweight model screening: Run a coarse model first to find candidate change segments, then extract frames at high density within those segments ("coarse-to-fine" is usually more efficient)
Method 2: AI-Assisted Labeling
Workflow:
- Extract keyframes
- AI-assisted labeling of keyframes
- Interpolation to generate intermediate frame annotations
- Manual review and fine-tuning
Advantages:
- Dramatically reduces labeling workload
- Improves labeling efficiency
- Maintains labeling consistency
In practice, AI assistance is best suited for two things:
- Cold start: Quickly generating the first version of boxes/classes, reducing time from 0 to 1
- Batch consistency: "Aligning" boundary standards for similar targets (e.g., box tightness, whether to include shadows/reflections)
At the same time, note: AI output should be treated as a "draft," not a "final answer." You need to embed QC processes to achieve stable output at scale.
More specifically, AI assistance typically has 3 deployment approaches, which you can upgrade progressively as your project matures:
- Approach A: Pre-labeling: AI generates boxes/classes first, humans only correct (most common)
- Approach B: Semi-automatic propagation: You label keyframes, AI tracks/propagates to adjacent frames, humans only intervene at "change points"
- Approach C: Active learning: After model training, select "uncertain/error-prone" frames for priority labeling, making every hour more valuable
If you use "chat-based annotation/prompts" to drive AI (especially suitable for keyframes), it's recommended to standardize them as templates to reduce ad-hoc improvisation:
Task: Object detection
Category set: {car, person, bicycle}
Labeling rules:
1) bbox must tightly fit the target's outer contour, allowing minimal background but not truncating the main body
2) Occlusion: still label if >50% occluded, box the visible part, and set occluded=true (if attributes are supported)
3) Distant small targets: ignore if longest side <12px (per your guidelines)
Output: Return each object as {class, bbox[x1,y1,x2,y2]}, pixel coordinates
Common failure modes (knowing these in advance saves a lot of rework):
- Small target missed detection: Balls, distant pedestrians, tiny components
- Heavy occlusion misclassification: Treating two targets as one when crowds/traffic overlap
- Reflection/screen content false detection: Glass reflections, advertising screens, mirrors
- Ambiguous category boundaries: e.g., "van vs truck," "person vs mannequin"
🛠️ Using TjMakeBot for Video Annotation
Step 1: Upload Video
Supported Formats:
- MP4
- AVI
- MOV
- Other common video formats
Upload Methods:
- Drag and drop
- Click to select
- Batch upload
Tip: If you have multiple videos, prioritize uploading them grouped by "scene/camera angle/time period" — this way, subsequent frame rate settings, category sets, and QC sampling strategies can be reused, reducing repetitive configuration.
Two small things to do before uploading (especially for team collaboration):
- Naming convention:
scene_camera_date_segmentID.mp4— this makes locating problem frames much faster later - Segmenting: Cut out "high information density segments" separately (intersections/goals/anomalous behavior) — these can later use higher fps and higher QC sampling ratios
If you have control over the video source, prefer more "training-friendly" source files:
- Avoid re-compression whenever possible: Compression artifacts blur small targets/boundaries, hurting both labeling and model performance
- Don't randomly change resolution: Keep resolution uniform or grouped within the same project (otherwise data distribution becomes more complex)
- Preserve original frame rate information: Makes reproducing "frame extraction settings" and tracing errors much easier later
Step 2: Set Extraction Parameters
Frame Rate Settings:
- Default: 1fps (1 frame per second)
- Customizable: 0.5fps – 30fps
- Adjust based on requirements
How to choose frame rate (priority: target speed > task type > error tolerance):
- Slow-moving targets / static scenes: 0.5–1 fps (surveillance, retail foot traffic, warehouses)
- Normal motion / dashcam: 2–5 fps (vehicles, pedestrians, cycling)
- Fast action / brief key moments: 10–30 fps (sports ball games, gestures, high-speed industrial stations)
A simple rule of thumb: if a target moves more than half its own size within 1 second, 1fps will likely miss key pose/position changes; in that case, increase fps or switch to change detection/keyframe strategies.
Extraction Strategy:
- Fixed interval
- Change detection (future feature)
If you can currently only use fixed intervals, you can still improve results through "segmented extraction": For example, use different fps for different segments of the same video (higher fps for high-speed segments, lower fps for static segments), ensuring key segment quality while controlling overall cost.
Additional reminders (common pitfalls):
- Source video may be variable frame rate (VFR): Using "every N frames" will be unstable — fps-based sampling is recommended
- Motion blur/compression artifacts: Higher fps doesn't always mean better — consider improving bitrate or using clearer video sources when necessary
- Repeated footage: If the video contains lots of repeated segments (live replays/looping surveillance), add a "similar frame deduplication" layer to avoid redundant labeling
Step 3: Extract Frame Images
Automatic Extraction:
- Automatically decodes video
- Extracts at specified frame rate
- Generates image files
Batch Processing:
- Supports multiple videos
- Parallel processing
- Improved efficiency
Optional: If you want to do a reproducible frame extraction locally/on a server (for version management), you can use ffmpeg:
# Example: Export at 2 frames per second (2fps) as jpg
ffmpeg -i input.mp4 -vf fps=2 output_%06d.jpg
# Example: Scene-based segmentation (rough idea: detect scene change threshold), suitable for picking "obviously changed" frames
ffmpeg -i input.mp4 -vf "select='gt(scene,0.3)',showinfo" -vsync vfr output_scene_%06d.jpg
Tip: The scene threshold needs to be adjusted per video content (0.2–0.5 is common). This command works as an "auxiliary candidate frame selection" method, not the sole approach.
To make subsequent exports more stable, it's recommended to establish these conventions during frame extraction:
- Uniform resolution: Either keep the original resolution or uniformly scale to training resolution (avoid mixed sizes within the same project)
- Uniform naming and numbering: e.g.,
videoA_000001.jpg, which naturally expresses temporal order and source traceability - Preserve timestamp mapping: If the tool supports it, save a "frame number/timestamp ↔ image filename" index for faster error tracing later
Step 4: Label Frame Images
AI-Assisted Labeling:
- Use AI chat-based annotation
- Quickly label keyframes
- Batch processing
Manual Labeling:
- Precise positioning
- Adjust bounding boxes
- Supplementary labeling
3 tips for improving "keyframe labeling" quality (directly impacts subsequent interpolation/propagation results):
- Define guidelines before starting: How to handle occlusion/truncation? How tight should boxes be? Should small targets be labeled?
- Do a small-sample consistency check first: Will the same target in 10 frames be labeled differently by different people?
- Turn hard cases into rules: For reflections, mirrors, motion blur, overlapping targets — create example illustrations to reduce rework.
If your task includes "tracking/cross-frame consistency" (track ID), establish two rules during the keyframe phase:
- When to break an ID: Does a target that reappears after complete occlusion count as the same ID or a new one?
- When to merge IDs: When two targets overlap and then separate, how do you ensure IDs don't swap? The earlier you define these rules, the more you save later.
Step 5: Apply to Video
Interpolation Generation:
- Based on keyframe annotations
- Automatically generates intermediate frame annotations
- Maintains continuity
Export Formats:
- YOLO format
- VOC format
- COCO format
How to choose export format (and the most common pitfalls):
- YOLO: Lighter files, more direct training, but watch out for category mapping and coordinate normalization
- Common format:
class_id x_center y_center width height(usually 0–1 normalized) - Most common pitfalls:
class_idchanges, forgetting to sync normalization after image size changes, image and label filename mismatches
- Common format:
- COCO: Stronger structure (JSON can carry more information), suitable for more complex training and analysis pipelines
- Most common pitfalls: Image ID/annotation ID mismatches, misunderstanding bbox coordinate system (
[x,y,w,h])
- Most common pitfalls: Image ID/annotation ID mismatches, misunderstanding bbox coordinate system (
- VOC: Compatible with many legacy tools, but relatively limited in expressiveness
Regardless of which format you export, it's recommended to do a "quick self-check" before training (a few minutes can save half a day of debugging):
- Randomly render annotations on 50–200 images (check for "obvious offset/wrong class/missed labels")
- Check whether sample counts per class are reasonable (whether any class is nearly 0 or abnormally high)
- Check whether train/val/test splits are done by video/scene (avoid adjacent frame leakage causing inflated metrics)
Interpolation is good at solving "continuous position change" problems, but not at handling "semantic discontinuities." For the following situations, increase keyframe density or manually add frames at change points:
- Target suddenly appears/disappears (entering/leaving frame, being occluded)
- Target undergoes deformation/rapid pose change (turning, jumping, waving)
- Multiple targets with heavy occlusion (overlap, crossing, clustering)
If you're building an object detection training set, the goal of interpolation is "reducing repetitive labor," not "generating perfect annotations." Sampling QC is still needed as a safety net.
Interpolation/propagation in engineering typically falls into 3 categories (think of it as a "multiple choice"):
- Linear interpolation: Cheapest, suitable for smooth target movement with no occlusion
- Tracker propagation: Run a tracker between keyframes to propagate bboxes, suitable for medium-complexity videos
- Optical flow/segmentation propagation: More powerful but heavier, suitable for mask/pose tasks requiring pixel-level continuity
One final step before export — do an "automated health check" (many errors can be caught by rules):
- Are bboxes out of bounds, negative, or zero-area?
- Does the same track ID show unreasonable jumps between adjacent frames (sudden displacement/sudden size change)?
- Are categories within the allowed set? Are there unmapped class IDs (common YOLO pitfall)?
