是否可以在 Google Cloud 上使用 Docker 部署的 Python Web 应用程序中生成声音?
我构建了一个简单的网络应用程序,它应该测试用户的听力频率范围。它构建在 JustPy 框架中,使用 pysinewave(又基于 sounddevice)连续生成声音。我已将其部署在 Google Cloud 上的 Docker 容器中,网站部分工作正常,但声音生成部分导致问题。以下是调试器输出的一部分:
500 Server Error
PortAudioError: Error querying device -1
Traceback
File /usr/local/lib/python3.10/site-packages/sounddevice.py, line 564, in query_devices ‒
561. device = _get_device_id(device, kind, raise_on_error=True)
562. info = _lib.Pa_GetDeviceInfo(device)
563. if not info:
564. raise PortAudioError('Error querying device {}'.format(device))
565. assert info.structVersion == 2
566. name_bytes = _ffi.string(info.name)
567. try:
File /usr/local/lib/python3.10/site-packages/sounddevice.py, line 2654, in _get_stream_parameters ‒
2651. samplerate = default.samplerate
2652.
2653. device = _get_device_id(device, kind, raise_on_error=True)
2654. info = query_devices(device)
2655. if channels is None:
2656. channels = info['max_' + kind + '_channels']
2657. try:
File /usr/local/lib/python3.10/site-packages/sounddevice.py, line 811, in __init__ ‒
808. samplerate = isamplerate
809. else:
810. parameters, self._dtype, self._samplesize, samplerate = \
811. _get_stream_parameters(kind, device, channels, dtype, latency,
812. extra_settings, samplerate)
813. self._device = parameters.device
814. self._channels = parameters.channelCount
File /usr/local/lib/python3.10/site-packages/sounddevice.py, line 1488, in __init__ ‒
1485. Stream, RawOutputStream
1486.
1487.
1488. _StreamBase.__init__(self, kind='output', wrap_callback='array',
1489. **_remove_self(locals()))
1490.
1491. def write(self, data):
File /usr/local/lib/python3.10/site-packages/pysinewave/sinewave.py, line 21, in __init__ ‒
18. samplerate=samplerate)
19.
20. # Create the output stream
21. self.output_stream = sd.OutputStream(channels=1, callback= lambda *args: self._callback(*args),
22. samplerate=samplerate)
23.
24. def _callback(self, outdata, frames, time, status):
File /app/./soundgen.py, line 7, in __init__ ‒
4. class SoundGen(SineWave):
5.
6. def __init__(self, freq, vol):
7. super().__init__(pitch=9, pitch_per_second=10000, decibels=-30, decibels_per_second=10000)
8. self.set_frequency(freq)
9. self.set_volume(vol)
10. self.volume = self.sinewave_generator.amplitude
File /app/./main.py, line 23, in serve ‒
20. def serve(cls, req):
21.
22. # sine wave generator
23. sound = SoundGen(440, 0.15)
24.
25. freq_dict = cls.gen_freq_dict()
26.
我已在 Dockerfile
中使用以下命令安装了其他库(基于 这个线程):
RUN apt-get update
RUN apt-get install libasound-dev libportaudio2 libportaudiocpp0 portaudio19-dev -y
但显然,这还不够。我是否缺少一个重要的库来实现此功能,或者这种功能(通过远程服务器上托管的 Web 应用程序在用户浏览器中生成声音)是否无法以这种方式实现?
重申一下:该应用程序在本地运行时完全可以正常工作,并且使用 JustPy 生成的前端部分(禁用声音功能)在部署在 Google Cloud 上时也可以正常工作。
我将非常感谢您的建议。
I have built a simple web application, which is supposed to test hearing frequency range of the user. It is built in JustPy framework and it uses pysinewave
(in turn based on sounddevice
) to generate sound continuously. I have deployed it in a Docker container on Google Cloud and the website part works just fine, but the sound-generating part is causing problems. Below is a part of debugger output:
500 Server Error
PortAudioError: Error querying device -1
Traceback
File /usr/local/lib/python3.10/site-packages/sounddevice.py, line 564, in query_devices ‒
561. device = _get_device_id(device, kind, raise_on_error=True)
562. info = _lib.Pa_GetDeviceInfo(device)
563. if not info:
564. raise PortAudioError('Error querying device {}'.format(device))
565. assert info.structVersion == 2
566. name_bytes = _ffi.string(info.name)
567. try:
File /usr/local/lib/python3.10/site-packages/sounddevice.py, line 2654, in _get_stream_parameters ‒
2651. samplerate = default.samplerate
2652.
2653. device = _get_device_id(device, kind, raise_on_error=True)
2654. info = query_devices(device)
2655. if channels is None:
2656. channels = info['max_' + kind + '_channels']
2657. try:
File /usr/local/lib/python3.10/site-packages/sounddevice.py, line 811, in __init__ ‒
808. samplerate = isamplerate
809. else:
810. parameters, self._dtype, self._samplesize, samplerate = \
811. _get_stream_parameters(kind, device, channels, dtype, latency,
812. extra_settings, samplerate)
813. self._device = parameters.device
814. self._channels = parameters.channelCount
File /usr/local/lib/python3.10/site-packages/sounddevice.py, line 1488, in __init__ ‒
1485. Stream, RawOutputStream
1486.
1487.
1488. _StreamBase.__init__(self, kind='output', wrap_callback='array',
1489. **_remove_self(locals()))
1490.
1491. def write(self, data):
File /usr/local/lib/python3.10/site-packages/pysinewave/sinewave.py, line 21, in __init__ ‒
18. samplerate=samplerate)
19.
20. # Create the output stream
21. self.output_stream = sd.OutputStream(channels=1, callback= lambda *args: self._callback(*args),
22. samplerate=samplerate)
23.
24. def _callback(self, outdata, frames, time, status):
File /app/./soundgen.py, line 7, in __init__ ‒
4. class SoundGen(SineWave):
5.
6. def __init__(self, freq, vol):
7. super().__init__(pitch=9, pitch_per_second=10000, decibels=-30, decibels_per_second=10000)
8. self.set_frequency(freq)
9. self.set_volume(vol)
10. self.volume = self.sinewave_generator.amplitude
File /app/./main.py, line 23, in serve ‒
20. def serve(cls, req):
21.
22. # sine wave generator
23. sound = SoundGen(440, 0.15)
24.
25. freq_dict = cls.gen_freq_dict()
26.
I have installed additional libraries with the following commands in Dockerfile
(based on the answer in this thread):
RUN apt-get update
RUN apt-get install libasound-dev libportaudio2 libportaudiocpp0 portaudio19-dev -y
But clearly, this is not enough. Am I missing an important library for this to work, or is this kind of functionality - generating sound in user's browser through a web application hosted on a remote server - just impossible to achieve in this manner?
To reiterate: the application works completely fine when run locally, and the frontend part generated with JustPy (with the sound functionality disabled) also works fine when deployed on Google Cloud.
I would be extremely grateful for suggestions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在我看来,您想在用户的设备上部署一个播放音频的Web应用程序。当您将应用程序托管在云上时,运行应用程序的服务器将是后端端,您使用了
soundgen
类。当您触发声音时,它会搜索音频设备 - 云服务器中不可用,因此会引发异常。如果您在您的计算机上托管了应用程序时,Docker运行时可以访问您的音频外围设备并播放想要的声音。您可能想做的是将声音生成从后端代码中移出并进入前端部分。在触发器上(例如,单击按钮),仅使用前端代码在客户端的设备 - 浏览器上播放您想要的声音。不幸的是,我不熟悉Justpy,所以我不能为您编写示例代码,但是希望这仍然有所帮助。
It seems to me that you want to deploy a web app that plays audio on the user's device. When you host your app on the cloud, the server that runs your app will be the backend side, where you have used your
SoundGen
class. When you trigger it to make the sound, it searches for audio devices - that is not available in the cloud server, therefore it throws the exception.In the case when you have hosted your app on your computer, the docker runtime was able to access your audio peripherals and play the sound you wanted. What you might want to do instead is to move the sound generation out of the backend code and into the frontend part. On trigger (eg. button click), use only frontend code to play the sound you wanted on the client's device - the browser. Unfortunately, I am unfamiliar with JustPy, so I cannot write an example code for you, but hopefully, this still helped.