写了个带声音和文字提醒的倒计时应用并彻底解决pygame的Unable to open file错误和播放闪退

2020年03月02日 2765点热度 1人点赞 0条评论

碎碎念

一眨眼七个多月过去了,博客都没有更新,最近公司项目实在多,累得不行,再加上我偷懒的原因所以到现在才更新一篇。

开始

我新建了一个repo,地址在这里,代码拉下来后运行sudo pip3 install --requirement requirements.txt安装pygame库。

使用方法

$ python3 countdown.py -h
usage: countdown.py [-h] [-m MINUTE] [-t TASK_CONTENT]

A simple countdown app to help you deal with the daily things

optional arguments:
  -h, --help            show this help message and exit
  -m MINUTE, --minute MINUTE
                        The minute(s) you want to count down
  -t TASK_CONTENT, --task_content TASK_CONTENT
                     The content of the task you want to create

初衷

之所以写了这个库主要是最近用手机玩了几款大型游戏狂野飙车,暗影之枪,暗黑复仇者,特别是暗影之枪把画质调到60fps后手机发热简直了,所以我就想到放进冰箱里冻一下,一般五分钟就行了,冰箱在客厅外面,我在卧室,如果在手机上用闹钟APP设置个倒计时的话我在房间听不到,一开始搜了一下Mac如何设置提醒,结果搜到一篇教你用Mac自带的Remainder应用设置提醒的,测试了一下到时间后只会在右上角有一个悬浮窗出现连个声音提醒都没有,失望之余打开了App Store搜了一下闹钟应用结果返回的基本都是To-do类的应用,不过这次却也意外发现了滴答清单竟然有Mac版,下载之后发现非常难用,尤其是设置提醒时间总是各种bug,要么提醒不工作,要么设置时间的功能有问题,几经周转之后我决定自己写个命令行版本的简单倒计时应用。

干货

倒计时的一个主要功能是播放音乐,Google了一下用python有好几种方案,最终尝试下来决定使用pygame,虽然用pygame实现的代码只有几行,可是几番试下来都卡在了下面的错误,

$ python3 test.py
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
import pygame
Traceback (most recent call last):
  File "test.py", line 3, in <module>
    pygame.mixer.Sound('love.mp3').play()
pygame.error: Unable to open file 'love.mp3'

这个错误乍一看像是个IO错误,可是一番搜索下来发现问题可不简单,竟然还牵扯到了对音乐的再编码。我主要参考的是这个Stack Overflow上的问题下面的答案,解决这个问题要自行Google下载一个叫Audacity的应用,这个应用竟然有Mac版的,把音乐加载后直接选择导出为16位的wav格式就行了,导出是在菜单选择File-->Export-->Export as wav,然后File type选择下面这个,
Audacity应用
虽然我现在说得挺简单的当初也是折腾了半天,另外说一下,并不是所有的音乐文件都要这样再编码,比如我从我的MIUI9系统里面提取的一个ogg铃声文件就不需要重新导出编码。
解决了这个问题后运行脚本会发现脚本一闪马上就自动结束了,音乐并没有响起,要想解决这个问题主要是要添加两行弹出窗口的代码如下:

DISPLAYSURF = pygame.display.set_mode((400, 300))
pygame.display.set_caption(task_content)

紧接着说一下我对Stack Overflow上的问题下面的答案中的一段事件监听代码的改造,原始核心代码如下:

soundObj.play()
time.sleep(1) #wait and let the sound play for X second
soundObj.stop()

while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
        pygame.display.update()

我改造完后的如下:

soundObj.play()
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            soundObj.stop()
            pygame.quit()
            sys.exit()
    pygame.display.update()

改造之前的代码效果是必须等到音乐播放完了才能显示窗口标题然后关闭窗口,改造之后的代码可以实现同时直接显示带标题的窗口和播放音乐,然后随时都可以关掉窗口暂停音乐。

效果图

修复一个Bug

主要修复了音乐播放完毕后程序就崩溃的问题,代码主要参考了下面两篇博文:
- http://thacorag.com/102z
- http://thacorag.com/103n

Sharp

"A Linux user and a Python{}".format('er')