@@ -54,6 +54,7 @@ def __init__(self, posthog_client: Optional[PostHogClient] = None, **kwargs):
5454 self ._original_embeddings = getattr (self , "embeddings" , None )
5555 self ._original_beta = getattr (self , "beta" , None )
5656 self ._original_responses = getattr (self , "responses" , None )
57+ self ._original_audio = getattr (self , "audio" , None )
5758
5859 # Replace with wrapped versions (only if originals exist)
5960 if self ._original_chat is not None :
@@ -68,6 +69,9 @@ def __init__(self, posthog_client: Optional[PostHogClient] = None, **kwargs):
6869 if self ._original_responses is not None :
6970 self .responses = WrappedResponses (self , self ._original_responses )
7071
72+ if self ._original_audio is not None :
73+ self .audio = WrappedAudio (self , self ._original_audio )
74+
7175
7276class WrappedResponses :
7377 """Async wrapper for OpenAI responses that tracks usage in PostHog."""
@@ -589,6 +593,119 @@ async def create(
589593 return response
590594
591595
596+ class WrappedAudio :
597+ """Async wrapper for OpenAI audio that tracks usage in PostHog."""
598+
599+ def __init__ (self , client : AsyncOpenAI , original_audio ):
600+ self ._client = client
601+ self ._original = original_audio
602+
603+ def __getattr__ (self , name ):
604+ """Fallback to original audio object for any methods we don't explicitly handle."""
605+ return getattr (self ._original , name )
606+
607+ @property
608+ def transcriptions (self ):
609+ return WrappedTranscriptions (self ._client , self ._original .transcriptions )
610+
611+
612+ class WrappedTranscriptions :
613+ """Async wrapper for OpenAI audio transcriptions that tracks usage in PostHog."""
614+
615+ def __init__ (self , client : AsyncOpenAI , original_transcriptions ):
616+ self ._client = client
617+ self ._original = original_transcriptions
618+
619+ def __getattr__ (self , name ):
620+ """Fallback to original transcriptions object for any methods we don't explicitly handle."""
621+ return getattr (self ._original , name )
622+
623+ async def create (
624+ self ,
625+ posthog_distinct_id : Optional [str ] = None ,
626+ posthog_trace_id : Optional [str ] = None ,
627+ posthog_properties : Optional [Dict [str , Any ]] = None ,
628+ posthog_privacy_mode : bool = False ,
629+ posthog_groups : Optional [Dict [str , Any ]] = None ,
630+ ** kwargs : Any ,
631+ ):
632+ """
633+ Create a transcription using OpenAI's 'audio.transcriptions.create' method,
634+ and track usage in PostHog.
635+
636+ Args:
637+ posthog_distinct_id: Optional ID to associate with the usage event.
638+ posthog_trace_id: Optional trace UUID for linking events.
639+ posthog_properties: Optional dictionary of extra properties to include in the event.
640+ posthog_privacy_mode: Whether to anonymize the input and output.
641+ posthog_groups: Optional dictionary of groups to associate with the event.
642+ **kwargs: Any additional parameters for the OpenAI Transcriptions API.
643+
644+ Returns:
645+ The response from OpenAI's audio.transcriptions.create call.
646+ """
647+ if posthog_trace_id is None :
648+ posthog_trace_id = str (uuid .uuid4 ())
649+
650+ start_time = time .time ()
651+ response = await self ._original .create (** kwargs )
652+ end_time = time .time ()
653+
654+ latency = end_time - start_time
655+
656+ # Extract file info
657+ file_obj = kwargs .get ("file" )
658+ file_name = getattr (file_obj , "name" , None ) if file_obj else None
659+
660+ # Extract transcription output
661+ output_text = getattr (response , "text" , None )
662+
663+ # Extract duration if available (verbose_json response format)
664+ duration = getattr (response , "duration" , None )
665+
666+ # Build event properties
667+ event_properties = {
668+ "$ai_provider" : "openai" ,
669+ "$ai_model" : kwargs .get ("model" ),
670+ "$ai_input" : with_privacy_mode (
671+ self ._client ._ph_client ,
672+ posthog_privacy_mode ,
673+ file_name ,
674+ ),
675+ "$ai_output_text" : with_privacy_mode (
676+ self ._client ._ph_client ,
677+ posthog_privacy_mode ,
678+ output_text ,
679+ ),
680+ "$ai_http_status" : 200 ,
681+ "$ai_latency" : latency ,
682+ "$ai_trace_id" : posthog_trace_id ,
683+ "$ai_base_url" : str (self ._client .base_url ),
684+ ** (posthog_properties or {}),
685+ }
686+
687+ # Add optional properties
688+ if kwargs .get ("language" ):
689+ event_properties ["$ai_language" ] = kwargs .get ("language" )
690+
691+ if duration is not None :
692+ event_properties ["$ai_audio_duration" ] = duration
693+
694+ if posthog_distinct_id is None :
695+ event_properties ["$process_person_profile" ] = False
696+
697+ # Capture event
698+ if hasattr (self ._client ._ph_client , "capture" ):
699+ self ._client ._ph_client .capture (
700+ distinct_id = posthog_distinct_id or posthog_trace_id ,
701+ event = "$ai_transcription" ,
702+ properties = event_properties ,
703+ groups = posthog_groups ,
704+ )
705+
706+ return response
707+
708+
592709class WrappedBeta :
593710 """Async wrapper for OpenAI beta features that tracks usage in PostHog."""
594711
0 commit comments