diff --git a/CHANGES.md b/CHANGES.md index b136d66..26715e9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,15 +11,22 @@ ## develop +- [CHANGE] client_cert と client_key の指定にはパスではなく中身の文字列を指定するようにする + - C++ SDK 側の仕様変更に追従する + - @voluntas - [ADD] サーバー証明書チェック用の CA 証明書を指定できるようにする - `Sora.create_connection()` の引数に `ca_cert` を追加する - @voluntas +- [ADD] `on_ws_close` コールバックを追加する + - @tnoho - [ADD] `on_signaling_message` コールバックを追加する - @tnoho - [ADD] Ubuntu 24.04 armv8 に対応する - @melpon +- [ADD] `on_ws_close` コールバックを追加する + - @tnoho - [UPDATE] Sora C++ SDK のバージョンを `2024.8.0` に上げる - - WEBRTC_BUILD_VERSION を `m128.6613.2.0` に上げる + - WEBRTC_BUILD_VERSION を `m129.6668.1.0` に上げる - libwebrtc のモジュール分割に追従するため rtc::CreateRandomString のヘッダを追加 - CMAKE_VERSION を `3.30.3` に上げる - BOOST_VERSION を `1.86.0` に上げる diff --git a/README.md b/README.md index 39a911b..c2d29b0 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ PyPI 経由ではインストールできません。 - macOS Ventura 14 arm64 - macOS Sonoma 13 arm64 - Ubuntu 24.04 LTS x86_64 +- Ubuntu 24.04 LTS arm64 - Ubuntu 22.04 LTS x86_64 - Ubuntu 22.04 LTS arm64 (NVIDIA Jetson JetPack SDK 6) - PyPI からではなくパッケージファイルを利用してください diff --git a/VERSION b/VERSION index 8aabb39..971f08d 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ -SORA_CPP_SDK_VERSION=2024.8.0-canary.8 -WEBRTC_BUILD_VERSION=m128.6613.3.1 +SORA_CPP_SDK_VERSION=2024.8.0-canary.10 +WEBRTC_BUILD_VERSION=m129.6668.1.0 BOOST_VERSION=1.86.0 CMAKE_VERSION=3.30.3 OPENH264_VERSION=v2.4.1 diff --git a/src/sora_connection.cpp b/src/sora_connection.cpp index 075a623..cd50409 100644 --- a/src/sora_connection.cpp +++ b/src/sora_connection.cpp @@ -197,6 +197,12 @@ void SoraConnection::OnSignalingMessage(sora::SoraSignalingType type, } } +void SoraConnection::OnWsClose(uint16_t code, std::string message) { + if (on_ws_close_) { + on_ws_close_(code, message); + } +} + void SoraConnection::OnTrack( rtc::scoped_refptr transceiver) { if (on_track_) { diff --git a/src/sora_connection.h b/src/sora_connection.h index 96da921..bfb80c0 100644 --- a/src/sora_connection.h +++ b/src/sora_connection.h @@ -105,6 +105,7 @@ class SoraConnection : public sora::SoraSignalingObserver, void OnSignalingMessage(sora::SoraSignalingType type, sora::SoraSignalingDirection direction, std::string message) override; + void OnWsClose(uint16_t code, std::string message); void OnTrack( rtc::scoped_refptr transceiver) override; void OnRemoveTrack( @@ -116,6 +117,7 @@ class SoraConnection : public sora::SoraSignalingObserver, void(sora::SoraSignalingType, sora::SoraSignalingDirection, std::string)> on_signaling_message_; std::function on_set_offer_; + std::function on_ws_close_; std::function on_disconnect_; std::function on_notify_; std::function on_push_; diff --git a/src/sora_sdk_ext.cpp b/src/sora_sdk_ext.cpp index 2d8e839..2faab11 100644 --- a/src/sora_sdk_ext.cpp +++ b/src/sora_sdk_ext.cpp @@ -97,6 +97,11 @@ int connection_tp_traverse(PyObject* self, visitproc visit, void* arg) { Py_VISIT(on_set_offer.ptr()); } + if (conn->on_ws_close_) { + nb::object on_ws_close = nb::cast(conn->on_ws_close_, nb::rv_policy::none); + Py_VISIT(on_ws_close.ptr()); + } + if (conn->on_disconnect_) { nb::object on_disconnect = nb::cast(conn->on_disconnect_, nb::rv_policy::none); @@ -301,6 +306,7 @@ NB_MODULE(sora_sdk_ext, m) { "data"_a) .def("get_stats", &SoraConnection::GetStats) .def_rw("on_set_offer", &SoraConnection::on_set_offer_) + .def_rw("on_ws_close", &SoraConnection::on_ws_close_) .def_rw("on_disconnect", &SoraConnection::on_disconnect_) .def_rw("on_signaling_message", &SoraConnection::on_signaling_message_) .def_rw("on_notify", &SoraConnection::on_notify_) diff --git a/tests/client.py b/tests/client.py index 3cf8e02..1de2562 100644 --- a/tests/client.py +++ b/tests/client.py @@ -33,6 +33,7 @@ def __init__( video_codec_type: Optional[str] = None, video_bit_rate: Optional[int] = None, data_channel_signaling: Optional[bool] = None, + ignore_disconnect_websocket: Optional[bool] = None, openh264_path: Optional[str] = None, use_hwa: bool = False, audio_channels: int = 1, @@ -71,6 +72,7 @@ def __init__( video_codec_type=video_codec_type, video_bit_rate=video_bit_rate, data_channel_signaling=data_channel_signaling, + ignore_disconnect_websocket=ignore_disconnect_websocket, audio_source=self._audio_source, video_source=self._video_source, ca_cert=ca_cert, @@ -79,6 +81,8 @@ def __init__( self._connected: Event = Event() self._switched: bool = False + self._ignore_disconnect_websocket: bool = False + self._ws_close: bool = False self._closed: Event = Event() self._default_connection_timeout_s: float = 10.0 @@ -98,6 +102,7 @@ def __init__( self._connection.on_switched = self._on_switched self._connection.on_notify = self._on_notify self._connection.on_disconnect = self._on_disconnect + self._connection.on_ws_close = self._on_ws_close def connect(self, fake_audio=False, fake_video=False) -> None: self._connection.connect() @@ -162,6 +167,14 @@ def connected(self) -> bool: def switched(self) -> bool: return self._switched + @property + def ignore_disconnect_websocket(self) -> bool: + return self._ignore_disconnect_websocket + + @property + def ws_close(self) -> bool: + return self._ws_close + def _fake_audio_loop(self): while not self._closed.is_set(): time.sleep(0.02) @@ -222,6 +235,7 @@ def _on_switched(self, raw_message: str) -> None: if message["type"] == "switched": print(f"Switched to DataChannel Signaling: connection_id={self._connection_id}") self._switched = True + self._ignore_disconnect_websocket = message["ignore_disconnect_websocket"] def _on_notify(self, raw_message: str) -> None: message: dict[str, Any] = json.loads(raw_message) @@ -244,6 +258,10 @@ def _on_disconnect(self, error_code: SoraSignalingErrorCode, message: str) -> No if self._fake_video_thread is not None: self._fake_video_thread.join(timeout=10) + def _on_ws_close(self, code: int, reason: str) -> None: + print(f"WebSocket closed: code={code} reason={reason}") + self._ws_close = True + class Recvonly: def __init__( @@ -275,6 +293,7 @@ def __init__( self._connected: Event = Event() self._switched: bool = False + self._ws_close: bool = False self._closed: Event = Event() self._default_connection_timeout_s: float = 10.0 @@ -299,6 +318,7 @@ def __init__( self._connection.on_switched = self._on_switched self._connection.on_notify = self._on_notify self._connection.on_disconnect = self._on_disconnect + self._connection.on_ws_close = self._on_ws_close self._connection.on_track = self._on_track def connect(self) -> None: @@ -359,6 +379,10 @@ def connected(self) -> bool: def switched(self) -> bool: return self._switched + @property + def ws_close(self) -> bool: + return self._ws_close + @property def closed(self): return self._closed.is_set() @@ -427,6 +451,10 @@ def _on_disconnect(self, error_code: SoraSignalingErrorCode, message: str) -> No self._connected.clear() self._closed.is_set() + def _on_ws_close(self, code: int, reason: str) -> None: + print(f"WebSocket closed: code={code} reason={reason}") + self._ws_close = True + def _on_video_frame(self, frame: SoraVideoFrame) -> None: self._q_out.put(frame) diff --git a/uv.lock b/uv.lock index c9b3a08..3581ded 100644 --- a/uv.lock +++ b/uv.lock @@ -239,41 +239,41 @@ wheels = [ [[package]] name = "ruff" -version = "0.6.5" +version = "0.6.8" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/3f/29b2d3d90f811f6fb5b90242309f4668cd8c2482aab86ffc23099000545b/ruff-0.6.5.tar.gz", hash = "sha256:4d32d87fab433c0cf285c3683dd4dae63be05fd7a1d65b3f5bf7cdd05a6b96fb", size = 2476127 } +sdist = { url = "https://files.pythonhosted.org/packages/74/f9/4ce3e765a72ab8fe0f80f48508ea38b4196daab3da14d803c21349b2d367/ruff-0.6.8.tar.gz", hash = "sha256:a5bf44b1aa0adaf6d9d20f86162b34f7c593bfedabc51239953e446aefc8ce18", size = 3084543 } wheels = [ - { url = "https://files.pythonhosted.org/packages/64/05/cc62df44b5a0271b29f11d687aa89e85943e0d26e5bb773dbc1456d9885d/ruff-0.6.5-py3-none-linux_armv6l.whl", hash = "sha256:7e4e308f16e07c95fc7753fc1aaac690a323b2bb9f4ec5e844a97bb7fbebd748", size = 9770988 }, - { url = "https://files.pythonhosted.org/packages/09/3d/89dac56ab7053d5b7cba723c9cae1a29b7a2978174c67e2441525ee00343/ruff-0.6.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:932cd69eefe4daf8c7d92bd6689f7e8182571cb934ea720af218929da7bd7d69", size = 9423303 }, - { url = "https://files.pythonhosted.org/packages/70/76/dc04654d26beace866a3c9e0c87112304e3d6406e1ee8ca0d9bebbd82d91/ruff-0.6.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3a8d42d11fff8d3143ff4da41742a98f8f233bf8890e9fe23077826818f8d680", size = 9134078 }, - { url = "https://files.pythonhosted.org/packages/da/52/6a492cffcd2c6e243043937ab52811b6ebb10cb5b77a68cc98e7676ceaef/ruff-0.6.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a50af6e828ee692fb10ff2dfe53f05caecf077f4210fae9677e06a808275754f", size = 10105094 }, - { url = "https://files.pythonhosted.org/packages/59/7c/fd76a583ae59a276537d71921d616a83ec7774027d0812049afb6af8a07f/ruff-0.6.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:794ada3400a0d0b89e3015f1a7e01f4c97320ac665b7bc3ade24b50b54cb2972", size = 9542751 }, - { url = "https://files.pythonhosted.org/packages/56/5b/4e8928fa11412b16ecf7d7755fe45db6dfa7abce32841f6aec33bae3a7da/ruff-0.6.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:381413ec47f71ce1d1c614f7779d88886f406f1fd53d289c77e4e533dc6ea200", size = 10358844 }, - { url = "https://files.pythonhosted.org/packages/bd/a8/315ea8f71b111c8fb2b681c88a3e7a707d74308eb1435dc6ee3e6637a286/ruff-0.6.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:52e75a82bbc9b42e63c08d22ad0ac525117e72aee9729a069d7c4f235fc4d276", size = 11075199 }, - { url = "https://files.pythonhosted.org/packages/d9/1c/3a3728d42db52bfe418d8c913b453531766be1383719573f2458e8b59990/ruff-0.6.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09c72a833fd3551135ceddcba5ebdb68ff89225d30758027280968c9acdc7810", size = 10661186 }, - { url = "https://files.pythonhosted.org/packages/d4/0c/ae25e213461aab274822081923d747f02929d71843c42b8f56018a7ec636/ruff-0.6.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:800c50371bdcb99b3c1551d5691e14d16d6f07063a518770254227f7f6e8c178", size = 11747444 }, - { url = "https://files.pythonhosted.org/packages/c4/e3/9d0ff218c7663ab9d53abe02911bec03d32b8ced7f78c1c49c2af84903a2/ruff-0.6.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e25ddd9cd63ba1f3bd51c1f09903904a6adf8429df34f17d728a8fa11174253", size = 10266302 }, - { url = "https://files.pythonhosted.org/packages/ac/03/f158cc24120bf277b0cd7906ba509a2db74531003663500a0d1781cd7448/ruff-0.6.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7291e64d7129f24d1b0c947ec3ec4c0076e958d1475c61202497c6aced35dd19", size = 10104976 }, - { url = "https://files.pythonhosted.org/packages/91/d0/0bacdffc234e588ec05834186ad11ec8281a6ca598d0106892497bbcfa44/ruff-0.6.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9ad7dfbd138d09d9a7e6931e6a7e797651ce29becd688be8a0d4d5f8177b4b0c", size = 9625374 }, - { url = "https://files.pythonhosted.org/packages/1a/ad/721003cde8abd9f50bff74acbcb21852531036451d48a1abddba4dd84025/ruff-0.6.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:005256d977021790cc52aa23d78f06bb5090dc0bfbd42de46d49c201533982ae", size = 9959661 }, - { url = "https://files.pythonhosted.org/packages/37/84/8d70a3eacaacb65b4bb1461fc1a59e37ff165152b7e507692109117c877f/ruff-0.6.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:482c1e6bfeb615eafc5899127b805d28e387bd87db38b2c0c41d271f5e58d8cc", size = 10327408 }, - { url = "https://files.pythonhosted.org/packages/54/7e/6b0a9ab30428a9e3d9607f6dd2e4fb743594d42bd1b6ba7b7b239acda921/ruff-0.6.5-py3-none-win32.whl", hash = "sha256:cf4d3fa53644137f6a4a27a2b397381d16454a1566ae5335855c187fbf67e4f5", size = 8012512 }, - { url = "https://files.pythonhosted.org/packages/d8/88/176f50162a219e3039f21e9e4323869fc62bf8d3afb4147a390d6c744bd8/ruff-0.6.5-py3-none-win_amd64.whl", hash = "sha256:3e42a57b58e3612051a636bc1ac4e6b838679530235520e8f095f7c44f706ff9", size = 8804438 }, - { url = "https://files.pythonhosted.org/packages/67/a0/1b488bbe35a7ff8296fdea1ec1a9c2676cecc7e42bda63860f9397d59140/ruff-0.6.5-py3-none-win_arm64.whl", hash = "sha256:51935067740773afdf97493ba9b8231279e9beef0f2a8079188c4776c25688e0", size = 8179780 }, + { url = "https://files.pythonhosted.org/packages/db/07/42ee57e8b76ca585297a663a552b4f6d6a99372ca47fdc2276ef72cc0f2f/ruff-0.6.8-py3-none-linux_armv6l.whl", hash = "sha256:77944bca110ff0a43b768f05a529fecd0706aac7bcce36d7f1eeb4cbfca5f0f2", size = 10404327 }, + { url = "https://files.pythonhosted.org/packages/eb/51/d42571ff8156d65086acb72d39aa64cb24181db53b497d0ed6293f43f07a/ruff-0.6.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:27b87e1801e786cd6ede4ada3faa5e254ce774de835e6723fd94551464c56b8c", size = 10018797 }, + { url = "https://files.pythonhosted.org/packages/c1/d7/fa5514a60b03976af972b67fe345deb0335dc96b9f9a9fa4df9890472427/ruff-0.6.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:cd48f945da2a6334f1793d7f701725a76ba93bf3d73c36f6b21fb04d5338dcf5", size = 9691303 }, + { url = "https://files.pythonhosted.org/packages/d6/c4/d812a74976927e51d0782a47539069657ac78535779bfa4d061c4fc8d89d/ruff-0.6.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:677e03c00f37c66cea033274295a983c7c546edea5043d0c798833adf4cf4c6f", size = 10719452 }, + { url = "https://files.pythonhosted.org/packages/ec/b6/aa700c4ae6db9b3ee660e23f3c7db596e2b16a3034b797704fba33ddbc96/ruff-0.6.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9f1476236b3eacfacfc0f66aa9e6cd39f2a624cb73ea99189556015f27c0bdeb", size = 10161353 }, + { url = "https://files.pythonhosted.org/packages/ea/39/0b10075ffcd52ff3a581b9b69eac53579deb230aad300ce8f9d0b58e77bc/ruff-0.6.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f5a2f17c7d32991169195d52a04c95b256378bbf0de8cb98478351eb70d526f", size = 10980630 }, + { url = "https://files.pythonhosted.org/packages/c1/af/9eb9efc98334f62652e2f9318f137b2667187851911fac3b395365a83708/ruff-0.6.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5fd0d4b7b1457c49e435ee1e437900ced9b35cb8dc5178921dfb7d98d65a08d0", size = 11768996 }, + { url = "https://files.pythonhosted.org/packages/e0/59/8b1369cf7878358952b1c0a1559b4d6b5c824c003d09b0db26d26c9d094f/ruff-0.6.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8034b19b993e9601f2ddf2c517451e17a6ab5cdb1c13fdff50c1442a7171d87", size = 11317469 }, + { url = "https://files.pythonhosted.org/packages/b9/6d/e252e9b11bbca4114c386ee41ad559d0dac13246201d77ea1223c6fea17f/ruff-0.6.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6cfb227b932ba8ef6e56c9f875d987973cd5e35bc5d05f5abf045af78ad8e098", size = 12467185 }, + { url = "https://files.pythonhosted.org/packages/48/44/7caa223af7d4ea0f0b2bd34acca65a7694a58317714675a2478815ab3f45/ruff-0.6.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ef0411eccfc3909269fed47c61ffebdcb84a04504bafa6b6df9b85c27e813b0", size = 10887766 }, + { url = "https://files.pythonhosted.org/packages/81/ed/394aff3a785f171869158b9d5be61eec9ffb823c3ad5d2bdf2e5f13cb029/ruff-0.6.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:007dee844738c3d2e6c24ab5bc7d43c99ba3e1943bd2d95d598582e9c1b27750", size = 10711609 }, + { url = "https://files.pythonhosted.org/packages/47/31/f31d04c842e54699eab7e3b864538fea26e6c94b71806cd10aa49f13e1c1/ruff-0.6.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ce60058d3cdd8490e5e5471ef086b3f1e90ab872b548814e35930e21d848c9ce", size = 10237621 }, + { url = "https://files.pythonhosted.org/packages/20/95/a764e84acf11d425f2f23b8b78b4fd715e9c20be4aac157c6414ca859a67/ruff-0.6.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1085c455d1b3fdb8021ad534379c60353b81ba079712bce7a900e834859182fa", size = 10558329 }, + { url = "https://files.pythonhosted.org/packages/2a/76/d4e38846ac9f6dd62dce858a54583911361b5339dcf8f84419241efac93a/ruff-0.6.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:70edf6a93b19481affd287d696d9e311388d808671bc209fb8907b46a8c3af44", size = 10954102 }, + { url = "https://files.pythonhosted.org/packages/e7/36/f18c678da6c69f8d022480f3e8ddce6e4a52e07602c1d212056fbd234f8f/ruff-0.6.8-py3-none-win32.whl", hash = "sha256:792213f7be25316f9b46b854df80a77e0da87ec66691e8f012f887b4a671ab5a", size = 8511090 }, + { url = "https://files.pythonhosted.org/packages/4c/c4/0ca7d8ffa358b109db7d7d045a1a076fd8e5d9cbeae022242d3c060931da/ruff-0.6.8-py3-none-win_amd64.whl", hash = "sha256:ec0517dc0f37cad14a5319ba7bba6e7e339d03fbf967a6d69b0907d61be7a263", size = 9350079 }, + { url = "https://files.pythonhosted.org/packages/d9/bd/a8b0c64945a92eaeeb8d0283f27a726a776a1c9d12734d990c5fc7a1278c/ruff-0.6.8-py3-none-win_arm64.whl", hash = "sha256:8d3bb2e3fbb9875172119021a13eed38849e762499e3cfde9588e4b4d70968dc", size = 8669595 }, ] [[package]] name = "setuptools" -version = "75.0.0" +version = "75.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a7/17/133e1cd1e24373e1898ca3c7330f5c385b46c7091f0451e678f37245591b/setuptools-75.0.0.tar.gz", hash = "sha256:25af69c809d9334cd8e653d385277abeb5a102dca255954005a7092d282575ea", size = 1347819 } +sdist = { url = "https://files.pythonhosted.org/packages/27/b8/f21073fde99492b33ca357876430822e4800cdf522011f18041351dfa74b/setuptools-75.1.0.tar.gz", hash = "sha256:d59a21b17a275fb872a9c3dae73963160ae079f1049ed956880cd7c09b120538", size = 1348057 } wheels = [ - { url = "https://files.pythonhosted.org/packages/8e/69/f90971743a7cc451b93be8f5eb60b7e506896b7e81e6be6272858b2a9d46/setuptools-75.0.0-py3-none-any.whl", hash = "sha256:791ae94f04f78c880b5e614e560dd32d4b4af5d151bd9e7483e3377846caf90a", size = 1248237 }, + { url = "https://files.pythonhosted.org/packages/ff/ae/f19306b5a221f6a436d8f2238d5b80925004093fa3edea59835b514d9057/setuptools-75.1.0-py3-none-any.whl", hash = "sha256:35ab7fd3bcd95e6b7fd704e4a1539513edad446c097797f2985e0e4b960772f2", size = 1248506 }, ] [[package]] name = "sora-sdk" -version = "2024.4.0.dev5" +version = "2024.4.0.dev8" source = { editable = "." } [package.dev-dependencies]