You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现循环播放声音并按ENTER停止,添加后台计数器?

解决方案

问题1:声音循环播放并按ENTER停止

pygame.mixer 的 play(-1) 参数已经支持音频无限循环。要实现按ENTER键停止播放且不阻塞其他操作,我们可以用线程监听用户输入,避免主线程被卡死:

  • 创建独立线程等待用户输入,一旦检测到ENTER,立即调用 ringtone.stop() 终止音频。
  • 该线程不会影响主线程或后台计数器的运行。

问题2:后台运行的计数器

使用Python的 threading 模块创建后台线程,让计数器在后台独立执行,同时主线程可以正常处理输入、打印等操作:

  • 将线程设置为 daemon=True,确保主线程退出时后台线程自动终止。
  • 用 threading.Event 作为信号量,控制计数器的启停,避免线程无法正常结束。

修改后的完整代码

import time
import sys
import threading
from time import strftime, localtime
from pygame import mixer
import os
import pyautogui as spam

mixer.init()  # 初始化pygame mixer
tick = mixer.Sound('sounds/245764888.mp3')

def delete_last_line():
    sys.stdout.write('\x1b[1A')
    sys.stdout.write('\x1b[2K')

def clock():
    current_time = strftime("At: %a, %d %b %Y %H:%M:%S %p", localtime())
    print(current_time)

def tk():
    for i in range(2):
        print(".")
        time.sleep(0.3)
        delete_last_line()
        print("..")
        time.sleep(0.3)
        delete_last_line()
        print("...")
        time.sleep(0.3)
        delete_last_line()
        print("....")
        time.sleep(0.3)
        delete_last_line()

ringtone = mixer.Sound('sounds/pill.wav')  # 加载提示音文件

# 后台计数器逻辑
def background_counter(stop_event):
    count = 0
    while not stop_event.is_set():
        # 用\r覆盖当前行,避免控制台刷屏
        print(f"后台计数器: {count}", end='\r')
        count += 1
        time.sleep(1)

while True:
    samay = 0
    os.system("cls")

    print("Started", end=" "); clock()
    time_inout_frm_usr = int(input('\nEnter the times in seconds: '))

    while samay < time_inout_frm_usr:
        samay += 1
        tick.play()
        print(samay)
        time.sleep(1)
        delete_last_line()
        
        if samay == time_inout_frm_usr:
            ringtone.play(-1)  # 无限循环播放提示音
            print('\nTIME OUT!!!\n')
            print("Ended", end=" "); clock()
            
            # 创建停止事件,用于同步线程停止信号
            stop_event = threading.Event()
            
            # 启动后台计数器线程(守护线程)
            counter_thread = threading.Thread(target=background_counter, args=(stop_event,), daemon=True)
            counter_thread.start()
            
            # 监听用户输入的线程
            def wait_for_stop():
                input("Press Enter to stop")
                ringtone.stop()
                stop_event.set()  # 通知后台计数器停止
            
            stop_thread = threading.Thread(target=wait_for_stop)
            stop_thread.start()
            stop_thread.join()  # 等待用户输入完成
            
            delete_last_line()
            break

    ask_cont = input("\nTo use again [ENTER] to continue or [NO] to close: ")
    if ask_cont == '':
        delete_last_line()
        print("Starting again in a sec")
        tk()
    else:
        os.system("cls")
        print("Closing in a sec")
        tk()
        spam.typewrite("exit")
        spam.press("Enter")
        break

关键修改说明

  1. 多线程处理:
    • 新增 background_counter 函数,通过 stop_event 控制计数器启停,在后台独立运行。
    • 超时后启动两个线程:一个监听用户输入,一个运行后台计数器,避免主线程阻塞。
  2. 音频控制:
    • 保留 ringtone.play(-1) 实现无限循环,通过输入监听线程触发 ringtone.stop() 终止播放。
  3. 控制台优化:
    • 后台计数器用 end='\r' 覆盖当前行,避免控制台被重复打印刷屏。

内容的提问来源于stack exchange,提问作者Eco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 21:35:27