Text to speech - Chuyển văn bản thành giọng nói
This post hasn't been updated for 5 years
Mở đầu
Bài viết không liên quan tới machine learning. Chúng ta sẽ gọi api của fpt.Ở bài viết này mình sẽ hướng dẫn cho các bạn tạo app text to speech. Có luôn source code để các bạn tải về dùng miễn phí hoàn toàn. Các bạn có thể dùng để nghe truyện, đọc báo hoặc tạo giọng nói cho nhà thông minh, chatbot của bạn chẳng hạn rất tiện phải không.
Xin lỗi mình không nhúng được file mp3 vào đây. bạn có thể vào link nhé Đây là một đoạn của google translate.
Đây là api fpt
Đây là phần giới thiệu của fpt
Tổng hợp tiếng nói (Speech synthesis) là bài toán cơ bản trong bài toán lớn về giao tiếp giữa người và máy (Human-Machine Interface).
Với tham vọng riêng của mình, Ban công nghệ FPT (FTI) đã nỗ lực nghiên cứu suốt gần 5 năm qua để cho ra mắt sản phẩm FPT Speech Synthesis. Sản phẩm là sự kết hợp của:
- Ngôn ngữ học (Linguistics): âm vị học (Phonology), hình thái học (Morphology), ngữ dụng học (Pragmatics)
- Vật lý học: âm học
- Công nghệ: Xử lý ngôn ngữ tự nhiên (Natural Language Processing) , học máy (Machine Learning), xử lý tín hiệu số (Digital Signal Processing)
Text to speech
Mình viết bằng python. Đầu tiên ta cần vào https://dev.openfpt.vn/ đăng ký tài khoản và tạo key để dùng cho app. Ok có cả phần test luôn. Các bạn có thể thử để xem chất lượng giọng nói.Tài liệu ở đây. Chúng ta bắt đầu code.
Khởi tạo các tham số
Keys xin phép được ẩn đi. Mình chẳng tiếc nhưng sợ đông người dùng các bạn làm chậm của nhau. May cho chúng ta có phần comment của thằng bạn mình.Source code ở phía cuối bài viết, mình cũng lười không làm cái ứng dụng giao diện tử tế. Quan trọng là ý tưởng phải không .
Chúng ta dùng nhiều key bởi vì fpt sẽ chặn số lượng request tính trên phút. Mình sẽ thay đổi liên tục các keys để lack vụ này .
import sys
import requests
#API Key của bạn
keys = [
'#############################',
'#############################',
'#############################',
'#############################'
]
#Xác định các giọng đọc, voice có các giá trị là leminh (giọng nam miền bắc), male (giọng nam miền bắc),
#female (giọng nữ miền bắc), hatieumai (giọng nữ miền nam), ngoclam (giọng nữ Huế)
voice = "leminh"
# Xác định các giọng đọc, voice có các giá trị là:
# leminh (giọng nam miền bắc nghe ấm ),
# male (giọng nam miền bắc hơi già có tiếng thở),
# female (giọng nữ miền bắc trẻ, giọng trong đọc hơi chậm so với các giọng khác),
# hatieumai (giọng nữ miền nam nghe đk),
# ngoclam (giọng nữ Huế đọc hơi bị ngắt nên cho chậm lại)
speed= "0"
#ngữ điệu 1 on. 0 off
prosody= "0"
#phần dưới này để phục vụ cho việc nhận tham số từ cmd khi sử dụng file start.py
# vd call file "start.py input" #input là input.txt lưu văn bản cần chuyển thành giọng nói
# hoặc chỉnh sửa short_direct đối với dùng jupyter notebook
# ngoài cách chạy command line có thể sử dụng jupyter notebook chủ yếu cho người phát triển
args = sys.argv
if len(args) >= 1:
short_direct = args[1]
direc = '{}/'.format(args[1])
# Thay ten file
short_direct = 'starttq'
direc = f'{short_direct}/'
Backup file mp3 trước đó
Mục đích tránh ghi đè mất file mp3 ở đợt trướcimport os
import datetime
#backup file full.mp3
if short_direct not in os.listdir():
os.mkdir(short_direct)
if 'full.mp3' in os.listdir('{}'.format(direc)):
#create folder backup if not exists
if 'backup' not in os.listdir('{}'.format(direc)):
os.mkdir('{}backup'.format(direc))
now = str(datetime.datetime.now()).replace(" ", "_").replace(":", "_")
os.rename("{}full.mp3".format(direc), "{}backup/{}.mp3".format(direc, now))
print('backup file full mp3 to {}backup/{}.mp3'.format(direc, now))
# Remove all file mp3
for item in os.listdir('{}'.format(direc)):
if item.endswith(".mp3"):
os.remove(os.path.join(direc, item))
print('remove all file mp3')
Kết quả
Gọi API và tải các file nhạc
Vì fpt giới hạn số lượng ký tự. Nên ta cần cắt ra thành nhiều đoạn. Cắt thế nào để không vào giữa một chữ (phải là "xin chào" chứ không thể cắt "xin ch" rồi file sau là "ào" được). Cách làm đơn giản là lấy 500 (giới hạn của fpt) lùi lại đến khi gặp dấu cách thôi rồi cắt từ đó. Mình để 480 cho chắc :D. Đối với python thì chúng ta có thư viện textwrap.from textwrap import wrap
import time
import wget
import random
file = open("{}.txt".format(short_direct), "r", encoding="utf-8")
content = file.read()
wraptexts = wrap(content, 480)
for i in range(len(wraptexts)):
while True:
try:
text = wraptexts[i]
api_key = random.choice(keys)
print('\n', api_key)
url = "http://api.openfpt.vn/text2speech/v4?api_key={}&voice={}&speed={}&prosody={}".format(api_key, voice, speed, prosody)
response = requests.post(url, data=text.encode('utf-8'), headers={'voice':voice, 'speed':speed, 'prosody':prosody})
response = response.json()
print('\n', response['async'])
file = response['async']
print("downloading file {}/{} ".format(i+1, len(wraptexts)), "{}{:03}.mp3".format(direc, i))
except :
time.sleep(1)
continue
break
while True:
try:
wget.download(file, "{}{:03}.mp3".format(direc, i))
except :
time.sleep(0.1)
print('Co loi. Thu lai', end='')
continue
break
print('\nCOMPLETE')
Kết quả:
Gộp files
Sau bước trên ta đã tải được các file đơn bây giờ gộp lại. Trên linux thì mình nhớ có sẵn lệnh split và merge file rồi. Trước mình đã thử chia nhỏ ảnh của mình và merge lại vẫn dùng được. Còn trên windows thì không có mình dùng một cái ffmpeg để merge file audios. Còn tải ở đâu thì mình không nhớ, các bạn có thể xem tài liệu https://trac.ffmpeg.org/wiki/Concatenate, hoặc tải 3 file exe ở phần sourcecode.#create list for merge
import subprocess
f = open("{}create_list.bat".format(direc), "w")
f.write("(for %%i in (*.mp3) do @echo file '%%i') > list.txt")
f.close()
s = "{}create_list.bat".format(direc)
os.chdir(short_direct)
print(os.listdir())
print(s)
# os.system("create_list2.bat".format(direc))
subprocess.Popen("create_list.bat")
os.chdir('..')
#merge file for create
#output: full.mp3
p = subprocess.run('ffmpeg -f concat -safe 0 -i {}list.txt -c copy {}full.mp3'.format(direc, direc))
Vậy là xong. Bạn muốn thưởng thức thì quay lại phần đầu mở audio lên.
All Rights Reserved