树莓派智能语音助手实现音乐播放

树莓派语音助手从诞生的第一天开始,我就想着让它能像小爱音箱一样,可以语音控制播放音乐。经过这些日子的倒腾,今天终于实现了。

接下里,和大家分享下我的实现方法:首先音乐播放模块用的是我在上一篇博文写的《用sounddevice实现连续的音乐曲库播放》,然后语义解析部分依旧用的是RASA,具体做法同前不久实现的《让树莓派智能语音助手实现定时提醒功能》,即用RASA解析语义,返回关键字指令给语音助手,语音助手负责调用sounddevice编写的语音库执行指令。

RASA部分主要定义了4个新的intent和4个新的actions。

如上分别是stories.md和nlu.md新增部分,最右边的是其中一个actions的举例,没啥技术含量,剩下三个就不贴了。另外,domain.yml部分记得把intent和actions定义一下。这些就是RASA的全部内容了。

再来看语音助手的demo.py部分。这次我把收到语义解析后的代码都重新改写了一下:

python 复制代码
if resp == "有需要再叫我":
           print("对话结束,等待呼唤......"+time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))) 
           status = 0
        elif resp == 'play_music':
           resp = ""
           if flag:
               playMusic()
        elif resp == 'next_song':
           resp = ""
           nextSong()
        elif resp == 'prev_song':
           resp = ""
           prevSong()
        elif resp == 'stop_music':
           resp = ""
           stopMusic()
        else:
           index0 = resp.find('5分钟后提醒')
           if index0 != -1:
              text0 = '/EXTERNAL_reminder'
              t = threading.Timer(300, act_remind, args=[text0])
              t.start()
        if resp != "":
           print("回复内容:"+resp)
           tts.text_to_speech(resp)
        else:
           print("播放音乐,对话结束,等待呼唤......"+time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
           status = 0
        time.sleep(0.5)

以上代码放在callback函数"print("解析耗时:"+f'{time.time() - t:.4f}s')"这句话之后。除了这部分,再定义四个函数。

python 复制代码
import music
import random

musicThreads = []
count = 0
index = 0
flag = True

def playMusic():
   global index
   global count
   global flag
   global musicThreads
   musicThread = music.MusicThread()
   musicThreads.append(musicThread)
   count = musicThread.getCount()
   index = random.randint(0, count-1)
   musicThread.setId(index)
   musicThread.start()
   flag = False

def stopMusic():
   global index
   global count
   global flag
   global musicThreads
   index = musicThreads[-1].getId()
   musicThreads[-1].setId(count-1)
   musicThreads[-1].stop()
   flag = True

def nextSong():
   global index
   global musicThreads
   musicThreads[-1].stop() 

def prevSong():
   global index
   global musicThreads
   index = index - 1
   musicThreads[-1].setId(index)
   musicThreads[-1].stop()

所有这些语音助手部分的代码都是基于最初的《树莓派智能语音助手之功能整合》修改的,有兴趣的小伙伴可以自行拼接。

好了,执行了如上代码后,树莓派智能语音助手也可以通过语音播放音乐了。

最后补充3个事情:

1.语音控制模块我是调用了sounddevice和soundfile的库,其中soundfile又是基于libsndfile来解码音频文件的。但是,我的raspbian能升级的libsndfile版本最高只有1.0.28,这个库在1.1.0版本下是不支持MP3解码的,所以,最终播放的音乐,我都是在pc端把MP3转格式为wav后才能使用。但是我在pc端windows下没有这个问题。在使用这个库之前可以先查看一下libsndfile的版本。

2.用于语音识别的录音模块我用的也是sounddevice,所以,要修改下record.py,在下面这句中添加一个参数device=,等号后面填写你录音所用的设备编号。

audio = sd.rec(int(self.duration * self.sample_rate), samplerate=self.sample_rate, channels=1)

查看有哪些音频设备,可以在终端输入:

python -m sounddevice

回车后就会list你可用音频设备列表,如下图就是我树莓派上的,我选择的是2号USB PNP SOUND DEVICE,所以上面新增的device参数可以写device=3

这样修改后,就可以让音乐播放和语音输入两个功能相对独立存在。

3.一开始在执行音乐播放时遇到了output underflow的提示,导致语音助手都卡壳了。后来查了文档解决了这个问题,具体解决方法可以看:

​​​​​​​用sounddevice播放音乐遇到output underflow提示-CSDN博客

相关推荐
乔江seven11 小时前
【python轻量级Web框架 Flask 】2 构建稳健 API:集成 MySQL 参数化查询与 DBUtils 连接池
前端·python·mysql·flask·web
放氮气的蜗牛11 小时前
从头开始学习AI:第五章 - 多分类与正则化技术
人工智能·学习·分类
Black蜡笔小新11 小时前
终结“监控盲区”:EasyGBS视频质量诊断技术多场景应用设计
人工智能·音视频·视频质量诊断
聊聊科技11 小时前
打破固化编曲思维,AI编曲软件为原创音乐人注入制作歌曲伴奏新创意
人工智能
智驱力人工智能11 小时前
货车违规变道检测 高速公路安全治理的工程实践 货车变道检测 高速公路货车违规变道抓拍系统 城市快速路货车压实线识别方案
人工智能·opencv·算法·安全·yolo·目标检测·边缘计算
乾元11 小时前
实战案例:解析某次真实的“AI vs. AI”攻防演练
运维·人工智能·安全·web安全·机器学习·架构
AiTop10011 小时前
智谱开源GLM-OCR:0.9B小模型在复杂文档处理登顶SOTA
人工智能·ai·aigc
晓晓不觉早11 小时前
OpenAI Codex App的推出:多代理工作流的新时代
人工智能·gpt
大数据在线12 小时前
硬件涨价超级周期:智算中心价值逻辑迎来重构
人工智能·数据中心·智算中心·内存涨价·曙光存储
2301_8107301012 小时前
python第四次作业
数据结构·python·算法