驚!Python居然可以讀故事了

2020-10-25 14:01:02

我有故事,讓機器人來讀

最近工作較忙,回家閒下來只想閉目休息,一分鐘螢幕都不想再看,然而我又想追更之前看的小說,於是,需求來了——我需要一個給我講故事的機器人!

瀏覽器或者閱讀器App裡其實也有朗讀功能,但是比較僵硬,總是將引人入勝的情節念成流水賬,分分鐘讓人棄坑,所以我考慮自己使用爬蟲定時下載更新的章節,而後將文字合成儲存到音訊檔,這樣不僅可以選擇一個靠譜的語音合成工具來處理文字,而且儲存下來的音訊還能反覆收聽,一舉兩得。

文字整合容易,但是如何將其快速轉換成音訊呢?難道要自己訓練模型「煉丹」解決?no no ,費力不討好,畢竟自己手頭這點演演算法知識非常淺顯,而且硬體條件也不允許,本著「能用就行」的原則,我決定先使用市面上開放平臺的產品來解決。經過對比,發現有道智雲的語音合成還不錯(此處可體驗),決定使用有道智雲的語音合成API進行開發。

效果先睹為快:

我拿來朱自清先生的《荷塘月色》的其中兩段作為實驗素材,開發了簡單的demo,走通了從載入文字到生成音訊檔的邏輯,下面我來詳細介紹開發過程。

在這裡插入圖片描述

需要語音合成的文字:

在這裡插入圖片描述

合成結果(第一段):

合成結果(第二段):

很可惜,這裡不能上傳mp3格式的音樂檔案

在這裡插入圖片描述

呼叫API介面的準備工作

首先,是需要在有道智雲的個人頁面上建立範例、建立應用、繫結應用和範例,獲取到應用的id和金鑰。具體個人註冊的過程和應用建立過程詳見文章分享一次批次檔案翻譯的開發過程

在這裡插入圖片描述

開發過程詳細介紹

下面介紹具體的程式碼開發過程。

首先根據檔案分析有道智雲的API輸入輸出規範。語音合成API呼叫十分簡單,該API採用https方式通訊,所需引數如下表:

欄位名型別含義必填備註
qtext待合成音訊檔的文字字串True比如:您好
langTypetext合成文字的語言型別True支援語言
appKeytext應用 IDTrue可在 應用管理 檢視
salttextUUIDTrueUUID
signtextTrueMD5(應用ID+q+salt+應用金鑰)
voicetext翻譯結果發音選擇,0為女聲,1為男聲,預設為女聲false0
formattext目標音訊格式,支援mp3falsemp3
speedtext合成音訊的語速false比如:"1"為正常速度
volumetext合成音訊的音量false正常為"1.00",最大為"5.00",最小為"0.50"

簡單概括,組織好自己的語言(utf-8編碼文字),輔以簽名等必要引數,並告訴API所需要的音訊特徵,即可得到一份令人滿意的合成音訊。

介面輸出中,如果合成成功,正常返回為二進位制語音檔案,具體header資訊 Content-type: audio/mp3,如果合成出現錯誤,則會返回json結果,具體header資訊為:Content-type: application/json,可據此判斷執行情況。

Demo開發:

這個demo使用python3開發,包括maindow.py,synthesis.py,synthesistool.py三個檔案,分別為demo的介面、介面邏輯處理和語音合成介面呼叫工具封裝。

  1. 介面部分:

    介面部分程式碼如下,比較簡單。

    root=tk.Tk()
    root.title("youdao speech synthesis test")
    frm = tk.Frame(root)
    frm.grid(padx='50', pady='50')
    # 檔案選取按鈕
    btn_get_file = tk.Button(frm, text='選擇待合成檔案', command=get_files)
    btn_get_file.grid(row=0, column=0, ipadx='3', ipady='3', padx='10', pady='20')
    # 所選檔案列表展示框
    text1 = tk.Text(frm, width='40', height='10')
    text1.grid(row=0, column=1)
    # 啟動按鈕
    btn_sure=tk.Button(frm,text="合成",command=synthesis_files)
    btn_sure.grid(row=1,column=1)
    

    其中啟動按鈕btn_sure的繫結事件synthesis_files()來收集帶所有的文字檔案,啟動合成,並列印執行結果:

    def synthesis_files():
        if syn_m.file_paths:
            message=syn_m.get_synthesis_result()
            tk.messagebox.showinfo("提示", message)
            os.system('start' + '.\\result')
        else :
            tk.messagebox.showinfo("提示","無檔案")
    
  2. synthesis.py

    這裡主要是配合介面實現一些文字讀取和請求介面處理返回值的邏輯。首先定義一個Synthesis_model

    class Synthesis_model():
        def __init__(self,file_paths,result_root_path,syn_type):
            self.file_paths=file_paths				# 待合成檔案路徑
            self.result_root_path=result_root_path  # 結果路徑
            self.syn_type=syn_type                  # 合成型別
    

    get_synthesis_result()方法實現了批次讀取檔案並呼叫合成方法、處理返回資訊的邏輯:

        def get_synthesis_result(self):
            syn_result=""
            for file_path in self.file_paths:
                # 讀取檔案
                file_name=os.path.basename(file_path).split('.')[0]
                file_content=open(file_path,encoding='utf-8').read()
                # 呼叫合成方法
                result=self.synthesis_use_netease(file_name,file_content)
                # 處理返回訊息
                if result=="1":
                    syn_result=syn_result+file_path+" ok !\n"
                else:
                    syn_result=syn_result+file_path+result
            return syn_result
    

    單獨定義了方法synthesis_use_netease()具體實現呼叫API的方法,這樣增加了demo的擴充套件性,實現了一種合成模組可插拔的鬆耦合形式:

    def synthesis_use_netease(self,file_name,text):
        result=connect(text,'zh-CHS')
        print(result)
        if result.headers['Content-Type']=="audio/mp3":
            millis = int(round(time.time() * 1000))
            filePath = "./result/" + file_name+"-"+str(millis) + ".mp3"
            fo = open(filePath, 'wb')
            fo.write(result.content)
            fo.close()
            return "1"
        else:
            return "error:"+result.content
    
  3. synthesistool.py
    1. synthesistool.py中是和請求有道智雲API直接相關的一些方法,最核心的是connect()方法,整合了API所要求的各個引數,並呼叫執行請求的方法do_request(),並返回API處理結果。

      def connect(text,lang_type):
          q = text
      
          data = {}
          data['langType'] = lang_type
          salt = str(uuid.uuid1())
          signStr = APP_KEY + q + salt + APP_SECRET
          sign = encrypt(signStr)
          data['appKey'] = APP_KEY
          data['q'] = q
          data['salt'] = salt
          data['sign'] = sign
      
          response = do_request(data)
          return response
      

    需要體驗一下的小夥伴,請下載我的程式碼自行嘗試或去官網體驗 : P。專案地址:https://github.com/LemonQH/SpeechSynthesis

    特別提示:
    1、執行demo時,需要替換synthesistool.py模組中的 APP_KEY 、 APP_SECRET為你自己生成的 APP_KEY、APP_SECRET哦
    2、該工程預設存放結果存在./result 資料夾下,你需要手動在專案路徑下建立該目錄。或者修改為任意你想存放的位置

總結

以上就是我的開發過程,有道智雲的語音合成API檔案清晰,呼叫過程全程無坑,開發體驗和合成效果都令人感到舒適。

我有故事,我把它交給機器人來講,閉目養神不枯燥,真是一件美事!

歡迎關注我,一塊來履行我之前的承諾連更一個月之內,把幾篇寫完。

序號預計完成時間開發dome名字以及功能&釋出文章內容是否已寫完文章連結
19月3文字翻譯,單文字翻譯,批次翻譯demo。已完成CSDN:點我直達
微信公眾號:點我直達
29月11OCR-demo,完成批次上傳識別;在一個demo中可選擇不同型別的OCR識別《包含手寫體/印刷體/身份證/表格/整題/名片),然後呼叫平臺能力,具體實現步驟等。已完成CSDN:點我直達
微信公眾號:
310月27語音識別demo,demo中上傳—段視訊,並擷取視訊中短語音識別-demo的一段音訊進行短語音識別CSDN:點我直達
微信公眾號:
49月17智慧語音評測-demoCSDN:
微信公眾號:
59月24作文批改-demoCSDN:
微信公眾號:
69月30語音合成-demoCSDN:
微信公眾號:
710月15單題拍搜-demoCSDN:
微信公眾號:
810月20圖片翻譯-demoCSDN:
微信公眾號:

關注我微信公眾號第一時間推播給你哦:

回覆選單,更有好禮,驚喜在等著你。

在這裡插入圖片描述

歡迎掃碼加入我建立的社群群哦,可以與我更進一步的交流,群裡還有很多大佬等著你,一起玩耍,一起進步!!!
在這裡插入圖片描述

TrueDei CSDN認證部落格專家 Linux 分散式 Java
不荒廢現在,不畏懼未來!我認為把知識給別人講會,講明白,自己才徹底明白。努力把文章寫好,寫明白每一篇文章,分享給更多人。