11from __future__ import annotations
22
33import asyncio
4+ import time
45
56from livekit import rtc
67
1718from ..transcription import find_micro_track_id
1819
1920
20- class _InterruptedError (Exception ):
21- pass
22-
23-
2421class _ParticipantAudioOutput (io .AudioOutput ):
2522 def __init__ (
2623 self ,
@@ -60,8 +57,7 @@ def __init__(
6057
6158 self ._playback_enabled = asyncio .Event ()
6259 self ._playback_enabled .set ()
63-
64- self ._first_frame_fut : asyncio .Future [None ] | None = None
60+ self ._first_frame_event = asyncio .Event ()
6561
6662 async def _publish_track (self ) -> None :
6763 async with self ._lock :
@@ -103,21 +99,9 @@ async def capture_frame(self, frame: rtc.AudioFrame) -> None:
10399 await self ._flush_task
104100
105101 for f in self ._audio_bstream .push (frame .data ):
106- if self ._pushed_duration == 0 :
107- self ._first_frame_fut = asyncio .Future [None ]()
108-
109102 await self ._audio_buf .send (f )
110103 self ._pushed_duration += f .duration
111104
112- # wait for the first frame to be captured
113- if self ._first_frame_fut and not self ._first_frame_fut .done ():
114- try :
115- await self ._first_frame_fut
116- except _InterruptedError :
117- continue
118- finally :
119- self ._first_frame_fut = None
120-
121105 def flush (self ) -> None :
122106 super ().flush ()
123107
@@ -150,6 +134,7 @@ def pause(self) -> None:
150134 def resume (self ) -> None :
151135 super ().resume ()
152136 self ._playback_enabled .set ()
137+ self ._first_frame_event .clear ()
153138
154139 async def _wait_for_playout (self ) -> None :
155140 wait_for_interruption = asyncio .create_task (self ._interrupted_event .wait ())
@@ -185,9 +170,7 @@ async def _wait_buffered_audio() -> None:
185170
186171 self ._pushed_duration = 0
187172 self ._interrupted_event .clear ()
188- if self ._first_frame_fut and not self ._first_frame_fut .done ():
189- self ._first_frame_fut .set_exception (_InterruptedError ())
190- self ._first_frame_fut = None
173+ self ._first_frame_event .clear ()
191174 self .on_playback_finished (playback_position = pushed_duration , interrupted = interrupted )
192175
193176 async def _forward_audio (self ) -> None :
@@ -198,18 +181,16 @@ async def _forward_audio(self) -> None:
198181 # TODO(long): save the frames in the queue and play them later
199182 # TODO(long): ignore frames from previous syllable
200183
201- if self ._interrupted_event .is_set () or (
202- self ._pushed_duration == 0 and not self ._first_frame_fut
203- ):
184+ if self ._interrupted_event .is_set () or self ._pushed_duration == 0 :
204185 if self ._interrupted_event .is_set () and self ._flush_task :
205186 await self ._flush_task
206187
207188 # ignore frames if interrupted
208189 continue
209190
210- if self . _first_frame_fut and not self ._first_frame_fut . done ():
211- self ._first_frame_fut . set_result ( None )
212- self ._first_frame_fut = None
191+ if not self ._first_frame_event . is_set ():
192+ self ._first_frame_event . set ( )
193+ self .on_playback_started ( created_at = time . time ())
213194 await self ._audio_source .capture_frame (frame )
214195
215196 def _on_reconnected (self ) -> None :
0 commit comments