语音合成,让阿里云小姐姐为你的视频配音

@NH4L
轻松实现语音合成,让阿里云小姐姐为你的视频配音
本次调用的是阿里云的语音合成SDK,调用接口进行语音合成。
下面来看看具体实现步骤以及两种利用python进行语音的代码。

一、注册登录阿里云获取appkey

1.登入阿里云:https://www.aliyun.com/
2.需要实名认证才行哟
3.点击控制台
4.在搜索界面搜索智能语音交互,进入智能语音交互控制台

5.点击进入后点击我的项目–创建项目


6.随便输入项目名词和描述即可

7.即可得到项目appkey

8.点击总览,点击获取AccessToken

在其中还有很多音频可以试听,可以选择自己喜欢的声音。
这是语音合成的接口说明,不同的声音又不用的voice参数值。
https://help.aliyun.com/document_detail/84435.html?spm=a2c4g.11186623.6.591.73831e0duk4FNT

二、普通方式获得语音合成

通过将网址放入浏览器获取语音,修改自己的appkey和accessToken和需要语音合成的语句即可。

https://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/tts?appkey=你的appkey&token=你的accesstoken&format=mp3&voice=Aixia&speech_rate=0&volume=100&text=你好呀,小姐姐

下面是各个参数说明

将你的语句修改即可,这种方式最多300个字符,如果需要更多的话,就需要利用python来解决了。

三、利用python调用SDK进行语音合成

有两种方式

1.官方SDK

第一种是调用阿里云SDK,大家可以到https://help.aliyun.com/document_detail/120699.html?spm=a2c4g.11186623.6.594.3e86259esNOsnh中了解详情及配制相关包。
下面铺上代码:

# -*- coding: utf-8 -*-
import threading
import ali_speech
from ali_speech.callbacks import SpeechSynthesizerCallback
from ali_speech.constant import TTSFormat
from ali_speech.constant import TTSSampleRate

class MyCallback(SpeechSynthesizerCallback):
    # 参数name用于指定保存音频的文件
    def __init__(self, name):
        self._name = name
        self._fout = open(name, 'wb')
    def on_binary_data_received(self, raw):
        print('MyCallback.on_binary_data_received: %s' % len(raw))
        self._fout.write(raw)
    def on_completed(self, message):
        print('MyCallback.OnRecognitionCompleted: %s' % message)
        self._fout.close()
    def on_task_failed(self, message):
        print('MyCallback.OnRecognitionTaskFailed-task_id:%s, status_text:%s' % (
            message['header']['task_id'], message['header']['status_text']))
        self._fout.close()
    def on_channel_closed(self):
        print('MyCallback.OnRecognitionChannelClosed')

def process(client, appkey, token, text, audio_name, voice):
    callback = MyCallback(audio_name)
    synthesizer = client.create_synthesizer(callback)
    synthesizer.set_appkey(appkey)
    synthesizer.set_token(token)
    synthesizer.set_voice(voice)
    synthesizer.set_text(text)
    synthesizer.set_format(TTSFormat.WAV)
    synthesizer.set_sample_rate(TTSSampleRate.SAMPLE_RATE_16K)
    synthesizer.set_volume(50)
    synthesizer.set_speech_rate(0)
    synthesizer.set_pitch_rate(0)
    try:
        ret = synthesizer.start()
        if ret < 0:
            return ret
        synthesizer.wait_completed()
    except Exception as e:
        print(e)
    finally:
        synthesizer.close()

def process_multithread(client, appkey, token, number):
    thread_list = []
    for i in range(0, number):
        text = "这是线程" + str(i) + "的合成。"
        audio_name = "sy_audio_" + str(i) + ".wav"
        thread = threading.Thread(target=process, args=(client, appkey, token, text, audio_name))
        thread_list.append(thread)
        thread.start()
    for thread in thread_list:
        thread.join()

if __name__ == "__main__":
    client = ali_speech.NlsClient()
    client.set_log_level('INFO')
    voice = 'Aixia'
    appkey = '你的appkey'
    token = '你的token'
    text = "哼!都怪你,也不哄哄人家,人家超想哭的,捶你胸口,大坏蛋!捶你胸口你好讨厌!要抱抱嘤嘤嘤哼,人家拿小拳拳捶你胸口!大坏蛋,打死你..."
    audio_name = 'audio.mp3'
    process(client, appkey, token, text, audio_name, voice)
    # 多线程示例
    # process_multithread(client, appkey, token, 2)

2.访问url获取

这种方式唯一的好处就是不用安装SDK,pip中有requests即可。
这里我自己做了一个根据句号的中文字符串切割算法,限制结束符为句号"。",同时一段文字只能小于300字符(免费的情况下),进行循环获取每段语音的音频文件(1.mp3, 2.mp3,·····)。
代码如下:

# encoding:utf-8 
import requests
from requests.exceptions import RequestException
import urllib.parse
import urllib.request
import os
import re

def get_voice(url, name):
    headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"}
    response = requests.get(url, headers=headers)
    print(response.status_code)
    try:
        if response.status_code == 200:
            download_voice(url, name)
        return None
 except RequestException:
        return None   def download_voice(url, name):
    file_path = r'{}.mp3'.format(name)
    if not os.path.exists(file_path):
        print('正在下载:', name, url)
        urllib.request.urlretrieve(url, file_path)
        print('ok!!!!!!!!!')
    else:
        print('下载出错')

def not_empty(s):
    return s and s.strip()

def cut_text(text, length):
    text = re.sub('[\r\n\t]', '', text)
    text_array = list(filter(not_empty, text.split('。')))
    text_i = [0]
    text_len = 0
  list_1 = []
    for i in range(len(text_array)):
        list_1.append(i)
        text_len = text_len + len(text_array[i])
        print(text_len)
        if text_len > length:
            text_len = 0
  text_len = text_len + len(text_array[i])
            print(text_len)
            text_i.append(i-1)
            list_1.clear()

    if text_i[-1] < (len(text_array) -1):
        text_i.append(len(text_array) -1)

    # print(text_i)
  new_text_i = []
    for i in range(len(text_i) - 1):
        list1 = []
        for a in range(text_i[i] + 1, text_i[i+1] + 1):
            list1.append(a)
        new_text_i.append(list1)
    new_text_i[0].insert(0, 0)
    # print(new_text_i)    new_text_array = []
    for t in new_text_i:
        x = ''
  for t1 in range(len(t)):
            x += text_array[t[t1]] + '。'
  new_text_array.append(x)

    return new_text_array

def main():
    voice = 'Aixia'
  appkey = 'VNSQETOK5RRVSeRH'
  token = 'faf7fd0920a04b5da73f898846aa65c2'
  speech_rate = -100
  file_name = 'voice'
  text = '''七尺阔、十二尺深的工房楼下,横七竖八地躺满了十六七个“猪猡”。跟着这种有威势的喊声,在充满了汗臭、粪臭和湿气的空气里面,她们很快地就像被搅动了的蜂窝一般骚动起来。打呵欠,叹气,寻衣服,穿错了别人的鞋子,胡乱地踏在别人身上,叫喊,在离开别人头部不到一尺的马桶上很响地小便。成人期女孩所共有的害羞的感觉,在这些被叫做“猪猡”的生物中间,已经很迟钝了。半裸体地起来开门,拎着裤子争夺马桶,将身体稍稍背转一下就会公然地在男人面前换衣服。
 那男人虎虎地在起得慢一点的“猪猡”身上踢了几脚,回转身来站在不满二尺阔的楼梯上面,向着楼上的另一群生物呼喊:  “揍你的!再不起来?懒虫!等太阳上山吗?”
  蓬头、赤脚,一边扣着纽扣,几个睡眼惺松的“懒虫”从楼上冲下来了。自来水龙头边挤满了人,用手捧些水来浇在脸上。“芦柴棒”着急地要将大锅里的稀饭烧滚,但是倒冒出来的青烟引起了她一阵猛烈的咳嗽。十五六岁,除了老板之外,大概很少有人知道她的姓名。手脚瘦得像芦棒梗一样,于是大家就拿“芦柴棒”当做了她的名字。  “上午四点过一刻”,“鸽子笼一般”的住房里,包身工起床,开始了一天非人的生活。
 这是杨树浦福临路东洋纱厂的工房。长方形的,红砖墙严密地封锁着的工房区域,像一条水门汀的弄堂马路划成狭长的两块。像鸽子笼一般地分得均匀,每边八排,每排五户,一共八十户一楼一底的房屋,每间工房的楼上楼下,平均住着三十二三个“懒虫”和“猪猡”,所以,除了“带工”老板、老板娘、他们的家族亲戚和穿拷绸衣服的同一职务的打杂、请愿警之外,这工房区域的墙圈里面住着二千左右衣服褴褛而替别人制造衣料的“猪猡”。
 写包身工清晨起身的情况,恶劣的住宿条件。以清晨破题,以黑夜收尾。明写一天,暗含“日复一日,年复一年”的寓意。工房的气味,骚动的声音与动作,这一场面描写,从居住条件的恶劣表现包身工的非人生活。
 但是,她们正式的名称却是“包身工”。她们的身体,已经以一种奇妙的方式包给了叫做“带工”的老板。每年特别是水灾、旱灾的时候,这些在东洋厂里有“脚路”的带工,就亲自或者派人到他们家乡或者灾荒区域,用他们多年熟练了的可以将一根稻草讲成金条的嘴巴,去游说可又不忍让他们的儿女饿死的同乡。
 用“但是”这个转折联词,笔锋一转,承上启下,说明她们并非“猪猡”,“正式的名称却是‘包身工’”。然后十分巧妙、自然地插叙了关于包身工的来历,指出包身工是被“带工”凭着“将一根稻草讲成金条的嘴巴”从农村骗来的,是“顺从地替带工赚钱的‘机器’”。两相对照,以铁一般的事实戳穿了带工们的无耻谎言。  “还用说?住的是洋式的公司房子。吃的是鱼肉荤腥。一个月休息两天,咱们带着到马路上去玩耍。嘿,几十层楼的高房子,两层楼的汽车,各种各样好看好用的外国东西。老乡!人生一世,你也得去见识一下啊!──做满三年,以后赚的钱就归你啦。块把钱一天的工钱,嘿,别人给我叩了头也不替她写进去!咱们是同乡,有交情。──交给我带去,有什么三差二错,我还能回家乡吗?”
  这样说着,咬着草根树皮的女孩子可不必说,就是她们的父母,也会怨恨自己没有跟去享福的福份了。于是,在预备好了的“包身契”上画一个十字,包身费大洋二十元,期限三年,三年之内,由带工的供给住食,介绍工作,赚钱归带工者收用,生死疾病一听天命,先付包洋十元,人银两交,“恐后无凭,立此包身契据是实!”
  福临路工房的二千左右的包身工人,隶属在五十个以上的“带工”头手下,她们是顺从地替带工赚钱的“机器”。所以,每个“带工”所带包身工的人数也就表示了他们的手面和财产。少一点的,三十五十,多一点的带着一百五十个以上。手面宽一点的“带工”,不仅可以放债、买田、起屋,还能兼营茶楼、浴室、理发铺一类的买卖。'''
  text_array = cut_text(text, 300)
    # print(text_array)
  for text in range(len(text_array)):
        url = 'https://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/tts?appkey=' + appkey \
          + '&token=' + token + '&format=mp3&voice=' + voice + '&speech_rate=' + str(speech_rate) + '&volume=100&text=' + urllib.parse.quote(text_array[text])
        get_voice(url, file_name + str(text))

if __name__ == '__main__':
    main()

总结

通过语音合成,经常做视频配音的人压力可以小点了,阿里云的语音技术拟人化也比较高,声音也比较甜美,听起来也舒服,也不会出错,确实是一种很好的配音选择。
用第二种方法文本的字数都没有限制,大家可以放心使用。

这里是看到b站@JOKER鹏少的视频来的灵感,看到有这么好的语音合成技术,便把免费语音合成的代码写出来与大家分享。
同时也可以到知乎@NH4L看看语音合成的具体效果:https://zhuanlan.zhihu.com/p/123930042
参考链接:https://help.aliyun.com/document_detail/120699.html?spm=a2c4g.11174283.6.594.59e87275VzZhum
https://www.bilibili.com/video/BV1MV411f7Uc

发布了20 篇原创文章 · 获赞 40 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/LeeGe666/article/details/105353599