首页 > 编程问答 >如何修复我的 python flet 音频可视化工具在终端中不出现错误的情况下无法工作

如何修复我的 python flet 音频可视化工具在终端中不出现错误的情况下无法工作

时间:2024-07-26 06:55:31浏览次数:7  
标签:python matplotlib flet

标题:音频播放,但频谱可视化未在 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 音频可视化工具无法正常工作的原因有几个潜在问题:

  1. 线程阻塞: visualize_audio 函数中的 make_chunks for 循环可能会阻塞 Flet 更新 UI 的主线程。由于 Flet 是单线程的,因此长时间运行的任务会阻止 UI 更新,导致可视化无法显示。

  2. Matplotlib 后端: Matplotlib 默认使用可能与 Flet 不兼容的阻塞绘图后端。

  3. 页面更新计时: update_visualization 函数在 self.page 变量初始化之前被调用,这会导致 self.page.update() 失败并且可视化无法显示。

解决方案:

  1. 使用 asyncio 进行非阻塞音频处理和可视化。 Flet 与 asyncio 库很好地集成,以实现非阻塞操作。使用 asyncio ,你可以将长时间运行的任务(例如音频处理和可视化)分成更小的块,这些块允许 Flet 主线程更新 UI。

  2. 使用与 Flet 兼容的 Matplotlib 后端。 你可以通过在导入 matplotlib.pyplot 之前设置 matplotlib.use('agg') 来切换到非阻塞后端。

  3. 确保在调用 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

相关文章

  • 使用隐式 __init__ 方法向 python 数据类添加显式 dunder 方法
    我在python中创建了一个数据类,选择使用隐式定义的__init__方法。然后,我尝试显式重写比较dunder方法之一(__eq__)。因为没有明确的__init__方法,所以'this'参数不存在,所以python抛出了一个NameError。为了做到这一点,即使自动生成的很好,我是否也必......
  • 84 我正在使用 Python 开发 selenium 自动化项目。我收到错误 .NoSuchElementExceptio
    场景是这样的,我将打开一个网页,在使用selenium单击该网页后,它会要求位置访问权限,屏幕上会出现一堆按钮,我正在尝试定位其中一个按钮,但即使正确给出了Xpath地址,我得到.NoSuchElementException:错误能够单击目标按钮你正在使用Selenium在Python中开发自动化项目,并遇到......
  • 在Python 3中删除两个指定字符串之间的字符串
    我正在从事一个NLP项目,该项目要求我从一段文本中删除计算机代码。代码包含在标签<pre><code>和</code></pre>之间。现在我可以做一个简单的正则表达式匹配,但我想概括这个函数,以便它可以删除任何两个指定字符串之间的文本,即使它们是嵌套的。例如,如果我有一个......
  • Azure Open AI - Python 和 Java API 之间 gpt4o 的结果截然不同
    我使用Java和PythonAPI对AzureOpenAI进行相同的调用,但收到截然不同的结果:相同的系统提示相同的用户提示适用于Java和Python的azureai包的相同(最新)版本尽管输入的用户和系统提示完全相同,但响应却非常不同-python提示是“正确的”并......
  • leetcode 输出错误? (Python)
    我的VSCode/本地终端给出了[1,4,1,5,1,6]的正确输出,但不知何故leetcode给了我完全不同的输出。我在这里错过了什么吗?这怎么可能?顺便说一下,这是wigglesort2将我的本地代码复制粘贴到leetcode中给出了不同的输出数组很难在没有看到你的代码的情况下......
  • 当 python 窗口的一部分不在屏幕上时,如何让它自己被记录?
    在Windows10中,大多数应用程序窗口都可以使用OBS等程序进行记录。当窗口被拖动以致其部分内容在显示屏上不可见时,通常OBS仍会接收窗口的内容,即使它在屏幕上不可见。但是,在编写python应用程序时,这似乎不以相同的方式工作。我尝试了几种不同的类似GUI的模块......
  • 使用 aws cdk 设置用户池客户端属性以具有读/写访问权限 - Python
    我试图根据属性给予一些自定义属性特定的读/写访问权限。我收到此错误。资源处理程序返回消息:“无效写入创建客户端时指定的属性(服务:CognitoIdentityProvider,状态代码:400,请求ID:<request_id>)”(RequestToken:<request_token>,HandlerErrorCode:InvalidRequest)任何人都可以为......
  • 试图找出此页面的逻辑:存储了大约 ++ 100 个结果 - 并使用 Python 和 BS4 进行了解析
    试图找出此页面背后的逻辑:我们已将一些结果存储在以下数据库中:https://www.raiffeisen.ch/rch/de/ueber-uns/raiffeisen-gruppe/Organization/raiffeisenbanken/deutsche-schweiz.html#accordionitem_18104049731620873397从a到z大约:120个结果或更多:......
  • 如何在 Numpy Python 中将 4 维数组的下三角形复制到上三角形?
    目标是将下三角形复制到上三角形。根据OP中提出的建议,起草了以下代码。importnumpyasnplw_up_pair=np.tril_indices(4,-1)arr=np.zeros((4,4,1,1))arr[1,:1,:,0]=1arr[2,:2,0,0]=2arr[3,:3,0,0]=3arr=arr+arr.T-np.diag(np.diag(arr))但是,它......
  • 如何在 Python 中对多行使用单个 INSERT INTO 语句?
    我目前正在开发一个DiscordPython机器人,我在其中循环遍历ForumTags列表,并为每个对象生成INSERTINTOSQL语句以将数据插入MySQL数据库。但是,我想要通过将所有这些单独的INSERTINTO语句组合到单个查询中来优化我的代码,如下所示:INSERTINTO......