一個資深小說迷打開小說的正確姿勢(續)----百度AI文字轉語音

前段時間閒得無聊,使用python抓取了自己想看的小說,抓取方法:一個資深小說迷打開小說的正確姿勢
在這裏插入圖片描述
最近發現連續長時間盯着屏幕,眼睛實在是有點遭不住。對於我這種又想保護視力,又不想放下小說的人來說,簡直就是遇到了像 “ 魚與熊掌不可兼得” 一般的世紀難題。
在這裏插入圖片描述
正當我思考如何兩害取其輕的時候,有人私信我幫忙做一個文字轉語音的接口,我突然靈機一動,這簡直就是送上門來的滿分答案啊
在這裏插入圖片描述
當然,對於我這種社畜來說,是萬萬不可能自己實現文字轉語音功能的,我沒有那個精力,更沒有那個 money
在這裏插入圖片描述
不過,咱不會煮飯,咱還不會點外賣麼?O(∩_∩)O哈哈~
在這裏插入圖片描述
打開快被我點裂開了的 google chrome 搜了搜,果然很多公司都提供現成的免費接口,比如百度、訊飛…最後我選擇了百度AI接口(這種東西啊,就和點外賣是一樣的,同樣都是芋兒雞,店家不一樣,做出來的味道就有好有壞。當你都沒吃過時,牌子大一點的店或許是個不壞的選擇)
在這裏插入圖片描述
言歸正傳,首先你得去百度控制檯登錄一下,沒有百度賬號的需要註冊:
https://ai.baidu.com/tech/speech
在這裏插入圖片描述

然後需要創建一個應用,創建好了之後,就能拿到我們想要的三個東西
在這裏插入圖片描述
然後,python需要安裝兩個庫(百度接口庫和語音播放庫),如果不需要python播放音頻的話,只需要安裝第一個庫就行:

pip install baidu-aip
pip install playsound

根據百度提供的接口文檔https://ai.baidu.com/ai-doc/SPEECH/Gk4nlz8tc,我們可以很容易的將一段文本翻譯成音頻文件,如:

from aip import AipSpeech	# 導入api接口
from playsound import playsound	# 音頻模塊

#對應填入百度控制檯獲取的三個參數
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)

data = '你是最棒的,hello world'
result = client.synthesis(data, 'zh', 1, {
    'per': 4,
    'spd': 3,    # 速度
    'vol': 7   # 音量
})
if not isinstance(result, dict):
    with open('hello.mp3', 'wb') as f:
        f.write(result)

# 播放
playsound("hello.mp3")

上面這段代碼,你只需要對應的填入百度後臺獲取的三個參數,然後運行文件,就會在你的代碼文件同級目錄下生成一個音頻文件hello.mp3,並且會有美女誇你
在這裏插入圖片描述
有美女誇固然是好,可是我們最初的夢想是聽小說啊。
在這裏插入圖片描述
彆着急,你只需要將代碼中的 data 內容換成咱們使用爬蟲爬下來的小說內容,如:

#讀取文本文件內容
    with open(file_name, 'r', encoding='utf-8') as f:
        data = f.read()

此時要注意,百度API每一次翻譯的文本長度必須小於1024字節,小說每一章的內容往往大於1024字節,怎麼辦呢?
咱們可以將文本分割,然後多次請求就行了,寫一個分割方法,像這樣:

#按指定字節數分割字符串
def byte_split(seq):
    list = []
    while seq:
        if len(seq) >= 1024:
            list.append(seq[:1024])
            seq = seq[1024:]
        else:
            list.append(seq)
            seq = []
    return list

簡單封裝一下,第一版就出爐啦:

from aip import AipSpeech	# 導入api接口
from playsound import playsound	# 音頻模塊
import sys


#百度賬號信息配置
#對應填入百度控制檯獲取的三個參數
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''

client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)

#按指定字節數分割字符串
def byte_split(seq):
    list = []
    while seq:
        if len(seq) >= 1024:
            list.append(seq[:1024])
            seq = seq[1024:]
        else:
            list.append(seq)
            seq = []
    return list
 
'''
 @desc 寫入音頻
 
 @param data_arr list 文件數組
 @param vedio_name string 音頻文件名
 
 @return 音頻文件名
'''
def vedio_write(data_arr, vedio_name):
    name = vedio_name + '.mp3'
    for i in data_arr:
        #請求百度接口,獲取語音二進制
        result = client.synthesis(i, 'zh', 1, {
            'per': 4,
            'spd': 3,    # 速度
            'vol': 7   # 音量
        })
        #判斷是否翻譯成功-成功則寫入,失敗則打印錯誤信息
        if not isinstance(result, dict):
            with open(name, 'ab') as f:
                f.write(result)
        else:
            print(result)
    return name    


#主函數
if __name__ == "__main__":
    #文本文件
    file_name = r'../novel/quanzhifashi/第1章 世界大變.txt'
    #音頻文件名
    vedio_name = file_name.split('/')[-1].split('.')[0]
    

    #讀取文本文件內容
    with open(file_name, 'r', encoding='utf-8') as f:
        data = f.read()

    #按字符串拆分成數組
    data_arr = byte_split(data) 
    
    #寫入音頻,返回音頻文件名
    vedio = vedio_write(data_arr, vedio_name)     
    
    # 播放
    playsound(vedio)

點擊運行,在我的保存目錄找到了自己想要的結果
在這裏插入圖片描述
但是並沒有給我播放視頻,而且反手扔給我一個Error
在這裏插入圖片描述
查看報錯信息發現,由於我的音頻文件是中文名,所以播放失敗了,將中文換掉就可以正常播放。

但是總有像我一樣槓中帶倔的人,喜歡將音頻文件命名爲中文,怎麼辦呢?當然是打開我那要裂開了的google chrome 啊。巡視了一圈,最後發現pygame庫可以解決這個問題。好嘛,安裝pygame庫:

pip install pygame

封裝個方法,使用pygame播放音頻:

# 播放音頻
# 貌似只能播放單聲道音樂,可能是pygame模塊限制
def playMusic(filename, loops=0, start=0.0, value=0.5):
    """
    :param filename: 文件名
    :param loops: 循環次數
    :param start: 從多少秒開始播放
    :param value: 設置播放的音量,音量value的範圍爲0.0到1.0
    :return:
    """
    flag = False  # 是否播放過
    pygame.mixer.init()  # 音樂模塊初始化
    while 1:
        if flag == 0:
            pygame.mixer.music.load(filename)
            # pygame.mixer.music.play(loops=0, start=0.0) loops和start分別代表重複的次數和開始播放的位置。
            pygame.mixer.music.play(loops=loops, start=start)
            pygame.mixer.music.set_volume(value)  # 來設置播放的音量,音量value的範圍爲0.0到1.0。
        if pygame.mixer.music.get_busy() == True:
            flag = True
        else:
            if flag:
                pygame.mixer.music.stop()  # 停止播放
                break

再將之前的代碼整合一下子,最終版本就出爐了:

from aip import AipSpeech	# 導入api接口
#from playsound import playsound	# 音頻模塊
import sys
import pygame


#百度賬號信息配置
#對應填入百度控制檯獲取的三個參數
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''

client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)

#按指定字節數分割字符串
def byte_split(seq):
    list = []
    while seq:
        if len(seq) >= 1024:
            list.append(seq[:1024])
            seq = seq[1024:]
        else:
            list.append(seq)
            seq = []
    return list
 
'''
 @desc 寫入音頻
 
 @param data_arr list 文件數組
 @param vedio_name string 音頻文件名
 
 @return 音頻文件名
'''
def vedio_write(data_arr, vedio_name):
    name = vedio_name + '.mp3'
    for i in data_arr:
        #請求百度接口,獲取語音二進制
        result = client.synthesis(i, 'zh', 1, {
            'per': 4,
            'spd': 3,    # 速度
            'vol': 7   # 音量
        })
        #判斷是否翻譯成功-成功則寫入,失敗則打印錯誤信息
        if not isinstance(result, dict):
            with open(name, 'ab') as f:
                f.write(result)
        else:
            print(result)
    return name    

# 播放音頻
# 貌似只能播放單聲道音樂,可能是pygame模塊限制
def playMusic(filename, loops=0, start=0.0, value=0.5):
    """
    :param filename: 文件名
    :param loops: 循環次數
    :param start: 從多少秒開始播放
    :param value: 設置播放的音量,音量value的範圍爲0.0到1.0
    :return:
    """
    flag = False  # 是否播放過
    pygame.mixer.init()  # 音樂模塊初始化
    while 1:
        if flag == 0:
            pygame.mixer.music.load(filename)
            # pygame.mixer.music.play(loops=0, start=0.0) loops和start分別代表重複的次數和開始播放的位置。
            pygame.mixer.music.play(loops=loops, start=start)
            pygame.mixer.music.set_volume(value)  # 來設置播放的音量,音量value的範圍爲0.0到1.0。
        if pygame.mixer.music.get_busy() == True:
            flag = True
        else:
            if flag:
                pygame.mixer.music.stop()  # 停止播放
                break



#主函數
if __name__ == "__main__":
    #文本文件
    file_name = r'../novel/quanzhifashi/第1章 世界大變.txt'
    #音頻文件名
    vedio_name = file_name.split('/')[-1].split('.')[0]
    

    #讀取文本文件內容
    with open(file_name, 'r', encoding='utf-8') as f:
        data = f.read()

    #按字符串拆分成數組
    data_arr = byte_split(data) 
    
    #寫入音頻,返回音頻文件名
    vedio = vedio_write(data_arr, vedio_name)     

    #音頻播放
    playMusic(vedio)
    #playMusic('out.wav')
    
    # 播放
    #playsound(vedio)

誰說魚與熊掌不可兼得?

The end !

一個人最好的生活狀態,有自己的生活和情趣,努力完善自己。沒人愛時專注自己,有人愛時,有能力擁抱彼此。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章