refactor: switch Mumble voice to pymumble transport
asyncio's SSL memory-BIO transport silently drops voice packets even though text works fine. pymumble uses blocking ssl.SSLSocket.send() which reliably delivers voice data. - Rewrite MumbleBot to use pymumble for connection, SSL, ping, and voice encoding/sending - Bridge pymumble thread callbacks to asyncio via run_coroutine_threadsafe for text dispatch - Voice via sound_output.add_sound(pcm) -- pymumble handles Opus encoding, packetization, and timing - Remove custom protobuf codec, voice varint, and opus ctypes wrapper - Add container patches for pymumble ssl.wrap_socket (Python 3.13) and opuslib find_library (musl/Alpine) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
45
patches/apply_pymumble_ssl.py
Normal file
45
patches/apply_pymumble_ssl.py
Normal file
@@ -0,0 +1,45 @@
|
||||
"""Patch pymumble deps for Python 3.13+ / musl (Alpine).
|
||||
|
||||
1. pymumble: ssl.wrap_socket was removed in 3.13
|
||||
2. opuslib: ctypes.util.find_library fails on musl-based distros
|
||||
"""
|
||||
|
||||
import pathlib
|
||||
import sysconfig
|
||||
|
||||
site = sysconfig.get_path("purelib")
|
||||
|
||||
# -- pymumble: replace ssl.wrap_socket with SSLContext --
|
||||
p = pathlib.Path(f"{site}/pymumble_py3/mumble.py")
|
||||
src = p.read_text()
|
||||
|
||||
old = """\
|
||||
try:
|
||||
self.control_socket = ssl.wrap_socket(std_sock, certfile=self.certfile, keyfile=self.keyfile, ssl_version=ssl.PROTOCOL_TLS)
|
||||
except AttributeError:
|
||||
self.control_socket = ssl.wrap_socket(std_sock, certfile=self.certfile, keyfile=self.keyfile, ssl_version=ssl.PROTOCOL_TLSv1)
|
||||
try:"""
|
||||
|
||||
new = """\
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
if self.certfile:
|
||||
ctx.load_cert_chain(certfile=self.certfile, keyfile=self.keyfile)
|
||||
self.control_socket = ctx.wrap_socket(std_sock, server_hostname=self.host)
|
||||
try:"""
|
||||
|
||||
assert old in src, "pymumble ssl patch target not found"
|
||||
p.write_text(src.replace(old, new))
|
||||
print("pymumble ssl patch applied")
|
||||
|
||||
# -- opuslib: find_library fails on musl, use direct CDLL fallback --
|
||||
p = pathlib.Path(f"{site}/opuslib/api/__init__.py")
|
||||
src = p.read_text()
|
||||
|
||||
old_opus = "lib_location = find_library('opus')"
|
||||
new_opus = "lib_location = find_library('opus') or 'libopus.so.0'"
|
||||
|
||||
assert old_opus in src, "opuslib find_library patch target not found"
|
||||
p.write_text(src.replace(old_opus, new_opus))
|
||||
print("opuslib musl patch applied")
|
||||
Reference in New Issue
Block a user