community
community copied to clipboard
ffpyplayer crashes on Linux after a number of files played
Software Versions
- Python: 3.8 and 3.10
- OS: Ubuntu 18.04 and Ubuntu 22.04
- Kivy: 2.1.0, 2.2.0, 2.2.1
- Kivy installation method: pip and compiled from source on the platforms
Describe the bug When playing a ogg sound file while using ffpyplayer as the audio provider after 15 times playing the ffpyplayer will crash:
[WARNING] [ffpyplayer ] [ffpyplayer_abuffersink @ 0x7f99b0006a80] Removing channel layout 0x4, redundant with 1 channels [WARNING] [ffpyplayer ] [ffpyplayer_abuffersink @ 0x7f99b001fac0] Removing channel layout 0x4, redundant with 1 channels
[WARNING] [ffpyplayer ] SDL_OpenAudio (1 channels, 48000 Hz): Too many open audio devices [WARNING] [ffpyplayer ] SDL_OpenAudio (1 channels, 44100 Hz): Too many open audio devices [ERROR ] [ffpyplayer ] No more channel combinations to try, audio open failed [CRITICAL] [ffpyplayer ] Failed to open file '/mnt/nvme0n1p1/Github/btp-kivy/test_opus.ogg' or configure filtergraph
A way to prevent the crash is to unload the file after it played. See also the test code below.
It doesn't matter if we install kivy with pip on python 3.8 or 3.10 or compile kivy for those platforms. Ffpyplayer will always crash after a few times playing if you don't unload the file. We also tried using different versions of ffmpeg but it makes no difference. This problem occurs on all kind of hardware, we have thousands of systems in use in about 10 different hardware configurations and all experiences this problem if we don't unload the sound after playing. This was also the reason we compiled our own kivy with gstreamer support the last few years but unfortunately newer python/kivy versions don't compile anymore with gtreamer support on Ubuntu 22.04 so we needed a hack to prevent the ffpyplayer from crashing.
Expected behavior Don't crash ;-)
To Reproduce Use the provided code example but just playing a file more then 15 times will also crash ffpyplayer. I couldn't attached the code and the test ogg file. The ogg file is a opus ogg produced by google TTS. But the crash will also happen with any other ogg/mp3 file. Run the code as is, with 'do_unload' set to False. Setting the 'do_unload' to True will prevent the crash.
Code and Logs and screenshots The test code starts with playing without unloading and when you set the global var 'do_unload' to True it will start and unload each file after it plays.
soundfile = 'test_opus.ogg'
do_unload = True
import os
os.environ['KIVY_NO_FILELOG'] = "1"
os.environ['KIVY_GL_BACKEND'] = 'sdl2'
os.environ['KIVY_VIDEO'] = 'ffpyplayer' #'gstplayer'
os.environ['KIVY_AUDIO'] = 'ffpyplayer' #gstplayer'
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.core.audio import SoundLoader
Builder.load_string("""
<Content>:
Button:
text: "Press me to start playing sound"
size_hint: (0.5, 0.5)
on_press: root.start_play()
""")
class Content(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.current_sound = None
def start_play(self, *args):
if self.current_sound and do_unload:
print("Unloading previous sound")
self.current_sound.unload()
self.play()
def play(self, *args):
sound = SoundLoader.load(soundfile)
self.current_sound = sound
sound.bind(on_stop=self.start_play)
sound.play()
class TestApp(App):
def build(self):
fl = Content()
return fl
TestApp().run()
Additional context This is an issue we have a couple of years now and we compiled kivy our self with gstreamer support. But as our older OS versions aren't compiling anymore with newer kivy versions we must use ffpyplayer now with the unload "fix". This way we use ffpyplayer and kivy on our thousands Ubuntu 18.04 and 22.04 systems without any issues. This problem was also discussed on the group ML: https://groups.google.com/g/kivy-users/c/m28VkNVfwpo
Is the same issue happening if you use ffpyplayer directly, without Kivy (e.g. in a cli demo script)?
That would help redirecting the issue to the proper channel (kivy or ffpyplayer)
Not sure how to use ffpyplayer directly as the docs only talk about transcoding etc and this will produce a core dump: from ffpyplayer.player import MediaPlayer player = MediaPlayer('test_opus.ogg')
Ps, the solution isn't difficult. We use a patched version of the kivy/core/audio/ffpyplayer by adding self.unload() to the 'stop' method of the SoundFFPy class. (By using from kivy.resources import resource_add_path, we patch more stuff like opencv) I can make a one line PR if you want but it's pretty trivial to fix this.
It seems the issue is more troublesome then I suspected. The unloading seems to prevent the issue but after a longer time the "Too many open devices" returned :-(
And this is on a kivy 2.2.1 compiled with gstreamer support but using ffpyplayer by setting os.environ['KIVY_AUDIO'] = 'ffpyplayer'
(Taken from a log on one of our machines)
[WARNING] [ffpyplayer ] [ffpyplayer_abuffersink @ 0x7f22280806c0] Removing channel layout 0x4, redundant with 1 channels
[WARNING] [ffpyplayer ] [ffpyplayer_abuffersink @ 0x7f222807cc00] Removing channel layout 0x4, redundant with 1 channels
[[1;36mDEBUG[0m]-2024-06-14 12:50:29,076-sp.audio.Player:56 > play: /opt/App/BtpKivy_Xf_19.2/lib/SPData/sounds/silence_1000.ogg
[DEBUG ] [play ] /opt/App/BtpKivy_Xf_19.2/lib/SPData/sounds/silence_1000.ogg
[WARNING] [ffpyplayer ] SDL_OpenAudio (2 channels, 44100 Hz): Too many open audio devices
[WARNING] [ffpyplayer ] SDL_OpenAudio (1 channels, 44100 Hz): Too many open audio devices
[ERROR ] [ffpyplayer ] No more channel combinations to try, audio open failed
We never had this issue prior to kivy 2.2.1 :-(
Looks like a (old?) ffpyplayer/sdl issue: https://github.com/matham/ffpyplayer/issues/71 It has the exact same errors