在树莓派上定时播放语音的原因是家里的小朋友早上起床和出门拖延严重,另外有的时候忘记看天气预报带雨伞。
树莓派的好处是耗电少,环保一些。也确实不会因为要做个提醒的功能一直开着电脑。实际上家里的电脑还真是一直开着。原因是远程打印,需要通过家里的电脑一直开着云打印。
虽然功能比较简单,但是还是挺曲折的。
1、语音:纠结是自己录音,还是使用大厂的语音合成服务。讯飞,可以免费一年,百度好像直接要钱。最后,还是自己录音,简单实用。
2、手机录音后是m4a的格式。中间有一个多小时是找转mp3的软件。手机上下载了2个软件,电脑上也找了2个软件,结果,都是要买会员才能够使用。后面,在树莓派上安装ffmpeg,再通过ffmpeg将m4a转成了mp3格式。
pip3 install ffmpegffmpeg -i sunny.m4a sunny.mp3
3、mp3的播放,最初在windows上使用的系统自带的media player,m4a和mp3都支持;在linux上使用的是mpv。通过获取操作系统,再调用os.system执行相应的命令。然后,想着能不能统一一下,使用纯python进行播放?于是,使用pygame进行播放,使用mutagen.mp3获取语音的时长。找了半天,只成功的使用mutagen.mp3包获取到了mp3的时长。因此,才会需要将m4a转了mp3。
但是,很遗憾,将代码部署到树莓派上后,执行报无法找到设备的错误。于是,又从pygame转到了使用系统中的播放器。
4、代码里面有一个weather类是通过高德地图获取天气预报的。
5、Holiday类是判断节假日的。原先也是想通过大厂的API获取。还是发现要收费,于是自己加了个配置表,判断是否为节假日。节假日,起床和出门的提醒就跳过。
6、代码没有全部贴出来,不可以直接执行。
# -*- coding: utf-8 -*-# @Time : -1-1# @Author : Fred Liuimport timeimport osfrom Holiday import Holidayimport platformimport scheduleimport loggingfrom mutagen.mp3 import MP3import pygamefrom Weather import Weatherclass Reminder():logging.basicConfig(level=logging.INFO,format='%(asctime)s %(filename)s %(levelname)s %(message)s',datefmt='%a %d %b %Y %H:%M:%S',filename='my.log',filemode='w')mediaPlayer = {'Windows': '' , 'Linux': '/usr/bin/mpv'}mediaPlayerOption = {'Windows': '' , 'Linux': '--no-video'} blank = ' 'platformSystem = platform.system()#起床提醒def getUp(self, audio={'Linux':'/home/pi/Music/getup.mp3', \'Windows':'C:/Users/Administrator/Downloads/getup.mp3'}, \horw:str='W',remindTimes:int = 60):monRemind(audio=audio, horw=horw, remindTimes=remindTimes)#出门提醒def getOut(self, audio={'Linux':'/home/pi/Music/getout.mp3', \'Windows':'C:/Users/Administrator/Downloads/getout.mp3'}, \horw:str='W',remindTimes:int = 60):monRemind(audio=audio, horw=horw, remindTimes=remindTimes)#社团课提醒def sheTuanKe(self,audio={'Linux':'/home/pi/Music/shetuanke.mp3', \'Windows':'C:/Users/Administrator/Downloads/shetuanke.mp3'}, \horw:str='W',remindTimes:int = 2):#社团课dateSpecial = time.strftime("%Y-%m-%d", time.localtime())holiday = Holiday(dateSpecial)holiday.isHoliday()if holiday.getWeekDate() != 7 :#如果不是周四,不需要提醒passelse:monRemind(audio=audio, horw=horw, remindTimes=remindTimes)# #工作日,有社团课# systemType = platform.system()# if 'Windows' == systemType:#os.system('C:/Users/Administrator/Downloads/shetuanke.mp3')# elif 'Linux' == systemType:#os.system('/usr/bin/mpv /home/pi/Music/shetuanke.mp3 --no-video ')#天气提醒def weatherWarning(self, horw:str='A', remindTimes:int = 6):weather = Weather()warningInfos = weather.getWarning()if warningInfos == None or warningInfos == []:audio={'Linux':'/home/pi/Music/sunny.mp3', \'Windows':'C:/Users/Administrator/Downloads/sunny.mp3'}monRemind(audio=audio, horw=horw, remindTimes=2)return for warningInfo in warningInfos:if warningInfo == '雨':audio={'Linux':'/home/pi/Music/rainny.mp3', \'Windows':'C:/Users/Administrator/Downloads/rainny.mp3'}monRemind(audio=audio, horw=horw, remindTimes=remindTimes)if warningInfo == '雪':audio={'Linux':'/home/pi/Music/rainny.mp3', \'Windows':'C:/Users/Administrator/Downloads/rainny.mp3'}monRemind(audio=audio, horw=horw, remindTimes=remindTimes)if warningInfo == '霾':audio={'Linux':'/home/pi/Music/rainny.mp3', \'Windows':'C:/Users/Administrator/Downloads/rainny.mp3'}monRemind(audio=audio, horw=horw, remindTimes=remindTimes)#通用提醒def commonRemind(self, audio={'Linux':'/home/pi/Music/Ddadiaoxiaobuwuqu.mp3', \'Windows':'C:/Users/Administrator/Downloads/Ddadiaoxiaobuwuqu.mp3'}, \horw:str='A', remindTimes:int = 2):logging.info(audio)logging.info(Reminder.platformSystem)print(audio)print(Reminder.platformSystem)"""校验节假日是否需要提醒:A:提醒H:节目日提醒W:工作日提醒"""holiday = Holiday()holiday.isHoliday()if horw == 'A':passelif holiday.getStatus() != horw:returnelse:pass#调用播音audioMp3 = MP3(audio[Reminder.platformSystem])audioLength = int(audioMp3.info.length)logging.info(audioMp3.info.length)print(audioMp3.info.length)print((audioLength+1) * 1000)try:for i in range(remindTimes):os.system(Reminder.mediaPlayer[Reminder.platformSystem] + Reminder.blank \+ audio[Reminder.platformSystem] + Reminder.blank \+ Reminder.mediaPlayerOption[Reminder.platformSystem])time.sleep(audioLength+1)# mp3File = audio[Reminder.platformSystem]# pygame.mixer.init()# track = pygame.mixer.music.load(mp3File)# pygame.mixer.music.play()# audioMp3 = MP3(mp3File)# audioLength = int(audioMp3.info.length)# print(audioLength)# time.sleep(audioLength+2)# pygame.mixer.music.stop() except:logging.error('播报异常')if __name__ == '__main__':reminder = Reminder()#测试reminder.sheTuanKe(horw='A', remindTimes=2)reminder.getUp(horw='A', remindTimes=2)reminder.getOut(horw='A', remindTimes=2)reminder.weatherWarning(horw='A', remindTimes=2)# schedule.every(2).minutes.do(reminder.getUp)schedule.every().day.at("06:58").do(reminder.getUp)schedule.every().day.at("07:50").do(reminder.getOut)schedule.every().day.at("07:30").do(reminder.weatherWarning)while True:schedule.run_pending()time.sleep(30)
# -*- coding: utf-8 -*-# @Time : -1-1# @Author : Fred Liu qipingimport sysimport timefrom MariaDbPool import MariaDbPoolclass Holiday():"""节假日类"""def __init__(self, dateSpecial:str=None, status:str=None, ps:str=None, comm:str=None ) -> None:self.dateSpecial = dateSpecial #字符串类型,格式要求:yyyy-mm-ddself.status = statusself.ps = m = commdef setDateSpecial(self, dateSpecial:str):self.dateSpecial = dateSpecialdef setStatus(self, status):self.status = statusdef setPs(self, ps):self.ps = psdef setComm(self, comm):m = commdef getDateSpecial(self):return self.dateSpecial def getStatus(self):return self.statusdef getPs(self):return self.psdef getComm(self):return mdef isHoliday(self):"""通过数据库判断传入的日期是否是节假日1.首先判断录入的日期是否在idoit.holidays配置表中,如果在,以配置表中的配置为准2.如果配置表中没有该日期的配置:则记录该日期是否为周六、周日,如果是,则为节假日;否则,为工作日。 星期一:1星期二:2星期日:7 """#先从数据库中检查是否存在特殊节假日if self.status == None or self.status == '':try:conn = MariaDbPool().pool.get_connection()sql = """SELECT date_format(date_special,'%Y-%m-%d') AS date_special, STATUS, ps, comm FROM idoit.holidays WHERE date_special = date(?)"""cur = conn.cursor()print(self.dateSpecial)param = []param.append(self.dateSpecial)cur.execute(sql, param)res = cur.fetchone()if res != None:self.setStatus(res[1])self.ps= res[2]m = res[3]finally:cur.close()conn.close()#再判断是否为周六、周日if self.status == None or self.status == '':weekDate = self.getWeekDate()if (6 == weekDate or 7 == weekDate):self.setStatus('H')else:self.setStatus('W')return self.statusdef getWeekDate(self):""" 蔡勒公式,参考了某一位老师的实际。w:星期; w对7取模得:0-星期日,1-星期一,2-星期二,3-星期三,4-星期四,5-星期五,6-星期六c:世纪(注:一般情况下,在公式中取值为已经过的世纪数,也就是年份除以一百的结果,而非正在进行的世纪,也就是现在常用的年份除以一百加一;不过如果年份是公元前的年份且非整百数的话,c应该等于所在世纪的编号,如公元前253年,是公元前3世纪,c就等于-3)y:年(一般情况下是后两位数,如果是公元前的年份且非整百数,y应该等于cMOD100+100)m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月来计算,比如1月1日要看作2002年的13月1日来计算)d:日[ ]代表取整,即只要整数部分。"""if self.dateSpecial == None:return -1delimiter = '-'year, month, day = [int(x) for x in self.dateSpecial.split(delimiter)]century = int(year/100)year = year - int(year / 100) * 100 if month == 1 or month == 2:month = month + 12if year == 0:year = 99century = century - 1else:year = year - 1week = year + int(year/4) + int(century/4) - 2 * century + int(26 * (month + 1)/10) + day - 1if week < 0:weekDay = (week % 7 + 7) % 7else:weekDay = week % 7#周日调整为7if weekDay == 0 :weekDay = 7return weekDayif __name__ == '__main__':dateSpecial = time.strftime("%Y-%m-%d", time.localtime())# print(dateSpecial)holiday = Holiday(dateSpecial)holiday.isHoliday()# print(holiday.getStatus())if holiday.getStatus() == 'H' :sys.exit(1)else:sys.exit(0)
如果觉得《在树莓派上定时播放语音》对你有帮助,请点赞、收藏,并留下你的观点哦!