AI understanding¶
Transcribe audio, classify sounds, detect scenes and objects, describe shots, and track faces. For one aggregate object across all of these, see Video analysis.
| Class | Local model family |
|---|---|
AudioToText |
faster-whisper float32 (+ pyannote for diarization) |
AudioClassifier |
AST |
SemanticSceneDetector |
TransNetV2 |
SceneVLM |
Ollama vision model |
FaceShotTracker / FaceSmoothingTracker |
OpenCV YuNet |
ObjectDetector |
D-FINE (COCO) |
AudioToText¶
Model sizes: tiny, base, small, medium, large, turbo (default). Diarization is
opt-in with enable_diarization=True. VAD-gated language detection runs by default;
enable_vad=False detects from the leading audio instead.
Diarization skips speaker embeddings for chunk/speaker pairs with no speech. Compatible
pyannote embedding backends also share frame extraction across speakers in each chunk, then apply
each speaker's original mask separately. Segmentation overlap, precision, and clustering
settings are unchanged. Other embedding models keep the existing extraction path.
When frame extraction is shared, the backend's embedding_batch_size counts audio
chunks rather than chunk/speaker pairs. Pooling materializes one frame row per active
pair in addition to the shared chunk frames. Thus, a batch of 32 chunks with three
active speakers per chunk can hold 32 shared plus 96 pooled frame rows. This uses
more frame-tensor memory than the upstream batch of 32 pairs; it is not a fourfold
estimate of total GPU memory. The measured optimization retains this batching strategy.
Measured timing and comparison limits are in the diarization verification record.
Downstream speaker identification¶
Speaker labels such as SPEAKER_00 identify speakers within one recording. They are
not person identities and are not stable across recordings. Downstream applications
can use Transcription.speakers and each segment's speaker, start, and end to
select audio with Audio.slice(), then run their own identity embedding and matching
models. Model selection, enrollment, and similarity thresholds belong to that consumer.
Videopython does not expose its internal diarization embeddings as identity vectors.
ASR and diarization can also run as separate jobs: call AudioToText().transcribe(audio)
for timed words, then AudioToText(enable_diarization=True).diarize_transcription(audio,
transcription) to attach speaker labels without loading Whisper again.
Anti-hallucination knobs¶
Three Whisper decoder kwargs are surfaced for noisy or sparse-speech audio. Defaults:
condition_on_previous_text=False (the cascading-hallucination fix),
no_speech_threshold=0.6, logprob_threshold=-1.0.
AudioToText(no_speech_threshold=0.4) # lower the no-speech probability cutoff
AudioToText(condition_on_previous_text=True) # Whisper's upstream default; helps on clean podcasts
Brand-name vocabulary biasing¶
Biases Whisper's first-window decoder toward supplied proper nouns via the native
initial_prompt channel, recovering near-mishears (Klarna → "carna", InPost → "in
post") with no extra model dependency.
transcriber = AudioToText(vocabulary=["Klarna", "Allegro", "InPost"]) # instance default
result = transcriber.transcribe(video, vocabulary=["Pyszne", "Wolt"]) # per-call override
The list is normalized at construction: whitespace stripped, case-insensitive dedup, the
casing of the first occurrence preserved. Whisper reserves ~224 tokens for the prompt;
longer lists are trimmed from the tail with one WARNING log line naming the dropped
count. It recovers names Whisper almost heard — it will not catch zero-prior names.
VideoDubber and LocalDubbingPipeline take the same vocabulary kwarg. Inside
VideoAnalyzer, pass it through analyzer_params:
Per-segment confidence¶
TranscriptionSegment carries avg_logprob, no_speech_prob and compression_ratio
from the raw Whisper output. They are None when unavailable — for example on the
diarization-only path that builds segments from words without an overlap match, or on
transcripts loaded from formats that do not carry the metadata.
These feed the dubbing transcript-quality gate and the translator's confidence-aware prompt, and are useful for dropping low-quality segments downstream.
for segment in result.segments:
if segment.avg_logprob is not None and segment.avg_logprob < -1.0:
print(f"low confidence: {segment.text!r}")
AudioToText
¶
Bases: ManagedPredictor
Transcription service for audio and video using local Whisper models.
Uses faster-whisper in float32 for transcription (with word-level timestamps) and
pyannote-audio for optional speaker diarization. By default, Silero VAD
runs before Whisper to gate language detection on a 30s window built from
voiced regions only — fixes Whisper's tendency to lock onto the wrong
language when the file opens with silence, music, or non-vocal credits.
Set enable_vad=False to detect language from the leading audio without
voice-activity gating.
Three Whisper decoder kwargs are surfaced for anti-hallucination tuning:
condition_on_previous_textdefaults toFalse(Whisper's own default isTrue). With conditioning on, a single hallucinated filler phrase cascades through the rest of the file because each window's decoder is primed by the previous window's decoded text. Turning it off is the most commonly recommended fix for that failure mode; the cost on clean audio is small (slightly less context for ambiguous homophones across sentence boundaries).no_speech_thresholdandlogprob_thresholdare forwarded with Whisper's defaults (0.6and-1.0). Loweringno_speech_thresholdmakes the no-speech probability gate easier to trigger;logprob_thresholdalso affects whether a window is skipped.
vocabulary biases Whisper's first-window decoder toward a caller-
supplied list of brand names, product names, or proper nouns via the
native initial_prompt channel. Recovers near-mishears (e.g. Klarna
→ "carna") without new model deps; will not catch zero-prior names.
Per-call override is available on :meth:transcribe.
Source code in src/videopython/ai/understanding/audio.py
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 | |
diarize_transcription
¶
Attach speaker labels to a pre-computed transcription using pyannote.
Useful when callers have a transcription (e.g. pre-computed and edited)
but no speakers, and want per-speaker voice cloning in dubbing without
re-running Whisper. Runs pyannote standalone on audio and overlays
speakers onto the supplied transcription's words.
Requires word-level timings: at least one segment must contain more than one word. Transcriptions loaded from SRT (one synthetic word per segment) will not produce useful speakers and are rejected.
Source code in src/videopython/ai/understanding/audio.py
transcribe
¶
Transcribe audio or video to text.
vocabulary overrides the constructor default for this call only;
a per-call list wins over the instance's vocabulary so one
:class:AudioToText instance can serve multiple tenants. Pass
None (the default) to use the constructor's list.
Source code in src/videopython/ai/understanding/audio.py
AudioClassifier¶
Sound, music and audio-event classification with timestamps, using an Audio Spectrogram Transformer.
from videopython.ai import AudioClassifier
result = AudioClassifier(confidence_threshold=0.3).classify(video)
for label, confidence in result.clip_predictions.items():
print(f"{label}: {confidence:.2f}")
for event in result.events:
print(f"{event.start:.1f}s - {event.end:.1f}s: {event.label} ({event.confidence:.2f})")
AudioClassifier
¶
Bases: ManagedPredictor
Audio event and sound classification using AST.
Source code in src/videopython/ai/understanding/classification.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | |
classify
¶
Classify audio events in audio or video.
Source code in src/videopython/ai/understanding/classification.py
SceneVLM¶
Describes scenes with an Ollama vision model. Needs a running Ollama server and a
vision model that supports structured output; model is any tag you have pulled (default
qwen3.6:27b).
analyze_scene() and analyze_frame() return a
SceneDescription: a one-sentence caption, an open-list
subjects, and a closed-enum shot_type. The schema is handed to Ollama's format, so
the model returns valid JSON directly.
from videopython.ai import SceneVLM
vlm = SceneVLM()
description = vlm.analyze_frame(frame_array)
description.caption # "A man in a cap speaks into a microphone."
description.subjects # ["man", "microphone", "cap"]
description.shot_type # "medium"
SceneVLM.unload() clears the Ollama client, for low_memory parity.
SceneVLM
¶
Bases: ManagedPredictor
Generates structured scene descriptions with a local Ollama vision model.
The model must be vision-capable and support Ollama's structured-output
format; ollama pull <model> first. options are extra Ollama
generation options merged over temperature=0.
A scene's frames are sent as one multi-image request, so the context window
is sized to the frame count automatically -- Ollama's 4096-token default
fits only one or two frames and fails anything larger. Pass an explicit
num_ctx in options to override that sizing.
Source code in src/videopython/ai/understanding/image.py
analyze_frame
¶
Analyze one frame and return a structured scene description.
analyze_scene
¶
Analyze a scene's frames and return a structured description.
Source code in src/videopython/ai/understanding/image.py
SemanticSceneDetector¶
TransNetV2 scene-boundary detection — more accurate than histogram methods, especially on fades and dissolves.
from videopython.ai import SemanticSceneDetector
detector = SemanticSceneDetector(threshold=0.5, min_scene_length=1.0)
for scene in detector.detect_streaming("video.mp4"):
print(f"{scene.start:.1f}s - {scene.end:.1f}s ({scene.duration:.1f}s)")
SemanticSceneDetector
¶
Bases: ManagedPredictor
ML-based scene detection using TransNetV2.
TransNetV2 is a neural network specifically designed for shot boundary detection, providing more accurate scene boundaries than histogram-based methods, especially for gradual transitions.
Uses the transnetv2-pytorch package with pretrained weights.
Example
from videopython.ai.understanding import SemanticSceneDetector detector = SemanticSceneDetector() scenes = detector.detect_streaming("video.mp4") for scene in scenes: ... print(f"Scene: {scene.start:.2f}s - {scene.end:.2f}s")
Source code in src/videopython/ai/understanding/temporal.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | |
__init__
¶
Initialize the semantic scene detector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
threshold
|
float
|
Confidence threshold for scene boundaries (0.0-1.0). Higher values = fewer, more confident boundaries. |
0.5
|
min_scene_length
|
float
|
Minimum scene duration in seconds. |
0.5
|
device
|
str | None
|
Device to run on ('cuda', 'mps', 'cpu', or None for auto). Note: MPS may have numerical inconsistencies; use 'cpu' for reproducible results. |
None
|
Source code in src/videopython/ai/understanding/temporal.py
detect
¶
Detect scenes in a video using ML-based boundary detection.
Note: This method requires saving video to a temporary file for TransNetV2 processing. For better performance, use detect_streaming() with a file path directly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
video
|
Video
|
Video object to analyze. |
required |
Returns:
| Type | Description |
|---|---|
list[SceneBoundary]
|
List of SceneBoundary objects representing detected scenes. |
Source code in src/videopython/ai/understanding/temporal.py
detect_streaming
¶
Detect scenes from a video file.
Uses TransNetV2 with pretrained weights for accurate shot boundary detection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Path to video file. |
required |
Returns:
| Type | Description |
|---|---|
list[SceneBoundary]
|
List of SceneBoundary objects representing detected scenes. |
Source code in src/videopython/ai/understanding/temporal.py
detect_from_path
classmethod
¶
detect_from_path(
path: str | Path,
threshold: float = 0.5,
min_scene_length: float = 0.5,
) -> list[SceneBoundary]
Convenience method for one-shot scene detection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Path to video file. |
required |
threshold
|
float
|
Scene boundary threshold (0.0-1.0). |
0.5
|
min_scene_length
|
float
|
Minimum scene duration in seconds. |
0.5
|
Returns:
| Type | Description |
|---|---|
list[SceneBoundary]
|
List of SceneBoundary objects representing detected scenes. |
Source code in src/videopython/ai/understanding/temporal.py
Face tracking¶
Two YuNet-based trackers share one detector, one per use case:
FaceShotTracker.track_shot(frames, frame_indices)returnsFaceTrackobjects with ids that are stable within a shot, associated by IoU. There is no embedding re-identification, so a track does not survive a shot boundary. This is whatVideoAnalyzeruses.FaceSmoothingTracker.detect_and_track(frame, frame_index)/track_video(frames)are the single-subject smoothed-position APIs behindFaceTrackingCrop.
from videopython.ai import FaceShotTracker
for track in FaceShotTracker().track_shot(frames):
print(f"track #{track.track_id}: {track.length} frames, first {track.frame_indices[0]}")
FaceShotTracker
¶
Bases: _FaceTrackerBase
Per-shot multi-track face association via IoU.
Detects faces on every input frame and stitches them into FaceTracks
greedily by best IoU. Tracks do not survive across shot boundaries
(IoU-only association; no embedding re-id). Used by the video-analysis
pipeline to bind detections to subjects within one shot.
Source code in src/videopython/ai/understanding/faces.py
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 | |
__init__
¶
__init__(
min_face_size: int = 30,
batch_size: int = 16,
iou_match_threshold: float = DEFAULT_IOU_MATCH_THRESHOLD,
max_missed_frames: int = DEFAULT_MAX_MISSED_FRAMES,
)
Initialize the per-shot tracker.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_face_size
|
int
|
Minimum face size in pixels for detection. |
30
|
batch_size
|
int
|
Batch size for detection. Default 16. |
16
|
iou_match_threshold
|
float
|
Minimum IoU between consecutive detections to continue an existing track. |
DEFAULT_IOU_MATCH_THRESHOLD
|
max_missed_frames
|
int
|
Consecutive frames a track may go without a detection before it is closed. |
DEFAULT_MAX_MISSED_FRAMES
|
Source code in src/videopython/ai/understanding/faces.py
track_shot
¶
track_shot(
frames: list[ndarray] | ndarray,
frame_indices: list[int] | None = None,
) -> list[FaceTrack]
Per-shot multi-track association via IoU.
Detection is run on every input frame (caller is expected to have
already chosen the sampling cadence -- the analysis pipeline
passes one frame per scene-VLM sample, lip-sync passes every
frame in the shot). Tracks are stitched together greedily by
best IoU above iou_match_threshold; tracks with no match for
max_missed_frames consecutive frames are closed and won't
accept future associations.
Track ids are integers starting at 1 within this shot. They are not stable across shots — embedding re-id is deferred.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frames
|
list[ndarray] | ndarray
|
Frames in the shot (list or stacked ndarray). |
required |
frame_indices
|
list[int] | None
|
Source-video frame indices. Defaults to
|
None
|
Returns:
| Type | Description |
|---|---|
list[FaceTrack]
|
List of |
list[FaceTrack]
|
tracked in the shot. |
Source code in src/videopython/ai/understanding/faces.py
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 | |
FaceSmoothingTracker
¶
Bases: _FaceTrackerBase
Single-subject face tracker with EMA position smoothing.
Selects one face per frame (selection_strategy) and returns a smoothed
(cx, cy, w, h) tuple in normalized coords via detect_and_track /
track_video. Used by FaceTrackingCrop to drive a follow-the-speaker
crop.
Source code in src/videopython/ai/understanding/faces.py
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | |
__init__
¶
__init__(
selection_strategy: Literal[
"largest", "centered", "index"
] = "largest",
face_index: int = 0,
smoothing: float = 0.8,
detection_interval: int = 3,
min_face_size: int = 30,
batch_size: int = 16,
)
Initialize the smoothing tracker.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
selection_strategy
|
Literal['largest', 'centered', 'index']
|
Which face to track — "largest" (biggest box),
"centered" (closest to frame center), or "index" ( |
'largest'
|
face_index
|
int
|
Index of face to track when using the "index" strategy. |
0
|
smoothing
|
float
|
Exponential moving average factor (0-1). Higher = smoother. |
0.8
|
detection_interval
|
int
|
Run detection every N frames, hold position between. |
3
|
min_face_size
|
int
|
Minimum face size in pixels for detection. |
30
|
batch_size
|
int
|
Frames per detection batch in |
16
|
Source code in src/videopython/ai/understanding/faces.py
detect_and_track
¶
Detect face in frame and return smoothed position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frame
|
ndarray
|
Video frame as numpy array (H, W, 3). |
required |
frame_index
|
int
|
Index of current frame. |
required |
Returns:
| Type | Description |
|---|---|
tuple[float, float, float, float] | None
|
Tuple of (center_x, center_y, width, height) in normalized coords, |
tuple[float, float, float, float] | None
|
or None if no face detected and no fallback available. |
Source code in src/videopython/ai/understanding/faces.py
reset
¶
track_video
¶
Track the face through a whole clip via batched per-frame detection.
Detection runs on every frame (the YuNet detector is CPU-only), then each frame's selected face is EMA-smoothed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frames
|
ndarray
|
Video frames array of shape (N, H, W, 3). |
required |
Returns:
| Type | Description |
|---|---|
list[tuple[float, float, float, float] | None]
|
List of face positions (cx, cy, w, h) for each frame, or None where |
list[tuple[float, float, float, float] | None]
|
no face was detected and no fallback was available. |
Source code in src/videopython/ai/understanding/faces.py
ObjectDetector¶
Runs a D-FINE COCO model and returns DetectedObject per frame, with
normalized bounding boxes sorted by confidence. Weights (Apache-2.0) download from
HuggingFace on first use; class names come from the model config.
class_filter accepts D-FINE's VOC-style names and their standard COCO equivalents
(for example, motorbike or motorcycle, and tvmonitor or tv). Names are
normalized for case and spacing; unknown names are logged after the model loads.
from videopython.ai import ObjectDetector
detector = ObjectDetector(model_name="ustc-community/dfine-nano-coco",
class_filter=("person", "car"))
for obj in detector.detect(video.frames[0]):
print(f"{obj.label} {obj.confidence:.2f} @ {obj.bounding_box}")
per_frame = detector.detect_batch(video.frames[:16])
ObjectDetector
¶
Bases: DetectorBase[DetectedObject]
Lazy D-FINE COCO object detector returning normalized detections.
The D-FINE weights (default ustc-community/dfine-nano-coco) download from
HuggingFace on first real use; class names come from the model config.
Detection is gated by confidence_threshold and optionally restricted to
class_filter, which accepts either D-FINE's VOC-style spellings or the
standard COCO ones (motorcycle, airplane, couch, potted plant,
dining table, tv) -- see :func:normalize_class_names.
Source code in src/videopython/ai/understanding/objects.py
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | |
__init__
¶
__init__(
model_name: str = DEFAULT_MODEL,
confidence_threshold: float = DEFAULT_CONFIDENCE_THRESHOLD,
class_filter: tuple[str, ...] = (),
backend: Backend = "auto",
)
Initialize the detector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_name
|
str
|
D-FINE COCO HuggingFace repo id (e.g.
|
DEFAULT_MODEL
|
confidence_threshold
|
float
|
Minimum detection confidence in |
DEFAULT_CONFIDENCE_THRESHOLD
|
class_filter
|
tuple[str, ...]
|
If non-empty, only these COCO class names are kept.
Either spelling works -- |
()
|
backend
|
Backend
|
Detection device - |
'auto'
|
Source code in src/videopython/ai/understanding/objects.py
unknown_filter_classes
¶
class_filter names this model never emits (empty until it loads).
Source code in src/videopython/ai/understanding/objects.py
Result types¶
Shared, AI-free Pydantic models from videopython.base, produced by the analyzers above and
consumed by videopython.editing.
SceneBoundary
¶
Bases: _ResultModel
Timing information for a detected scene.
A lightweight structure representing scene boundaries returned by
scene detectors (e.g. videopython.ai.SemanticSceneDetector). This
is a backbone type — higher-level scene analysis lives in orchestration
packages.
Attributes:
| Name | Type | Description |
|---|---|---|
start |
float
|
Scene start time in seconds |
end |
float
|
Scene end time in seconds |
start_frame |
int
|
Index of the first frame in this scene |
end_frame |
int
|
Index of the last frame in this scene (exclusive) |
Source code in src/videopython/base/description.py
SceneDescription
¶
Bases: _ResultModel
Structured visual scene description from the SceneVLM.
The v1 schema is intentionally narrow (caption + subjects + shot_type). Wider schemas drop JSON parse rate on small models without eval data to defend the cost. Fields are added in v2 as parse-rate measurements justify them; closed enums first, open lists last.
Attributes:
| Name | Type | Description |
|---|---|---|
caption |
str
|
One-sentence summary of the scene. |
subjects |
list[str]
|
Open list of named subjects visible in the frames. |
shot_type |
str | None
|
Closed enum framing the camera distance, or None when JSON parsing fell back to raw text. |
Source code in src/videopython/base/description.py
BoundingBox
¶
Bases: _ResultModel
A bounding box for detected objects or crop regions in an image.
Coordinates are normalized to [0, 1] relative to image dimensions.
It can be embedded directly into Operation fields (for example,
KenBurns.start_region) and validated as part of an operation's JSON
wire format.
Source code in src/videopython/base/description.py
DetectedObject
¶
Bases: _ResultModel
An object detected in a video frame.
Attributes:
| Name | Type | Description |
|---|---|---|
label |
str
|
Name/class of the detected object (e.g., "person", "car", "dog") |
confidence |
float
|
Detection confidence score between 0 and 1 |
bounding_box |
BoundingBox | None
|
Optional bounding box location of the object |
Source code in src/videopython/base/description.py
DetectedFace
¶
Bases: _ResultModel
A face detected in a video frame.
Attributes:
| Name | Type | Description |
|---|---|---|
bounding_box |
BoundingBox | None
|
Bounding box location of the face (normalized 0-1 coordinates). May be None for cloud backends that only return face counts. |
confidence |
float
|
Detection confidence score between 0 and 1 |
Source code in src/videopython/base/description.py
DetectedText
¶
Bases: _ResultModel
Text detected in a video frame.
Attributes:
| Name | Type | Description |
|---|---|---|
text |
str
|
OCR text content |
confidence |
float
|
Detection confidence score between 0 and 1 |
bounding_box |
BoundingBox | None
|
Optional normalized bounding box for the text region |
Source code in src/videopython/base/description.py
FaceTrack
¶
Bases: _ResultModel
A face tracked across consecutive frames within a single shot.
Tracks are produced by IoU association — no embedding re-id, so a
track does not survive across shot/scene boundaries. frame_indices
and boxes are parallel lists of equal length.
Attributes:
| Name | Type | Description |
|---|---|---|
track_id |
int
|
Stable id within the shot the track was produced in. Not globally unique across scenes. |
frame_indices |
list[int]
|
Source-video frame indices for each detection. |
boxes |
list[BoundingBox]
|
Per-frame bounding boxes (normalized 0-1 coords). |
confidences |
list[float]
|
Per-frame detection confidence in [0, 1]. |
Source code in src/videopython/base/description.py
MotionInfo
¶
Bases: _ResultModel
Motion characteristics between consecutive frames.
Attributes:
| Name | Type | Description |
|---|---|---|
motion_type |
str
|
Classification of camera/scene motion - "static": No significant motion - "pan": Horizontal camera movement - "tilt": Vertical camera movement - "zoom": Camera zoom in/out - "complex": Mixed or irregular motion |
magnitude |
float
|
Normalized motion magnitude (0.0 = no motion, 1.0 = high motion) |
raw_magnitude |
float
|
Raw optical flow magnitude (pixels/frame) |
Source code in src/videopython/base/description.py
AudioEvent
¶
Bases: _ResultModel
A detected audio event with timestamp.
Attributes:
| Name | Type | Description |
|---|---|---|
start |
float
|
Start time in seconds |
end |
float
|
End time in seconds |
label |
str
|
Name of the detected sound (e.g., "Music", "Speech", "Dog bark") |
confidence |
float
|
Detection confidence score between 0 and 1 |
Source code in src/videopython/base/description.py
AudioClassification
¶
Bases: _ResultModel
Complete audio classification results.
Attributes:
| Name | Type | Description |
|---|---|---|
events |
list[AudioEvent]
|
List of detected audio events with timestamps |
clip_predictions |
dict[str, float]
|
Overall class probabilities for the entire audio clip |