diff --git a/.github/workflows/check-types.yml b/.github/workflows/check-types.yml index c4490611..0e6e6e04 100644 --- a/.github/workflows/check-types.yml +++ b/.github/workflows/check-types.yml @@ -29,7 +29,7 @@ jobs: run: python -m pip install --upgrade mypy - name: Install packages - run: python -m pip install pytest ./livekit-api ./livekit-protocol ./livekit-rtc pydantic + run: python -m pip install pytest ./livekit-api ./livekit-protocol ./livekit-rtc pydantic numpy - name: Check Types run: python -m mypy --install-type --non-interactive -p 'livekit-protocol' -p 'livekit-api' -p 'livekit-rtc' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index db7a89fe..576b56b1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -23,5 +23,5 @@ jobs: - name: Run tests run: | python3 ./livekit-rtc/rust-sdks/download_ffi.py --output livekit-rtc/livekit/rtc/resources - pip3 install pytest ./livekit-protocol ./livekit-api ./livekit-rtc pydantic + pip3 install pytest ./livekit-protocol ./livekit-api ./livekit-rtc pydantic numpy pytest . --ignore=livekit-rtc/rust-sdks diff --git a/livekit-rtc/livekit/rtc/__init__.py b/livekit-rtc/livekit/rtc/__init__.py index 65379111..f1309e1b 100644 --- a/livekit-rtc/livekit/rtc/__init__.py +++ b/livekit-rtc/livekit/rtc/__init__.py @@ -77,6 +77,7 @@ from .video_source import VideoSource from .video_stream import VideoFrameEvent, VideoStream from .audio_resampler import AudioResampler, AudioResamplerQuality +from .apm import AudioProcessingModule from .utils import combine_audio_frames from .rpc import RpcError, RpcInvocationData from .synchronizer import AVSynchronizer @@ -163,5 +164,6 @@ "TextStreamWriter", "ByteStreamReader", "ByteStreamWriter", + "AudioProcessingModule", "__version__", ] diff --git a/livekit-rtc/livekit/rtc/_ffi_client.py b/livekit-rtc/livekit/rtc/_ffi_client.py index 0c7465e1..a1c60549 100644 --- a/livekit-rtc/livekit/rtc/_ffi_client.py +++ b/livekit-rtc/livekit/rtc/_ffi_client.py @@ -104,6 +104,9 @@ def dispose(self) -> None: self._disposed = True assert ffi_lib.livekit_ffi_drop_handle(ctypes.c_uint64(self.handle)) + def __repr__(self) -> str: + return f"FfiHandle({self.handle})" + T = TypeVar("T") diff --git a/livekit-rtc/livekit/rtc/_proto/audio_frame_pb2.py b/livekit-rtc/livekit/rtc/_proto/audio_frame_pb2.py index fd35778d..b4007e96 100644 --- a/livekit-rtc/livekit/rtc/_proto/audio_frame_pb2.py +++ b/livekit-rtc/livekit/rtc/_proto/audio_frame_pb2.py @@ -16,7 +16,7 @@ from . import track_pb2 as track__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11\x61udio_frame.proto\x12\rlivekit.proto\x1a\x0chandle.proto\x1a\x0btrack.proto\"\xc4\x01\n\x15NewAudioStreamRequest\x12\x14\n\x0ctrack_handle\x18\x01 \x02(\x04\x12,\n\x04type\x18\x02 \x02(\x0e\x32\x1e.livekit.proto.AudioStreamType\x12\x13\n\x0bsample_rate\x18\x03 \x01(\r\x12\x14\n\x0cnum_channels\x18\x04 \x01(\r\x12\x1e\n\x16\x61udio_filter_module_id\x18\x05 \x01(\t\x12\x1c\n\x14\x61udio_filter_options\x18\x06 \x01(\t\"I\n\x16NewAudioStreamResponse\x12/\n\x06stream\x18\x01 \x02(\x0b\x32\x1f.livekit.proto.OwnedAudioStream\"\x88\x02\n!AudioStreamFromParticipantRequest\x12\x1a\n\x12participant_handle\x18\x01 \x02(\x04\x12,\n\x04type\x18\x02 \x02(\x0e\x32\x1e.livekit.proto.AudioStreamType\x12\x30\n\x0ctrack_source\x18\x03 \x01(\x0e\x32\x1a.livekit.proto.TrackSource\x12\x13\n\x0bsample_rate\x18\x05 \x01(\r\x12\x14\n\x0cnum_channels\x18\x06 \x01(\r\x12\x1e\n\x16\x61udio_filter_module_id\x18\x07 \x01(\t\x12\x1c\n\x14\x61udio_filter_options\x18\x08 \x01(\t\"U\n\"AudioStreamFromParticipantResponse\x12/\n\x06stream\x18\x01 \x02(\x0b\x32\x1f.livekit.proto.OwnedAudioStream\"\xbb\x01\n\x15NewAudioSourceRequest\x12,\n\x04type\x18\x01 \x02(\x0e\x32\x1e.livekit.proto.AudioSourceType\x12\x32\n\x07options\x18\x02 \x01(\x0b\x32!.livekit.proto.AudioSourceOptions\x12\x13\n\x0bsample_rate\x18\x03 \x02(\r\x12\x14\n\x0cnum_channels\x18\x04 \x02(\r\x12\x15\n\rqueue_size_ms\x18\x05 \x01(\r\"I\n\x16NewAudioSourceResponse\x12/\n\x06source\x18\x01 \x02(\x0b\x32\x1f.livekit.proto.OwnedAudioSource\"f\n\x18\x43\x61ptureAudioFrameRequest\x12\x15\n\rsource_handle\x18\x01 \x02(\x04\x12\x33\n\x06\x62uffer\x18\x02 \x02(\x0b\x32#.livekit.proto.AudioFrameBufferInfo\"-\n\x19\x43\x61ptureAudioFrameResponse\x12\x10\n\x08\x61sync_id\x18\x01 \x02(\x04\"<\n\x19\x43\x61ptureAudioFrameCallback\x12\x10\n\x08\x61sync_id\x18\x01 \x02(\x04\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"0\n\x17\x43learAudioBufferRequest\x12\x15\n\rsource_handle\x18\x01 \x02(\x04\"\x1a\n\x18\x43learAudioBufferResponse\"\x1a\n\x18NewAudioResamplerRequest\"R\n\x19NewAudioResamplerResponse\x12\x35\n\tresampler\x18\x01 \x02(\x0b\x32\".livekit.proto.OwnedAudioResampler\"\x93\x01\n\x17RemixAndResampleRequest\x12\x18\n\x10resampler_handle\x18\x01 \x02(\x04\x12\x33\n\x06\x62uffer\x18\x02 \x02(\x0b\x32#.livekit.proto.AudioFrameBufferInfo\x12\x14\n\x0cnum_channels\x18\x03 \x02(\r\x12\x13\n\x0bsample_rate\x18\x04 \x02(\r\"P\n\x18RemixAndResampleResponse\x12\x34\n\x06\x62uffer\x18\x01 \x02(\x0b\x32$.livekit.proto.OwnedAudioFrameBuffer\"\x9c\x02\n\x16NewSoxResamplerRequest\x12\x12\n\ninput_rate\x18\x01 \x02(\x01\x12\x13\n\x0boutput_rate\x18\x02 \x02(\x01\x12\x14\n\x0cnum_channels\x18\x03 \x02(\r\x12<\n\x0finput_data_type\x18\x04 \x02(\x0e\x32#.livekit.proto.SoxResamplerDataType\x12=\n\x10output_data_type\x18\x05 \x02(\x0e\x32#.livekit.proto.SoxResamplerDataType\x12\x37\n\x0equality_recipe\x18\x06 \x02(\x0e\x32\x1f.livekit.proto.SoxQualityRecipe\x12\r\n\x05\x66lags\x18\x07 \x01(\r\"l\n\x17NewSoxResamplerResponse\x12\x35\n\tresampler\x18\x01 \x01(\x0b\x32 .livekit.proto.OwnedSoxResamplerH\x00\x12\x0f\n\x05\x65rror\x18\x02 \x01(\tH\x00\x42\t\n\x07message\"S\n\x17PushSoxResamplerRequest\x12\x18\n\x10resampler_handle\x18\x01 \x02(\x04\x12\x10\n\x08\x64\x61ta_ptr\x18\x02 \x02(\x04\x12\x0c\n\x04size\x18\x03 \x02(\r\"K\n\x18PushSoxResamplerResponse\x12\x12\n\noutput_ptr\x18\x01 \x02(\x04\x12\x0c\n\x04size\x18\x02 \x02(\r\x12\r\n\x05\x65rror\x18\x03 \x01(\t\"4\n\x18\x46lushSoxResamplerRequest\x12\x18\n\x10resampler_handle\x18\x01 \x02(\x04\"L\n\x19\x46lushSoxResamplerResponse\x12\x12\n\noutput_ptr\x18\x01 \x02(\x04\x12\x0c\n\x04size\x18\x02 \x02(\r\x12\r\n\x05\x65rror\x18\x03 \x01(\t\"p\n\x14\x41udioFrameBufferInfo\x12\x10\n\x08\x64\x61ta_ptr\x18\x01 \x02(\x04\x12\x14\n\x0cnum_channels\x18\x02 \x02(\r\x12\x13\n\x0bsample_rate\x18\x03 \x02(\r\x12\x1b\n\x13samples_per_channel\x18\x04 \x02(\r\"y\n\x15OwnedAudioFrameBuffer\x12-\n\x06handle\x18\x01 \x02(\x0b\x32\x1d.livekit.proto.FfiOwnedHandle\x12\x31\n\x04info\x18\x02 \x02(\x0b\x32#.livekit.proto.AudioFrameBufferInfo\"?\n\x0f\x41udioStreamInfo\x12,\n\x04type\x18\x01 \x02(\x0e\x32\x1e.livekit.proto.AudioStreamType\"o\n\x10OwnedAudioStream\x12-\n\x06handle\x18\x01 \x02(\x0b\x32\x1d.livekit.proto.FfiOwnedHandle\x12,\n\x04info\x18\x02 \x02(\x0b\x32\x1e.livekit.proto.AudioStreamInfo\"\x9f\x01\n\x10\x41udioStreamEvent\x12\x15\n\rstream_handle\x18\x01 \x02(\x04\x12;\n\x0e\x66rame_received\x18\x02 \x01(\x0b\x32!.livekit.proto.AudioFrameReceivedH\x00\x12,\n\x03\x65os\x18\x03 \x01(\x0b\x32\x1d.livekit.proto.AudioStreamEOSH\x00\x42\t\n\x07message\"I\n\x12\x41udioFrameReceived\x12\x33\n\x05\x66rame\x18\x01 \x02(\x0b\x32$.livekit.proto.OwnedAudioFrameBuffer\"\x10\n\x0e\x41udioStreamEOS\"e\n\x12\x41udioSourceOptions\x12\x19\n\x11\x65\x63ho_cancellation\x18\x01 \x02(\x08\x12\x19\n\x11noise_suppression\x18\x02 \x02(\x08\x12\x19\n\x11\x61uto_gain_control\x18\x03 \x02(\x08\"?\n\x0f\x41udioSourceInfo\x12,\n\x04type\x18\x02 \x02(\x0e\x32\x1e.livekit.proto.AudioSourceType\"o\n\x10OwnedAudioSource\x12-\n\x06handle\x18\x01 \x02(\x0b\x32\x1d.livekit.proto.FfiOwnedHandle\x12,\n\x04info\x18\x02 \x02(\x0b\x32\x1e.livekit.proto.AudioSourceInfo\"\x14\n\x12\x41udioResamplerInfo\"u\n\x13OwnedAudioResampler\x12-\n\x06handle\x18\x01 \x02(\x0b\x32\x1d.livekit.proto.FfiOwnedHandle\x12/\n\x04info\x18\x02 \x02(\x0b\x32!.livekit.proto.AudioResamplerInfo\"\x12\n\x10SoxResamplerInfo\"q\n\x11OwnedSoxResampler\x12-\n\x06handle\x18\x01 \x02(\x0b\x32\x1d.livekit.proto.FfiOwnedHandle\x12-\n\x04info\x18\x02 \x02(\x0b\x32\x1f.livekit.proto.SoxResamplerInfo\"\\\n\x1cLoadAudioFilterPluginRequest\x12\x13\n\x0bplugin_path\x18\x01 \x02(\t\x12\x14\n\x0c\x64\x65pendencies\x18\x02 \x03(\t\x12\x11\n\tmodule_id\x18\x03 \x02(\t\".\n\x1dLoadAudioFilterPluginResponse\x12\r\n\x05\x65rror\x18\x01 \x01(\t*J\n\x14SoxResamplerDataType\x12\x18\n\x14SOXR_DATATYPE_INT16I\x10\x00\x12\x18\n\x14SOXR_DATATYPE_INT16S\x10\x01*\x8b\x01\n\x10SoxQualityRecipe\x12\x16\n\x12SOXR_QUALITY_QUICK\x10\x00\x12\x14\n\x10SOXR_QUALITY_LOW\x10\x01\x12\x17\n\x13SOXR_QUALITY_MEDIUM\x10\x02\x12\x15\n\x11SOXR_QUALITY_HIGH\x10\x03\x12\x19\n\x15SOXR_QUALITY_VERYHIGH\x10\x04*\x97\x01\n\x0bSoxFlagBits\x12\x16\n\x12SOXR_ROLLOFF_SMALL\x10\x00\x12\x17\n\x13SOXR_ROLLOFF_MEDIUM\x10\x01\x12\x15\n\x11SOXR_ROLLOFF_NONE\x10\x02\x12\x18\n\x14SOXR_HIGH_PREC_CLOCK\x10\x03\x12\x19\n\x15SOXR_DOUBLE_PRECISION\x10\x04\x12\x0b\n\x07SOXR_VR\x10\x05*A\n\x0f\x41udioStreamType\x12\x17\n\x13\x41UDIO_STREAM_NATIVE\x10\x00\x12\x15\n\x11\x41UDIO_STREAM_HTML\x10\x01**\n\x0f\x41udioSourceType\x12\x17\n\x13\x41UDIO_SOURCE_NATIVE\x10\x00\x42\x10\xaa\x02\rLiveKit.Proto') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11\x61udio_frame.proto\x12\rlivekit.proto\x1a\x0chandle.proto\x1a\x0btrack.proto\"\xc4\x01\n\x15NewAudioStreamRequest\x12\x14\n\x0ctrack_handle\x18\x01 \x02(\x04\x12,\n\x04type\x18\x02 \x02(\x0e\x32\x1e.livekit.proto.AudioStreamType\x12\x13\n\x0bsample_rate\x18\x03 \x01(\r\x12\x14\n\x0cnum_channels\x18\x04 \x01(\r\x12\x1e\n\x16\x61udio_filter_module_id\x18\x05 \x01(\t\x12\x1c\n\x14\x61udio_filter_options\x18\x06 \x01(\t\"I\n\x16NewAudioStreamResponse\x12/\n\x06stream\x18\x01 \x02(\x0b\x32\x1f.livekit.proto.OwnedAudioStream\"\x88\x02\n!AudioStreamFromParticipantRequest\x12\x1a\n\x12participant_handle\x18\x01 \x02(\x04\x12,\n\x04type\x18\x02 \x02(\x0e\x32\x1e.livekit.proto.AudioStreamType\x12\x30\n\x0ctrack_source\x18\x03 \x01(\x0e\x32\x1a.livekit.proto.TrackSource\x12\x13\n\x0bsample_rate\x18\x05 \x01(\r\x12\x14\n\x0cnum_channels\x18\x06 \x01(\r\x12\x1e\n\x16\x61udio_filter_module_id\x18\x07 \x01(\t\x12\x1c\n\x14\x61udio_filter_options\x18\x08 \x01(\t\"U\n\"AudioStreamFromParticipantResponse\x12/\n\x06stream\x18\x01 \x02(\x0b\x32\x1f.livekit.proto.OwnedAudioStream\"\xbb\x01\n\x15NewAudioSourceRequest\x12,\n\x04type\x18\x01 \x02(\x0e\x32\x1e.livekit.proto.AudioSourceType\x12\x32\n\x07options\x18\x02 \x01(\x0b\x32!.livekit.proto.AudioSourceOptions\x12\x13\n\x0bsample_rate\x18\x03 \x02(\r\x12\x14\n\x0cnum_channels\x18\x04 \x02(\r\x12\x15\n\rqueue_size_ms\x18\x05 \x01(\r\"I\n\x16NewAudioSourceResponse\x12/\n\x06source\x18\x01 \x02(\x0b\x32\x1f.livekit.proto.OwnedAudioSource\"f\n\x18\x43\x61ptureAudioFrameRequest\x12\x15\n\rsource_handle\x18\x01 \x02(\x04\x12\x33\n\x06\x62uffer\x18\x02 \x02(\x0b\x32#.livekit.proto.AudioFrameBufferInfo\"-\n\x19\x43\x61ptureAudioFrameResponse\x12\x10\n\x08\x61sync_id\x18\x01 \x02(\x04\"<\n\x19\x43\x61ptureAudioFrameCallback\x12\x10\n\x08\x61sync_id\x18\x01 \x02(\x04\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"0\n\x17\x43learAudioBufferRequest\x12\x15\n\rsource_handle\x18\x01 \x02(\x04\"\x1a\n\x18\x43learAudioBufferResponse\"\x1a\n\x18NewAudioResamplerRequest\"R\n\x19NewAudioResamplerResponse\x12\x35\n\tresampler\x18\x01 \x02(\x0b\x32\".livekit.proto.OwnedAudioResampler\"\x93\x01\n\x17RemixAndResampleRequest\x12\x18\n\x10resampler_handle\x18\x01 \x02(\x04\x12\x33\n\x06\x62uffer\x18\x02 \x02(\x0b\x32#.livekit.proto.AudioFrameBufferInfo\x12\x14\n\x0cnum_channels\x18\x03 \x02(\r\x12\x13\n\x0bsample_rate\x18\x04 \x02(\r\"P\n\x18RemixAndResampleResponse\x12\x34\n\x06\x62uffer\x18\x01 \x02(\x0b\x32$.livekit.proto.OwnedAudioFrameBuffer\"\x95\x01\n\rNewApmRequest\x12\x1e\n\x16\x65\x63ho_canceller_enabled\x18\x01 \x02(\x08\x12\x1f\n\x17gain_controller_enabled\x18\x02 \x02(\x08\x12 \n\x18high_pass_filter_enabled\x18\x03 \x02(\x08\x12!\n\x19noise_suppression_enabled\x18\x04 \x02(\x08\"6\n\x0eNewApmResponse\x12$\n\x03\x61pm\x18\x01 \x02(\x0b\x32\x17.livekit.proto.OwnedApm\"x\n\x17\x41pmProcessStreamRequest\x12\x12\n\napm_handle\x18\x01 \x02(\x04\x12\x10\n\x08\x64\x61ta_ptr\x18\x02 \x02(\x04\x12\x0c\n\x04size\x18\x03 \x02(\r\x12\x13\n\x0bsample_rate\x18\x04 \x02(\r\x12\x14\n\x0cnum_channels\x18\x05 \x02(\r\")\n\x18\x41pmProcessStreamResponse\x12\r\n\x05\x65rror\x18\x01 \x01(\t\"\x7f\n\x1e\x41pmProcessReverseStreamRequest\x12\x12\n\napm_handle\x18\x01 \x02(\x04\x12\x10\n\x08\x64\x61ta_ptr\x18\x02 \x02(\x04\x12\x0c\n\x04size\x18\x03 \x02(\r\x12\x13\n\x0bsample_rate\x18\x04 \x02(\r\x12\x14\n\x0cnum_channels\x18\x05 \x02(\r\"0\n\x1f\x41pmProcessReverseStreamResponse\x12\r\n\x05\x65rror\x18\x01 \x01(\t\"\x9c\x02\n\x16NewSoxResamplerRequest\x12\x12\n\ninput_rate\x18\x01 \x02(\x01\x12\x13\n\x0boutput_rate\x18\x02 \x02(\x01\x12\x14\n\x0cnum_channels\x18\x03 \x02(\r\x12<\n\x0finput_data_type\x18\x04 \x02(\x0e\x32#.livekit.proto.SoxResamplerDataType\x12=\n\x10output_data_type\x18\x05 \x02(\x0e\x32#.livekit.proto.SoxResamplerDataType\x12\x37\n\x0equality_recipe\x18\x06 \x02(\x0e\x32\x1f.livekit.proto.SoxQualityRecipe\x12\r\n\x05\x66lags\x18\x07 \x01(\r\"l\n\x17NewSoxResamplerResponse\x12\x35\n\tresampler\x18\x01 \x01(\x0b\x32 .livekit.proto.OwnedSoxResamplerH\x00\x12\x0f\n\x05\x65rror\x18\x02 \x01(\tH\x00\x42\t\n\x07message\"S\n\x17PushSoxResamplerRequest\x12\x18\n\x10resampler_handle\x18\x01 \x02(\x04\x12\x10\n\x08\x64\x61ta_ptr\x18\x02 \x02(\x04\x12\x0c\n\x04size\x18\x03 \x02(\r\"K\n\x18PushSoxResamplerResponse\x12\x12\n\noutput_ptr\x18\x01 \x02(\x04\x12\x0c\n\x04size\x18\x02 \x02(\r\x12\r\n\x05\x65rror\x18\x03 \x01(\t\"4\n\x18\x46lushSoxResamplerRequest\x12\x18\n\x10resampler_handle\x18\x01 \x02(\x04\"L\n\x19\x46lushSoxResamplerResponse\x12\x12\n\noutput_ptr\x18\x01 \x02(\x04\x12\x0c\n\x04size\x18\x02 \x02(\r\x12\r\n\x05\x65rror\x18\x03 \x01(\t\"p\n\x14\x41udioFrameBufferInfo\x12\x10\n\x08\x64\x61ta_ptr\x18\x01 \x02(\x04\x12\x14\n\x0cnum_channels\x18\x02 \x02(\r\x12\x13\n\x0bsample_rate\x18\x03 \x02(\r\x12\x1b\n\x13samples_per_channel\x18\x04 \x02(\r\"y\n\x15OwnedAudioFrameBuffer\x12-\n\x06handle\x18\x01 \x02(\x0b\x32\x1d.livekit.proto.FfiOwnedHandle\x12\x31\n\x04info\x18\x02 \x02(\x0b\x32#.livekit.proto.AudioFrameBufferInfo\"?\n\x0f\x41udioStreamInfo\x12,\n\x04type\x18\x01 \x02(\x0e\x32\x1e.livekit.proto.AudioStreamType\"o\n\x10OwnedAudioStream\x12-\n\x06handle\x18\x01 \x02(\x0b\x32\x1d.livekit.proto.FfiOwnedHandle\x12,\n\x04info\x18\x02 \x02(\x0b\x32\x1e.livekit.proto.AudioStreamInfo\"\x9f\x01\n\x10\x41udioStreamEvent\x12\x15\n\rstream_handle\x18\x01 \x02(\x04\x12;\n\x0e\x66rame_received\x18\x02 \x01(\x0b\x32!.livekit.proto.AudioFrameReceivedH\x00\x12,\n\x03\x65os\x18\x03 \x01(\x0b\x32\x1d.livekit.proto.AudioStreamEOSH\x00\x42\t\n\x07message\"I\n\x12\x41udioFrameReceived\x12\x33\n\x05\x66rame\x18\x01 \x02(\x0b\x32$.livekit.proto.OwnedAudioFrameBuffer\"\x10\n\x0e\x41udioStreamEOS\"e\n\x12\x41udioSourceOptions\x12\x19\n\x11\x65\x63ho_cancellation\x18\x01 \x02(\x08\x12\x19\n\x11noise_suppression\x18\x02 \x02(\x08\x12\x19\n\x11\x61uto_gain_control\x18\x03 \x02(\x08\"?\n\x0f\x41udioSourceInfo\x12,\n\x04type\x18\x02 \x02(\x0e\x32\x1e.livekit.proto.AudioSourceType\"o\n\x10OwnedAudioSource\x12-\n\x06handle\x18\x01 \x02(\x0b\x32\x1d.livekit.proto.FfiOwnedHandle\x12,\n\x04info\x18\x02 \x02(\x0b\x32\x1e.livekit.proto.AudioSourceInfo\"\x14\n\x12\x41udioResamplerInfo\"u\n\x13OwnedAudioResampler\x12-\n\x06handle\x18\x01 \x02(\x0b\x32\x1d.livekit.proto.FfiOwnedHandle\x12/\n\x04info\x18\x02 \x02(\x0b\x32!.livekit.proto.AudioResamplerInfo\"9\n\x08OwnedApm\x12-\n\x06handle\x18\x01 \x02(\x0b\x32\x1d.livekit.proto.FfiOwnedHandle\"\x12\n\x10SoxResamplerInfo\"q\n\x11OwnedSoxResampler\x12-\n\x06handle\x18\x01 \x02(\x0b\x32\x1d.livekit.proto.FfiOwnedHandle\x12-\n\x04info\x18\x02 \x02(\x0b\x32\x1f.livekit.proto.SoxResamplerInfo\"\\\n\x1cLoadAudioFilterPluginRequest\x12\x13\n\x0bplugin_path\x18\x01 \x02(\t\x12\x14\n\x0c\x64\x65pendencies\x18\x02 \x03(\t\x12\x11\n\tmodule_id\x18\x03 \x02(\t\".\n\x1dLoadAudioFilterPluginResponse\x12\r\n\x05\x65rror\x18\x01 \x01(\t*J\n\x14SoxResamplerDataType\x12\x18\n\x14SOXR_DATATYPE_INT16I\x10\x00\x12\x18\n\x14SOXR_DATATYPE_INT16S\x10\x01*\x8b\x01\n\x10SoxQualityRecipe\x12\x16\n\x12SOXR_QUALITY_QUICK\x10\x00\x12\x14\n\x10SOXR_QUALITY_LOW\x10\x01\x12\x17\n\x13SOXR_QUALITY_MEDIUM\x10\x02\x12\x15\n\x11SOXR_QUALITY_HIGH\x10\x03\x12\x19\n\x15SOXR_QUALITY_VERYHIGH\x10\x04*\x97\x01\n\x0bSoxFlagBits\x12\x16\n\x12SOXR_ROLLOFF_SMALL\x10\x00\x12\x17\n\x13SOXR_ROLLOFF_MEDIUM\x10\x01\x12\x15\n\x11SOXR_ROLLOFF_NONE\x10\x02\x12\x18\n\x14SOXR_HIGH_PREC_CLOCK\x10\x03\x12\x19\n\x15SOXR_DOUBLE_PRECISION\x10\x04\x12\x0b\n\x07SOXR_VR\x10\x05*A\n\x0f\x41udioStreamType\x12\x17\n\x13\x41UDIO_STREAM_NATIVE\x10\x00\x12\x15\n\x11\x41UDIO_STREAM_HTML\x10\x01**\n\x0f\x41udioSourceType\x12\x17\n\x13\x41UDIO_SOURCE_NATIVE\x10\x00\x42\x10\xaa\x02\rLiveKit.Proto') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -24,16 +24,16 @@ if not _descriptor._USE_C_DESCRIPTORS: _globals['DESCRIPTOR']._loaded_options = None _globals['DESCRIPTOR']._serialized_options = b'\252\002\rLiveKit.Proto' - _globals['_SOXRESAMPLERDATATYPE']._serialized_start=3651 - _globals['_SOXRESAMPLERDATATYPE']._serialized_end=3725 - _globals['_SOXQUALITYRECIPE']._serialized_start=3728 - _globals['_SOXQUALITYRECIPE']._serialized_end=3867 - _globals['_SOXFLAGBITS']._serialized_start=3870 - _globals['_SOXFLAGBITS']._serialized_end=4021 - _globals['_AUDIOSTREAMTYPE']._serialized_start=4023 - _globals['_AUDIOSTREAMTYPE']._serialized_end=4088 - _globals['_AUDIOSOURCETYPE']._serialized_start=4090 - _globals['_AUDIOSOURCETYPE']._serialized_end=4132 + _globals['_SOXRESAMPLERDATATYPE']._serialized_start=4262 + _globals['_SOXRESAMPLERDATATYPE']._serialized_end=4336 + _globals['_SOXQUALITYRECIPE']._serialized_start=4339 + _globals['_SOXQUALITYRECIPE']._serialized_end=4478 + _globals['_SOXFLAGBITS']._serialized_start=4481 + _globals['_SOXFLAGBITS']._serialized_end=4632 + _globals['_AUDIOSTREAMTYPE']._serialized_start=4634 + _globals['_AUDIOSTREAMTYPE']._serialized_end=4699 + _globals['_AUDIOSOURCETYPE']._serialized_start=4701 + _globals['_AUDIOSOURCETYPE']._serialized_end=4743 _globals['_NEWAUDIOSTREAMREQUEST']._serialized_start=64 _globals['_NEWAUDIOSTREAMREQUEST']._serialized_end=260 _globals['_NEWAUDIOSTREAMRESPONSE']._serialized_start=262 @@ -64,48 +64,62 @@ _globals['_REMIXANDRESAMPLEREQUEST']._serialized_end=1507 _globals['_REMIXANDRESAMPLERESPONSE']._serialized_start=1509 _globals['_REMIXANDRESAMPLERESPONSE']._serialized_end=1589 - _globals['_NEWSOXRESAMPLERREQUEST']._serialized_start=1592 - _globals['_NEWSOXRESAMPLERREQUEST']._serialized_end=1876 - _globals['_NEWSOXRESAMPLERRESPONSE']._serialized_start=1878 - _globals['_NEWSOXRESAMPLERRESPONSE']._serialized_end=1986 - _globals['_PUSHSOXRESAMPLERREQUEST']._serialized_start=1988 - _globals['_PUSHSOXRESAMPLERREQUEST']._serialized_end=2071 - _globals['_PUSHSOXRESAMPLERRESPONSE']._serialized_start=2073 - _globals['_PUSHSOXRESAMPLERRESPONSE']._serialized_end=2148 - _globals['_FLUSHSOXRESAMPLERREQUEST']._serialized_start=2150 - _globals['_FLUSHSOXRESAMPLERREQUEST']._serialized_end=2202 - _globals['_FLUSHSOXRESAMPLERRESPONSE']._serialized_start=2204 - _globals['_FLUSHSOXRESAMPLERRESPONSE']._serialized_end=2280 - _globals['_AUDIOFRAMEBUFFERINFO']._serialized_start=2282 - _globals['_AUDIOFRAMEBUFFERINFO']._serialized_end=2394 - _globals['_OWNEDAUDIOFRAMEBUFFER']._serialized_start=2396 - _globals['_OWNEDAUDIOFRAMEBUFFER']._serialized_end=2517 - _globals['_AUDIOSTREAMINFO']._serialized_start=2519 - _globals['_AUDIOSTREAMINFO']._serialized_end=2582 - _globals['_OWNEDAUDIOSTREAM']._serialized_start=2584 - _globals['_OWNEDAUDIOSTREAM']._serialized_end=2695 - _globals['_AUDIOSTREAMEVENT']._serialized_start=2698 - _globals['_AUDIOSTREAMEVENT']._serialized_end=2857 - _globals['_AUDIOFRAMERECEIVED']._serialized_start=2859 - _globals['_AUDIOFRAMERECEIVED']._serialized_end=2932 - _globals['_AUDIOSTREAMEOS']._serialized_start=2934 - _globals['_AUDIOSTREAMEOS']._serialized_end=2950 - _globals['_AUDIOSOURCEOPTIONS']._serialized_start=2952 - _globals['_AUDIOSOURCEOPTIONS']._serialized_end=3053 - _globals['_AUDIOSOURCEINFO']._serialized_start=3055 - _globals['_AUDIOSOURCEINFO']._serialized_end=3118 - _globals['_OWNEDAUDIOSOURCE']._serialized_start=3120 - _globals['_OWNEDAUDIOSOURCE']._serialized_end=3231 - _globals['_AUDIORESAMPLERINFO']._serialized_start=3233 - _globals['_AUDIORESAMPLERINFO']._serialized_end=3253 - _globals['_OWNEDAUDIORESAMPLER']._serialized_start=3255 - _globals['_OWNEDAUDIORESAMPLER']._serialized_end=3372 - _globals['_SOXRESAMPLERINFO']._serialized_start=3374 - _globals['_SOXRESAMPLERINFO']._serialized_end=3392 - _globals['_OWNEDSOXRESAMPLER']._serialized_start=3394 - _globals['_OWNEDSOXRESAMPLER']._serialized_end=3507 - _globals['_LOADAUDIOFILTERPLUGINREQUEST']._serialized_start=3509 - _globals['_LOADAUDIOFILTERPLUGINREQUEST']._serialized_end=3601 - _globals['_LOADAUDIOFILTERPLUGINRESPONSE']._serialized_start=3603 - _globals['_LOADAUDIOFILTERPLUGINRESPONSE']._serialized_end=3649 + _globals['_NEWAPMREQUEST']._serialized_start=1592 + _globals['_NEWAPMREQUEST']._serialized_end=1741 + _globals['_NEWAPMRESPONSE']._serialized_start=1743 + _globals['_NEWAPMRESPONSE']._serialized_end=1797 + _globals['_APMPROCESSSTREAMREQUEST']._serialized_start=1799 + _globals['_APMPROCESSSTREAMREQUEST']._serialized_end=1919 + _globals['_APMPROCESSSTREAMRESPONSE']._serialized_start=1921 + _globals['_APMPROCESSSTREAMRESPONSE']._serialized_end=1962 + _globals['_APMPROCESSREVERSESTREAMREQUEST']._serialized_start=1964 + _globals['_APMPROCESSREVERSESTREAMREQUEST']._serialized_end=2091 + _globals['_APMPROCESSREVERSESTREAMRESPONSE']._serialized_start=2093 + _globals['_APMPROCESSREVERSESTREAMRESPONSE']._serialized_end=2141 + _globals['_NEWSOXRESAMPLERREQUEST']._serialized_start=2144 + _globals['_NEWSOXRESAMPLERREQUEST']._serialized_end=2428 + _globals['_NEWSOXRESAMPLERRESPONSE']._serialized_start=2430 + _globals['_NEWSOXRESAMPLERRESPONSE']._serialized_end=2538 + _globals['_PUSHSOXRESAMPLERREQUEST']._serialized_start=2540 + _globals['_PUSHSOXRESAMPLERREQUEST']._serialized_end=2623 + _globals['_PUSHSOXRESAMPLERRESPONSE']._serialized_start=2625 + _globals['_PUSHSOXRESAMPLERRESPONSE']._serialized_end=2700 + _globals['_FLUSHSOXRESAMPLERREQUEST']._serialized_start=2702 + _globals['_FLUSHSOXRESAMPLERREQUEST']._serialized_end=2754 + _globals['_FLUSHSOXRESAMPLERRESPONSE']._serialized_start=2756 + _globals['_FLUSHSOXRESAMPLERRESPONSE']._serialized_end=2832 + _globals['_AUDIOFRAMEBUFFERINFO']._serialized_start=2834 + _globals['_AUDIOFRAMEBUFFERINFO']._serialized_end=2946 + _globals['_OWNEDAUDIOFRAMEBUFFER']._serialized_start=2948 + _globals['_OWNEDAUDIOFRAMEBUFFER']._serialized_end=3069 + _globals['_AUDIOSTREAMINFO']._serialized_start=3071 + _globals['_AUDIOSTREAMINFO']._serialized_end=3134 + _globals['_OWNEDAUDIOSTREAM']._serialized_start=3136 + _globals['_OWNEDAUDIOSTREAM']._serialized_end=3247 + _globals['_AUDIOSTREAMEVENT']._serialized_start=3250 + _globals['_AUDIOSTREAMEVENT']._serialized_end=3409 + _globals['_AUDIOFRAMERECEIVED']._serialized_start=3411 + _globals['_AUDIOFRAMERECEIVED']._serialized_end=3484 + _globals['_AUDIOSTREAMEOS']._serialized_start=3486 + _globals['_AUDIOSTREAMEOS']._serialized_end=3502 + _globals['_AUDIOSOURCEOPTIONS']._serialized_start=3504 + _globals['_AUDIOSOURCEOPTIONS']._serialized_end=3605 + _globals['_AUDIOSOURCEINFO']._serialized_start=3607 + _globals['_AUDIOSOURCEINFO']._serialized_end=3670 + _globals['_OWNEDAUDIOSOURCE']._serialized_start=3672 + _globals['_OWNEDAUDIOSOURCE']._serialized_end=3783 + _globals['_AUDIORESAMPLERINFO']._serialized_start=3785 + _globals['_AUDIORESAMPLERINFO']._serialized_end=3805 + _globals['_OWNEDAUDIORESAMPLER']._serialized_start=3807 + _globals['_OWNEDAUDIORESAMPLER']._serialized_end=3924 + _globals['_OWNEDAPM']._serialized_start=3926 + _globals['_OWNEDAPM']._serialized_end=3983 + _globals['_SOXRESAMPLERINFO']._serialized_start=3985 + _globals['_SOXRESAMPLERINFO']._serialized_end=4003 + _globals['_OWNEDSOXRESAMPLER']._serialized_start=4005 + _globals['_OWNEDSOXRESAMPLER']._serialized_end=4118 + _globals['_LOADAUDIOFILTERPLUGINREQUEST']._serialized_start=4120 + _globals['_LOADAUDIOFILTERPLUGINREQUEST']._serialized_end=4212 + _globals['_LOADAUDIOFILTERPLUGINRESPONSE']._serialized_start=4214 + _globals['_LOADAUDIOFILTERPLUGINRESPONSE']._serialized_end=4260 # @@protoc_insertion_point(module_scope) diff --git a/livekit-rtc/livekit/rtc/_proto/audio_frame_pb2.pyi b/livekit-rtc/livekit/rtc/_proto/audio_frame_pb2.pyi index 98dfaeed..89c0ad37 100644 --- a/livekit-rtc/livekit/rtc/_proto/audio_frame_pb2.pyi +++ b/livekit-rtc/livekit/rtc/_proto/audio_frame_pb2.pyi @@ -449,6 +449,142 @@ class RemixAndResampleResponse(google.protobuf.message.Message): global___RemixAndResampleResponse = RemixAndResampleResponse +@typing.final +class NewApmRequest(google.protobuf.message.Message): + """AEC""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ECHO_CANCELLER_ENABLED_FIELD_NUMBER: builtins.int + GAIN_CONTROLLER_ENABLED_FIELD_NUMBER: builtins.int + HIGH_PASS_FILTER_ENABLED_FIELD_NUMBER: builtins.int + NOISE_SUPPRESSION_ENABLED_FIELD_NUMBER: builtins.int + echo_canceller_enabled: builtins.bool + gain_controller_enabled: builtins.bool + high_pass_filter_enabled: builtins.bool + noise_suppression_enabled: builtins.bool + def __init__( + self, + *, + echo_canceller_enabled: builtins.bool | None = ..., + gain_controller_enabled: builtins.bool | None = ..., + high_pass_filter_enabled: builtins.bool | None = ..., + noise_suppression_enabled: builtins.bool | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["echo_canceller_enabled", b"echo_canceller_enabled", "gain_controller_enabled", b"gain_controller_enabled", "high_pass_filter_enabled", b"high_pass_filter_enabled", "noise_suppression_enabled", b"noise_suppression_enabled"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["echo_canceller_enabled", b"echo_canceller_enabled", "gain_controller_enabled", b"gain_controller_enabled", "high_pass_filter_enabled", b"high_pass_filter_enabled", "noise_suppression_enabled", b"noise_suppression_enabled"]) -> None: ... + +global___NewApmRequest = NewApmRequest + +@typing.final +class NewApmResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + APM_FIELD_NUMBER: builtins.int + @property + def apm(self) -> global___OwnedApm: ... + def __init__( + self, + *, + apm: global___OwnedApm | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["apm", b"apm"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["apm", b"apm"]) -> None: ... + +global___NewApmResponse = NewApmResponse + +@typing.final +class ApmProcessStreamRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + APM_HANDLE_FIELD_NUMBER: builtins.int + DATA_PTR_FIELD_NUMBER: builtins.int + SIZE_FIELD_NUMBER: builtins.int + SAMPLE_RATE_FIELD_NUMBER: builtins.int + NUM_CHANNELS_FIELD_NUMBER: builtins.int + apm_handle: builtins.int + data_ptr: builtins.int + """*mut i16""" + size: builtins.int + """in bytes""" + sample_rate: builtins.int + num_channels: builtins.int + def __init__( + self, + *, + apm_handle: builtins.int | None = ..., + data_ptr: builtins.int | None = ..., + size: builtins.int | None = ..., + sample_rate: builtins.int | None = ..., + num_channels: builtins.int | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["apm_handle", b"apm_handle", "data_ptr", b"data_ptr", "num_channels", b"num_channels", "sample_rate", b"sample_rate", "size", b"size"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["apm_handle", b"apm_handle", "data_ptr", b"data_ptr", "num_channels", b"num_channels", "sample_rate", b"sample_rate", "size", b"size"]) -> None: ... + +global___ApmProcessStreamRequest = ApmProcessStreamRequest + +@typing.final +class ApmProcessStreamResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ERROR_FIELD_NUMBER: builtins.int + error: builtins.str + def __init__( + self, + *, + error: builtins.str | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["error", b"error"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["error", b"error"]) -> None: ... + +global___ApmProcessStreamResponse = ApmProcessStreamResponse + +@typing.final +class ApmProcessReverseStreamRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + APM_HANDLE_FIELD_NUMBER: builtins.int + DATA_PTR_FIELD_NUMBER: builtins.int + SIZE_FIELD_NUMBER: builtins.int + SAMPLE_RATE_FIELD_NUMBER: builtins.int + NUM_CHANNELS_FIELD_NUMBER: builtins.int + apm_handle: builtins.int + data_ptr: builtins.int + """*mut i16""" + size: builtins.int + """in bytes""" + sample_rate: builtins.int + num_channels: builtins.int + def __init__( + self, + *, + apm_handle: builtins.int | None = ..., + data_ptr: builtins.int | None = ..., + size: builtins.int | None = ..., + sample_rate: builtins.int | None = ..., + num_channels: builtins.int | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["apm_handle", b"apm_handle", "data_ptr", b"data_ptr", "num_channels", b"num_channels", "sample_rate", b"sample_rate", "size", b"size"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["apm_handle", b"apm_handle", "data_ptr", b"data_ptr", "num_channels", b"num_channels", "sample_rate", b"sample_rate", "size", b"size"]) -> None: ... + +global___ApmProcessReverseStreamRequest = ApmProcessReverseStreamRequest + +@typing.final +class ApmProcessReverseStreamResponse(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ERROR_FIELD_NUMBER: builtins.int + error: builtins.str + def __init__( + self, + *, + error: builtins.str | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["error", b"error"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["error", b"error"]) -> None: ... + +global___ApmProcessReverseStreamResponse = ApmProcessReverseStreamResponse + @typing.final class NewSoxResamplerRequest(google.protobuf.message.Message): """New resampler using SoX (much better quality)""" @@ -832,6 +968,27 @@ class OwnedAudioResampler(google.protobuf.message.Message): global___OwnedAudioResampler = OwnedAudioResampler +@typing.final +class OwnedApm(google.protobuf.message.Message): + """ + AEC + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + HANDLE_FIELD_NUMBER: builtins.int + @property + def handle(self) -> handle_pb2.FfiOwnedHandle: ... + def __init__( + self, + *, + handle: handle_pb2.FfiOwnedHandle | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["handle", b"handle"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["handle", b"handle"]) -> None: ... + +global___OwnedApm = OwnedApm + @typing.final class SoxResamplerInfo(google.protobuf.message.Message): """ diff --git a/livekit-rtc/livekit/rtc/_proto/ffi_pb2.py b/livekit-rtc/livekit/rtc/_proto/ffi_pb2.py index 96700e02..659b299b 100644 --- a/livekit-rtc/livekit/rtc/_proto/ffi_pb2.py +++ b/livekit-rtc/livekit/rtc/_proto/ffi_pb2.py @@ -21,7 +21,7 @@ from . import rpc_pb2 as rpc__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\tffi.proto\x12\rlivekit.proto\x1a\ne2ee.proto\x1a\x0btrack.proto\x1a\x17track_publication.proto\x1a\nroom.proto\x1a\x11video_frame.proto\x1a\x11\x61udio_frame.proto\x1a\trpc.proto\"\xf9\x1a\n\nFfiRequest\x12\x30\n\x07\x64ispose\x18\x02 \x01(\x0b\x32\x1d.livekit.proto.DisposeRequestH\x00\x12\x30\n\x07\x63onnect\x18\x03 \x01(\x0b\x32\x1d.livekit.proto.ConnectRequestH\x00\x12\x36\n\ndisconnect\x18\x04 \x01(\x0b\x32 .livekit.proto.DisconnectRequestH\x00\x12;\n\rpublish_track\x18\x05 \x01(\x0b\x32\".livekit.proto.PublishTrackRequestH\x00\x12?\n\x0funpublish_track\x18\x06 \x01(\x0b\x32$.livekit.proto.UnpublishTrackRequestH\x00\x12\x39\n\x0cpublish_data\x18\x07 \x01(\x0b\x32!.livekit.proto.PublishDataRequestH\x00\x12=\n\x0eset_subscribed\x18\x08 \x01(\x0b\x32#.livekit.proto.SetSubscribedRequestH\x00\x12\x44\n\x12set_local_metadata\x18\t \x01(\x0b\x32&.livekit.proto.SetLocalMetadataRequestH\x00\x12<\n\x0eset_local_name\x18\n \x01(\x0b\x32\".livekit.proto.SetLocalNameRequestH\x00\x12H\n\x14set_local_attributes\x18\x0b \x01(\x0b\x32(.livekit.proto.SetLocalAttributesRequestH\x00\x12\x42\n\x11get_session_stats\x18\x0c \x01(\x0b\x32%.livekit.proto.GetSessionStatsRequestH\x00\x12K\n\x15publish_transcription\x18\r \x01(\x0b\x32*.livekit.proto.PublishTranscriptionRequestH\x00\x12@\n\x10publish_sip_dtmf\x18\x0e \x01(\x0b\x32$.livekit.proto.PublishSipDtmfRequestH\x00\x12\x44\n\x12\x63reate_video_track\x18\x0f \x01(\x0b\x32&.livekit.proto.CreateVideoTrackRequestH\x00\x12\x44\n\x12\x63reate_audio_track\x18\x10 \x01(\x0b\x32&.livekit.proto.CreateAudioTrackRequestH\x00\x12@\n\x10local_track_mute\x18\x11 \x01(\x0b\x32$.livekit.proto.LocalTrackMuteRequestH\x00\x12\x46\n\x13\x65nable_remote_track\x18\x12 \x01(\x0b\x32\'.livekit.proto.EnableRemoteTrackRequestH\x00\x12\x33\n\tget_stats\x18\x13 \x01(\x0b\x32\x1e.livekit.proto.GetStatsRequestH\x00\x12\x63\n\"set_track_subscription_permissions\x18\x30 \x01(\x0b\x32\x35.livekit.proto.SetTrackSubscriptionPermissionsRequestH\x00\x12@\n\x10new_video_stream\x18\x14 \x01(\x0b\x32$.livekit.proto.NewVideoStreamRequestH\x00\x12@\n\x10new_video_source\x18\x15 \x01(\x0b\x32$.livekit.proto.NewVideoSourceRequestH\x00\x12\x46\n\x13\x63\x61pture_video_frame\x18\x16 \x01(\x0b\x32\'.livekit.proto.CaptureVideoFrameRequestH\x00\x12;\n\rvideo_convert\x18\x17 \x01(\x0b\x32\".livekit.proto.VideoConvertRequestH\x00\x12Y\n\x1dvideo_stream_from_participant\x18\x18 \x01(\x0b\x32\x30.livekit.proto.VideoStreamFromParticipantRequestH\x00\x12@\n\x10new_audio_stream\x18\x19 \x01(\x0b\x32$.livekit.proto.NewAudioStreamRequestH\x00\x12@\n\x10new_audio_source\x18\x1a \x01(\x0b\x32$.livekit.proto.NewAudioSourceRequestH\x00\x12\x46\n\x13\x63\x61pture_audio_frame\x18\x1b \x01(\x0b\x32\'.livekit.proto.CaptureAudioFrameRequestH\x00\x12\x44\n\x12\x63lear_audio_buffer\x18\x1c \x01(\x0b\x32&.livekit.proto.ClearAudioBufferRequestH\x00\x12\x46\n\x13new_audio_resampler\x18\x1d \x01(\x0b\x32\'.livekit.proto.NewAudioResamplerRequestH\x00\x12\x44\n\x12remix_and_resample\x18\x1e \x01(\x0b\x32&.livekit.proto.RemixAndResampleRequestH\x00\x12*\n\x04\x65\x32\x65\x65\x18\x1f \x01(\x0b\x32\x1a.livekit.proto.E2eeRequestH\x00\x12Y\n\x1d\x61udio_stream_from_participant\x18 \x01(\x0b\x32\x30.livekit.proto.AudioStreamFromParticipantRequestH\x00\x12\x42\n\x11new_sox_resampler\x18! \x01(\x0b\x32%.livekit.proto.NewSoxResamplerRequestH\x00\x12\x44\n\x12push_sox_resampler\x18\" \x01(\x0b\x32&.livekit.proto.PushSoxResamplerRequestH\x00\x12\x46\n\x13\x66lush_sox_resampler\x18# \x01(\x0b\x32\'.livekit.proto.FlushSoxResamplerRequestH\x00\x12\x42\n\x11send_chat_message\x18$ \x01(\x0b\x32%.livekit.proto.SendChatMessageRequestH\x00\x12\x42\n\x11\x65\x64it_chat_message\x18% \x01(\x0b\x32%.livekit.proto.EditChatMessageRequestH\x00\x12\x37\n\x0bperform_rpc\x18& \x01(\x0b\x32 .livekit.proto.PerformRpcRequestH\x00\x12\x46\n\x13register_rpc_method\x18\' \x01(\x0b\x32\'.livekit.proto.RegisterRpcMethodRequestH\x00\x12J\n\x15unregister_rpc_method\x18( \x01(\x0b\x32).livekit.proto.UnregisterRpcMethodRequestH\x00\x12[\n\x1erpc_method_invocation_response\x18) \x01(\x0b\x32\x31.livekit.proto.RpcMethodInvocationResponseRequestH\x00\x12]\n\x1f\x65nable_remote_track_publication\x18* \x01(\x0b\x32\x32.livekit.proto.EnableRemoteTrackPublicationRequestH\x00\x12p\n)update_remote_track_publication_dimension\x18+ \x01(\x0b\x32;.livekit.proto.UpdateRemoteTrackPublicationDimensionRequestH\x00\x12\x44\n\x12send_stream_header\x18, \x01(\x0b\x32&.livekit.proto.SendStreamHeaderRequestH\x00\x12\x42\n\x11send_stream_chunk\x18- \x01(\x0b\x32%.livekit.proto.SendStreamChunkRequestH\x00\x12\x46\n\x13send_stream_trailer\x18. \x01(\x0b\x32\'.livekit.proto.SendStreamTrailerRequestH\x00\x12x\n.set_data_channel_buffered_amount_low_threshold\x18/ \x01(\x0b\x32>.livekit.proto.SetDataChannelBufferedAmountLowThresholdRequestH\x00\x12O\n\x18load_audio_filter_plugin\x18\x31 \x01(\x0b\x32+.livekit.proto.LoadAudioFilterPluginRequestH\x00\x42\t\n\x07message\"\xe5\x1a\n\x0b\x46\x66iResponse\x12\x31\n\x07\x64ispose\x18\x02 \x01(\x0b\x32\x1e.livekit.proto.DisposeResponseH\x00\x12\x31\n\x07\x63onnect\x18\x03 \x01(\x0b\x32\x1e.livekit.proto.ConnectResponseH\x00\x12\x37\n\ndisconnect\x18\x04 \x01(\x0b\x32!.livekit.proto.DisconnectResponseH\x00\x12<\n\rpublish_track\x18\x05 \x01(\x0b\x32#.livekit.proto.PublishTrackResponseH\x00\x12@\n\x0funpublish_track\x18\x06 \x01(\x0b\x32%.livekit.proto.UnpublishTrackResponseH\x00\x12:\n\x0cpublish_data\x18\x07 \x01(\x0b\x32\".livekit.proto.PublishDataResponseH\x00\x12>\n\x0eset_subscribed\x18\x08 \x01(\x0b\x32$.livekit.proto.SetSubscribedResponseH\x00\x12\x45\n\x12set_local_metadata\x18\t \x01(\x0b\x32\'.livekit.proto.SetLocalMetadataResponseH\x00\x12=\n\x0eset_local_name\x18\n \x01(\x0b\x32#.livekit.proto.SetLocalNameResponseH\x00\x12I\n\x14set_local_attributes\x18\x0b \x01(\x0b\x32).livekit.proto.SetLocalAttributesResponseH\x00\x12\x43\n\x11get_session_stats\x18\x0c \x01(\x0b\x32&.livekit.proto.GetSessionStatsResponseH\x00\x12L\n\x15publish_transcription\x18\r \x01(\x0b\x32+.livekit.proto.PublishTranscriptionResponseH\x00\x12\x41\n\x10publish_sip_dtmf\x18\x0e \x01(\x0b\x32%.livekit.proto.PublishSipDtmfResponseH\x00\x12\x45\n\x12\x63reate_video_track\x18\x0f \x01(\x0b\x32\'.livekit.proto.CreateVideoTrackResponseH\x00\x12\x45\n\x12\x63reate_audio_track\x18\x10 \x01(\x0b\x32\'.livekit.proto.CreateAudioTrackResponseH\x00\x12\x41\n\x10local_track_mute\x18\x11 \x01(\x0b\x32%.livekit.proto.LocalTrackMuteResponseH\x00\x12G\n\x13\x65nable_remote_track\x18\x12 \x01(\x0b\x32(.livekit.proto.EnableRemoteTrackResponseH\x00\x12\x34\n\tget_stats\x18\x13 \x01(\x0b\x32\x1f.livekit.proto.GetStatsResponseH\x00\x12\x64\n\"set_track_subscription_permissions\x18/ \x01(\x0b\x32\x36.livekit.proto.SetTrackSubscriptionPermissionsResponseH\x00\x12\x41\n\x10new_video_stream\x18\x14 \x01(\x0b\x32%.livekit.proto.NewVideoStreamResponseH\x00\x12\x41\n\x10new_video_source\x18\x15 \x01(\x0b\x32%.livekit.proto.NewVideoSourceResponseH\x00\x12G\n\x13\x63\x61pture_video_frame\x18\x16 \x01(\x0b\x32(.livekit.proto.CaptureVideoFrameResponseH\x00\x12<\n\rvideo_convert\x18\x17 \x01(\x0b\x32#.livekit.proto.VideoConvertResponseH\x00\x12Z\n\x1dvideo_stream_from_participant\x18\x18 \x01(\x0b\x32\x31.livekit.proto.VideoStreamFromParticipantResponseH\x00\x12\x41\n\x10new_audio_stream\x18\x19 \x01(\x0b\x32%.livekit.proto.NewAudioStreamResponseH\x00\x12\x41\n\x10new_audio_source\x18\x1a \x01(\x0b\x32%.livekit.proto.NewAudioSourceResponseH\x00\x12G\n\x13\x63\x61pture_audio_frame\x18\x1b \x01(\x0b\x32(.livekit.proto.CaptureAudioFrameResponseH\x00\x12\x45\n\x12\x63lear_audio_buffer\x18\x1c \x01(\x0b\x32\'.livekit.proto.ClearAudioBufferResponseH\x00\x12G\n\x13new_audio_resampler\x18\x1d \x01(\x0b\x32(.livekit.proto.NewAudioResamplerResponseH\x00\x12\x45\n\x12remix_and_resample\x18\x1e \x01(\x0b\x32\'.livekit.proto.RemixAndResampleResponseH\x00\x12Z\n\x1d\x61udio_stream_from_participant\x18\x1f \x01(\x0b\x32\x31.livekit.proto.AudioStreamFromParticipantResponseH\x00\x12+\n\x04\x65\x32\x65\x65\x18 \x01(\x0b\x32\x1b.livekit.proto.E2eeResponseH\x00\x12\x43\n\x11new_sox_resampler\x18! \x01(\x0b\x32&.livekit.proto.NewSoxResamplerResponseH\x00\x12\x45\n\x12push_sox_resampler\x18\" \x01(\x0b\x32\'.livekit.proto.PushSoxResamplerResponseH\x00\x12G\n\x13\x66lush_sox_resampler\x18# \x01(\x0b\x32(.livekit.proto.FlushSoxResamplerResponseH\x00\x12\x43\n\x11send_chat_message\x18$ \x01(\x0b\x32&.livekit.proto.SendChatMessageResponseH\x00\x12\x38\n\x0bperform_rpc\x18% \x01(\x0b\x32!.livekit.proto.PerformRpcResponseH\x00\x12G\n\x13register_rpc_method\x18& \x01(\x0b\x32(.livekit.proto.RegisterRpcMethodResponseH\x00\x12K\n\x15unregister_rpc_method\x18\' \x01(\x0b\x32*.livekit.proto.UnregisterRpcMethodResponseH\x00\x12\\\n\x1erpc_method_invocation_response\x18( \x01(\x0b\x32\x32.livekit.proto.RpcMethodInvocationResponseResponseH\x00\x12^\n\x1f\x65nable_remote_track_publication\x18) \x01(\x0b\x32\x33.livekit.proto.EnableRemoteTrackPublicationResponseH\x00\x12q\n)update_remote_track_publication_dimension\x18* \x01(\x0b\x32<.livekit.proto.UpdateRemoteTrackPublicationDimensionResponseH\x00\x12\x45\n\x12send_stream_header\x18+ \x01(\x0b\x32\'.livekit.proto.SendStreamHeaderResponseH\x00\x12\x43\n\x11send_stream_chunk\x18, \x01(\x0b\x32&.livekit.proto.SendStreamChunkResponseH\x00\x12G\n\x13send_stream_trailer\x18- \x01(\x0b\x32(.livekit.proto.SendStreamTrailerResponseH\x00\x12y\n.set_data_channel_buffered_amount_low_threshold\x18. \x01(\x0b\x32?.livekit.proto.SetDataChannelBufferedAmountLowThresholdResponseH\x00\x12P\n\x18load_audio_filter_plugin\x18\x30 \x01(\x0b\x32,.livekit.proto.LoadAudioFilterPluginResponseH\x00\x42\t\n\x07message\"\xdf\x0c\n\x08\x46\x66iEvent\x12.\n\nroom_event\x18\x01 \x01(\x0b\x32\x18.livekit.proto.RoomEventH\x00\x12\x30\n\x0btrack_event\x18\x02 \x01(\x0b\x32\x19.livekit.proto.TrackEventH\x00\x12=\n\x12video_stream_event\x18\x03 \x01(\x0b\x32\x1f.livekit.proto.VideoStreamEventH\x00\x12=\n\x12\x61udio_stream_event\x18\x04 \x01(\x0b\x32\x1f.livekit.proto.AudioStreamEventH\x00\x12\x31\n\x07\x63onnect\x18\x05 \x01(\x0b\x32\x1e.livekit.proto.ConnectCallbackH\x00\x12\x37\n\ndisconnect\x18\x07 \x01(\x0b\x32!.livekit.proto.DisconnectCallbackH\x00\x12\x31\n\x07\x64ispose\x18\x08 \x01(\x0b\x32\x1e.livekit.proto.DisposeCallbackH\x00\x12<\n\rpublish_track\x18\t \x01(\x0b\x32#.livekit.proto.PublishTrackCallbackH\x00\x12@\n\x0funpublish_track\x18\n \x01(\x0b\x32%.livekit.proto.UnpublishTrackCallbackH\x00\x12:\n\x0cpublish_data\x18\x0b \x01(\x0b\x32\".livekit.proto.PublishDataCallbackH\x00\x12L\n\x15publish_transcription\x18\x0c \x01(\x0b\x32+.livekit.proto.PublishTranscriptionCallbackH\x00\x12G\n\x13\x63\x61pture_audio_frame\x18\r \x01(\x0b\x32(.livekit.proto.CaptureAudioFrameCallbackH\x00\x12\x45\n\x12set_local_metadata\x18\x0e \x01(\x0b\x32\'.livekit.proto.SetLocalMetadataCallbackH\x00\x12=\n\x0eset_local_name\x18\x0f \x01(\x0b\x32#.livekit.proto.SetLocalNameCallbackH\x00\x12I\n\x14set_local_attributes\x18\x10 \x01(\x0b\x32).livekit.proto.SetLocalAttributesCallbackH\x00\x12\x34\n\tget_stats\x18\x11 \x01(\x0b\x32\x1f.livekit.proto.GetStatsCallbackH\x00\x12\'\n\x04logs\x18\x12 \x01(\x0b\x32\x17.livekit.proto.LogBatchH\x00\x12\x43\n\x11get_session_stats\x18\x13 \x01(\x0b\x32&.livekit.proto.GetSessionStatsCallbackH\x00\x12%\n\x05panic\x18\x14 \x01(\x0b\x32\x14.livekit.proto.PanicH\x00\x12\x41\n\x10publish_sip_dtmf\x18\x15 \x01(\x0b\x32%.livekit.proto.PublishSipDtmfCallbackH\x00\x12>\n\x0c\x63hat_message\x18\x16 \x01(\x0b\x32&.livekit.proto.SendChatMessageCallbackH\x00\x12\x38\n\x0bperform_rpc\x18\x17 \x01(\x0b\x32!.livekit.proto.PerformRpcCallbackH\x00\x12H\n\x15rpc_method_invocation\x18\x18 \x01(\x0b\x32\'.livekit.proto.RpcMethodInvocationEventH\x00\x12\x45\n\x12send_stream_header\x18\x19 \x01(\x0b\x32\'.livekit.proto.SendStreamHeaderCallbackH\x00\x12\x43\n\x11send_stream_chunk\x18\x1a \x01(\x0b\x32&.livekit.proto.SendStreamChunkCallbackH\x00\x12G\n\x13send_stream_trailer\x18\x1b \x01(\x0b\x32(.livekit.proto.SendStreamTrailerCallbackH\x00\x42\t\n\x07message\"\x1f\n\x0e\x44isposeRequest\x12\r\n\x05\x61sync\x18\x01 \x02(\x08\"#\n\x0f\x44isposeResponse\x12\x10\n\x08\x61sync_id\x18\x01 \x01(\x04\"#\n\x0f\x44isposeCallback\x12\x10\n\x08\x61sync_id\x18\x01 \x02(\x04\"\x85\x01\n\tLogRecord\x12&\n\x05level\x18\x01 \x02(\x0e\x32\x17.livekit.proto.LogLevel\x12\x0e\n\x06target\x18\x02 \x02(\t\x12\x13\n\x0bmodule_path\x18\x03 \x01(\t\x12\x0c\n\x04\x66ile\x18\x04 \x01(\t\x12\x0c\n\x04line\x18\x05 \x01(\r\x12\x0f\n\x07message\x18\x06 \x02(\t\"5\n\x08LogBatch\x12)\n\x07records\x18\x01 \x03(\x0b\x32\x18.livekit.proto.LogRecord\"\x18\n\x05Panic\x12\x0f\n\x07message\x18\x01 \x02(\t*S\n\x08LogLevel\x12\r\n\tLOG_ERROR\x10\x00\x12\x0c\n\x08LOG_WARN\x10\x01\x12\x0c\n\x08LOG_INFO\x10\x02\x12\r\n\tLOG_DEBUG\x10\x03\x12\r\n\tLOG_TRACE\x10\x04\x42\x10\xaa\x02\rLiveKit.Proto') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\tffi.proto\x12\rlivekit.proto\x1a\ne2ee.proto\x1a\x0btrack.proto\x1a\x17track_publication.proto\x1a\nroom.proto\x1a\x11video_frame.proto\x1a\x11\x61udio_frame.proto\x1a\trpc.proto\"\xc5\x1c\n\nFfiRequest\x12\x30\n\x07\x64ispose\x18\x02 \x01(\x0b\x32\x1d.livekit.proto.DisposeRequestH\x00\x12\x30\n\x07\x63onnect\x18\x03 \x01(\x0b\x32\x1d.livekit.proto.ConnectRequestH\x00\x12\x36\n\ndisconnect\x18\x04 \x01(\x0b\x32 .livekit.proto.DisconnectRequestH\x00\x12;\n\rpublish_track\x18\x05 \x01(\x0b\x32\".livekit.proto.PublishTrackRequestH\x00\x12?\n\x0funpublish_track\x18\x06 \x01(\x0b\x32$.livekit.proto.UnpublishTrackRequestH\x00\x12\x39\n\x0cpublish_data\x18\x07 \x01(\x0b\x32!.livekit.proto.PublishDataRequestH\x00\x12=\n\x0eset_subscribed\x18\x08 \x01(\x0b\x32#.livekit.proto.SetSubscribedRequestH\x00\x12\x44\n\x12set_local_metadata\x18\t \x01(\x0b\x32&.livekit.proto.SetLocalMetadataRequestH\x00\x12<\n\x0eset_local_name\x18\n \x01(\x0b\x32\".livekit.proto.SetLocalNameRequestH\x00\x12H\n\x14set_local_attributes\x18\x0b \x01(\x0b\x32(.livekit.proto.SetLocalAttributesRequestH\x00\x12\x42\n\x11get_session_stats\x18\x0c \x01(\x0b\x32%.livekit.proto.GetSessionStatsRequestH\x00\x12K\n\x15publish_transcription\x18\r \x01(\x0b\x32*.livekit.proto.PublishTranscriptionRequestH\x00\x12@\n\x10publish_sip_dtmf\x18\x0e \x01(\x0b\x32$.livekit.proto.PublishSipDtmfRequestH\x00\x12\x44\n\x12\x63reate_video_track\x18\x0f \x01(\x0b\x32&.livekit.proto.CreateVideoTrackRequestH\x00\x12\x44\n\x12\x63reate_audio_track\x18\x10 \x01(\x0b\x32&.livekit.proto.CreateAudioTrackRequestH\x00\x12@\n\x10local_track_mute\x18\x11 \x01(\x0b\x32$.livekit.proto.LocalTrackMuteRequestH\x00\x12\x46\n\x13\x65nable_remote_track\x18\x12 \x01(\x0b\x32\'.livekit.proto.EnableRemoteTrackRequestH\x00\x12\x33\n\tget_stats\x18\x13 \x01(\x0b\x32\x1e.livekit.proto.GetStatsRequestH\x00\x12\x63\n\"set_track_subscription_permissions\x18\x30 \x01(\x0b\x32\x35.livekit.proto.SetTrackSubscriptionPermissionsRequestH\x00\x12@\n\x10new_video_stream\x18\x14 \x01(\x0b\x32$.livekit.proto.NewVideoStreamRequestH\x00\x12@\n\x10new_video_source\x18\x15 \x01(\x0b\x32$.livekit.proto.NewVideoSourceRequestH\x00\x12\x46\n\x13\x63\x61pture_video_frame\x18\x16 \x01(\x0b\x32\'.livekit.proto.CaptureVideoFrameRequestH\x00\x12;\n\rvideo_convert\x18\x17 \x01(\x0b\x32\".livekit.proto.VideoConvertRequestH\x00\x12Y\n\x1dvideo_stream_from_participant\x18\x18 \x01(\x0b\x32\x30.livekit.proto.VideoStreamFromParticipantRequestH\x00\x12@\n\x10new_audio_stream\x18\x19 \x01(\x0b\x32$.livekit.proto.NewAudioStreamRequestH\x00\x12@\n\x10new_audio_source\x18\x1a \x01(\x0b\x32$.livekit.proto.NewAudioSourceRequestH\x00\x12\x46\n\x13\x63\x61pture_audio_frame\x18\x1b \x01(\x0b\x32\'.livekit.proto.CaptureAudioFrameRequestH\x00\x12\x44\n\x12\x63lear_audio_buffer\x18\x1c \x01(\x0b\x32&.livekit.proto.ClearAudioBufferRequestH\x00\x12\x46\n\x13new_audio_resampler\x18\x1d \x01(\x0b\x32\'.livekit.proto.NewAudioResamplerRequestH\x00\x12\x44\n\x12remix_and_resample\x18\x1e \x01(\x0b\x32&.livekit.proto.RemixAndResampleRequestH\x00\x12*\n\x04\x65\x32\x65\x65\x18\x1f \x01(\x0b\x32\x1a.livekit.proto.E2eeRequestH\x00\x12Y\n\x1d\x61udio_stream_from_participant\x18 \x01(\x0b\x32\x30.livekit.proto.AudioStreamFromParticipantRequestH\x00\x12\x42\n\x11new_sox_resampler\x18! \x01(\x0b\x32%.livekit.proto.NewSoxResamplerRequestH\x00\x12\x44\n\x12push_sox_resampler\x18\" \x01(\x0b\x32&.livekit.proto.PushSoxResamplerRequestH\x00\x12\x46\n\x13\x66lush_sox_resampler\x18# \x01(\x0b\x32\'.livekit.proto.FlushSoxResamplerRequestH\x00\x12\x42\n\x11send_chat_message\x18$ \x01(\x0b\x32%.livekit.proto.SendChatMessageRequestH\x00\x12\x42\n\x11\x65\x64it_chat_message\x18% \x01(\x0b\x32%.livekit.proto.EditChatMessageRequestH\x00\x12\x37\n\x0bperform_rpc\x18& \x01(\x0b\x32 .livekit.proto.PerformRpcRequestH\x00\x12\x46\n\x13register_rpc_method\x18\' \x01(\x0b\x32\'.livekit.proto.RegisterRpcMethodRequestH\x00\x12J\n\x15unregister_rpc_method\x18( \x01(\x0b\x32).livekit.proto.UnregisterRpcMethodRequestH\x00\x12[\n\x1erpc_method_invocation_response\x18) \x01(\x0b\x32\x31.livekit.proto.RpcMethodInvocationResponseRequestH\x00\x12]\n\x1f\x65nable_remote_track_publication\x18* \x01(\x0b\x32\x32.livekit.proto.EnableRemoteTrackPublicationRequestH\x00\x12p\n)update_remote_track_publication_dimension\x18+ \x01(\x0b\x32;.livekit.proto.UpdateRemoteTrackPublicationDimensionRequestH\x00\x12\x44\n\x12send_stream_header\x18, \x01(\x0b\x32&.livekit.proto.SendStreamHeaderRequestH\x00\x12\x42\n\x11send_stream_chunk\x18- \x01(\x0b\x32%.livekit.proto.SendStreamChunkRequestH\x00\x12\x46\n\x13send_stream_trailer\x18. \x01(\x0b\x32\'.livekit.proto.SendStreamTrailerRequestH\x00\x12x\n.set_data_channel_buffered_amount_low_threshold\x18/ \x01(\x0b\x32>.livekit.proto.SetDataChannelBufferedAmountLowThresholdRequestH\x00\x12O\n\x18load_audio_filter_plugin\x18\x31 \x01(\x0b\x32+.livekit.proto.LoadAudioFilterPluginRequestH\x00\x12/\n\x07new_apm\x18\x32 \x01(\x0b\x32\x1c.livekit.proto.NewApmRequestH\x00\x12\x44\n\x12\x61pm_process_stream\x18\x33 \x01(\x0b\x32&.livekit.proto.ApmProcessStreamRequestH\x00\x12S\n\x1a\x61pm_process_reverse_stream\x18\x34 \x01(\x0b\x32-.livekit.proto.ApmProcessReverseStreamRequestH\x00\x42\t\n\x07message\"\xb4\x1c\n\x0b\x46\x66iResponse\x12\x31\n\x07\x64ispose\x18\x02 \x01(\x0b\x32\x1e.livekit.proto.DisposeResponseH\x00\x12\x31\n\x07\x63onnect\x18\x03 \x01(\x0b\x32\x1e.livekit.proto.ConnectResponseH\x00\x12\x37\n\ndisconnect\x18\x04 \x01(\x0b\x32!.livekit.proto.DisconnectResponseH\x00\x12<\n\rpublish_track\x18\x05 \x01(\x0b\x32#.livekit.proto.PublishTrackResponseH\x00\x12@\n\x0funpublish_track\x18\x06 \x01(\x0b\x32%.livekit.proto.UnpublishTrackResponseH\x00\x12:\n\x0cpublish_data\x18\x07 \x01(\x0b\x32\".livekit.proto.PublishDataResponseH\x00\x12>\n\x0eset_subscribed\x18\x08 \x01(\x0b\x32$.livekit.proto.SetSubscribedResponseH\x00\x12\x45\n\x12set_local_metadata\x18\t \x01(\x0b\x32\'.livekit.proto.SetLocalMetadataResponseH\x00\x12=\n\x0eset_local_name\x18\n \x01(\x0b\x32#.livekit.proto.SetLocalNameResponseH\x00\x12I\n\x14set_local_attributes\x18\x0b \x01(\x0b\x32).livekit.proto.SetLocalAttributesResponseH\x00\x12\x43\n\x11get_session_stats\x18\x0c \x01(\x0b\x32&.livekit.proto.GetSessionStatsResponseH\x00\x12L\n\x15publish_transcription\x18\r \x01(\x0b\x32+.livekit.proto.PublishTranscriptionResponseH\x00\x12\x41\n\x10publish_sip_dtmf\x18\x0e \x01(\x0b\x32%.livekit.proto.PublishSipDtmfResponseH\x00\x12\x45\n\x12\x63reate_video_track\x18\x0f \x01(\x0b\x32\'.livekit.proto.CreateVideoTrackResponseH\x00\x12\x45\n\x12\x63reate_audio_track\x18\x10 \x01(\x0b\x32\'.livekit.proto.CreateAudioTrackResponseH\x00\x12\x41\n\x10local_track_mute\x18\x11 \x01(\x0b\x32%.livekit.proto.LocalTrackMuteResponseH\x00\x12G\n\x13\x65nable_remote_track\x18\x12 \x01(\x0b\x32(.livekit.proto.EnableRemoteTrackResponseH\x00\x12\x34\n\tget_stats\x18\x13 \x01(\x0b\x32\x1f.livekit.proto.GetStatsResponseH\x00\x12\x64\n\"set_track_subscription_permissions\x18/ \x01(\x0b\x32\x36.livekit.proto.SetTrackSubscriptionPermissionsResponseH\x00\x12\x41\n\x10new_video_stream\x18\x14 \x01(\x0b\x32%.livekit.proto.NewVideoStreamResponseH\x00\x12\x41\n\x10new_video_source\x18\x15 \x01(\x0b\x32%.livekit.proto.NewVideoSourceResponseH\x00\x12G\n\x13\x63\x61pture_video_frame\x18\x16 \x01(\x0b\x32(.livekit.proto.CaptureVideoFrameResponseH\x00\x12<\n\rvideo_convert\x18\x17 \x01(\x0b\x32#.livekit.proto.VideoConvertResponseH\x00\x12Z\n\x1dvideo_stream_from_participant\x18\x18 \x01(\x0b\x32\x31.livekit.proto.VideoStreamFromParticipantResponseH\x00\x12\x41\n\x10new_audio_stream\x18\x19 \x01(\x0b\x32%.livekit.proto.NewAudioStreamResponseH\x00\x12\x41\n\x10new_audio_source\x18\x1a \x01(\x0b\x32%.livekit.proto.NewAudioSourceResponseH\x00\x12G\n\x13\x63\x61pture_audio_frame\x18\x1b \x01(\x0b\x32(.livekit.proto.CaptureAudioFrameResponseH\x00\x12\x45\n\x12\x63lear_audio_buffer\x18\x1c \x01(\x0b\x32\'.livekit.proto.ClearAudioBufferResponseH\x00\x12G\n\x13new_audio_resampler\x18\x1d \x01(\x0b\x32(.livekit.proto.NewAudioResamplerResponseH\x00\x12\x45\n\x12remix_and_resample\x18\x1e \x01(\x0b\x32\'.livekit.proto.RemixAndResampleResponseH\x00\x12Z\n\x1d\x61udio_stream_from_participant\x18\x1f \x01(\x0b\x32\x31.livekit.proto.AudioStreamFromParticipantResponseH\x00\x12+\n\x04\x65\x32\x65\x65\x18 \x01(\x0b\x32\x1b.livekit.proto.E2eeResponseH\x00\x12\x43\n\x11new_sox_resampler\x18! \x01(\x0b\x32&.livekit.proto.NewSoxResamplerResponseH\x00\x12\x45\n\x12push_sox_resampler\x18\" \x01(\x0b\x32\'.livekit.proto.PushSoxResamplerResponseH\x00\x12G\n\x13\x66lush_sox_resampler\x18# \x01(\x0b\x32(.livekit.proto.FlushSoxResamplerResponseH\x00\x12\x43\n\x11send_chat_message\x18$ \x01(\x0b\x32&.livekit.proto.SendChatMessageResponseH\x00\x12\x38\n\x0bperform_rpc\x18% \x01(\x0b\x32!.livekit.proto.PerformRpcResponseH\x00\x12G\n\x13register_rpc_method\x18& \x01(\x0b\x32(.livekit.proto.RegisterRpcMethodResponseH\x00\x12K\n\x15unregister_rpc_method\x18\' \x01(\x0b\x32*.livekit.proto.UnregisterRpcMethodResponseH\x00\x12\\\n\x1erpc_method_invocation_response\x18( \x01(\x0b\x32\x32.livekit.proto.RpcMethodInvocationResponseResponseH\x00\x12^\n\x1f\x65nable_remote_track_publication\x18) \x01(\x0b\x32\x33.livekit.proto.EnableRemoteTrackPublicationResponseH\x00\x12q\n)update_remote_track_publication_dimension\x18* \x01(\x0b\x32<.livekit.proto.UpdateRemoteTrackPublicationDimensionResponseH\x00\x12\x45\n\x12send_stream_header\x18+ \x01(\x0b\x32\'.livekit.proto.SendStreamHeaderResponseH\x00\x12\x43\n\x11send_stream_chunk\x18, \x01(\x0b\x32&.livekit.proto.SendStreamChunkResponseH\x00\x12G\n\x13send_stream_trailer\x18- \x01(\x0b\x32(.livekit.proto.SendStreamTrailerResponseH\x00\x12y\n.set_data_channel_buffered_amount_low_threshold\x18. \x01(\x0b\x32?.livekit.proto.SetDataChannelBufferedAmountLowThresholdResponseH\x00\x12P\n\x18load_audio_filter_plugin\x18\x30 \x01(\x0b\x32,.livekit.proto.LoadAudioFilterPluginResponseH\x00\x12\x30\n\x07new_apm\x18\x31 \x01(\x0b\x32\x1d.livekit.proto.NewApmResponseH\x00\x12\x45\n\x12\x61pm_process_stream\x18\x32 \x01(\x0b\x32\'.livekit.proto.ApmProcessStreamResponseH\x00\x12T\n\x1a\x61pm_process_reverse_stream\x18\x33 \x01(\x0b\x32..livekit.proto.ApmProcessReverseStreamResponseH\x00\x42\t\n\x07message\"\xdf\x0c\n\x08\x46\x66iEvent\x12.\n\nroom_event\x18\x01 \x01(\x0b\x32\x18.livekit.proto.RoomEventH\x00\x12\x30\n\x0btrack_event\x18\x02 \x01(\x0b\x32\x19.livekit.proto.TrackEventH\x00\x12=\n\x12video_stream_event\x18\x03 \x01(\x0b\x32\x1f.livekit.proto.VideoStreamEventH\x00\x12=\n\x12\x61udio_stream_event\x18\x04 \x01(\x0b\x32\x1f.livekit.proto.AudioStreamEventH\x00\x12\x31\n\x07\x63onnect\x18\x05 \x01(\x0b\x32\x1e.livekit.proto.ConnectCallbackH\x00\x12\x37\n\ndisconnect\x18\x07 \x01(\x0b\x32!.livekit.proto.DisconnectCallbackH\x00\x12\x31\n\x07\x64ispose\x18\x08 \x01(\x0b\x32\x1e.livekit.proto.DisposeCallbackH\x00\x12<\n\rpublish_track\x18\t \x01(\x0b\x32#.livekit.proto.PublishTrackCallbackH\x00\x12@\n\x0funpublish_track\x18\n \x01(\x0b\x32%.livekit.proto.UnpublishTrackCallbackH\x00\x12:\n\x0cpublish_data\x18\x0b \x01(\x0b\x32\".livekit.proto.PublishDataCallbackH\x00\x12L\n\x15publish_transcription\x18\x0c \x01(\x0b\x32+.livekit.proto.PublishTranscriptionCallbackH\x00\x12G\n\x13\x63\x61pture_audio_frame\x18\r \x01(\x0b\x32(.livekit.proto.CaptureAudioFrameCallbackH\x00\x12\x45\n\x12set_local_metadata\x18\x0e \x01(\x0b\x32\'.livekit.proto.SetLocalMetadataCallbackH\x00\x12=\n\x0eset_local_name\x18\x0f \x01(\x0b\x32#.livekit.proto.SetLocalNameCallbackH\x00\x12I\n\x14set_local_attributes\x18\x10 \x01(\x0b\x32).livekit.proto.SetLocalAttributesCallbackH\x00\x12\x34\n\tget_stats\x18\x11 \x01(\x0b\x32\x1f.livekit.proto.GetStatsCallbackH\x00\x12\'\n\x04logs\x18\x12 \x01(\x0b\x32\x17.livekit.proto.LogBatchH\x00\x12\x43\n\x11get_session_stats\x18\x13 \x01(\x0b\x32&.livekit.proto.GetSessionStatsCallbackH\x00\x12%\n\x05panic\x18\x14 \x01(\x0b\x32\x14.livekit.proto.PanicH\x00\x12\x41\n\x10publish_sip_dtmf\x18\x15 \x01(\x0b\x32%.livekit.proto.PublishSipDtmfCallbackH\x00\x12>\n\x0c\x63hat_message\x18\x16 \x01(\x0b\x32&.livekit.proto.SendChatMessageCallbackH\x00\x12\x38\n\x0bperform_rpc\x18\x17 \x01(\x0b\x32!.livekit.proto.PerformRpcCallbackH\x00\x12H\n\x15rpc_method_invocation\x18\x18 \x01(\x0b\x32\'.livekit.proto.RpcMethodInvocationEventH\x00\x12\x45\n\x12send_stream_header\x18\x19 \x01(\x0b\x32\'.livekit.proto.SendStreamHeaderCallbackH\x00\x12\x43\n\x11send_stream_chunk\x18\x1a \x01(\x0b\x32&.livekit.proto.SendStreamChunkCallbackH\x00\x12G\n\x13send_stream_trailer\x18\x1b \x01(\x0b\x32(.livekit.proto.SendStreamTrailerCallbackH\x00\x42\t\n\x07message\"\x1f\n\x0e\x44isposeRequest\x12\r\n\x05\x61sync\x18\x01 \x02(\x08\"#\n\x0f\x44isposeResponse\x12\x10\n\x08\x61sync_id\x18\x01 \x01(\x04\"#\n\x0f\x44isposeCallback\x12\x10\n\x08\x61sync_id\x18\x01 \x02(\x04\"\x85\x01\n\tLogRecord\x12&\n\x05level\x18\x01 \x02(\x0e\x32\x17.livekit.proto.LogLevel\x12\x0e\n\x06target\x18\x02 \x02(\t\x12\x13\n\x0bmodule_path\x18\x03 \x01(\t\x12\x0c\n\x04\x66ile\x18\x04 \x01(\t\x12\x0c\n\x04line\x18\x05 \x01(\r\x12\x0f\n\x07message\x18\x06 \x02(\t\"5\n\x08LogBatch\x12)\n\x07records\x18\x01 \x03(\x0b\x32\x18.livekit.proto.LogRecord\"\x18\n\x05Panic\x12\x0f\n\x07message\x18\x01 \x02(\t*S\n\x08LogLevel\x12\r\n\tLOG_ERROR\x10\x00\x12\x0c\n\x08LOG_WARN\x10\x01\x12\x0c\n\x08LOG_INFO\x10\x02\x12\r\n\tLOG_DEBUG\x10\x03\x12\r\n\tLOG_TRACE\x10\x04\x42\x10\xaa\x02\rLiveKit.Proto') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -29,24 +29,24 @@ if not _descriptor._USE_C_DESCRIPTORS: _globals['DESCRIPTOR']._loaded_options = None _globals['DESCRIPTOR']._serialized_options = b'\252\002\rLiveKit.Proto' - _globals['_LOGLEVEL']._serialized_start=8981 - _globals['_LOGLEVEL']._serialized_end=9064 + _globals['_LOGLEVEL']._serialized_start=9392 + _globals['_LOGLEVEL']._serialized_end=9475 _globals['_FFIREQUEST']._serialized_start=140 - _globals['_FFIREQUEST']._serialized_end=3589 - _globals['_FFIRESPONSE']._serialized_start=3592 - _globals['_FFIRESPONSE']._serialized_end=7021 - _globals['_FFIEVENT']._serialized_start=7024 - _globals['_FFIEVENT']._serialized_end=8655 - _globals['_DISPOSEREQUEST']._serialized_start=8657 - _globals['_DISPOSEREQUEST']._serialized_end=8688 - _globals['_DISPOSERESPONSE']._serialized_start=8690 - _globals['_DISPOSERESPONSE']._serialized_end=8725 - _globals['_DISPOSECALLBACK']._serialized_start=8727 - _globals['_DISPOSECALLBACK']._serialized_end=8762 - _globals['_LOGRECORD']._serialized_start=8765 - _globals['_LOGRECORD']._serialized_end=8898 - _globals['_LOGBATCH']._serialized_start=8900 - _globals['_LOGBATCH']._serialized_end=8953 - _globals['_PANIC']._serialized_start=8955 - _globals['_PANIC']._serialized_end=8979 + _globals['_FFIREQUEST']._serialized_end=3793 + _globals['_FFIRESPONSE']._serialized_start=3796 + _globals['_FFIRESPONSE']._serialized_end=7432 + _globals['_FFIEVENT']._serialized_start=7435 + _globals['_FFIEVENT']._serialized_end=9066 + _globals['_DISPOSEREQUEST']._serialized_start=9068 + _globals['_DISPOSEREQUEST']._serialized_end=9099 + _globals['_DISPOSERESPONSE']._serialized_start=9101 + _globals['_DISPOSERESPONSE']._serialized_end=9136 + _globals['_DISPOSECALLBACK']._serialized_start=9138 + _globals['_DISPOSECALLBACK']._serialized_end=9173 + _globals['_LOGRECORD']._serialized_start=9176 + _globals['_LOGRECORD']._serialized_end=9309 + _globals['_LOGBATCH']._serialized_start=9311 + _globals['_LOGBATCH']._serialized_end=9364 + _globals['_PANIC']._serialized_start=9366 + _globals['_PANIC']._serialized_end=9390 # @@protoc_insertion_point(module_scope) diff --git a/livekit-rtc/livekit/rtc/_proto/ffi_pb2.pyi b/livekit-rtc/livekit/rtc/_proto/ffi_pb2.pyi index f45bc6a7..73ed7790 100644 --- a/livekit-rtc/livekit/rtc/_proto/ffi_pb2.pyi +++ b/livekit-rtc/livekit/rtc/_proto/ffi_pb2.pyi @@ -142,6 +142,9 @@ class FfiRequest(google.protobuf.message.Message): SEND_STREAM_TRAILER_FIELD_NUMBER: builtins.int SET_DATA_CHANNEL_BUFFERED_AMOUNT_LOW_THRESHOLD_FIELD_NUMBER: builtins.int LOAD_AUDIO_FILTER_PLUGIN_FIELD_NUMBER: builtins.int + NEW_APM_FIELD_NUMBER: builtins.int + APM_PROCESS_STREAM_FIELD_NUMBER: builtins.int + APM_PROCESS_REVERSE_STREAM_FIELD_NUMBER: builtins.int @property def dispose(self) -> global___DisposeRequest: ... @property @@ -256,6 +259,12 @@ class FfiRequest(google.protobuf.message.Message): def load_audio_filter_plugin(self) -> audio_frame_pb2.LoadAudioFilterPluginRequest: """Audio Filter Plugin""" + @property + def new_apm(self) -> audio_frame_pb2.NewApmRequest: ... + @property + def apm_process_stream(self) -> audio_frame_pb2.ApmProcessStreamRequest: ... + @property + def apm_process_reverse_stream(self) -> audio_frame_pb2.ApmProcessReverseStreamRequest: ... def __init__( self, *, @@ -307,10 +316,13 @@ class FfiRequest(google.protobuf.message.Message): send_stream_trailer: room_pb2.SendStreamTrailerRequest | None = ..., set_data_channel_buffered_amount_low_threshold: room_pb2.SetDataChannelBufferedAmountLowThresholdRequest | None = ..., load_audio_filter_plugin: audio_frame_pb2.LoadAudioFilterPluginRequest | None = ..., + new_apm: audio_frame_pb2.NewApmRequest | None = ..., + apm_process_stream: audio_frame_pb2.ApmProcessStreamRequest | None = ..., + apm_process_reverse_stream: audio_frame_pb2.ApmProcessReverseStreamRequest | None = ..., ) -> None: ... - def HasField(self, field_name: typing.Literal["audio_stream_from_participant", b"audio_stream_from_participant", "capture_audio_frame", b"capture_audio_frame", "capture_video_frame", b"capture_video_frame", "clear_audio_buffer", b"clear_audio_buffer", "connect", b"connect", "create_audio_track", b"create_audio_track", "create_video_track", b"create_video_track", "disconnect", b"disconnect", "dispose", b"dispose", "e2ee", b"e2ee", "edit_chat_message", b"edit_chat_message", "enable_remote_track", b"enable_remote_track", "enable_remote_track_publication", b"enable_remote_track_publication", "flush_sox_resampler", b"flush_sox_resampler", "get_session_stats", b"get_session_stats", "get_stats", b"get_stats", "load_audio_filter_plugin", b"load_audio_filter_plugin", "local_track_mute", b"local_track_mute", "message", b"message", "new_audio_resampler", b"new_audio_resampler", "new_audio_source", b"new_audio_source", "new_audio_stream", b"new_audio_stream", "new_sox_resampler", b"new_sox_resampler", "new_video_source", b"new_video_source", "new_video_stream", b"new_video_stream", "perform_rpc", b"perform_rpc", "publish_data", b"publish_data", "publish_sip_dtmf", b"publish_sip_dtmf", "publish_track", b"publish_track", "publish_transcription", b"publish_transcription", "push_sox_resampler", b"push_sox_resampler", "register_rpc_method", b"register_rpc_method", "remix_and_resample", b"remix_and_resample", "rpc_method_invocation_response", b"rpc_method_invocation_response", "send_chat_message", b"send_chat_message", "send_stream_chunk", b"send_stream_chunk", "send_stream_header", b"send_stream_header", "send_stream_trailer", b"send_stream_trailer", "set_data_channel_buffered_amount_low_threshold", b"set_data_channel_buffered_amount_low_threshold", "set_local_attributes", b"set_local_attributes", "set_local_metadata", b"set_local_metadata", "set_local_name", b"set_local_name", "set_subscribed", b"set_subscribed", "set_track_subscription_permissions", b"set_track_subscription_permissions", "unpublish_track", b"unpublish_track", "unregister_rpc_method", b"unregister_rpc_method", "update_remote_track_publication_dimension", b"update_remote_track_publication_dimension", "video_convert", b"video_convert", "video_stream_from_participant", b"video_stream_from_participant"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["audio_stream_from_participant", b"audio_stream_from_participant", "capture_audio_frame", b"capture_audio_frame", "capture_video_frame", b"capture_video_frame", "clear_audio_buffer", b"clear_audio_buffer", "connect", b"connect", "create_audio_track", b"create_audio_track", "create_video_track", b"create_video_track", "disconnect", b"disconnect", "dispose", b"dispose", "e2ee", b"e2ee", "edit_chat_message", b"edit_chat_message", "enable_remote_track", b"enable_remote_track", "enable_remote_track_publication", b"enable_remote_track_publication", "flush_sox_resampler", b"flush_sox_resampler", "get_session_stats", b"get_session_stats", "get_stats", b"get_stats", "load_audio_filter_plugin", b"load_audio_filter_plugin", "local_track_mute", b"local_track_mute", "message", b"message", "new_audio_resampler", b"new_audio_resampler", "new_audio_source", b"new_audio_source", "new_audio_stream", b"new_audio_stream", "new_sox_resampler", b"new_sox_resampler", "new_video_source", b"new_video_source", "new_video_stream", b"new_video_stream", "perform_rpc", b"perform_rpc", "publish_data", b"publish_data", "publish_sip_dtmf", b"publish_sip_dtmf", "publish_track", b"publish_track", "publish_transcription", b"publish_transcription", "push_sox_resampler", b"push_sox_resampler", "register_rpc_method", b"register_rpc_method", "remix_and_resample", b"remix_and_resample", "rpc_method_invocation_response", b"rpc_method_invocation_response", "send_chat_message", b"send_chat_message", "send_stream_chunk", b"send_stream_chunk", "send_stream_header", b"send_stream_header", "send_stream_trailer", b"send_stream_trailer", "set_data_channel_buffered_amount_low_threshold", b"set_data_channel_buffered_amount_low_threshold", "set_local_attributes", b"set_local_attributes", "set_local_metadata", b"set_local_metadata", "set_local_name", b"set_local_name", "set_subscribed", b"set_subscribed", "set_track_subscription_permissions", b"set_track_subscription_permissions", "unpublish_track", b"unpublish_track", "unregister_rpc_method", b"unregister_rpc_method", "update_remote_track_publication_dimension", b"update_remote_track_publication_dimension", "video_convert", b"video_convert", "video_stream_from_participant", b"video_stream_from_participant"]) -> None: ... - def WhichOneof(self, oneof_group: typing.Literal["message", b"message"]) -> typing.Literal["dispose", "connect", "disconnect", "publish_track", "unpublish_track", "publish_data", "set_subscribed", "set_local_metadata", "set_local_name", "set_local_attributes", "get_session_stats", "publish_transcription", "publish_sip_dtmf", "create_video_track", "create_audio_track", "local_track_mute", "enable_remote_track", "get_stats", "set_track_subscription_permissions", "new_video_stream", "new_video_source", "capture_video_frame", "video_convert", "video_stream_from_participant", "new_audio_stream", "new_audio_source", "capture_audio_frame", "clear_audio_buffer", "new_audio_resampler", "remix_and_resample", "e2ee", "audio_stream_from_participant", "new_sox_resampler", "push_sox_resampler", "flush_sox_resampler", "send_chat_message", "edit_chat_message", "perform_rpc", "register_rpc_method", "unregister_rpc_method", "rpc_method_invocation_response", "enable_remote_track_publication", "update_remote_track_publication_dimension", "send_stream_header", "send_stream_chunk", "send_stream_trailer", "set_data_channel_buffered_amount_low_threshold", "load_audio_filter_plugin"] | None: ... + def HasField(self, field_name: typing.Literal["apm_process_reverse_stream", b"apm_process_reverse_stream", "apm_process_stream", b"apm_process_stream", "audio_stream_from_participant", b"audio_stream_from_participant", "capture_audio_frame", b"capture_audio_frame", "capture_video_frame", b"capture_video_frame", "clear_audio_buffer", b"clear_audio_buffer", "connect", b"connect", "create_audio_track", b"create_audio_track", "create_video_track", b"create_video_track", "disconnect", b"disconnect", "dispose", b"dispose", "e2ee", b"e2ee", "edit_chat_message", b"edit_chat_message", "enable_remote_track", b"enable_remote_track", "enable_remote_track_publication", b"enable_remote_track_publication", "flush_sox_resampler", b"flush_sox_resampler", "get_session_stats", b"get_session_stats", "get_stats", b"get_stats", "load_audio_filter_plugin", b"load_audio_filter_plugin", "local_track_mute", b"local_track_mute", "message", b"message", "new_apm", b"new_apm", "new_audio_resampler", b"new_audio_resampler", "new_audio_source", b"new_audio_source", "new_audio_stream", b"new_audio_stream", "new_sox_resampler", b"new_sox_resampler", "new_video_source", b"new_video_source", "new_video_stream", b"new_video_stream", "perform_rpc", b"perform_rpc", "publish_data", b"publish_data", "publish_sip_dtmf", b"publish_sip_dtmf", "publish_track", b"publish_track", "publish_transcription", b"publish_transcription", "push_sox_resampler", b"push_sox_resampler", "register_rpc_method", b"register_rpc_method", "remix_and_resample", b"remix_and_resample", "rpc_method_invocation_response", b"rpc_method_invocation_response", "send_chat_message", b"send_chat_message", "send_stream_chunk", b"send_stream_chunk", "send_stream_header", b"send_stream_header", "send_stream_trailer", b"send_stream_trailer", "set_data_channel_buffered_amount_low_threshold", b"set_data_channel_buffered_amount_low_threshold", "set_local_attributes", b"set_local_attributes", "set_local_metadata", b"set_local_metadata", "set_local_name", b"set_local_name", "set_subscribed", b"set_subscribed", "set_track_subscription_permissions", b"set_track_subscription_permissions", "unpublish_track", b"unpublish_track", "unregister_rpc_method", b"unregister_rpc_method", "update_remote_track_publication_dimension", b"update_remote_track_publication_dimension", "video_convert", b"video_convert", "video_stream_from_participant", b"video_stream_from_participant"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["apm_process_reverse_stream", b"apm_process_reverse_stream", "apm_process_stream", b"apm_process_stream", "audio_stream_from_participant", b"audio_stream_from_participant", "capture_audio_frame", b"capture_audio_frame", "capture_video_frame", b"capture_video_frame", "clear_audio_buffer", b"clear_audio_buffer", "connect", b"connect", "create_audio_track", b"create_audio_track", "create_video_track", b"create_video_track", "disconnect", b"disconnect", "dispose", b"dispose", "e2ee", b"e2ee", "edit_chat_message", b"edit_chat_message", "enable_remote_track", b"enable_remote_track", "enable_remote_track_publication", b"enable_remote_track_publication", "flush_sox_resampler", b"flush_sox_resampler", "get_session_stats", b"get_session_stats", "get_stats", b"get_stats", "load_audio_filter_plugin", b"load_audio_filter_plugin", "local_track_mute", b"local_track_mute", "message", b"message", "new_apm", b"new_apm", "new_audio_resampler", b"new_audio_resampler", "new_audio_source", b"new_audio_source", "new_audio_stream", b"new_audio_stream", "new_sox_resampler", b"new_sox_resampler", "new_video_source", b"new_video_source", "new_video_stream", b"new_video_stream", "perform_rpc", b"perform_rpc", "publish_data", b"publish_data", "publish_sip_dtmf", b"publish_sip_dtmf", "publish_track", b"publish_track", "publish_transcription", b"publish_transcription", "push_sox_resampler", b"push_sox_resampler", "register_rpc_method", b"register_rpc_method", "remix_and_resample", b"remix_and_resample", "rpc_method_invocation_response", b"rpc_method_invocation_response", "send_chat_message", b"send_chat_message", "send_stream_chunk", b"send_stream_chunk", "send_stream_header", b"send_stream_header", "send_stream_trailer", b"send_stream_trailer", "set_data_channel_buffered_amount_low_threshold", b"set_data_channel_buffered_amount_low_threshold", "set_local_attributes", b"set_local_attributes", "set_local_metadata", b"set_local_metadata", "set_local_name", b"set_local_name", "set_subscribed", b"set_subscribed", "set_track_subscription_permissions", b"set_track_subscription_permissions", "unpublish_track", b"unpublish_track", "unregister_rpc_method", b"unregister_rpc_method", "update_remote_track_publication_dimension", b"update_remote_track_publication_dimension", "video_convert", b"video_convert", "video_stream_from_participant", b"video_stream_from_participant"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["message", b"message"]) -> typing.Literal["dispose", "connect", "disconnect", "publish_track", "unpublish_track", "publish_data", "set_subscribed", "set_local_metadata", "set_local_name", "set_local_attributes", "get_session_stats", "publish_transcription", "publish_sip_dtmf", "create_video_track", "create_audio_track", "local_track_mute", "enable_remote_track", "get_stats", "set_track_subscription_permissions", "new_video_stream", "new_video_source", "capture_video_frame", "video_convert", "video_stream_from_participant", "new_audio_stream", "new_audio_source", "capture_audio_frame", "clear_audio_buffer", "new_audio_resampler", "remix_and_resample", "e2ee", "audio_stream_from_participant", "new_sox_resampler", "push_sox_resampler", "flush_sox_resampler", "send_chat_message", "edit_chat_message", "perform_rpc", "register_rpc_method", "unregister_rpc_method", "rpc_method_invocation_response", "enable_remote_track_publication", "update_remote_track_publication_dimension", "send_stream_header", "send_stream_chunk", "send_stream_trailer", "set_data_channel_buffered_amount_low_threshold", "load_audio_filter_plugin", "new_apm", "apm_process_stream", "apm_process_reverse_stream"] | None: ... global___FfiRequest = FfiRequest @@ -367,6 +379,9 @@ class FfiResponse(google.protobuf.message.Message): SEND_STREAM_TRAILER_FIELD_NUMBER: builtins.int SET_DATA_CHANNEL_BUFFERED_AMOUNT_LOW_THRESHOLD_FIELD_NUMBER: builtins.int LOAD_AUDIO_FILTER_PLUGIN_FIELD_NUMBER: builtins.int + NEW_APM_FIELD_NUMBER: builtins.int + APM_PROCESS_STREAM_FIELD_NUMBER: builtins.int + APM_PROCESS_REVERSE_STREAM_FIELD_NUMBER: builtins.int @property def dispose(self) -> global___DisposeResponse: ... @property @@ -479,6 +494,12 @@ class FfiResponse(google.protobuf.message.Message): def load_audio_filter_plugin(self) -> audio_frame_pb2.LoadAudioFilterPluginResponse: """Audio Filter Plugin""" + @property + def new_apm(self) -> audio_frame_pb2.NewApmResponse: ... + @property + def apm_process_stream(self) -> audio_frame_pb2.ApmProcessStreamResponse: ... + @property + def apm_process_reverse_stream(self) -> audio_frame_pb2.ApmProcessReverseStreamResponse: ... def __init__( self, *, @@ -529,10 +550,13 @@ class FfiResponse(google.protobuf.message.Message): send_stream_trailer: room_pb2.SendStreamTrailerResponse | None = ..., set_data_channel_buffered_amount_low_threshold: room_pb2.SetDataChannelBufferedAmountLowThresholdResponse | None = ..., load_audio_filter_plugin: audio_frame_pb2.LoadAudioFilterPluginResponse | None = ..., + new_apm: audio_frame_pb2.NewApmResponse | None = ..., + apm_process_stream: audio_frame_pb2.ApmProcessStreamResponse | None = ..., + apm_process_reverse_stream: audio_frame_pb2.ApmProcessReverseStreamResponse | None = ..., ) -> None: ... - def HasField(self, field_name: typing.Literal["audio_stream_from_participant", b"audio_stream_from_participant", "capture_audio_frame", b"capture_audio_frame", "capture_video_frame", b"capture_video_frame", "clear_audio_buffer", b"clear_audio_buffer", "connect", b"connect", "create_audio_track", b"create_audio_track", "create_video_track", b"create_video_track", "disconnect", b"disconnect", "dispose", b"dispose", "e2ee", b"e2ee", "enable_remote_track", b"enable_remote_track", "enable_remote_track_publication", b"enable_remote_track_publication", "flush_sox_resampler", b"flush_sox_resampler", "get_session_stats", b"get_session_stats", "get_stats", b"get_stats", "load_audio_filter_plugin", b"load_audio_filter_plugin", "local_track_mute", b"local_track_mute", "message", b"message", "new_audio_resampler", b"new_audio_resampler", "new_audio_source", b"new_audio_source", "new_audio_stream", b"new_audio_stream", "new_sox_resampler", b"new_sox_resampler", "new_video_source", b"new_video_source", "new_video_stream", b"new_video_stream", "perform_rpc", b"perform_rpc", "publish_data", b"publish_data", "publish_sip_dtmf", b"publish_sip_dtmf", "publish_track", b"publish_track", "publish_transcription", b"publish_transcription", "push_sox_resampler", b"push_sox_resampler", "register_rpc_method", b"register_rpc_method", "remix_and_resample", b"remix_and_resample", "rpc_method_invocation_response", b"rpc_method_invocation_response", "send_chat_message", b"send_chat_message", "send_stream_chunk", b"send_stream_chunk", "send_stream_header", b"send_stream_header", "send_stream_trailer", b"send_stream_trailer", "set_data_channel_buffered_amount_low_threshold", b"set_data_channel_buffered_amount_low_threshold", "set_local_attributes", b"set_local_attributes", "set_local_metadata", b"set_local_metadata", "set_local_name", b"set_local_name", "set_subscribed", b"set_subscribed", "set_track_subscription_permissions", b"set_track_subscription_permissions", "unpublish_track", b"unpublish_track", "unregister_rpc_method", b"unregister_rpc_method", "update_remote_track_publication_dimension", b"update_remote_track_publication_dimension", "video_convert", b"video_convert", "video_stream_from_participant", b"video_stream_from_participant"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["audio_stream_from_participant", b"audio_stream_from_participant", "capture_audio_frame", b"capture_audio_frame", "capture_video_frame", b"capture_video_frame", "clear_audio_buffer", b"clear_audio_buffer", "connect", b"connect", "create_audio_track", b"create_audio_track", "create_video_track", b"create_video_track", "disconnect", b"disconnect", "dispose", b"dispose", "e2ee", b"e2ee", "enable_remote_track", b"enable_remote_track", "enable_remote_track_publication", b"enable_remote_track_publication", "flush_sox_resampler", b"flush_sox_resampler", "get_session_stats", b"get_session_stats", "get_stats", b"get_stats", "load_audio_filter_plugin", b"load_audio_filter_plugin", "local_track_mute", b"local_track_mute", "message", b"message", "new_audio_resampler", b"new_audio_resampler", "new_audio_source", b"new_audio_source", "new_audio_stream", b"new_audio_stream", "new_sox_resampler", b"new_sox_resampler", "new_video_source", b"new_video_source", "new_video_stream", b"new_video_stream", "perform_rpc", b"perform_rpc", "publish_data", b"publish_data", "publish_sip_dtmf", b"publish_sip_dtmf", "publish_track", b"publish_track", "publish_transcription", b"publish_transcription", "push_sox_resampler", b"push_sox_resampler", "register_rpc_method", b"register_rpc_method", "remix_and_resample", b"remix_and_resample", "rpc_method_invocation_response", b"rpc_method_invocation_response", "send_chat_message", b"send_chat_message", "send_stream_chunk", b"send_stream_chunk", "send_stream_header", b"send_stream_header", "send_stream_trailer", b"send_stream_trailer", "set_data_channel_buffered_amount_low_threshold", b"set_data_channel_buffered_amount_low_threshold", "set_local_attributes", b"set_local_attributes", "set_local_metadata", b"set_local_metadata", "set_local_name", b"set_local_name", "set_subscribed", b"set_subscribed", "set_track_subscription_permissions", b"set_track_subscription_permissions", "unpublish_track", b"unpublish_track", "unregister_rpc_method", b"unregister_rpc_method", "update_remote_track_publication_dimension", b"update_remote_track_publication_dimension", "video_convert", b"video_convert", "video_stream_from_participant", b"video_stream_from_participant"]) -> None: ... - def WhichOneof(self, oneof_group: typing.Literal["message", b"message"]) -> typing.Literal["dispose", "connect", "disconnect", "publish_track", "unpublish_track", "publish_data", "set_subscribed", "set_local_metadata", "set_local_name", "set_local_attributes", "get_session_stats", "publish_transcription", "publish_sip_dtmf", "create_video_track", "create_audio_track", "local_track_mute", "enable_remote_track", "get_stats", "set_track_subscription_permissions", "new_video_stream", "new_video_source", "capture_video_frame", "video_convert", "video_stream_from_participant", "new_audio_stream", "new_audio_source", "capture_audio_frame", "clear_audio_buffer", "new_audio_resampler", "remix_and_resample", "audio_stream_from_participant", "e2ee", "new_sox_resampler", "push_sox_resampler", "flush_sox_resampler", "send_chat_message", "perform_rpc", "register_rpc_method", "unregister_rpc_method", "rpc_method_invocation_response", "enable_remote_track_publication", "update_remote_track_publication_dimension", "send_stream_header", "send_stream_chunk", "send_stream_trailer", "set_data_channel_buffered_amount_low_threshold", "load_audio_filter_plugin"] | None: ... + def HasField(self, field_name: typing.Literal["apm_process_reverse_stream", b"apm_process_reverse_stream", "apm_process_stream", b"apm_process_stream", "audio_stream_from_participant", b"audio_stream_from_participant", "capture_audio_frame", b"capture_audio_frame", "capture_video_frame", b"capture_video_frame", "clear_audio_buffer", b"clear_audio_buffer", "connect", b"connect", "create_audio_track", b"create_audio_track", "create_video_track", b"create_video_track", "disconnect", b"disconnect", "dispose", b"dispose", "e2ee", b"e2ee", "enable_remote_track", b"enable_remote_track", "enable_remote_track_publication", b"enable_remote_track_publication", "flush_sox_resampler", b"flush_sox_resampler", "get_session_stats", b"get_session_stats", "get_stats", b"get_stats", "load_audio_filter_plugin", b"load_audio_filter_plugin", "local_track_mute", b"local_track_mute", "message", b"message", "new_apm", b"new_apm", "new_audio_resampler", b"new_audio_resampler", "new_audio_source", b"new_audio_source", "new_audio_stream", b"new_audio_stream", "new_sox_resampler", b"new_sox_resampler", "new_video_source", b"new_video_source", "new_video_stream", b"new_video_stream", "perform_rpc", b"perform_rpc", "publish_data", b"publish_data", "publish_sip_dtmf", b"publish_sip_dtmf", "publish_track", b"publish_track", "publish_transcription", b"publish_transcription", "push_sox_resampler", b"push_sox_resampler", "register_rpc_method", b"register_rpc_method", "remix_and_resample", b"remix_and_resample", "rpc_method_invocation_response", b"rpc_method_invocation_response", "send_chat_message", b"send_chat_message", "send_stream_chunk", b"send_stream_chunk", "send_stream_header", b"send_stream_header", "send_stream_trailer", b"send_stream_trailer", "set_data_channel_buffered_amount_low_threshold", b"set_data_channel_buffered_amount_low_threshold", "set_local_attributes", b"set_local_attributes", "set_local_metadata", b"set_local_metadata", "set_local_name", b"set_local_name", "set_subscribed", b"set_subscribed", "set_track_subscription_permissions", b"set_track_subscription_permissions", "unpublish_track", b"unpublish_track", "unregister_rpc_method", b"unregister_rpc_method", "update_remote_track_publication_dimension", b"update_remote_track_publication_dimension", "video_convert", b"video_convert", "video_stream_from_participant", b"video_stream_from_participant"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["apm_process_reverse_stream", b"apm_process_reverse_stream", "apm_process_stream", b"apm_process_stream", "audio_stream_from_participant", b"audio_stream_from_participant", "capture_audio_frame", b"capture_audio_frame", "capture_video_frame", b"capture_video_frame", "clear_audio_buffer", b"clear_audio_buffer", "connect", b"connect", "create_audio_track", b"create_audio_track", "create_video_track", b"create_video_track", "disconnect", b"disconnect", "dispose", b"dispose", "e2ee", b"e2ee", "enable_remote_track", b"enable_remote_track", "enable_remote_track_publication", b"enable_remote_track_publication", "flush_sox_resampler", b"flush_sox_resampler", "get_session_stats", b"get_session_stats", "get_stats", b"get_stats", "load_audio_filter_plugin", b"load_audio_filter_plugin", "local_track_mute", b"local_track_mute", "message", b"message", "new_apm", b"new_apm", "new_audio_resampler", b"new_audio_resampler", "new_audio_source", b"new_audio_source", "new_audio_stream", b"new_audio_stream", "new_sox_resampler", b"new_sox_resampler", "new_video_source", b"new_video_source", "new_video_stream", b"new_video_stream", "perform_rpc", b"perform_rpc", "publish_data", b"publish_data", "publish_sip_dtmf", b"publish_sip_dtmf", "publish_track", b"publish_track", "publish_transcription", b"publish_transcription", "push_sox_resampler", b"push_sox_resampler", "register_rpc_method", b"register_rpc_method", "remix_and_resample", b"remix_and_resample", "rpc_method_invocation_response", b"rpc_method_invocation_response", "send_chat_message", b"send_chat_message", "send_stream_chunk", b"send_stream_chunk", "send_stream_header", b"send_stream_header", "send_stream_trailer", b"send_stream_trailer", "set_data_channel_buffered_amount_low_threshold", b"set_data_channel_buffered_amount_low_threshold", "set_local_attributes", b"set_local_attributes", "set_local_metadata", b"set_local_metadata", "set_local_name", b"set_local_name", "set_subscribed", b"set_subscribed", "set_track_subscription_permissions", b"set_track_subscription_permissions", "unpublish_track", b"unpublish_track", "unregister_rpc_method", b"unregister_rpc_method", "update_remote_track_publication_dimension", b"update_remote_track_publication_dimension", "video_convert", b"video_convert", "video_stream_from_participant", b"video_stream_from_participant"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["message", b"message"]) -> typing.Literal["dispose", "connect", "disconnect", "publish_track", "unpublish_track", "publish_data", "set_subscribed", "set_local_metadata", "set_local_name", "set_local_attributes", "get_session_stats", "publish_transcription", "publish_sip_dtmf", "create_video_track", "create_audio_track", "local_track_mute", "enable_remote_track", "get_stats", "set_track_subscription_permissions", "new_video_stream", "new_video_source", "capture_video_frame", "video_convert", "video_stream_from_participant", "new_audio_stream", "new_audio_source", "capture_audio_frame", "clear_audio_buffer", "new_audio_resampler", "remix_and_resample", "audio_stream_from_participant", "e2ee", "new_sox_resampler", "push_sox_resampler", "flush_sox_resampler", "send_chat_message", "perform_rpc", "register_rpc_method", "unregister_rpc_method", "rpc_method_invocation_response", "enable_remote_track_publication", "update_remote_track_publication_dimension", "send_stream_header", "send_stream_chunk", "send_stream_trailer", "set_data_channel_buffered_amount_low_threshold", "load_audio_filter_plugin", "new_apm", "apm_process_stream", "apm_process_reverse_stream"] | None: ... global___FfiResponse = FfiResponse diff --git a/livekit-rtc/livekit/rtc/apm.py b/livekit-rtc/livekit/rtc/apm.py new file mode 100644 index 00000000..296ca55d --- /dev/null +++ b/livekit-rtc/livekit/rtc/apm.py @@ -0,0 +1,88 @@ +from __future__ import annotations + +from ._ffi_client import FfiClient, FfiHandle +from ._proto import ffi_pb2 as proto_ffi +from ._utils import get_address +from .audio_frame import AudioFrame + + +class AudioProcessingModule: + """ + Provides WebRTC audio processing capabilities including echo cancellation, noise suppression, + high-pass filtering, and gain control. + """ + + def __init__( + self, + *, + echo_canceller_enabled: bool = False, + noise_suppression_enabled: bool = False, + high_pass_filter_enabled: bool = False, + gain_controller_enabled: bool = False, + ) -> None: + """ + Initialize an AudioProcessingModule instance with the specified audio processing features. + + Args: + echo_canceller_enabled (bool, optional): Whether to enable echo cancellation. + noise_suppression_enabled (bool, optional): Whether to enable noise suppression. + high_pass_filter_enabled (bool, optional): Whether to enable a high-pass filter. + gain_controller_enabled (bool, optional): Whether to enable a gain controller. + """ + req = proto_ffi.FfiRequest() + req.new_apm.echo_canceller_enabled = echo_canceller_enabled + req.new_apm.noise_suppression_enabled = noise_suppression_enabled + req.new_apm.high_pass_filter_enabled = high_pass_filter_enabled + req.new_apm.gain_controller_enabled = gain_controller_enabled + + resp = FfiClient.instance.request(req) + self._ffi_handle = FfiHandle(resp.new_apm.apm.handle.id) + + def process_stream(self, data: AudioFrame) -> None: + """ + Process the provided audio frame using the configured audio processing features. + + The input audio frame is modified in-place (if applicable) by the underlying audio + processing module (e.g., echo cancellation, noise suppression, etc.). + + Important: + Audio frames must be exactly 10 ms in duration. + """ + bdata = data.data.cast("b") + + req = proto_ffi.FfiRequest() + req.apm_process_stream.apm_handle = self._ffi_handle.handle + req.apm_process_stream.data_ptr = get_address(memoryview(bdata)) + req.apm_process_stream.size = len(bdata) + req.apm_process_stream.sample_rate = data.sample_rate + req.apm_process_stream.num_channels = data.num_channels + + resp = FfiClient.instance.request(req) + + if resp.apm_process_stream.error: + raise RuntimeError(resp.apm_process_stream.error) + + def process_reverse_stream(self, data: AudioFrame) -> None: + """ + Process the reverse audio frame (typically used for echo cancellation in a full-duplex setup). + + In an echo cancellation scenario, this method is used to process the "far-end" audio + prior to mixing or feeding it into the echo canceller. Like `process_stream`, the + input audio frame is modified in-place by the underlying processing module. + + Important: + Audio frames must be exactly 10 ms in duration. + """ + bdata = data.data.cast("b") + + req = proto_ffi.FfiRequest() + req.apm_process_reverse_stream.apm_handle = self._ffi_handle.handle + req.apm_process_reverse_stream.data_ptr = get_address(memoryview(bdata)) + req.apm_process_reverse_stream.size = len(bdata) + req.apm_process_reverse_stream.sample_rate = data.sample_rate + req.apm_process_reverse_stream.num_channels = data.num_channels + + resp = FfiClient.instance.request(req) + + if resp.apm_process_stream.error: + raise RuntimeError(resp.apm_process_stream.error) diff --git a/livekit-rtc/rust-sdks b/livekit-rtc/rust-sdks index de91ada2..aea9f4e4 160000 --- a/livekit-rtc/rust-sdks +++ b/livekit-rtc/rust-sdks @@ -1 +1 @@ -Subproject commit de91ada2e0f26f14ebf95414953cef110c5288fe +Subproject commit aea9f4e47dbcb0d34d146bfe315f75e5bfd63cc2 diff --git a/livekit-rtc/tests/test_apm.py b/livekit-rtc/tests/test_apm.py new file mode 100644 index 00000000..d48cb958 --- /dev/null +++ b/livekit-rtc/tests/test_apm.py @@ -0,0 +1,78 @@ +import os +import wave +import numpy as np + +from livekit.rtc import AudioProcessingModule, AudioFrame + + +def test_audio_processing(): + sample_rate = 48000 + num_channels = 1 + frames_per_chunk = sample_rate // 100 + + current_dir = os.path.dirname(os.path.abspath(__file__)) + capture_wav = os.path.join(current_dir, "test_echo_capture.wav") + render_wav = os.path.join(current_dir, "test_echo_render.wav") + output_wav = os.path.join(current_dir, "test_processed.wav") + + # Initialize APM with echo cancellation enabled + apm = AudioProcessingModule( + echo_canceller_enabled=True, + noise_suppression_enabled=True, + high_pass_filter_enabled=True, + gain_controller_enabled=True, + ) + print("APM Internal Handle:", apm._ffi_handle) + + with ( + wave.open(capture_wav, "rb") as wf_in_cap, + wave.open(render_wav, "rb") as wf_in_rend, + wave.open(output_wav, "wb") as wf_out, + ): + assert wf_in_cap.getnchannels() == num_channels, "Capture file must be mono." + assert wf_in_rend.getnchannels() == num_channels, "Render file must be mono." + assert wf_in_cap.getframerate() == sample_rate, "Capture file must be 48 kHz." + assert wf_in_rend.getframerate() == sample_rate, "Render file must be 48 kHz." + + sampwidth = wf_in_cap.getsampwidth() + wf_out.setnchannels(num_channels) + wf_out.setsampwidth(sampwidth) + wf_out.setframerate(sample_rate) + + while True: + capture_bytes = wf_in_cap.readframes(frames_per_chunk) + render_bytes = wf_in_rend.readframes(frames_per_chunk) + + if not capture_bytes and not render_bytes: + break + + # Convert bytes to numpy arrays + capture_data = np.frombuffer(capture_bytes, dtype=np.int16) + render_data = np.frombuffer(render_bytes, dtype=np.int16) + + # Pad if necessary + if len(capture_data) < frames_per_chunk: + capture_data = np.pad(capture_data, (0, frames_per_chunk - len(capture_data))) + if len(render_data) < frames_per_chunk: + render_data = np.pad(render_data, (0, frames_per_chunk - len(render_data))) + + capture_frame = AudioFrame( + data=capture_data.tobytes(), + sample_rate=sample_rate, + num_channels=num_channels, + samples_per_channel=frames_per_chunk, + ) + render_frame = AudioFrame( + data=render_data.tobytes(), + sample_rate=sample_rate, + num_channels=num_channels, + samples_per_channel=frames_per_chunk, + ) + + # Process both streams + apm.process_reverse_stream(render_frame) + apm.process_stream(capture_frame) + + wf_out.writeframes(capture_frame.data.tobytes()) + + print("Done! Processed audio saved to:", output_wav) diff --git a/livekit-rtc/tests/test_echo_capture.wav b/livekit-rtc/tests/test_echo_capture.wav new file mode 100644 index 00000000..14035d71 --- /dev/null +++ b/livekit-rtc/tests/test_echo_capture.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:90626c2c532dfb8313ae52501a9500f1c90235570aab8ff1367e7f91fb697a7e +size 970796 diff --git a/livekit-rtc/tests/test_echo_render.wav b/livekit-rtc/tests/test_echo_render.wav new file mode 100644 index 00000000..3d061ce6 --- /dev/null +++ b/livekit-rtc/tests/test_echo_render.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf50f57f00fa941ab612c57c24a28811b93c878d3c98edcb4a8f21508aa8e566 +size 970796 diff --git a/livekit-rtc/tests/test_processed.wav b/livekit-rtc/tests/test_processed.wav new file mode 100644 index 00000000..c8520e86 --- /dev/null +++ b/livekit-rtc/tests/test_processed.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a48eb2f6a2143b4bc6adfe306983637f628fffc9d550c60b4ebcecd506d6245 +size 971564