1. 程式人生 > >使用樹莓派3B+開發智慧音樂播放器

使用樹莓派3B+開發智慧音樂播放器

一、功能描述

對麥克風說出歌名後,樹莓派自動下載對應歌曲的MP3,預設播放搜尋到的第一首歌曲。

二、硬體裝置

1、樹莓派3B+

2、sony的ps3 eye麥克風一個(淘寶20塊一個,帶攝像頭和4個麥克風陣列,USB連線)

3、藍芽音箱


三、需要的python庫

1、pyaudio:用於採集麥克風語音訊號

2、baidu-aip:使用百度的AI庫,用於語音識別,將語音轉化為文字和將文字轉化為語音。需要到百度AI上註冊,獲取ID和KEY

3、requests:網路爬蟲,用於搜尋歌曲的MP3並下載,爬取百度

4、pygame:用於音樂檔案播放

四、原始碼

# -*- coding: utf-8 -*-

from aip import AipSpeech  #百度語音識別庫
import pyaudio             #麥克風聲音採集庫
import wave
import requests,json       #音樂搜尋
import pygame              #mp3播放
import os
import time
import sys
""" 我的 APPID AK SK """
APP_ID = 'XXXXXXX' #需要到百度AI註冊申請ID  KEY 
API_KEY = 'XXXXXXXXXXXXXXXXXX'
SECRET_KEY = 'XXXXXXXXXXXXXXXXX'

#定義採集聲音檔案引數
CHUNK = 1024
FORMAT = pyaudio.paInt16 #16位採集
CHANNELS = 1             #單聲道
RATE = 16000             #取樣率
RECORD_SECONDS = 9       #取樣時長 定義為9秒的錄音
WAVE_OUTPUT_FILENAME = "/home/pi/my_python_programe/myvoice.pcm"  #採集聲音檔案儲存路徑

def get_file_content(filePath):
    with open(filePath, 'rb') as fp:
        return fp.read()

#獲取下載地址
def get_down_url(songid):
    req=requests.get("http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.song.play&format=jsonp&callback=jQuery17206073972467458864_1511011710426&songid=%s&_=1511011713541" %songid)
    req.encoding='utf-8'
    #print(json.loads(req.text))
    json1=json.loads(req.text.replace("jQuery17206073972467458864_1511011710426(","").replace(");",""))
    print("下載地址:",json1["bitrate"]['show_link'])
    return json1["bitrate"]['show_link']
#下載儲存檔案
def music_down(url,music_name,artistname):
    f=open(music_name+'-'+artistname+'.mp3','wb')
    req_mp3=requests.get(url)
    f.write(req_mp3.content)
    f.close()
#呼叫百度AI,將文字轉化為聲音輸出,用於提示音
def word_to_voice(text):
    result = client.synthesis(text, 'zh', 1, {
        'vol': 5, 'spd': 3, 'per': 3})
    if not isinstance(result, dict):
        with open('/home/pi/my_python_programe/audio.mp3', 'wb') as f:
            f.write(result)
            f.close()
    pygame.mixer.music.load('/home/pi/my_python_programe/audio.mp3')#text文字轉化的語音檔案
    pygame.mixer.music.play(loops=0)
    while pygame.mixer.music.get_busy() == True:
        print('waiting')

def word_to_voice1(text):
    result = client.synthesis(text, 'zh', 1, {
        'vol': 5, 'spd': 3, 'per': 3})
    if not isinstance(result, dict):
        with open('/home/pi/my_python_programe/audio1.mp3', 'wb') as f:
            f.write(result)
            f.close()
    pygame.mixer.music.load('/home/pi/my_python_programe/audio1.mp3')
    pygame.mixer.music.play(loops=0)
    while pygame.mixer.music.get_busy() == True:
        print('waiting')

#獲得麥克風輸入的聲音檔案,儲存在myvoice.pcm
def  get_mic_voice_file(p):
    word_to_voice('請說出歌名')

    stream = p.open(format=FORMAT,
                    channels=CHANNELS,
                    rate=RATE,
                    input=True,
                    frames_per_buffer=CHUNK)
    print("* recording")

    frames = []
    for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        data = stream.read(CHUNK)
        frames.append(data)
    print("* done recording")
    stream.stop_stream()
    stream.close()
    #p.terminate()#這裡先不使用p.terminate(),否則 p = pyaudio.PyAudio()將失效,還得重新初始化。
    wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b''.join(frames))
    wf.close()
    print('recording finished')

#百度語音識別出歌名文字並返回
def  baidu_get_song_name(client):
    results = client.asr(get_file_content(WAVE_OUTPUT_FILENAME), 'pcm', 16000, { 'dev_pid': 1536, })
    # print(results['result'])
    song_name=results['result'][0]
    print(song_name)
    return song_name

#百度音樂下載歌曲,取自百度
def download_music_file(song_name):
    req_url = "http://sug.music.baidu.com/info/suggestion?format=json&word=%s&version=2&from=0&callback=window.baidu.sug&third_type=0&client_type=0&_=1511013032878" % song_name
    req_so = requests.get(req_url)
    data = json.loads(req_so.text.replace("window.baidu.sug(", "").replace(");", ""))
    for i in data["data"]["song"]:
        print("\tsongid:" + str(i["songid"]), "音樂名字:" + i["songname"], "\t歌手:" + i["artistname"])
    input_songid = data["data"]["song"][0]["songid"]  # input("請輸入你要下載的songid:")
    for i in data["data"]["song"]:
        if input_songid == str(i["songid"]):
            url = get_down_url(i["songid"])
            music_down(url, i["songname"], i["artistname"])
            print("下載完成")
            music_name = i['songname']  # 獲取MP3檔案中的歌曲名
            artistname = i["artistname"]  # 獲取MP3檔案中的歌手名
    filename = '/home/pi/my_python_programe/' + music_name + '-' + artistname + '.mp3'
    print(filename)

    word_to_voice1('請欣賞')
    return filename

def play_mp3(music_file):
    pygame.mixer.music.load(music_file)
    '''while True:
        # 檢查音樂流播放,有返回True,沒有返回False
        # 如果一直有音樂流則選擇播放
        if pygame.mixer.music.get_busy() == False:
            pygame.mixer.music.play()'''
    pygame.mixer.music.play(loops=0)  #該函式執行後立即返回,音樂一直在後臺執行

def one_time_process(p):#一次麥克取樣+語音識別+音樂下載+自動播放
    get_mic_voice_file(p)
    play_mp3(download_music_file(baidu_get_song_name(client)))



if __name__=='__main__':
    #麥克風採集初始化、百度語音識別初始化、mp3檔案播放初始化
    p = pyaudio.PyAudio()
    client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
    pygame.mixer.init()
    #


    while 1:#迴圈呼叫麥克錄音
        one_time_process(p)
        while pygame.mixer.music.get_busy()==True:
            print('playing')

四、其他

1、在/home/pi下新建my_python_programe資料夾,將程式檔案拷貝到該資料夾下,“python3  檔名.py”執行程式。

2、程式只是個雛形,還有許多不完善和BUG,下一步將加入snowboy語音喚醒功能。