@@ -302,6 +302,71 @@ async def _continuous_reader(self, track):
302302 frames_received += 1
303303 assert frame .samples == 960
304304
305+ @pytest .mark .asyncio
306+ async def test_recv_does_not_reallocate_buffer (self ):
307+ """Test that recv consumes data in-place without creating a new buffer object."""
308+ track = AudioStreamTrack (sample_rate = 48000 , channels = 1 , format = "s16" )
309+
310+ # Write 40ms of data (enough for 2 frames)
311+ samples = np .zeros (1920 , dtype = np .int16 )
312+ pcm = PcmData (
313+ samples = samples ,
314+ sample_rate = 48000 ,
315+ format = AudioFormat .S16 ,
316+ channels = 1 ,
317+ )
318+ await track .write (pcm )
319+
320+ buffer_ref = track ._buffer # save reference before recv
321+
322+ # Receive a frame (consumes 20ms from buffer)
323+ await track .recv ()
324+
325+ assert track ._buffer is buffer_ref , (
326+ "recv should modify buffer in-place, not create a new one"
327+ )
328+ assert len (track ._buffer ) == 960 * 2 , (
329+ "should have 20ms of data remaining (960 samples * 2 bytes)"
330+ )
331+
332+ @pytest .mark .asyncio
333+ async def test_buffer_overflow_does_not_reallocate (self ):
334+ """Test that buffer overflow trims in-place without creating a new buffer object."""
335+ track = AudioStreamTrack (
336+ sample_rate = 48000 , channels = 1 , format = "s16" , audio_buffer_size_ms = 100
337+ )
338+
339+ # Write 50ms of data first to get a buffer reference
340+ samples_50ms = np .zeros (2400 , dtype = np .int16 )
341+ pcm = PcmData (
342+ samples = samples_50ms ,
343+ sample_rate = 48000 ,
344+ format = AudioFormat .S16 ,
345+ channels = 1 ,
346+ )
347+ await track .write (pcm )
348+ buffer_ref = track ._buffer # save reference before overflow
349+
350+ # Write 200ms of data (exceeds 100ms limit, triggers overflow trim)
351+ samples_200ms = np .zeros (9600 , dtype = np .int16 )
352+ pcm_large = PcmData (
353+ samples = samples_200ms ,
354+ sample_rate = 48000 ,
355+ format = AudioFormat .S16 ,
356+ channels = 1 ,
357+ )
358+ await track .write (pcm_large )
359+
360+ assert track ._buffer is buffer_ref , (
361+ "overflow trim should modify buffer in-place, not create a new one"
362+ )
363+ max_buffer_seconds = 100 / 1000
364+ bytes_per_sample = 2
365+ expected_max_bytes = int (max_buffer_seconds * 48000 ) * bytes_per_sample
366+ assert len (track ._buffer ) == expected_max_bytes , (
367+ "buffer should be trimmed to configured max size"
368+ )
369+
305370 @pytest .mark .asyncio
306371 async def test_media_stream_error (self ):
307372 """Test that MediaStreamError is raised when track is not live."""
0 commit comments