吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 684|回复: 11
收起左侧

[Python 原创] 希沃平板音量电平显示器

[复制链接]
sszyz 发表于 2026-4-21 16:04
本帖最后由 sszyz 于 2026-4-22 13:04 编辑

原程序调节灵敏度无效,已修复重新打包为1.2版,请重新下载,代码就不更新了,有兴趣的可以自己修改一下。
https://www.guangyapan.com/s/1893914594699915328_aeYQv5wocgzRgF-U?code=52pj
开发源于学校要求学生读书声音要大
希沃平板音量电平显示器(也可用于其他电脑) - 使用说明
====================================

简介
----
这是一个用于监测课室学生读书音量的Python程序,通过调用希沃平板电脑内置麦克风获取音频,并用电平条动态显示音量强度。电平强度从0到100用不同的颜色动态显示。

教育应用场景
------------
1. 课堂纪律管理:监测学生读书时的音量水平
2. 朗读训练:帮助学生控制朗读音量
3. 小组活动:监测小组讨论的音量
4. 演讲练习:训练学生控制演讲音量
5. 音乐教学:可视化声音强度变化

主要功能
--------
1. 实时音频采集(支持真实麦克风和模拟模式)
2. 音量电平显示(0-100%)
3. 动态颜色显示(绿色→黄色→橙色→红色)
4. 音量历史图表
5. 灵敏度调节
6. 实时日志记录
7. 支持GUI界面和控制台模式

快速开始
--------

安装依赖
--------
```bash
# 安装所有依赖
pip install -r requirements.txt

# 或手动安装
pip install numpy matplotlib

# 真实麦克风支持(Windows可能需要特殊安装,在设置对话框内可安装)
pip install pyaudio
```

Windows用户安装pyaudio的注意事项:
1. 如果直接安装失败,可以尝试:
   ```
   pip install pipwin
   pipwin install pyaudio
   ```
2. 或从以下网址下载预编译版本:
   https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio

使用指南
--------

### 新版GUI模式(推荐)
1. 运行程序后,一个竖条窗口会出现在屏幕最右边
2. 窗口高度为屏幕高度的80%,无边框、置顶显示
3. **程序自动开始检测电平**,无需手动点击开始
4. 竖条显示实时音量,颜色从绿色到红色渐变
5. **左键点击**竖条区域:暂停/恢复监测
6. **右键点击**竖条区域:打开设置对话框
7. 在设置对话框中可以调节灵敏度和窗口透明度
8. **默认灵敏度为1**(适中灵敏度,适合一般环境)
9. 竖条上显示当前音量百分比和等级
10. 顶部显示监测状态(绿色"监测中"或红色"已停止")
11. 底部显示操作提示

### 控制台模式
如果GUI不可用,程序会自动切换到控制台模式:
- 使用ASCII字符显示音量条
- 支持颜色编码显示
- 按`Ctrl+C`退出

### 颜色说明
- 绿色(0-50%): 音量较低
- 黄色(50-60%): 音量适中
- 橙色(60-90%): 音量较高
- 红色(90-100%): 音量过高

### 音量等级
0: 极静 (0-10%)
1: 很静 (10-20%)
2: 安静 (20-30%)
3: 较静 (30-40%)
4: 正常 (40-50%)
5: 适中 (50-60%)
6: 较响 (60-70%)
7: 响亮 (70-80%)
8: 很响 (80-90%)
9: 极响 (90-95%)
10: 爆表 (95-100%)


技术参数
--------
- 采样率: 44100 Hz
- 位深度: 16位
- 声道: 单声道
- 更新频率: 10次/秒
- 历史数据: 最近100个数据点

故障排除
--------

### 常见问题
1. 无法启动音频采集
   - 检查麦克风权限
   - 确保pyaudio正确安装
   - 尝试以管理员权限运行

2. GUI界面无法显示
   - 检查tkinter是否安装
   - 程序会自动切换到控制台模式

3. 音量显示不准确
   - 调整灵敏度滑块
   - 确保麦克风位置合适
   - 检查环境噪音水平

### 调试模式
如需调试,可以修改程序中的以下参数:
- `rate`: 采样率(默认44100)
- `chunk`: 每次处理的帧数(默认1024)
- `sensitivity`: 灵敏度乘数

扩展功能建议(未开发)
------------
1. 数据导出:将音量数据导出为CSV或Excel
2. 阈值报警:设置音量阈值,超过时发出提醒
3. 多设备支持:同时监测多个麦克风
4. 网络传输:将数据发送到服务器
5. 移动端应用:开发手机APP版本

许可证
------
本项目采用MIT许可证。

注意事项
--------
- 本程序仅用于教育目的
- 请勿用于非法监控或侵犯他人隐私
- 尊重他人隐私权,合理使用本程序

版本信息
--------
版本: 1.0.0
创建日期: 2026-04-20
[Python] 纯文本查看 复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
希沃平板电脑音量电平显示程序
通过调用内置麦克风获取课室学生读书音量,用电平显示
电平强度从0到100用不同的颜色动态显示
"""

import sys
import numpy as np
import threading
import time
from datetime import datetime
import json
import os

try:
    import pyaudio
    PYAUDIO_AVAILABLE = True
except ImportError:
    PYAUDIO_AVAILABLE = False
    print("提示: pyaudio 未安装,将使用模拟数据模式")
    print("如需使用真实麦克风,请安装: pip install pyaudio")
    print("Windows用户可能需要从以下网址下载预编译版本:")
    print("https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio")

try:
    import tkinter as tk
    from tkinter import ttk, messagebox
    TKINTER_AVAILABLE = True
except ImportError:
    TKINTER_AVAILABLE = False
    print("警告: tkinter 未安装,将使用控制台输出")

try:
    import matplotlib.pyplot as plt
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
    from matplotlib.figure import Figure
    MATPLOTLIB_AVAILABLE = True
except ImportError:
    MATPLOTLIB_AVAILABLE = False
    print("警告: matplotlib 未安装,将使用简单图形")


class AudioRecorder:
    """音频录制器类"""
    
    def __init__(self, rate=44100, chunk=1024, channels=1):
        """
        初始化音频录制器
        
        Args:
            rate: 采样率 (Hz)
            chunk: 每次读取的帧数
            channels: 声道数
        """
        self.rate = rate
        self.chunk = chunk
        self.channels = channels
        self.recording = False
        self.audio_data = []
        self.current_volume = 0
        self.volume_history = []
        self.max_history_length = 100
        
        # 音频增益,用于放大输入信号
        self.gain = 5.0  # 默认增益为5倍
        
        # 音频流
        self.stream = None
        self.p = None
        
    def start_recording(self):
        """开始录制音频"""
        if not PYAUDIO_AVAILABLE:
            print("错误: pyaudio 未安装,无法使用真实麦克风")
            print("请安装: pip install pyaudio")
            print("Windows用户可能需要从以下网址下载预编译版本:")
            print("https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyaudio")
            return False
        
        try:
            self.p = pyaudio.PyAudio()
            self.stream = self.p.open(
                format=pyaudio.paInt16,
                channels=self.channels,
                rate=self.rate,
                input=True,
                frames_per_buffer=self.chunk
            )
            self.recording = True
            self.audio_data = []
            self.volume_history = []
            
            # 启动音频处理线程
            self._audio_thread = threading.Thread(target=self._process_audio)
            self._audio_thread.daemon = True
            self._audio_thread.start()
            
            print(f"音频录制已开始 (采样率: {self.rate}Hz, 块大小: {self.chunk})")
            return True
            
        except Exception as e:
            print(f"启动音频录制失败: {e}")
            print("请检查麦克风是否连接并可用")
            return False
    
    def stop_recording(self):
        """停止录制音频"""
        self.recording = False
        
        if self.stream:
            self.stream.stop_stream()
            self.stream.close()
            if self.p:
                self.p.terminate()
            print("音频录制已停止")
    

    
    def _process_audio(self):
        """处理音频数据"""
        while self.recording and self.stream:
            try:
                # 读取音频数据
                data = self.stream.read(self.chunk, exception_on_overflow=False)
                
                # 转换为numpy数组
                audio_array = np.frombuffer(data, dtype=np.int16)
                
                # 计算音量 (RMS)
                if len(audio_array) > 0:
                    rms = np.sqrt(np.mean(audio_array.astype(np.float32) ** 2))
                    
                    # 转换为0-100的电平值
                    # 假设最大可能值为32767 (16位有符号整数)
                    max_possible = 32767.0
                    # 应用增益放大输入信号,确保即使小声也能有足够的显示范围
                    volume_percent = min(100, (rms / max_possible) * 100 * self.gain)
                    
                    self.current_volume = volume_percent
                    
                    # 保存历史数据
                    self.volume_history.append(volume_percent)
                    if len(self.volume_history) > self.max_history_length:
                        self.volume_history.pop(0)
                    
                    # 保存原始音频数据(可选,用于分析)
                    self.audio_data.append(audio_array)
                    
            except Exception as e:
                if self.recording:  # 仅在仍然录制时打印错误
                    print(f"音频处理错误: {e}")
                break
    

    
    def get_current_volume(self):
        """获取当前音量"""
        return self.current_volume
    
    def get_volume_history(self):
        """获取音量历史"""
        return self.volume_history.copy()
    
    def get_average_volume(self, window=10):
        """获取平均音量"""
        if not self.volume_history:
            return 0
        recent = self.volume_history[-window:] if len(self.volume_history) >= window else self.volume_history
        return sum(recent) / len(recent)
    
    def get_volume_level(self):
        """获取音量等级 (0-10)"""
        volume = self.current_volume
        if volume < 10:
            return 0
        elif volume < 20:
            return 1
        elif volume < 30:
            return 2
        elif volume < 40:
            return 3
        elif volume < 50:
            return 4
        elif volume < 60:
            return 5
        elif volume < 70:
            return 6
        elif volume < 80:
            return 7
        elif volume < 90:
            return 8
        elif volume < 95:
            return 9
        else:
            return 10


class VolumeMeterGUI:
    """音量电平显示GUI"""
    
    def __init__(self, recorder):
        """
        初始化GUI
        
        Args:
            recorder: AudioRecorder实例
        """
        self.recorder = recorder
        self.root = None
        self.canvas = None
        self.running = False
        self.use_simulation_var = None  # 将在start方法中初始化
        
        # 颜色定义 (从绿色渐变到红色,越接近峰值越红)
        self.colors = [
            "#00FF00",  # 亮绿色 (0-10%)
            "#33FF00",  # 黄绿色 (10-20%)
            "#66FF00",  # 黄绿色 (20-30%)
            "#99FF00",  # 黄绿色 (30-40%)
            "#CCFF00",  # 黄绿色 (40-50%)
            "#FFFF00",  # 黄色 (50-60%)
            "#FFCC00",  # 橙黄色 (60-70%)
            "#FF9900",  # 橙色 (70-80%)
            "#FF6600",  # 橙红色 (80-90%)
            "#FF3300",  # 红色 (90-95%)
            "#FF0000",  # 亮红色 (95-100%)
        ]
        
        # 音量等级标签
        self.level_labels = [
            "极静",    # 0
            "很静",    # 1
            "安静",    # 2
            "较静",    # 3
            "正常",    # 4
            "适中",    # 5
            "较响",    # 6
            "响亮",    # 7
            "很响",    # 8
            "极响",    # 9
            "爆表",    # 10
        ]
        
    def start(self):
        """启动GUI - 新版本:竖条吸附在屏幕右边"""
        if not TKINTER_AVAILABLE:
            print("错误: tkinter 不可用,无法启动GUI")
            return False
        
        self.root = tk.Tk()
        self.root.title("音量电平显示器 v1.0 - by:任我行电脑工作室")
        
        # 设置窗口图标
        try:
            self.root.iconbitmap("icon.ico")
        except Exception as e:
            print(f"警告: 无法加载图标文件: {e}")
        
        # 设置窗口无边框,置顶显示
        self.root.overrideredirect(True)  # 无边框
        self.root.attributes('-topmost', True)  # 置顶
        
        # 获取屏幕尺寸
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        
        # 计算窗口位置和大小
        window_width = 180  # 窗口宽度增加到180,确保右侧数值能完整显示
        window_height = int(screen_height * 0.8)  # 屏幕高度的80%
        window_x = screen_width - window_width  # 最右边
        window_y = (screen_height - window_height) // 2  # 垂直居中
        
        # 设置窗口位置和大小
        self.root.geometry(f"{window_width}x{window_height}+{window_x}+{window_y}")
        
        # 设置窗口背景为黑色
        self.root.configure(bg='black')
        
        # 创建主画布
        self.canvas = tk.Canvas(self.root, width=window_width, height=window_height, bg='black', highlightthickness=0)
        self.canvas.pack(fill=tk.BOTH, expand=True)
        
        # 绑定右键点击事件
        self.canvas.bind("<Button-3>", self.show_settings_dialog)  # 右键点击
        self.canvas.bind("<Button-1>", self.toggle_recording)  # 左键点击切换监测状态
        
        # 初始化显示变量
        self.volume_var = tk.StringVar(value="0.0")
        self.level_var = tk.StringVar(value="极静")
        self.status_var = tk.StringVar(value="就绪")
        self.sensitivity_var = tk.DoubleVar(value=1.0)  # 默认灵敏度改为1.0
        self.use_simulation_var = tk.BooleanVar(value=False)  # 音频模式(只使用真实麦克风)
        
        # 绘制初始竖条
        self.draw_vertical_meter(0)
        
        # 启动更新循环
        self.running = True
        self.update_display()
        
        # 自动开始检测电平
        self.auto_start_recording()
        
        # 启动主循环
        self.root.mainloop()
        
        return True
    
    def toggle_recording(self, event=None):
        """切换录制状态(左键点击触发)"""
        if not self.recorder.recording:
            # 开始录制
            if self.recorder.start_recording():
                self.log("开始监测课室音量")
            else:
                self.log("错误: 无法启动音频监测")
        else:
            # 停止录制
            self.recorder.stop_recording()
            self.log("停止监测课室音量")
    
    def show_settings_dialog(self, event):
        """显示设置对话框(右键点击触发)"""
        # 创建设置对话框
        settings_window = tk.Toplevel(self.root)
        settings_window.title("设置")
        settings_window.geometry("300x480")
        settings_window.resizable(False, False)
        
        # 设置对话框图标
        try:
            settings_window.iconbitmap("icon.ico")
        except Exception as e:
            print(f"警告: 无法加载对话框图标文件: {e}")
        
        # 使对话框模态
        settings_window.transient(self.root)
        settings_window.grab_set()
        
        # 居中显示
        settings_window.update_idletasks()
        width = settings_window.winfo_width()
        height = settings_window.winfo_height()
        x = (settings_window.winfo_screenwidth() // 2) - (width // 2)
        y = (settings_window.winfo_screenheight() // 2) - (height // 2)
        settings_window.geometry(f"{width}x{height}+{x}+{y}")
        
        # 设置对话框内容
        ttk.Label(settings_window, text="音量电平显示器设置", font=("Arial", 14, "bold")).pack(pady=10)
        
        # 灵敏度设置
        sensitivity_frame = ttk.LabelFrame(settings_window, text="灵敏度设置", padding=10)
        sensitivity_frame.pack(fill="x", padx=10, pady=5)
        
        # 创建水平布局框架
        sens_row_frame = ttk.Frame(sensitivity_frame)
        sens_row_frame.pack(fill="x", pady=5)
        
        ttk.Label(sens_row_frame, text="灵敏度:").pack(side="left", padx=(0, 10))
        
        # 灵敏度滑块
        sensitivity_scale = ttk.Scale(
            sens_row_frame,
            from_=0.1,
            to=3.0,
            variable=self.sensitivity_var,
            orient=tk.HORIZONTAL,
            length=150
        )
        sensitivity_scale.pack(side="left", padx=(0, 10))
        
        # 灵敏度值显示(在滑块旁边)
        sens_value_var = tk.StringVar(value=f"{self.sensitivity_var.get():.1f}x")
        sens_value_label = ttk.Label(sens_row_frame, textvariable=sens_value_var, width=6, anchor="center")
        sens_value_label.pack(side="left")
        
        def update_sens_label(val):
            sens_value_var.set(f"{float(val):.1f}x")
        
        sensitivity_scale.configure(command=update_sens_label)
        
        # 音频模式信息
        audio_frame = ttk.LabelFrame(settings_window, text="音频输入", padding=10)
        audio_frame.pack(fill="x", padx=10, pady=5)
        
        if PYAUDIO_AVAILABLE:
            mode_text = "当前模式: 真实麦克风"
            detail_text = "使用硬件麦克风采集真实音频"
        else:
            mode_text = "警告: pyaudio 未安装"
            detail_text = "请安装pyaudio以使用真实麦克风"
        
        audio_info = ttk.Label(
            audio_frame, 
            text=f"{mode_text}\n{detail_text}",
            justify="left"
        )
        audio_info.pack(anchor="w")
        
        if not PYAUDIO_AVAILABLE:
            install_button = ttk.Button(
                audio_frame,
                text="安装 pyaudio",
                command=self.install_pyaudio,
                width=15
            )
            install_button.pack(pady=(10, 0))
        
        # 显示设置
        display_frame = ttk.LabelFrame(settings_window, text="显示设置", padding=10)
        display_frame.pack(fill="x", padx=10, pady=5)
        
        # 窗口透明度
        opacity_row_frame = ttk.Frame(display_frame)
        opacity_row_frame.pack(fill="x", pady=5)
        
        ttk.Label(opacity_row_frame, text="透明度:").pack(side="left", padx=(0, 10))
        
        opacity_var = tk.DoubleVar(value=0.9)
        opacity_scale = ttk.Scale(
            opacity_row_frame,
            from_=0.3,
            to=1.0,
            variable=opacity_var,
            orient=tk.HORIZONTAL,
            length=150
        )
        opacity_scale.pack(side="left", padx=(0, 10))
        
        opacity_value_label = ttk.Label(opacity_row_frame, text=f"{opacity_var.get():.1f}", width=6, anchor="center")
        opacity_value_label.pack(side="left")
        
        def update_opacity(val):
            opacity = float(val)
            opacity_value_label.config(text=f"{opacity:.1f}")
            self.root.attributes('-alpha', opacity)
        
        opacity_scale.configure(command=update_opacity)
        
        # 控制按钮
        button_frame = ttk.Frame(settings_window)
        button_frame.pack(fill="x", padx=10, pady=20)
        
        # 重置按钮
        reset_button = ttk.Button(
            button_frame,
            text="重置数据",
            command=self.reset_display,
            width=12
        )
        reset_button.pack(side="left", padx=5)
        
        # 退出按钮
        exit_button = ttk.Button(
            button_frame,
            text="退出程序",
            command=self.exit_program,
            width=12
        )
        exit_button.pack(side="right", padx=5)
        
        # 关闭按钮
        close_button = ttk.Button(
            button_frame,
            text="关闭",
            command=settings_window.destroy,
            width=12
        )
        close_button.pack(side="right", padx=5)
        
        # 信息标签
        info_frame = ttk.LabelFrame(settings_window, text="程序信息", padding=10)
        info_frame.pack(fill="x", padx=10, pady=5)
        
        info_text = """音量电平显示器 v1.0
by:任我行电脑工作室

功能说明:
&#8226; 左键点击: 开始/停止监测
&#8226; 右键点击: 打开设置
&#8226; 竖条显示实时音量
&#8226; 颜色随音量变化

作者: CodeArts代码智能体"""
        
        ttk.Label(info_frame, text=info_text, justify="left").pack(anchor="w")
    

    
    def auto_start_recording(self):
        """自动开始录制(程序启动时调用)"""
        if not self.recorder.recording:
            if self.recorder.start_recording():
                self.log("程序启动,自动开始监测课室音量")
                self.log(f"默认灵敏度: {self.sensitivity_var.get():.1f}x")
            else:
                self.log("警告: 自动启动监测失败")
    
    def reset_display(self):
        """重置显示"""
        self.recorder.volume_history = []
        self.log("显示已重置")
    
    def exit_program(self):
        """退出程序"""
        self.running = False
        if self.recorder.recording:
            self.recorder.stop_recording()
        if self.root:
            self.root.quit()
            self.root.destroy()
    
    def install_pyaudio(self):
        """安装pyaudio依赖"""
        import subprocess
        import sys
        import tkinter.messagebox as messagebox
        
        try:
            # 显示安装提示
            messagebox.showinfo("安装pyaudio", "正在安装pyaudio,请稍候...")
            
            # 安装pyaudio
            result = subprocess.run(
                [sys.executable, "-m", "pip", "install", "pyaudio"],
                capture_output=True,
                text=True,
                check=True
            )
            
            if result.returncode == 0:
                messagebox.showinfo("安装成功", "pyaudio安装成功!\n请重启程序以使用真实麦克风。")
                # 退出程序,让用户重新启动
                self.exit_program()
            else:
                messagebox.showerror("安装失败", f"pyaudio安装失败:\n{result.stderr}")
                
        except subprocess.CalledProcessError as e:
            messagebox.showerror("安装错误", f"安装过程中出错:\n{e.stderr}")
        except Exception as e:
            messagebox.showerror("错误", f"无法安装pyaudio:\n{str(e)}")
    
    def update_display(self):
        """更新显示"""
        if not self.running or not self.root:
            return
        
        try:
            # 获取当前音量
            volume = self.recorder.get_current_volume()
            
            # 电平显示不受灵敏度调整影响,直接使用原始音量
            adjusted_volume = min(100, volume)
            
            # 获取音量等级
            level = self.recorder.get_volume_level()
            level = min(level, 10)  # 确保不超过10
            
            # 更新等级显示
            self.level_var.set(self.level_labels[level])
            
            # 绘制垂直音量条
            self.draw_vertical_meter(adjusted_volume)
            
            # 100ms后再次更新
            self.root.after(100, self.update_display)
            
        except Exception as e:
            print(f"更新显示时出错: {e}")
            self.root.after(100, self.update_display)
    
    def draw_vertical_meter(self, volume):
        """绘制垂直音量条(吸附在屏幕右边)"""
        if not self.canvas:
            return
        
        # 清空画布
        self.canvas.delete("all")
        
        # 获取画布尺寸
        canvas_width = self.canvas.winfo_width() or 120
        canvas_height = self.canvas.winfo_height() or 600
        
        # 计算竖条参数
        bar_width = 40  # 竖条宽度
        bar_margin = 20  # 边距
        bar_x = (canvas_width - bar_width) // 2  # 水平居中
        
        # 计算竖条高度(基于音量百分比)
        bar_height = int((volume / 100) * (canvas_height - 2 * bar_margin))
        bar_y_bottom = canvas_height - bar_margin
        bar_y_top = bar_y_bottom - bar_height
        
        # 计算颜色索引
        level = self.recorder.get_volume_level()
        level = min(level, 10)  # 确保不超过10
        color = self.colors[level]
        
        # 绘制背景(深灰色)
        self.canvas.create_rectangle(
            0, 0, canvas_width, canvas_height,
            fill="#1a1a1a", outline=""
        )
        
        # 绘制竖条背景(浅灰色)
        self.canvas.create_rectangle(
            bar_x, bar_margin,
            bar_x + bar_width, canvas_height - bar_margin,
            fill="#333333", outline="#666666", width=2
        )
        
        # 绘制音量填充条
        if volume > 0:
            self.canvas.create_rectangle(
                bar_x, bar_y_top,
                bar_x + bar_width, bar_y_bottom,
                fill=color, outline=color, width=2
            )
        
        # 绘制刻度线
        for i in range(0, 101, 10):
            y_pos = bar_margin + (100 - i) * (canvas_height - 2 * bar_margin) / 100
            # 主要刻度(每20%)
            if i % 20 == 0:
                self.canvas.create_line(
                    bar_x - 10, y_pos, bar_x + bar_width + 10, y_pos,
                    fill="white", width=2
                )
                # 刻度标签
                self.canvas.create_text(
                    bar_x + bar_width + 30, y_pos,  # 从25增加到30,确保有足够空间
                    text=f"{i}%",
                    fill="white",
                    font=("Arial", 10, "bold"),
                    anchor="w"
                )
            # 次要刻度(每10%)
            else:
                self.canvas.create_line(
                    bar_x - 5, y_pos, bar_x + bar_width + 5, y_pos,
                    fill="#888888", width=1
                )
        
        # 显示当前音量数值(在竖条顶部)
        if volume > 0:
            self.canvas.create_text(
                canvas_width // 2, bar_y_top - 20,
                text=f"{volume:.1f}%",
                fill="white",
                font=("Arial", 14, "bold")
            )
        
        # 显示音量等级(在竖条底部)
        level_text = self.level_labels[level]
        self.canvas.create_text(
            canvas_width // 2, canvas_height - bar_margin + 25,
            text=level_text,
            fill=color,
            font=("Arial", 12, "bold")
        )
        
        # 显示状态(在顶部)
        status_text = "监测中" if self.recorder.recording else "已停止"
        status_color = "#00FF00" if self.recorder.recording else "#FF0000"
        self.canvas.create_text(
            canvas_width // 2, 15,
            text=status_text,
            fill=status_color,
            font=("Arial", 10)
        )
        
        # 显示操作提示
        self.canvas.create_text(
            canvas_width // 2, canvas_height - 10,
            text="左键: 开始/停止 | 右键: 设置",
            fill="#888888",
            font=("Arial", 8)
        )
    
    def log(self, message):
        """添加日志消息(简化版,只打印到控制台)"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        print(f"[{timestamp}] {message}")
    
    def log(self, message):
        """添加日志消息(简化版,只打印到控制台)"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        print(f"[{timestamp}] {message}")


def check_dependencies():
    """检查依赖"""
    missing = []
    
    if not PYAUDIO_AVAILABLE:
        missing.append("pyaudio (用于音频录制)")
        print("提示: 安装 pyaudio: pip install pyaudio")
    
    if not TKINTER_AVAILABLE:
        missing.append("tkinter (用于GUI界面)")
        print("提示: tkinter 通常随Python一起安装")
    
    if not MATPLOTLIB_AVAILABLE:
        missing.append("matplotlib (用于图表显示)")
        print("提示: 安装 matplotlib: pip install matplotlib")
    
    if missing:
        print(f"缺少依赖: {', '.join(missing)}")
        print("程序将在有限功能下运行")
    
    return len(missing) == 0


def main():
    """主函数"""
    print("=" * 60)
    print("音量电平显示器 v1.0")
    print("by:任我行电脑工作室")
    print("用于监测课室学生读书音量")
    print("=" * 60)
    
    # 检查依赖
    all_deps_available = check_dependencies()
    
    if not all_deps_available:
        print("\n警告: 部分依赖不可用,程序功能可能受限")
        print("建议安装所有依赖以获得完整功能")
        print("将在3秒后自动继续...")
        import time
        time.sleep(3)
        # 自动继续运行
    
    # 创建音频录制器(只使用真实麦克风模式)
    recorder = AudioRecorder()
    
    # 创建GUI
    gui = VolumeMeterGUI(recorder)
    
    print("\n启动GUI界面...")
    print("使用说明:")
    print("1. 点击'开始监测'按钮开始采集音频")
    print("2. 调整灵敏度滑块以改变音量检测灵敏度")
    print("3. 点击'重置'按钮清除历史数据")
    print("4. 点击'退出'按钮结束程序")
    print("\n颜色说明:")
    print("绿色(0-50%): 音量较低")
    print("黄色(50-60%): 音量适中")
    print("橙色(60-90%): 音量较高")
    print("红色(90-100%): 音量过高")
    
    # 启动GUI
    try:
        gui.start()
    except Exception as e:
        print(f"启动GUI时出错: {e}")
        print("尝试使用控制台模式...")
        run_console_mode(recorder)
    
    print("程序结束")


def run_console_mode(recorder):
    """控制台模式"""
    print("\n控制台模式启动")
    print("按 Ctrl+C 退出")
    
    try:
        # 开始录制
        if recorder.start_recording():
            print("音频监测已开始")
            
            # 显示音量
            import time
            while True:
                volume = recorder.get_current_volume()
                level = recorder.get_volume_level()
                level_text = recorder.get_volume_level()
                
                # 创建简单的ASCII电平条
                bar_length = 20
                filled = int((volume / 100) * bar_length)
                bar = "█" * filled + "&#9617;" * (bar_length - filled)
                
                # 选择颜色代码
                if level <= 3:
                    color_code = "\033[92m"  # 绿色
                elif level <= 6:
                    color_code = "\033[93m"  # 黄色
                elif level <= 8:
                    color_code = "\033[91m"  # 红色
                else:
                    color_code = "\033[91;1m"  # 亮红色
                
                # 清屏并显示
                print("\033[2J\033[H")  # 清屏并移动光标到左上角
                print("课室音量监测 (控制台模式)")
                print("=" * 40)
                print(f"当前音量: {color_code}{volume:6.1f}%\033[0m")
                print(f"音量等级: {color_code}{level_text}\033[0m")
                print(f"电平条:  {color_code}{bar}\033[0m")
                print("=" * 40)
                print("颜色说明:")
                print("\033[92m绿色: 安静\033[0m")
                print("\033[93m黄色: 适中\033[0m")
                print("\033[91m红色: 响亮\033[0m")
                print("\033[91;1m亮红: 过响\033[0m")
                print("\n按 Ctrl+C 退出")
                
                time.sleep(0.1)  # 100ms更新一次
                
    except KeyboardInterrupt:
        print("\n\n停止监测...")
    finally:
        recorder.stop_recording()
        print("程序结束")


if __name__ == "__main__":
    main()
dp.JPG

免费评分

参与人数 3吾爱币 +3 热心值 +3 收起 理由
yjn866y + 1 + 1 谢谢@Thanks!
sdzdp + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Lishi8 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| sszyz 发表于 2026-4-22 07:47
本帖最后由 sszyz 于 2026-4-22 13:03 编辑
w531171352 发表于 2026-4-22 02:47
不懂得在哪有成品下载
原程序调节灵敏度无效,已修复重新打包为1.2版,请重新下载,代码就不更新了,有兴趣的自己修改一下。
https://www.guangyapan.com/s/1893914594699915328_aeYQv5wocgzRgF-U?code=52pj
czyy003 发表于 2026-4-21 22:55
w531171352 发表于 2026-4-22 02:47
有术有道 发表于 2026-4-22 06:56
厉害,专业
与时俱进 发表于 2026-4-22 07:15
如何让平板的音量变大呢
tonywenzi 发表于 2026-4-22 07:57
厉害,厉害。
douyacai 发表于 2026-4-22 08:17
厉害,这样读书的更有劲了,看谁声音大
 楼主| sszyz 发表于 2026-4-22 09:06
douyacai 发表于 2026-4-22 08:17
厉害,这样读书的更有劲了,看谁声音大

领导就这样子说的
小鸟会飞 发表于 2026-4-22 09:59
学生搁心里肯定会问候 老师  
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-4-23 16:29

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表