diff --git a/apps/proxy/ts_proxy/stream_buffer.py b/apps/proxy/ts_proxy/stream_buffer.py index 111468bf..42ceb2b7 100644 --- a/apps/proxy/ts_proxy/stream_buffer.py +++ b/apps/proxy/ts_proxy/stream_buffer.py @@ -132,6 +132,40 @@ class StreamBuffer: logger.error(f"Error adding chunk to buffer: {e}") return False + def reset_buffer_position(self): + """ + Reset internal buffers for a clean stream transition (failover). + + Called by stream_manager.update_url() when switching between FFmpeg + processes. Without this, _partial_packet from the old FFmpeg gets + concatenated with the first bytes from the new FFmpeg, creating + corrupted TS packets that break audio decoder sync in the client. + """ + try: + with self.lock: + old_write_size = len(self._write_buffer) + old_partial_size = len(getattr(self, '_partial_packet', b'')) + + self._write_buffer = bytearray() + if hasattr(self, '_partial_packet'): + self._partial_packet = bytearray() + + if old_write_size > 0 or old_partial_size > 0: + logger.info( + f"Reset buffer position for channel {self.channel_id}: " + f"cleared {old_write_size} bytes from write buffer, " + f"{old_partial_size} bytes from partial packet" + ) + else: + logger.debug( + f"Reset buffer position for channel {self.channel_id}: " + f"buffers were already clean" + ) + except Exception as e: + logger.error( + f"Error resetting buffer position for channel {self.channel_id}: {e}" + ) + def get_chunks(self, start_index=None): """Get chunks from the buffer with detailed logging""" try: