AI 文本语音互转的Python例子 (仅后台代码)

AI.py

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

# ################## 入口类 ##################
import os
from flask import Flask,render_template,request
from LogX import Log1
from AI_TTS_Azure import Azure
from AI_VoiceToText_Baidu import BaiduAi

log1 = Log1.log(None)
# static_url_path='' 指明静态资源在 /static/ 下,URL 路径则可以直接省略 static 路径
App3 = Flask(__name__, static_url_path='')
App3.secret_key = os.urandom(32) #'U2FsdGVkX19B/bZVZXszkfQOBEseDukn' # AES,jiami,Hsbc123#

########## 首页
@App3.route('/', methods=['GET', 'POST'])
@App3.route('/home', methods=['GET', 'POST'])
@App3.route('/index', methods=['GET', 'POST'])
def home():
    return render_template('home.html')

########## 文本转语音
@App3.route('/index1', methods=['GET'])
def index1():
    return render_template('index1.html')

########## 文本转语音
@App3.route('/index1', methods=['POST'])
def index1_tts():
    result = Azure.ttsMain(None,request0=request)
    return render_template('index1.html', msg=result['msg'], filepath=result['filepath'])

########## 文本转语音
@App3.route('/index2', methods=['GET'])
def index2():
    return render_template('index2.html')

########## 文本转语音
@App3.route('/index2', methods=['POST'])
def index2_stt():
    result = BaiduAi.sttMain(None,request0=request)
    return render_template('index2.html', msg=result['msg'], filepath=result['filepath'])


if __name__=='__main__':
    App3.run(host='0.0.0.0', port=6789)




AI_TTS_Azure.py

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


### 文本转语音 Azure ###
import os
import requests
import time
from xml.etree import ElementTree
from LogX import Log1
from ConfigFile import Config

log1 = Log1.log(None)
msg1 = '处理失败.'
filepath1 = ''

'''
快速入门:https://docs.microsoft.com/zh-cn/azure/cognitive-services/speech-service/quickstart-python-text-to-speech
官方源码:https://github.com/Azure-Samples/Cognitive-Speech-TTS/blob/master/Samples-Http/Python/TTSSample.py
获取密钥:https://azure.microsoft.com/zh-cn/try/cognitive-services/my-apis/?apiSlug=speech-services&country=China&allowContact=true&fromLogin=True
终结点: https://westus.api.cognitive.microsoft.com/sts/v1.0
获取Token接口:https://westus.api.cognitive.microsoft.com/sts/v1.0/issueToken
文本转语音接口:https://westus.tts.speech.microsoft.com/cognitiveservices/v1
密钥 1: 8c0779e6846c43478f83fb2bd2fdd610
密钥 2: c7fa26e8ea4c46368ddafbe76fdf0827
'''

proxyHttp   = Config.getBasic(None, 'http-proxy','http')
proxyHttps  = Config.getBasic(None, 'http-proxy','https')
azureKey1   = Config.getBasic(None, 'Azure-Key','key1')
azureKey2   = Config.getBasic(None, 'Azure-Key','key2')
azureKey    = azureKey1 if azureKey1=='' else azureKey2


class Azure(object):

    def ttsMain(self,request0):
        log1.warn(' >>> 进入 ttsMain ')
        global msg1
        global filepath1
        nowtime1 = time.strftime('%Y%m%d%H%M%S')
        texttype = request0.form['texttype']
        caiyanglv = request0.form['caiyanglv']
        yinse = request0.form['yinse']
        voicefilename1 = 'voice_' + nowtime1 + '_[' + caiyanglv + ']_[' + yinse + '].wav'

        voice_key = ''

        if texttype != '':  # 文本类型<表单输入文本,上传文件文本,指定网页文本>
            textcontent = ''
            uploadPath = os.getcwd() + '/upload/'
            if not os.path.exists(uploadPath):
                os.makedirs(uploadPath)

            #####[1] 表单文本
            if texttype == 'formtext':
                textcontent = request0.form['text1']
                if textcontent != '':
                    # log1.info(' 待转换的文本内容:\n' + textcontent)
                    log1.warn(' 开始转换语音-表单文本 ...')
                    filepath1 = Azure.textToVoice(None, text0=textcontent, voicefilename=voicefilename1,
                                                  voice_encode_type=caiyanglv, voice_speeker_type=yinse,
                                                  subscription_key=voice_key)
                    if filepath1 != '':
                        msg1 = '处理成功!'
                    else:
                        error = '处理失败!'
                else:
                    msg1 = '处理失败!请输入文本内容'
                    log1.error(' ' + msg1)

            #####[2] 文件文本
            elif texttype == 'filetext':
                fileObj1 = request0.files['file1']
                if fileObj1 != '':
                    filename0 = fileObj1.filename
                    filename0_ext = filename0.split('.')[-1]
                    filename0_ext_accept = ['txt', 'log', 'ini', 'conf']
                    if filename0_ext not in filename0_ext_accept:
                        msg1 = '处理失败!请上传纯文本格式的文件,支持的后缀:txt,log,ini,conf'
                        log1.error(' ' + msg1)
                    else:
                        filenamenew = nowtime1 + '.' + filename0_ext
                        abPath = uploadPath + '/text_' + filenamenew
                        log1.info(' 开始上传文件 ...')
                        fileObj1.save(abPath)
                        log1.info(' 文件上传成功:' + abPath)
                        fileUpload = open(abPath, 'r', encoding='utf-8').read()
                        for textline in fileUpload:
                            textcontent = textcontent + textline
                        log1.info(' 开始转换语音-上传文件 ...')
                        filepath1 = Azure.fileToVoice(None, filePath0=abPath, voicefilename=voicefilename1,
                                                      voice_encode_type=caiyanglv, voice_speeker_type=yinse,
                                                      subscription_key=voice_key)
                        if filepath1 != '':
                            msg1 = '处理成功!'
                        else:
                            msg1 = '处理失败!'
                else:
                    msg1 = '处理失败!请选择文件'
                    log1.error('>>> ' + msg1)

            #####[3] 网页文本
            elif texttype == 'webpagetext':
                msg1 = '您好,暂不支持网页方式.'
                log1.info(' ' + msg1)
                '''
                weburl1 = request.form['weburl1']
                if textcontent != '':
                    textcontent = weburl1 # 通过URL获取网页文本,应该加点过滤参数,获取指定DOM元素内的文本
                    log1.info('>>> 开始转换语音-网页地址 ...')
                    filepath1 = Azure.tts_text(None, text0=textcontent, voicefilename=voicefilename1,
                                               voice_encode_type=caiyanglv, voice_speeker_type=yinse, subscription_key=voice_key)
                    msg1 = '处理成功'
                else:
                    msg1 = '处理失败!请输入网页地址(URL)'
                    log1.info('>>> ' + msg1)
                '''
            #####[0] 参数错误
            else:
                msg1 = '处理失败!文本类型参数错误:texttype=' + texttype
                log1.error('>>> ' + msg1)

        else:
            msg1 = '处理失败!文本类型参数不能为空.'
            log1.error('>>> ' + msg1)

        if filepath1!='' :
            filepath1 = request0.url_root + filepath1.replace('static/', '')

        result = {'msg': msg1, 'filepath': filepath1}  # 返回结果,键值对,字典
        log1.warn('>>> 全部操作已经完成')
        log1.warn('>>> 返回结果:\nresult=' + str(result))

        return result


    ### 文件转语音
    def fileToVoice(self, filePath0, voicefilename, voice_encode_type, voice_speeker_type, subscription_key):
        filepath = ''

        log1.debug('传入的参数值:'
                      + '\nfilePath0=' + filePath0
                      + '\nvoicefilename=' + voicefilename
                      + '\nvoice_encode_type=' + voice_encode_type
                      + '\nvoice_speeker_type=' + voice_speeker_type)

        if subscription_key == '':
            subscription_key = 'c7fa26e8ea4c46368ddafbe76fdf0827'
        # tts = input('Input some text to convert to speech: ')  # 控制台输入
        # tts = 'Hello everyone, I am 18 years old and have a deposit of 1.23 million. I want to get a wife.'

        file_obj = open(filePath0, 'rb') # 英文内容:'rU',中文内容:,'rb'
        # tts = ''
        # for eachline in file_obj: # 一行一行读取
        #     if eachline != '':
        #         tts += eachline
        # tts = file_obj.read() # 英文内容
        tts = str(file_obj.read(), encoding='utf-8') # 中文内容
        #log1.debug(' 待转换文本:' + tts )

        timestr = time.strftime('%Y%m%d%H%M')
        proxies = {
            'http': proxyHttp,
            'https': proxyHttps,
        }
        fetch_token_url = 'https://westus.api.cognitive.microsoft.com/sts/v1.0/issueToken'
        headers = {
            'Ocp-Apim-Subscription-Key': subscription_key
        }
        response = requests.post(fetch_token_url, headers=headers, proxies=proxies, verify=False)
        access_token = str(response.text)
        #log1.debug(' 获取到Token:' + access_token)
        constructed_url = 'https://westus.tts.speech.microsoft.com/cognitiveservices/v1'
        headers = {
            # 前面带有单词 Bearer 的授权令牌
            'Authorization': 'Bearer ' + access_token,

            # 指定所提供的文本的内容类型。 接受的值:application/ssml+xml。
            'Content-Type': 'application/ssml+xml',

            # 指定音频输出格式,取值如下:
            # raw-16khz-16bit-mono-pcm  (百度AI的语音转文本时,需要采用这个格式,但Windows自带的播放器是无法播放的)
            # raw-8khz-8bit-mono-mulaw
            # riff-8khz-8bit-mono-alaw
            # riff-8khz-8bit-mono-mulaw
            # riff-16khz-16bit-mono-pcm
            # audio-16khz-128kbitrate-mono-mp3
            # audio-16khz-64kbitrate-mono-mp3
            # audio-16khz-32kbitrate-mono-mp3
            # raw-24khz-16bit-mono-pcm
            # riff-24khz-16bit-mono-pcm (这个格式 可以播放)
            # audio-24khz-160kbitrate-mono-mp3
            # audio-24khz-96kbitrate-mono-mp3
            # audio-24khz-48kbitrate-mono-mp3
            'X-Microsoft-OutputFormat': voice_encode_type,

            # 应用程序名称,少于 255 个字符。
            # Chrome的 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
            'User-Agent': 'Chrome/73.0.3683.86'
        }
        xml_body = ElementTree.Element('speak', version='1.0')
        xml_body.set('{http://www.w3.org/XML/1998/namespace}lang', 'en-us')
        voice = ElementTree.SubElement(xml_body, 'voice')
        voice.set('{http://www.w3.org/XML/1998/namespace}lang', 'en-US')
        # 标准语音列表:https://docs.microsoft.com/zh-cn/azure/cognitive-services/speech-service/language-support#standard-voices
        # 【下面5行:英语(美国)】	【语音性别,语音全称,语音简称】
        # 女	'Microsoft Server Speech Text to Speech Voice (en-US, ZiraRUS)'	'en-US-ZiraRUS'
        # 女	'Microsoft Server Speech Text to Speech Voice (en-US, JessaRUS)'	'en-US-JessaRUS'
        # 男	'Microsoft Server Speech Text to Speech Voice (en-US, BenjaminRUS)'	'en-US-BenjaminRUS'
        # 女	'Microsoft Server Speech Text to Speech Voice (en-US, Jessa24kRUS)'	'en-US-Jessa24kRUS'
        # 男	'Microsoft Server Speech Text to Speech Voice (en-US, Guy24kRUS)'	'en-US-Guy24kRUS'
        # 【下面3行:中文(中国)】
        # 女	'Microsoft Server Speech Text to Speech Voice (zh-CN, HuihuiRUS)'	'zh-CN-HuihuiRUS'
        # 女	'Microsoft Server Speech Text to Speech Voice (zh-CN, Yaoyao, Apollo)'	'zh-CN-Yaoyao-Apollo'
        # 男	'Microsoft Server Speech Text to Speech Voice (zh-CN, Kangkang, Apollo)'	'zh-CN-Kangkang-Apollo'
        voice.set('name',voice_speeker_type)
        voice.text = tts
        body = ElementTree.tostring(xml_body)
        log1.debug(' 调用接口转换语音中......')
        response = requests.post(constructed_url, headers=headers, data=body, proxies=proxies, verify=False)
        if response.status_code == 200:
            filepath = 'static/voice/' + voicefilename
            with open(filepath, 'wb') as audio:
                audio.write(response.content)
                log1.warn(' 文本转语音已完成,生成的音频文件:' + filepath)
        else:
            print('[失败] response code: ' + str(response.status_code)
                    + '\nresponse headers: ' + str(response.headers) )

        return filepath

    ### 文本转语音
    def textToVoice(self, text0, voicefilename, voice_encode_type, voice_speeker_type, subscription_key):
        filepath = ''

        log1.debug('传入的参数值:'
                      #+ '\ntext0=' + text0
                      + '\nvoicefilename=' + voicefilename
                      + '\nvoice_encode_type=' + voice_encode_type
                      + '\nvoice_speeker_type=' + voice_speeker_type )

        if subscription_key=='':
            subscription_key = 'c7fa26e8ea4c46368ddafbe76fdf0827'
        # tts = input('Input some text to convert to speech: ')  # 控制台输入
        tts = text0
        timestr = time.strftime('%Y%m%d%H%M')
        proxies = {
            'http': proxyHttp,
            'https': proxyHttps,
        }
        fetch_token_url = 'https://westus.api.cognitive.microsoft.com/sts/v1.0/issueToken'
        headers = {
            'Ocp-Apim-Subscription-Key': subscription_key
        }
        response = requests.post(fetch_token_url, headers=headers, proxies=proxies, verify=False)
        access_token = str(response.text)
        #log1.debug(' 获取到Token:' + access_token)
        constructed_url = 'https://westus.tts.speech.microsoft.com/cognitiveservices/v1'
        headers = {
            # 前面带有单词 Bearer 的授权令牌
            'Authorization': 'Bearer ' + access_token,

            # 指定所提供的文本的内容类型
            'Content-Type': 'application/ssml+xml',

            # 指定音频输出格式
            'X-Microsoft-OutputFormat': voice_encode_type,

            # 应用程序名称,少于 255 个字符。
            'User-Agent': 'Chrome/73.0.3683.86'
        }
        xml_body = ElementTree.Element('speak', version='1.0')
        xml_body.set('{http://www.w3.org/XML/1998/namespace}lang', 'en-us')
        voice = ElementTree.SubElement(xml_body, 'voice')
        voice.set('{http://www.w3.org/XML/1998/namespace}lang', 'en-US')
        # 'en-US-Guy24kRUS',全称:'Microsoft Server Speech Text to Speech Voice (en-US, Guy24KRUS)'
        voice.set('name',voice_speeker_type)
        voice.text = tts
        body = ElementTree.tostring(xml_body)
        log1.debug(' 调用接口转换语音中......')
        response = requests.post(constructed_url, headers=headers, data=body, proxies=proxies, verify=False)
        if response.status_code == 200:
            filepath = 'static/voice/' + voicefilename
            with open(filepath, 'wb') as audio:
                audio.write(response.content)
                log1.warn(' 文本转语音已完成,生成的音频文件:' + filepath)
        else:
            print('[失败] response code: ' + str(response.status_code)
                    + '\nresponse : ' + str(response.content) )
        return filepath

### 函数入口
if __name__ == '__main__':
    test = Azure()
    abPath = 'static/backup/text/tts_txt_zhcn.txt'
    caiyanglv = 'riff-24khz-16bit-mono-pcm'
    yinse = 'zh-CN-HuihuiRUS'
    voicefilename1 = 'voice_1001_[' + caiyanglv + ']_['+yinse+'].wav'
    test.fileToVoice( filePath0 = abPath, voicefilename = voicefilename1, voice_encode_type = caiyanglv,
             voice_speeker_type = yinse, subscription_key = '')

AI_VoiceToText_Baidu.py

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


### 语音识别 百度API ###
# Home:https://ai.baidu.com/tech/speech/asr
# API: https://ai.baidu.com/docs#/ASR-Online-Python-SDK/top
# Q&A: https://ai.baidu.com/docs#/FAQ/a53b4698
# 在线文本转语音(汇丰无法试听和下载):https://developer.baidu.com/vcast
from aip import AipSpeech
from ConfigFile import Config
from LogX import Log1
import time
import os

log1 = Log1.log(None)
msg1 = '处理失败.'
filepath1 = ''


class BaiduAi(object):

    """ 你的 APPID AK SK """
    proxyHttp = Config.getBasic(None, group0='http-proxy', key0='http')
    proxyHttps = Config.getBasic(None, group0='http-proxy', key0='https')
    APP_ID = Config.getBasic(None, group0='Baidu-Ai', key0='appid')
    API_KEY = Config.getBasic(None, group0='Baidu-Ai', key0='appkey')
    SECRET_KEY = Config.getBasic(None, group0='Baidu-Ai', key0='secretkey')

    # ### 语音转文本,表单入口
    def sttMain(self, request0):
        global msg1
        global filepath1
        nowtime1 = time.strftime('%Y%m%d%H%M%S')
        fromLanguage = request0.form['fromLanguage'] # 来源语言
        toLanguage   = request0.form['toLanguage']   # 目标语言
        textfilename1 = 'text_' + nowtime1 + '_[' + fromLanguage + ']_[' + toLanguage + '].txt'
        uploadPath = os.getcwd() + '/upload/'
        fileObj1 = request0.files['file1']
        if fileObj1 != '':
            filename0 = fileObj1.filename
            filename0_ext = filename0.split('.')[-1]
            filename0_ext_accept = ['wav']
            if filename0_ext not in filename0_ext_accept:
                msg1 = '处理失败!请上传wav格式的音频文件。'
                log1.error('>>> ' + msg1)
            else:
                filenamenew = nowtime1 + '.' + filename0_ext
                abPath = uploadPath + '/voice_' + filenamenew
                log1.info('>>> 开始上传文件 ...')
                fileObj1.save(abPath)
                log1.info('>>> 文件上传成功:' + abPath)

                # 开始转换语音
                textDict = BaiduAi.aiMain(None, filePath0=abPath, toLanguage0=toLanguage)
                if textDict != '':
                    err_no  = textDict['err_no']
                    err_msg = textDict['err_msg']
                    result  = textDict['result'][0]
                    log1.debug('>>> 状态码:' + str(err_no))
                    log1.debug('>>> 状态:' + err_msg)
                    log1.debug('>>> 结果:' + result)

                    # TODO 将文本写入文件
                    filepath1 = 'static/textfile/'+textfilename1
                    open(filepath1, "w", encoding='UTF-8').write(result)
                    log1.debug('>>> 写入文件完成:' + filepath1)
                    filepath1 = request0.url_root + 'textfile/' + textfilename1

                if filepath1 != '':
                    msg1 = '处理成功!'
                else:
                    msg1 = '处理失败!'
        else:
            msg1 = '处理失败!请选择文件'
            log1.error('>>> ' + msg1)

        result = {'msg': msg1, 'filepath': filepath1}  # 返回结果,键值对,字典
        log1.warn('>>> 全部操作已经完成')
        log1.warn('>>> 返回结果:\nresult=' + str(result))

        return result

    # ### 语音转文本,转换函数,返回字典类型
    def aiMain(self, filePath0, toLanguage0):

        # AipSpeech是语音识别的Python SDK客户端
        client = AipSpeech(BaiduAi.APP_ID, BaiduAi.API_KEY, BaiduAi.SECRET_KEY)  # 访问百度API,内置访问http的函数,并写死了URL路径
        proxies = {
            "http": BaiduAi.proxyHttp,
            "https": BaiduAi.proxyHttps,
        }
        client.setProxies(proxies)
        # client.setConnectionTimeoutInMillis( 10000 )  # 建立连接的超时时间(毫秒),默认不需要设置
        # client.setSocketTimeoutInMillis(300000)  # 通过打开的连接传输数据的超时时间(毫秒)

        # 上传 本地音频文件(SpeechToText.wav)
        # 支持的格式:原始 PCM 的录音参数必须符合 16k 采样率、16bit 位深、单声道,支持的格式有:pcm(不压缩)、wav(不压缩,pcm编码)、amr(压缩格式)。
        # 有长度限制(测试时尽量短一点)
        # 返回结果为字典类型(Dict / json)
        response = client.asr(BaiduAi.get_file_content(None,filePath=filePath0), 'wav', 16000, {
            # 1536:普通话(支持简单的英文识别)
            # 默认1537:普通话(纯中文识别)
            # 1737:英语
            # 1637:粤语
            'dev_pid': int(toLanguage0),
        })

        return response
        # {'corpus_no': '6714166347641437907', 'err_msg': 'success.', 'err_no': 0, 'result': ['识别后的内容'], 'sn': '602626830571563263672'}

    # ### 语音转文本,读取本地文件
    def get_file_content(self,filePath):
        with open(filePath, 'rb') as fp:
            return fp.read()

### 函数入口
if __name__ == "__main__":
    baidu = BaiduAi()
    filepath9 = 'static/backup/sound/voice_20190916142927_[raw-16khz-16bit-mono-pcm]_[en-US-ZiraRUS].wav'
    languageNum = 1737
    textDict = baidu.aiMain( filePath0=filepath9, toLanguage0=languageNum)
    print (str(textDict))
    if textDict!='':
        err_no  = textDict['err_no']
        err_msg = textDict['err_msg']
        result  = textDict['result'][0]
        print ('状态码:' + err_no)
        print ('状态:' + err_msg)
        print ('结果:' + result)


ConfigFile

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

import os
from configparser import ConfigParser


class Config(object):

    def __init__(self):
        super(Config, self).__init__()
        self.config = ConfigParser()
        #print('配置文件路径:'+os.getcwd()+'/configs/basic.ini')
        self.config.read(os.getcwd()+'/configs/basic.ini',encoding='utf-8')

    # ### 代理配置
    # user
    # pass
    def getBasic (self,group0, key0):
        cfg0    = Config().config
        value0  = cfg0.get(group0, key0)
        return value0

if __name__ == "__main__":
    cc = Config()
    # print (cc.getBasic( group0='http-proxy', key0='http' ))

LogX.py

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


import logging
import logging.handlers

class Log1(object):

    def log(self):
        # 日志对象
        logger1 = logging.getLogger('AIFuture')
        if not logger1.handlers:
            # 日志级别-会覆盖 Handler的子级别
            logfilePath = 'logs/AI.log'
            logger1.setLevel(logging.DEBUG)
            # 用于输出到文件
            #logfile1 = logging.FileHandler(logfilePath)
            logfile1 = logging.handlers.RotatingFileHandler(logfilePath, maxBytes=10 * 1024 * 1024, backupCount=5, encoding='utf-8')
            #logfile1.setLevel(logging.DEBUG)
            # 用于输出到控制台
            logcmd1 = logging.StreamHandler()
            #logcmd1.setLevel(logging.INFO)
            # 格式化日志
            logformatter = logging.Formatter('[%(asctime)s] [%(levelname)s] [%(filename)s(line:%(lineno)d)] %(message)s')
            # 应用格式
            logfile1.setFormatter(logformatter)
            logcmd1.setFormatter(logformatter)
            # 注入对象
            logger1.addHandler(logcmd1)
            logger1.addHandler(logfile1)

        return logger1

start_AI.sh

#! /bin/bash
. ~/.bash_profile
mypython -u AI.py


'''
进入目录: cd /home/pyai/tts
启动命令: nohup sh start_AI.sh > start_AI.sh.out &

停止命令:
查看进程: ps -ef|grep AI
显示 端口占用:netstat -lnt|grep 6789

sudo netstat -antup
sudo netstat -antup|grep PID号 
sudo ps -ef|grep 进程名

'''

'''
依赖插件:mypip install configparser --user
flask
jinja2
requests
logger1
baidu-aip
configparser
'''

configs/basic.ini

# http 代理配置
[http-proxy]
http  = http://***
https = http://***


# 微软 Azure 语音密钥
[Azure-Key]
key1 = 8c0779e6846c43478f83fb2bd2fdd610
key2 = c7fa26e8ea4c46368ddafbe76fdf0827

[Baidu-Ai]
appid     = 16735297
appkey    = P7IGlBm443VcSaCWCQT6WrXh
secretkey = pdlslL0ysPFUU8yF6dQtoN5yxrfdSupD

相关目录结构:

项目根目录/configs/basic.ini

项目根目录/logs

项目根目录/static/backup/sound
项目根目录/static/backup/text

项目根目录/static/history

项目根目录/static/textfile
项目根目录/static/voice

项目根目录/templates/***.html
项目根目录/upload
项目根目录/AI.py
项目根目录/AI_TTS_Azure.py
项目根目录/AI_VoiceToText_Baidu.py
项目根目录/ConfigFile.py
项目根目录/LogX.py
项目根目录/start_AI.py

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值