66"""
77
88import inspect
9+ import logging
910
1011import supervision as sv
1112
13+ logger = logging .getLogger (__name__ )
14+
1215
1316class ByteTrackFactory :
1417 """Lazy, class-based singleton for API-adaptive ByteTrack construction.
@@ -31,36 +34,69 @@ class ByteTrackFactory:
3134 def _build (cls ) -> sv .ByteTrack :
3235 """Build ByteTrack with correct parameters for installed supervision version.
3336
37+ Uses a defensive try-except approach: attempts both API signatures
38+ and uses whichever one succeeds.
39+
3440 Returns:
3541 sv.ByteTrack: Configured tracker instance
3642
3743 Raises:
38- RuntimeError: If neither old nor new API signatures are recognized
44+ RuntimeError: If both API signatures fail
3945 """
40- sig = inspect .signature (sv .ByteTrack )
41-
42- if "track_thresh" in sig .parameters :
43- # Older supervision API (< 0.23)
44- return sv .ByteTrack (
45- track_thresh = 0.25 ,
46- track_buffer = 30 ,
47- match_thresh = 0.8 ,
48- frame_rate = 30 ,
49- )
50-
51- if "track_activation_threshold" in sig .parameters :
52- # Newer supervision API (>= 0.23)
53- return sv .ByteTrack (
46+ sv_version = getattr (sv , "__version__" , "unknown" )
47+ logger .info ("ByteTrackFactory._build() called" )
48+ logger .info (f"supervision version: { sv_version } " )
49+
50+ # Inspect signature for logging
51+ try :
52+ sig = inspect .signature (sv .ByteTrack )
53+ params = list (sig .parameters .keys ())
54+ logger .info (f"sv.ByteTrack signature params: { params } " )
55+ except Exception as e :
56+ logger .warning (f"Could not inspect ByteTrack signature: { e } " )
57+ params = []
58+
59+ # STRATEGY: Try both APIs in order, use whichever works
60+ # This is more reliable than signature inspection which can be fooled
61+ # by decorators, wrappers, or __init__ overrides
62+
63+ # Try NEW API first (more recent supervision versions)
64+ logger .info ("Attempting NEW API (track_activation_threshold)..." )
65+ try :
66+ tracker = sv .ByteTrack (
5467 track_activation_threshold = 0.25 ,
5568 lost_track_buffer = 30 ,
5669 minimum_matching_threshold = 0.8 ,
5770 frame_rate = 30 ,
5871 )
59-
60- raise RuntimeError (
61- f"Unsupported ByteTrack constructor signature. "
62- f"Available params: { list (sig .parameters .keys ())} "
72+ logger .info ("SUCCESS: ByteTrack created with NEW API" )
73+ return tracker
74+ except TypeError as e :
75+ logger .info (f"NEW API failed: { e } " )
76+
77+ # Try OLD API (older supervision versions)
78+ logger .info ("Attempting OLD API (track_thresh)..." )
79+ try :
80+ tracker = sv .ByteTrack (
81+ track_thresh = 0.25 ,
82+ track_buffer = 30 ,
83+ match_thresh = 0.8 ,
84+ frame_rate = 30 ,
85+ )
86+ logger .info ("SUCCESS: ByteTrack created with OLD API" )
87+ return tracker
88+ except TypeError as e :
89+ logger .info (f"OLD API failed: { e } " )
90+
91+ # Neither worked - raise comprehensive error
92+ error_msg = (
93+ f"ByteTrack construction failed with both API signatures. "
94+ f"supervision version: { sv_version } , "
95+ f"detected params: { params } . "
96+ f"Please check supervision installation."
6397 )
98+ logger .error (error_msg )
99+ raise RuntimeError (error_msg )
64100
65101 @classmethod
66102 def get (cls ) -> sv .ByteTrack :
@@ -70,7 +106,10 @@ def get(cls) -> sv.ByteTrack:
70106 sv.ByteTrack: Singleton tracker instance
71107 """
72108 if cls ._instance is None :
109+ logger .debug ("Creating new ByteTrack singleton instance" )
73110 cls ._instance = cls ._build ()
111+ else :
112+ logger .debug ("Returning existing ByteTrack singleton instance" )
74113 return cls ._instance
75114
76115 @classmethod
@@ -79,4 +118,5 @@ def reset(cls) -> None:
79118
80119 Useful for testing or when tracker state needs to be cleared.
81120 """
121+ logger .debug ("Resetting ByteTrack singleton instance" )
82122 cls ._instance = None
0 commit comments