Hello everyone,
I’ve noticed that when a USB audio speaker is disconnected while a pipeline is running, it results in increased CPU and memory usage.
With GST_DEBUG=3, I can see the following error that can be caught in a bus error handler:
alsa gstalsasink.c:1112_alsasink_write:<alsasink0> error: Error outputting to audio device. The device has been disconnected.
However, if I don’t stop the program at this point, the CPU and memory usage continue to increase. Assuming that I also have video content to display, I don’t want the program to stop if the USB speaker is disconnected. Instead, should I explicitly discard the audio samples in some way, or is there a memory leak that needs to be addressed?
Here’s the Python code I’m using to reproduce this issue. Run it and unplug your USB speaker to see the problem in action ![]()
import gi
gi.require_version("Gst", "1.0")
from gi.repository import Gst
def main() -> None:
Gst.init(None)
pipeline = Gst.Pipeline.new()
audio = Gst.ElementFactory.make("audiotestsrc")
audio_sink = Gst.ElementFactory.make("alsasink")
# change with your device id
audio_sink.set_property("device", "hw:2,0")
video = Gst.ElementFactory.make("videotestsrc")
video_sink = Gst.ElementFactory.make("autovideosink")
if not pipeline or not audio or not audio_sink or not video or not video_sink:
print("Not all elements could be created.")
exit(-1)
pipeline.add(audio)
pipeline.add(audio_sink)
audio.link(audio_sink)
pipeline.add(video)
pipeline.add(video_sink)
video.link(video_sink)
ret = pipeline.set_state(Gst.State.PLAYING)
if ret == Gst.StateChangeReturn.FAILURE:
print("Error starting playback.")
exit(-1)
# Wait until error or EOS
bus = pipeline.get_bus()
try:
while True:
msg = bus.timed_pop_filtered(10 * Gst.MSECOND, Gst.MessageType.ANY)
if msg:
if msg.type == Gst.MessageType.ERROR:
err, debug = msg.parse_error()
if "The device has been disconnected" in str(err):
# print("device disconnected")
pass
else:
print(f"Error: {err}, {debug}")
break
elif msg.type == Gst.MessageType.EOS:
print("End-Of-Stream reached.")
break
# else:
# print(f"Message: {msg.type}")
except KeyboardInterrupt:
print("User exit")
finally:
pipeline.set_state(Gst.State.NULL)
Gst.deinit()
if __name__ == "__main__":
main()