以前的脚本基本都失效了,找 k2 写了个检测是否正在播放的脚本,可以半自动刷课
import pyaudio
import numpy as np
import threading
import time
# ---------- 可调参数 ----------
SAMPLE_RATE = 44100
CHUNK = int(0.1 * SAMPLE_RATE) # 100 ms
SILENCE_RMS = 0.01 # 静音阈值(0~1)
SILENCE_SEC = 2.0 # 持续多久算静音
BEEP_VOL = 0.5 # 报警音量 0~1
BEEP_DUR = 0.5 # 报警时长(秒)
# ------------------------------
p = pyaudio.PyAudio()
# 查找 loopback 设备
device_idx = None
for i in range(p.get_device_count()):
info = p.get_device_info_by_index(i)
if 'loopback' in info['name'].lower() or info['maxInputChannels'] > 0:
device_idx = i
break
if device_idx is None:
raise RuntimeError("找不到 loopback 设备")
in_stream = p.open(format=pyaudio.paInt16,
channels=2,
rate=SAMPLE_RATE,
input=True,
input_device_index=device_idx,
frames_per_buffer=CHUNK)
def rms(data):
samples = np.frombuffer(data, dtype=np.int16)
return np.sqrt(np.mean(samples.astype(np.float32) ** 2)) / 32768.0
# 播放报警声的线程函数
def _play_beep():
freq = 1000 # 440 Hz
t = np.linspace(0, BEEP_DUR, int(SAMPLE_RATE * BEEP_DUR), False)
wave = (np.sin(2 * np.pi * freq * t) * 32767 * BEEP_VOL).astype(np.int16)
# 双声道
stereo = np.empty(wave.size * 2, dtype=np.int16)
stereo[0::2] = wave
stereo[1::2] = wave
out_stream = p.open(format=pyaudio.paInt16,
channels=2,
rate=SAMPLE_RATE,
output=True)
out_stream.write(stereo.tobytes())
out_stream.stop_stream()
out_stream.close()
def alarm():
print(f"⚠️ 检测到 {SILENCE_SEC} 秒无声,发出警告!")
# 在后台线程播放,避免阻塞主循环
threading.Thread(target=_play_beep, daemon=True).start()
# 主循环
silent_chunks = int(SILENCE_SEC / 0.1)
silent_counter = 0
print("开始监听系统声音,按 Ctrl+C 退出…")
try:
while True:
data = in_stream.read(CHUNK, exception_on_overflow=False)
level = rms(data)
if level < SILENCE_RMS:
silent_counter += 1
else:
silent_counter = 0
if silent_counter >= silent_chunks:
alarm()
silent_counter = 0 # 重置计数器
except KeyboardInterrupt:
print("退出。")
finally:
in_stream.stop_stream()
in_stream.close()
p.terminate()