使用科大讯飞api以及文心一言模型实现对话(二)

接上篇语音转文字以及智能对话链接http://t.csdnimg.cn/LA0Lb 

以下代码实现文字转语音并且转化为可播放的wav的格式并且播报python代码

import websocket

import datetime

import hashlib

import base64

import hmac

import json

from urllib.parse import urlencode

import time

import ssl

from wsgiref.handlers import format_date_time

from datetime import datetime

from time import mktime

import _thread as thread

import os

import subprocess

import pygame

import platform

import wave

STATUS_FIRST_FRAME = 0  # 第一帧的标识

STATUS_CONTINUE_FRAME = 1  # 中间帧标识

STATUS_LAST_FRAME = 2  # 最后一帧的标识

counter = 0  # 定义全局变量 counter

# 创建一个全局变量来存储音频数据

audio_data = b''


 

class Ws_Param(object):

    # 初始化

    def __init__(self, APPID, APIKey, APISecret, Text, save_folder):

        self.APPID = APPID

        self.APIKey = APIKey

        self.APISecret = APISecret

        self.Text = Text

        self.save_folder = save_folder

        # 公共参数(common)

        self.CommonArgs = {"app_id": self.APPID}

        # 业务参数(business),更多个性化参数可在官网查看

        self.BusinessArgs = {"aue": "raw", "auf": "audio/L16;rate=16000", "vcn": "xiaoyan", "tte": "utf8"}

        self.Data = {"status": 2, "text": str(base64.b64encode(self.Text.encode('utf-8')), "UTF8")}

    # 生成url

    def create_url(self):

        url = 'wss://tts-api.xfyun.cn/v2/tts'

        # 生成RFC1123格式的时间戳

        now = datetime.now()

        date = format_date_time(mktime(now.timetuple()))

        # 拼接字符串

        signature_origin = "host: " + "ws-api.xfyun.cn" + "\n"

        signature_origin += "date: " + date + "\n"

        signature_origin += "GET " + "/v2/tts " + "HTTP/1.1"

        # 进行hmac-sha256进行加密

        signature_sha = hmac.new(self.APISecret.encode('utf-8'), signature_origin.encode('utf-8'),

                                 digestmod=hashlib.sha256).digest()

        signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')

        authorization_origin = "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"" % (

            self.APIKey, "hmac-sha256", "host date request-line", signature_sha)

        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')

        # 将请求的鉴权参数组合为字典

        v = {

            "authorization": authorization,

            "date": date,

            "host": "ws-api.xfyun.cn"

        }

        # 拼接鉴权参数,生成url

        url = url + '?' + urlencode(v)

        return url

def on_message(ws, message):

    global audio_data  # 声明我们要使用全局变量 audio_data

    try:

        message = json.loads(message)

        code = message["code"]

        sid = message["sid"]

        audio = message["data"]["audio"]

        audio = base64.b64decode(audio)

        status = message["data"]["status"]

        if status == 2:

            print("ws is closed")

            ws.close()

        if code != 0:

            errMsg = message["message"]

            print("sid:%s call error:%s code is:%s" % (sid, errMsg, code))

        else:

              # 将接收到的音频数据添加到 audio_data

            audio_data += audio

            if status == 2:  # 如果接收到表示音频结束的消息

                # 生成唯一的文件名

                filename = "output" + str(counter) + ".pcm"

                file_path = os.path.join(wsParam.save_folder, filename)

                with open(file_path, 'wb') as f:

                    f.write(audio_data)  # 将所有音频数据写入文件

                # 保存音频文件

                save_as_wav(file_path)

                # 播放文件

                audio_data = b''  # 清空 audio_data 以便于下一次使用

    except Exception as e:

        print("receive msg, but parse exception:", e)

def play_audio(file_path):

    # 初始化 pygame

    pygame.mixer.init()

    # 加载音频文件

    pygame.mixer.music.load(file_path)

    # 播放音频文件

    pygame.mixer.music.play()

    # 等待音频播放完毕

    while pygame.mixer.music.get_busy():

        pygame.time.Clock().tick(10)



 

def save_as_wav(file_path):

    # 将 PCM 格式的音频转换为 WAV 格式

    pcm_path = file_path

    wav_path = os.path.splitext(file_path)[0] + '.wav'

    with wave.open(wav_path, 'wb') as wf:

        wf.setnchannels(1)

        wf.setsampwidth(2)

        wf.setframerate(16000)

        with open(pcm_path, 'rb') as pcmf:

            data = pcmf.read()

            wf.writeframes(data)

    play_audio(wav_path)

# 收到websocket错误的处理

def on_error(ws, error):

    print("### error:", error)


 

# 收到websocket关闭的处理

def on_close(ws):

    print("### closed ###")


 

# 收到websocket连接建立的处理

def on_open(ws):

    def run(*args):

        d = {"common": wsParam.CommonArgs,

             "business": wsParam.BusinessArgs,

             "data": wsParam.Data,

             }

        d = json.dumps(d)

        print("------>开始发送文本数据")

        ws.send(d)

    thread.start_new_thread(run, ())


 

def text_to_speech(text, save_folder):

    global wsParam  # 声明我们要使用全局变量 wsParam

    # 使用讯飞的语音合成 API

    print("hello")

    if not isinstance(text, str) or not text:

        print("Error: text 参数必须是一个非空的字符串")

        return

   

       # 使用讯飞的语音合成 API

    wsParam = Ws_Param(APPID='a54e918d', APISecret='YjU5MjYwZmNmODM0YmM5ODA2MmI3YmNl',

                       APIKey='a0da0eb117e75c5b24dee425178f311d',

                       Text=text,

                       save_folder=save_folder)

    websocket.enableTrace(False)

    wsUrl = wsParam.create_url()

    ws = websocket.WebSocketApp(wsUrl, on_message=on_message, on_error=on_error, on_close=on_close)

    ws.on_open = on_open

    ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})




 

if __name__ == "__main__":

    # 指定保存音频文件的文件夹

    save_folder = r"C:\Usxxxxxxxxxxx"

    # 测试时候在此处正确填写相关信息即可运行

    wsParam = Ws_Param(APPID='a54e918d', APISecret='YjU5MjYwZmNmODM0YmM5ODxxxxxxNl',

                       APIKey='a0da0eb117e75c5b24dxxxxxx',

                       Text="这是一个语音合成示例1111111111",

                       save_folder=save_folder)

    websocket.enableTrace(False)

    wsUrl = wsParam.create_url()

    ws = websocket.WebSocketApp(wsUrl, on_message=on_message, on_error=on_error, on_close=on_close)

    ws.on_open = on_open

    ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})

  • 40
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值