getstream 3.3.3__tar.gz → 3.3.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. {getstream-3.3.3 → getstream-3.3.4}/PKG-INFO +1 -1
  2. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/encoders_patches.py +54 -8
  3. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pc.py +7 -6
  4. {getstream-3.3.3 → getstream-3.3.4}/.cursor/worktrees.json +0 -0
  5. {getstream-3.3.3 → getstream-3.3.4}/.env.example +0 -0
  6. {getstream-3.3.3 → getstream-3.3.4}/.github/actions/python-uv-setup/action.yml +0 -0
  7. {getstream-3.3.3 → getstream-3.3.4}/.github/workflows/ci.yml +0 -0
  8. {getstream-3.3.3 → getstream-3.3.4}/.github/workflows/release.yml +0 -0
  9. {getstream-3.3.3 → getstream-3.3.4}/.github/workflows/run_tests.yml +0 -0
  10. {getstream-3.3.3 → getstream-3.3.4}/.github/workflows/stream-py.code-workspace +0 -0
  11. {getstream-3.3.3 → getstream-3.3.4}/.gitignore +0 -0
  12. {getstream-3.3.3 → getstream-3.3.4}/.gitmodules +0 -0
  13. {getstream-3.3.3 → getstream-3.3.4}/.pre-commit-config.yaml +0 -0
  14. {getstream-3.3.3 → getstream-3.3.4}/AGENTS.md +0 -0
  15. {getstream-3.3.3 → getstream-3.3.4}/CHANGELOG.md +0 -0
  16. {getstream-3.3.3 → getstream-3.3.4}/DEVELOPMENT.md +0 -0
  17. {getstream-3.3.3 → getstream-3.3.4}/LICENSE.md +0 -0
  18. {getstream-3.3.3 → getstream-3.3.4}/MIGRATION_v2_to_v3.md +0 -0
  19. {getstream-3.3.3 → getstream-3.3.4}/Makefile +0 -0
  20. {getstream-3.3.3 → getstream-3.3.4}/README.md +0 -0
  21. {getstream-3.3.3 → getstream-3.3.4}/dev.py +0 -0
  22. {getstream-3.3.3 → getstream-3.3.4}/docs/migration-from-stream-chat-python/01-setup-and-auth.md +0 -0
  23. {getstream-3.3.3 → getstream-3.3.4}/docs/migration-from-stream-chat-python/02-users.md +0 -0
  24. {getstream-3.3.3 → getstream-3.3.4}/docs/migration-from-stream-chat-python/03-channels.md +0 -0
  25. {getstream-3.3.3 → getstream-3.3.4}/docs/migration-from-stream-chat-python/04-messages-and-reactions.md +0 -0
  26. {getstream-3.3.3 → getstream-3.3.4}/docs/migration-from-stream-chat-python/05-moderation.md +0 -0
  27. {getstream-3.3.3 → getstream-3.3.4}/docs/migration-from-stream-chat-python/06-devices.md +0 -0
  28. {getstream-3.3.3 → getstream-3.3.4}/docs/migration-from-stream-chat-python/README.md +0 -0
  29. {getstream-3.3.3 → getstream-3.3.4}/generate.sh +0 -0
  30. {getstream-3.3.3 → getstream-3.3.4}/generate_webrtc.sh +0 -0
  31. {getstream-3.3.3 → getstream-3.3.4}/getstream/__init__.py +0 -0
  32. {getstream-3.3.3 → getstream-3.3.4}/getstream/base.py +0 -0
  33. {getstream-3.3.3 → getstream-3.3.4}/getstream/chat/__init__.py +0 -0
  34. {getstream-3.3.3 → getstream-3.3.4}/getstream/chat/async_channel.py +0 -0
  35. {getstream-3.3.3 → getstream-3.3.4}/getstream/chat/async_client.py +0 -0
  36. {getstream-3.3.3 → getstream-3.3.4}/getstream/chat/async_rest_client.py +0 -0
  37. {getstream-3.3.3 → getstream-3.3.4}/getstream/chat/channel.py +0 -0
  38. {getstream-3.3.3 → getstream-3.3.4}/getstream/chat/client.py +0 -0
  39. {getstream-3.3.3 → getstream-3.3.4}/getstream/chat/rest_client.py +0 -0
  40. {getstream-3.3.3 → getstream-3.3.4}/getstream/common/__init__.py +0 -0
  41. {getstream-3.3.3 → getstream-3.3.4}/getstream/common/async_client.py +0 -0
  42. {getstream-3.3.3 → getstream-3.3.4}/getstream/common/async_rest_client.py +0 -0
  43. {getstream-3.3.3 → getstream-3.3.4}/getstream/common/client.py +0 -0
  44. {getstream-3.3.3 → getstream-3.3.4}/getstream/common/rest_client.py +0 -0
  45. {getstream-3.3.3 → getstream-3.3.4}/getstream/common/telemetry.py +0 -0
  46. {getstream-3.3.3 → getstream-3.3.4}/getstream/config.py +0 -0
  47. {getstream-3.3.3 → getstream-3.3.4}/getstream/feeds/__init__.py +0 -0
  48. {getstream-3.3.3 → getstream-3.3.4}/getstream/feeds/client.py +0 -0
  49. {getstream-3.3.3 → getstream-3.3.4}/getstream/feeds/feeds.py +0 -0
  50. {getstream-3.3.3 → getstream-3.3.4}/getstream/feeds/rest_client.py +0 -0
  51. {getstream-3.3.3 → getstream-3.3.4}/getstream/generic.py +0 -0
  52. {getstream-3.3.3 → getstream-3.3.4}/getstream/meta.py +0 -0
  53. {getstream-3.3.3 → getstream-3.3.4}/getstream/models/__init__.py +0 -0
  54. {getstream-3.3.3 → getstream-3.3.4}/getstream/moderation/__init__.py +0 -0
  55. {getstream-3.3.3 → getstream-3.3.4}/getstream/moderation/async_client.py +0 -0
  56. {getstream-3.3.3 → getstream-3.3.4}/getstream/moderation/async_rest_client.py +0 -0
  57. {getstream-3.3.3 → getstream-3.3.4}/getstream/moderation/client.py +0 -0
  58. {getstream-3.3.3 → getstream-3.3.4}/getstream/moderation/rest_client.py +0 -0
  59. {getstream-3.3.3 → getstream-3.3.4}/getstream/rate_limit.py +0 -0
  60. {getstream-3.3.3 → getstream-3.3.4}/getstream/stream.py +0 -0
  61. {getstream-3.3.3 → getstream-3.3.4}/getstream/stream_response.py +0 -0
  62. {getstream-3.3.3 → getstream-3.3.4}/getstream/tests/test_webhook.py +0 -0
  63. {getstream-3.3.3 → getstream-3.3.4}/getstream/utils/__init__.py +0 -0
  64. {getstream-3.3.3 → getstream-3.3.4}/getstream/utils/event_emitter.py +0 -0
  65. {getstream-3.3.3 → getstream-3.3.4}/getstream/utils/retry.py +0 -0
  66. {getstream-3.3.3 → getstream-3.3.4}/getstream/version.py +0 -0
  67. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/__init__.py +0 -0
  68. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/async_call.py +0 -0
  69. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/async_client.py +0 -0
  70. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/async_rest_client.py +0 -0
  71. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/call.py +0 -0
  72. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/client.py +0 -0
  73. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/openai.py +0 -0
  74. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rest_client.py +0 -0
  75. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/README.md +0 -0
  76. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/__init__.py +0 -0
  77. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/audio_track.py +0 -0
  78. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/connection_manager.py +0 -0
  79. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/connection_utils.py +0 -0
  80. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/coordinator/__init__.py +0 -0
  81. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/coordinator/backoff.py +0 -0
  82. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/coordinator/errors.py +0 -0
  83. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/coordinator/ws.py +0 -0
  84. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/coordinator_api.py +0 -0
  85. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/g711.py +0 -0
  86. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/location_discovery.py +0 -0
  87. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/models.py +0 -0
  88. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/network_monitor.py +0 -0
  89. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/participants.py +0 -0
  90. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/__init__.py +0 -0
  91. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/__init__.py +0 -0
  92. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/video/__init__.py +0 -0
  93. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/video/sfu/__init__.py +0 -0
  94. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/video/sfu/event/__init__.py +0 -0
  95. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/video/sfu/event/events_pb2.py +0 -0
  96. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/video/sfu/event/events_pb2.pyi +0 -0
  97. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/video/sfu/models/__init__.py +0 -0
  98. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/video/sfu/models/models_pb2.py +0 -0
  99. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/video/sfu/models/models_pb2.pyi +0 -0
  100. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/__init__.py +0 -0
  101. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_pb2.py +0 -0
  102. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_pb2.pyi +0 -0
  103. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_twirp.py +0 -0
  104. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/peer_connection.py +0 -0
  105. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/reconnection.py +0 -0
  106. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/recording.py +0 -0
  107. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/signaling.py +0 -0
  108. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/stats_reporter.py +0 -0
  109. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/stats_tracer.py +0 -0
  110. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/tracer.py +0 -0
  111. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/track_util.py +0 -0
  112. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/tracks.py +0 -0
  113. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/twirp_client_wrapper.py +0 -0
  114. {getstream-3.3.3 → getstream-3.3.4}/getstream/video/rtc/utils.py +0 -0
  115. {getstream-3.3.3 → getstream-3.3.4}/getstream/webhook.py +0 -0
  116. {getstream-3.3.3 → getstream-3.3.4}/pyproject.toml +0 -0
  117. {getstream-3.3.3 → getstream-3.3.4}/pytest.ini +0 -0
  118. {getstream-3.3.3 → getstream-3.3.4}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: getstream
3
- Version: 3.3.3
3
+ Version: 3.3.4
4
4
  Summary: GetStream Python SDK - Build scalable activity feeds, chat, and video calling applications
5
5
  Author-email: sachaarbonel <sacha.arbonel@hotmail.fr>, tbarbugli <tbarbugli@gmail.com>
6
6
  License-File: LICENSE.md
@@ -1,8 +1,11 @@
1
+ import fractions
1
2
  import logging
2
3
  import os
3
4
  from typing import Optional
4
5
 
6
+ import av
5
7
  from aiortc import RTCRtpCodecParameters
8
+ from aiortc.codecs.h264 import MAX_FRAME_RATE as H264_MAX_FRAME_RATE
6
9
  from aiortc.codecs.h264 import H264Encoder
7
10
  from aiortc.codecs.vpx import Vp8Encoder
8
11
  from aiortc.rtcrtpsender import RTCEncodedFrame, RTCRtpSender
@@ -26,6 +29,11 @@ BITRATE_PATCH_DISABLED = os.getenv(
26
29
  "off",
27
30
  )
28
31
 
32
+ # libx264 preset for the StreamH264Encoder. Defaults to "ultrafast" for
33
+ # real-time CPU; can be raised (e.g. "veryfast", "medium") for better
34
+ # quality-per-bit at the cost of more CPU per frame.
35
+ STREAM_H264_PRESET = os.getenv("STREAM_PATCH_AIORTC_H264_PRESET", "ultrafast").strip()
36
+
29
37
 
30
38
  try:
31
39
  # Verify the name-mangled attributes we depend on still exist.
@@ -51,11 +59,13 @@ try:
51
59
  self._Vp8Encoder__target_bitrate = bitrate
52
60
 
53
61
  class StreamH264Encoder(H264Encoder):
54
- """H264Encoder subclass with higher bitrate bounds for Stream calls."""
62
+ """H264Encoder subclass with higher bitrate bounds and a real-time
63
+ libx264 preset for Stream calls."""
55
64
 
56
65
  def __init__(self) -> None:
57
66
  super().__init__()
58
67
  self._H264Encoder__target_bitrate = STREAM_VIDEO_DEFAULT_BITRATE
68
+ self.preset = STREAM_H264_PRESET
59
69
 
60
70
  @property
61
71
  def target_bitrate(self) -> int:
@@ -68,10 +78,45 @@ try:
68
78
  )
69
79
  self._H264Encoder__target_bitrate = bitrate
70
80
 
81
+ def _encode_frame(self, frame, force_keyframe):
82
+ # Mirror parent's invalidation policy so we own codec creation in
83
+ # both first-init AND recreation (resolution/bitrate change) paths;
84
+ # otherwise parent's `if self.codec is None` branch silently
85
+ # reverts our preset to libx264's default `medium`.
86
+ codec = self.codec
87
+ if (
88
+ codec is not None
89
+ and codec.bit_rate
90
+ and (
91
+ frame.width != codec.width
92
+ or frame.height != codec.height
93
+ or abs(self.target_bitrate - codec.bit_rate) / codec.bit_rate > 0.1
94
+ )
95
+ ):
96
+ self.buffer_data = b""
97
+ self.buffer_pts = None
98
+ self.codec = None
99
+
100
+ if self.codec is None:
101
+ self.codec = av.CodecContext.create("libx264", "w")
102
+ self.codec.width = frame.width
103
+ self.codec.height = frame.height
104
+ self.codec.bit_rate = self.target_bitrate
105
+ self.codec.pix_fmt = "yuv420p"
106
+ self.codec.framerate = fractions.Fraction(H264_MAX_FRAME_RATE, 1)
107
+ self.codec.time_base = fractions.Fraction(1, H264_MAX_FRAME_RATE)
108
+ self.codec.options = {
109
+ "level": "31",
110
+ "tune": "zerolatency",
111
+ "preset": self.preset,
112
+ }
113
+ self.codec.profile = "Baseline"
114
+ yield from super()._encode_frame(frame, force_keyframe)
115
+
71
116
  except Exception:
72
117
  logger.warning(
73
- "Failed to patch aiortc video encoder subclasses with Stream bitrate values (aiortc internals may have changed), "
74
- "falling back to default aiortc bitrates. \n"
118
+ "Failed to patch aiortc encoder subclasses with Stream values (aiortc internals may have changed), "
119
+ "falling back to default aiortc encoders. \n"
75
120
  "Set STREAM_PATCH_AIORTC_BITRATES=0 to disable patching.",
76
121
  exc_info=True,
77
122
  )
@@ -80,10 +125,11 @@ except Exception:
80
125
 
81
126
 
82
127
  def patch_sender_encoder(sender: RTCRtpSender) -> None:
83
- """Patch a video sender to use Stream's higher-bitrate encoders.
128
+ """Patch a sender to use Stream's tuned encoders for the negotiated codec.
84
129
 
85
- If anything goes wrong (e.g. aiortc internals changed), the sender
86
- is left untouched and will use the stock encoder via get_encoder().
130
+ Works for video (VP8/H264) senders. If anything
131
+ goes wrong (e.g. aiortc internals changed), the sender is left untouched
132
+ and will use the stock encoder via get_encoder().
87
133
  """
88
134
  if StreamVp8Encoder is None or StreamH264Encoder is None:
89
135
  return
@@ -105,8 +151,8 @@ def patch_sender_encoder(sender: RTCRtpSender) -> None:
105
151
  sender._next_encoded_frame = _next_with_stream_encoder # type: ignore[method-assign]
106
152
  except Exception:
107
153
  logger.warning(
108
- "Failed to patch aiortc video encoder subclasses with Stream bitrate values (aiortc internals may have changed), "
109
- "falling back to default aiortc bitrates. \n"
154
+ "Failed to patch aiortc encoder subclasses with Stream values (aiortc internals may have changed), "
155
+ "falling back to default aiortc encoders. \n"
110
156
  "Set STREAM_PATCH_AIORTC_BITRATES=0 to disable patching.",
111
157
  exc_info=True,
112
158
  )
@@ -53,10 +53,6 @@ class PublisherPeerConnection(aiortc.RTCPeerConnection):
53
53
  self._closed = False
54
54
  self._connected_event = asyncio.Event()
55
55
 
56
- for transceiver in self.getTransceivers():
57
- if transceiver.kind == "video":
58
- transceiver.setCodecPreferences(publish_codec_preferences())
59
-
60
56
  @self.on("icegatheringstatechange")
61
57
  def on_icegatheringstatechange():
62
58
  logger.info(
@@ -79,8 +75,13 @@ class PublisherPeerConnection(aiortc.RTCPeerConnection):
79
75
 
80
76
  def addTrack(self, track: MediaStreamTrack) -> RTCRtpSender:
81
77
  sender = super().addTrack(track)
82
- if track.kind == "video" and not BITRATE_PATCH_DISABLED:
83
- patch_sender_encoder(sender)
78
+ if track.kind == "video":
79
+ for transceiver in self.getTransceivers():
80
+ if transceiver.sender is sender:
81
+ transceiver.setCodecPreferences(publish_codec_preferences())
82
+ break
83
+ if not BITRATE_PATCH_DISABLED:
84
+ patch_sender_encoder(sender)
84
85
  return sender
85
86
 
86
87
  async def handle_answer(self, response):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes