标题:音频播放,但频谱可视化未在 Flet Audio Visualizer 中显示
我正在使用 Flet 框架开发音频可视化器。声音播放正确,但频谱可视化未显示。这是我的代码:
import flet as ft
import numpy as np
from pydub import AudioSegment
from pydub.utils import make_chunks
import matplotlib.pyplot as plt
import io
import threading
import pygame
import queue
# Audio settings
sample_rate = 44100
chunk_size = 1024
class AudioVisualizer(ft.Container):
def __init__(self, file_path: str) -> None:
super().__init__()
self.file_path = file_path
self.image = ft.Image(src=io.BytesIO(), width=800, height=400)
self.page = None
self.audio_data = self.load_audio()
self.audio_queue = queue.Queue()
self.start_visualization()
def load_audio(self):
audio = AudioSegment.from_mp3(self.file_path)
audio = audio.set_frame_rate(sample_rate)
audio_data = np.array(audio.get_array_of_samples())
audio_data = audio_data / np.max(np.abs(audio_data)) # Normalize
return audio_data
def update_visualization(self, audio_data):
try:
plt.figure(figsize=(8, 4))
plt.plot(audio_data)
plt.ylim(-1, 1)
plt.gca().set_facecolor('white')
buf = io.BytesIO()
plt.savefig(buf, format='png', facecolor='white') # Set figure background to white
buf.seek(0)
self.image.src = buf
if self.page:
self.page.update() # Update the Flet image control
else:
print("Page reference is not set.")
plt.close()
except Exception as e:
print(f"Error in update_visualization: {e}")
def start_visualization(self):
try:
self.visualization_thread = threading.Thread(target=self.visualize_audio, daemon=True)
self.visualization_thread.start()
print("Visualization thread started.")
self.play_audio()
except Exception as e:
print(f"Error in start_visualization: {e}")
def visualize_audio(self):
chunks = make_chunks(self.audio_data, chunk_size)
for chunk in chunks:
self.audio_queue.put(chunk)
self.audio_queue.put(None) # Signal to stop the update loop
def play_audio(self):
try:
pygame.mixer.init()
pygame.mixer.music.load(self.file_path)
pygame.mixer.music.play()
print("Audio playback started.")
except Exception as e:
print(f"Error in play_audio: {e}")
def update_loop(self):
try:
while True:
audio_data = self.audio_queue.get()
if audio_data is None:
break
self.update_visualization(audio_data)
except Exception as e:
print(f"Error in update_loop: {e}")
def main(page: ft.Page) -> None:
try:
audio_file_path = "C:\\Users\\Administrator\\Desktop\\your_music_file.mp3"
visualizer = AudioVisualizer(audio_file_path)
visualizer.page = page
# Add controls to the page
page.add(
ft.Container(
content=visualizer.image,
alignment=ft.alignment.center,
expand=True,
)
)
page.update()
print("Page updated with visualizer.")
# Start the update loop in the main thread
visualizer.update_loop()
except Exception as e:
print(f"Error in main: {e}")
ft.app(target=main)
我已经尝试了我能想到的一切,但我无法显示频谱可视化。音频播放没有任何问题,终端中也没有错误。
我检查/尝试过的内容:
验证音频数据是否已正确加载和规范化。 确认正在使用音频数据块调用 update_visualization 方法。 确保 pygame.mixer 已正确初始化并且音频正在播放。 问题: 为什么未显示频谱可视化,以及如何修复它?
任何帮助或指示将不胜感激。谢谢你!
代码中导致 Flet 音频可视化工具无法正常工作的原因有几个潜在问题:
-
线程阻塞:
visualize_audio
函数中的make_chunks
和for
循环可能会阻塞 Flet 更新 UI 的主线程。由于 Flet 是单线程的,因此长时间运行的任务会阻止 UI 更新,导致可视化无法显示。 -
Matplotlib 后端: Matplotlib 默认使用可能与 Flet 不兼容的阻塞绘图后端。
-
页面更新计时:
update_visualization
函数在self.page
变量初始化之前被调用,这会导致self.page.update()
失败并且可视化无法显示。
解决方案:
-
使用
asyncio
进行非阻塞音频处理和可视化。 Flet 与asyncio
库很好地集成,以实现非阻塞操作。使用asyncio
,你可以将长时间运行的任务(例如音频处理和可视化)分成更小的块,这些块允许 Flet 主线程更新 UI。 -
使用与 Flet 兼容的 Matplotlib 后端。 你可以通过在导入
matplotlib.pyplot
之前设置matplotlib.use('agg')
来切换到非阻塞后端。 -
确保在调用
update_visualization
之前初始化页面: 将update_loop
调用移动到main
函数中,在将visualizer
添加到页面之后。
以下是如何使用这些解决方案修复代码的方法:
import flet as ft
import numpy as np
from pydub import AudioSegment
from pydub.utils import make_chunks
import matplotlib
matplotlib.use('agg') # 使用非阻塞后端
import matplotlib.pyplot as plt
import io
import asyncio
import pygame
import queue
# ...(其余代码与之前相同)
async def visualize_audio(self): # 使其成为异步函数
chunks = make_chunks(self.audio_data, chunk_size)
for chunk in chunks:
await self.audio_queue.put(chunk)
await asyncio.sleep(0) # 允许事件循环运行
await self.audio_queue.put(None)
async def update_loop(self): # 使其成为异步函数
try:
while True:
audio_data = await self.audio_queue.get()
if audio_data is None:
break
self.update_visualization(audio_data)
except Exception as e:
print(f"Error in update_loop: {e}")
def main(page: ft.Page) -> None:
try:
audio_file_path = "C:\\Users\\Administrator\\Desktop\\your_music_file.mp3"
visualizer = AudioVisualizer(audio_file_path)
visualizer.page = page # 在这里初始化页面引用
# 添加控件到页面
page.add(
ft.Container(
content=visualizer.image,
alignment=ft.alignment.center,
expand=True,
)
)
page.update()
print("页面已使用可视化工具更新。")
# 启动更新循环
asyncio.create_task(visualizer.update_loop())
except Exception as e:
print(f"Error in main: {e}")
ft.app(target=main)
这些更改通过以下方式解决了原始代码中的问题:
-
非阻塞音频处理和可视化:
visualize_audio
和update_loop
函数现在是异步的,使用await
来防止阻塞事件循环。这允许 Flet 在音频处理和可视化期间更新 UI。 -
兼容的 Matplotlib 后端:
matplotlib.use('agg')
行确保 Matplotlib 使用与 Flet 兼容的非阻塞后端。 -
页面更新计时:
visualizer.page
现在在调用update_visualization
之前初始化,确保页面更新按预期工作。
通过进行这些更改,音频可视化工具现在应该可以正常工作,并且可视化应该按预期更新,而不会出现任何错误。
标签:python,matplotlib,flet From: 78795663