11from pyee .asyncio import AsyncIOEventEmitter
22from ._ffi_client import (FfiClient , FfiHandle )
3- from livekit import (Track , Room , Participant )
4- from ._proto import track_pb2 as proto_track
3+ from livekit import Track
54from ._proto import ffi_pb2 as proto_ffi
6- from ._proto import video_frame_pb2 as proto_video_frame
7- from .video_frame import (VideoFrame , VideoFrameBuffer )
5+ from ._proto import audio_frame_pb2 as proto_audio_frame
6+ from .audio_frame import AudioFrame
7+ import ctypes
8+ import weakref
89
910
1011class AudioStream (AsyncIOEventEmitter ):
11- _streams : dict [int , 'AudioStream' ] = {}
12+ _streams : dict [int , weakref . ref [ 'AudioStream' ] ] = {}
1213 _initialized = False
1314
1415 @classmethod
@@ -23,9 +24,46 @@ def initalize(cls):
2324 cls ._on_audio_stream_event )
2425
2526 @classmethod
26- def _on_audio_stream_event (cls , event : proto_video_frame .AudioStreamEvent ):
27- pass
27+ def _on_audio_stream_event (cls , event : proto_audio_frame .AudioStreamEvent ):
28+ stream = cls ._streams .get (event .handle .id )
29+ if stream is None :
30+ return
31+
32+ stream = stream ()
33+ if stream is None :
34+ return
35+
36+ which = event .WhichOneof ('message' )
37+ if which == 'frame_received' :
38+ frame_info = event .frame_received .frame
39+ ffi_handle = FfiHandle (frame_info .handle .id )
40+ data_len = frame_info .num_channels * frame_info .samples_per_channel
41+ data = ctypes .cast (frame_info .data_ptr ,
42+ ctypes .POINTER (ctypes .c_uint16 * data_len )).contents
43+ frame = AudioFrame (
44+ frame_info .sample_rate , frame_info .num_channels , frame_info .samples_per_channel , data , ffi_handle )
45+ stream ._on_frame_received (frame )
2846
2947 def __init__ (self , track : Track ):
3048 super ().__init__ ()
3149 self .initalize ()
50+
51+ req = proto_ffi .FfiRequest ()
52+ new_audio_stream = req .new_audio_stream
53+ new_audio_stream .track_handle .id = track ._ffi_handle .handle
54+ new_audio_stream .type = proto_audio_frame .AudioStreamType .AUDIO_STREAM_NATIVE
55+
56+ ffi_client = FfiClient ()
57+ resp = ffi_client .request (req )
58+ stream_info = resp .new_audio_stream .stream
59+
60+ self ._streams [stream_info .handle .id ] = weakref .ref (self )
61+ self ._ffi_handle = FfiHandle (stream_info .handle .id )
62+ self ._info = stream_info
63+ self ._track = track
64+
65+ def _on_frame_received (self , frame : AudioFrame ):
66+ self .emit ('frame_received' , frame )
67+
68+ def __del__ (self ):
69+ self ._streams .pop (self ._ffi_handle .handle , None )
0 commit comments