bugfix
This commit is contained in:
parent
0bc047429f
commit
a737d25670
BIN
app/.f5tts.py.swp
Normal file
BIN
app/.f5tts.py.swp
Normal file
Binary file not shown.
@ -1,5 +1,4 @@
|
|||||||
import sys
|
import sys
|
||||||
sys.path.append('./F5TTS')
|
|
||||||
import argparse
|
import argparse
|
||||||
import codecs
|
import codecs
|
||||||
import re
|
import re
|
||||||
@ -7,11 +6,11 @@ from pathlib import Path
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import soundfile as sf
|
import soundfile as sf
|
||||||
import tomli
|
# import tomli
|
||||||
from cached_path import cached_path
|
from cached_path import cached_path
|
||||||
|
|
||||||
from model import DiT, UNetT
|
from f5_tts.model import DiT, UNetT
|
||||||
from model.utils_infer import (
|
from f5_tts.model.utils_infer import (
|
||||||
load_vocoder,
|
load_vocoder,
|
||||||
load_model,
|
load_model,
|
||||||
preprocess_ref_audio_text,
|
preprocess_ref_audio_text,
|
||||||
@ -23,9 +22,11 @@ import os
|
|||||||
import json
|
import json
|
||||||
from time import time
|
from time import time
|
||||||
from appPublic.dictObject import DictObject
|
from appPublic.dictObject import DictObject
|
||||||
from appPublic.zmq_reqrep import ZmqReplier
|
|
||||||
from appPublic.folderUtils import temp_file
|
from appPublic.folderUtils import temp_file
|
||||||
from appPublic.jsonConfig import getConfig
|
from appPublic.jsonConfig import getConfig
|
||||||
|
from appPublic.worker import awaitify
|
||||||
|
from ahserver.webapp import webapp
|
||||||
|
from ahserver.serverEnv import ServerEnv
|
||||||
|
|
||||||
n_mel_channels = 100
|
n_mel_channels = 100
|
||||||
hop_length = 256
|
hop_length = 256
|
||||||
@ -39,17 +40,10 @@ speed = 1.0
|
|||||||
class F5TTS:
|
class F5TTS:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.config = getConfig()
|
self.config = getConfig()
|
||||||
self.zmq_url = self.config.zmq_url
|
|
||||||
self.replier = ZmqReplier(self.config.zmq_url, self.generate)
|
|
||||||
# self.vocos = load_vocoder(is_local=True, local_path="../checkpoints/charactr/vocos-mel-24khz")
|
# self.vocos = load_vocoder(is_local=True, local_path="../checkpoints/charactr/vocos-mel-24khz")
|
||||||
self.load_model()
|
self.load_model()
|
||||||
self.setup_voice()
|
self.setup_voice()
|
||||||
|
|
||||||
def run(self):
|
|
||||||
print(f'running {self.zmq_url}')
|
|
||||||
self.replier._run()
|
|
||||||
print('ended ...')
|
|
||||||
|
|
||||||
def load_model(self):
|
def load_model(self):
|
||||||
# load models
|
# load models
|
||||||
ckpt_file = ''
|
ckpt_file = ''
|
||||||
@ -75,37 +69,6 @@ class F5TTS:
|
|||||||
self.config.vocab_file)
|
self.config.vocab_file)
|
||||||
self.model = self.model.to(self.config.device)
|
self.model = self.model.to(self.config.device)
|
||||||
|
|
||||||
def generate(self, d):
|
|
||||||
msg= d.decode('utf-8')
|
|
||||||
data = DictObject(**json.loads(msg))
|
|
||||||
print(data)
|
|
||||||
t1 = time()
|
|
||||||
if data.stream:
|
|
||||||
for wav in self.inference_stream(data.prompt, stream=data.stream):
|
|
||||||
d = {
|
|
||||||
"reqid":data.reqid,
|
|
||||||
"b64wave":b64str(wav),
|
|
||||||
"finish":False
|
|
||||||
}
|
|
||||||
self.replier.send(json.dumps(d))
|
|
||||||
t2 = time()
|
|
||||||
d = {
|
|
||||||
"reqid":data.reqid,
|
|
||||||
"time_cost":t2 - t1,
|
|
||||||
"finish":True
|
|
||||||
}
|
|
||||||
return json.dumps(d)
|
|
||||||
else:
|
|
||||||
audio_fn = self.inference(data.prompt)
|
|
||||||
t2 = time()
|
|
||||||
d = {
|
|
||||||
"reqid":data.reqid,
|
|
||||||
"audio_file":audio_fn,
|
|
||||||
"time_cost":t2 - t1
|
|
||||||
}
|
|
||||||
print(f'{d}')
|
|
||||||
return json.dumps(d)
|
|
||||||
|
|
||||||
def setup_voice(self):
|
def setup_voice(self):
|
||||||
main_voice = {"ref_audio": self.config.ref_audio_fn,
|
main_voice = {"ref_audio": self.config.ref_audio_fn,
|
||||||
"ref_text": self.config.ref_text}
|
"ref_text": self.config.ref_text}
|
||||||
@ -123,7 +86,7 @@ class F5TTS:
|
|||||||
print("Ref_text:", voices[voice]["ref_text"])
|
print("Ref_text:", voices[voice]["ref_text"])
|
||||||
self.voices = voices
|
self.voices = voices
|
||||||
|
|
||||||
def inference_stream(self, prompt):
|
def _inference_stream(self, prompt):
|
||||||
text_gen = prompt
|
text_gen = prompt
|
||||||
remove_silence = False
|
remove_silence = False
|
||||||
generated_audio_segments = []
|
generated_audio_segments = []
|
||||||
@ -157,11 +120,11 @@ class F5TTS:
|
|||||||
'finish':True
|
'finish':True
|
||||||
}
|
}
|
||||||
|
|
||||||
def inference(self, prompt):
|
def _inference(self, prompt):
|
||||||
generated_audio_segments = []
|
generated_audio_segments = []
|
||||||
remove_silence = self.config.remove_silence or False
|
remove_silence = self.config.remove_silence or False
|
||||||
final_sample_rate = 24000
|
final_sample_rate = 24000
|
||||||
for d in self.inference_stream(prompt):
|
for d in self._inference_stream(prompt):
|
||||||
if not d['finish']:
|
if not d['finish']:
|
||||||
audio = d['audio']
|
audio = d['audio']
|
||||||
final_sample_rate = d['sample_rate']
|
final_sample_rate = d['sample_rate']
|
||||||
@ -177,20 +140,11 @@ class F5TTS:
|
|||||||
remove_silence_for_generated_wav(f.name)
|
remove_silence_for_generated_wav(f.name)
|
||||||
return fn
|
return fn
|
||||||
|
|
||||||
|
def init():
|
||||||
|
g = ServerEnv()
|
||||||
|
f5 = F5TTS()
|
||||||
|
g.infer_stream = awaitify(f5._inference_stream)
|
||||||
|
g.infer = awaitify(f5._inference)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
workdir = os.getcwd()
|
webapp(init)
|
||||||
config = getConfig(workdir, {'workdir':workdir})
|
|
||||||
print(config.ref_audio_fn)
|
|
||||||
tts = F5TTS()
|
|
||||||
print('here')
|
|
||||||
tts.run()
|
|
||||||
"""
|
|
||||||
while True:
|
|
||||||
print('prompt:')
|
|
||||||
p = input()
|
|
||||||
if p != '':
|
|
||||||
t1 = time()
|
|
||||||
f = tts.inference(p)
|
|
||||||
t2 = time()
|
|
||||||
print(f'{f}, cost {t2-t1} seconds')
|
|
||||||
"""
|
|
14
app/w4a2wav.py
Normal file
14
app/w4a2wav.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pydub import AudioSegment
|
||||||
|
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
m4afn = sys.argv[1]
|
||||||
|
wavfn = m4afn[:-3] + 'wav'
|
||||||
|
# Load the m4a file
|
||||||
|
audio = AudioSegment.from_file(m4afn, format="m4a")
|
||||||
|
|
||||||
|
# Export the audio as a wav file
|
||||||
|
audio.export(wavfn, format="wav")
|
@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"zmq_url" : "tcp://127.0.0.1:10003",
|
|
||||||
"sample_rate":16000,
|
"sample_rate":16000,
|
||||||
"vocab_file":"",
|
"vocab_file":"",
|
||||||
"remove_silence":false,
|
"remove_silence":false,
|
||||||
@ -7,6 +6,61 @@
|
|||||||
"device":"cuda:0",
|
"device":"cuda:0",
|
||||||
"ref_audio_fn":"$[workdir]$/samples/ttt.wav",
|
"ref_audio_fn":"$[workdir]$/samples/ttt.wav",
|
||||||
"ref_text":"快点吃饭,上课要迟到了。",
|
"ref_text":"快点吃饭,上课要迟到了。",
|
||||||
"cross_fade_duration":0
|
"cross_fade_duration":0,
|
||||||
|
"website":{
|
||||||
|
"paths":[
|
||||||
|
["$[workdir]$/wwwroot",""]
|
||||||
|
],
|
||||||
|
"client_max_size":10000,
|
||||||
|
"host":"0.0.0.0",
|
||||||
|
"port":10099,
|
||||||
|
"coding":"utf-8",
|
||||||
|
"ssl_gg":{
|
||||||
|
"crtfile":"$[workdir]$/conf/www.bsppo.com.pem",
|
||||||
|
"keyfile":"$[workdir]$/conf/www.bsppo.com.key"
|
||||||
|
},
|
||||||
|
"indexes":[
|
||||||
|
"index.html",
|
||||||
|
"index.tmpl",
|
||||||
|
"index.ui",
|
||||||
|
"index.dspy",
|
||||||
|
"index.md"
|
||||||
|
],
|
||||||
|
"startswiths":[
|
||||||
|
{
|
||||||
|
"leading":"/idfile",
|
||||||
|
"registerfunction":"idFileDownload"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"processors":[
|
||||||
|
[".ws","ws"],
|
||||||
|
[".xterm","xterm"],
|
||||||
|
[".proxy","proxy"],
|
||||||
|
[".llm", "llm"],
|
||||||
|
[".llms", "llms"],
|
||||||
|
[".llma", "llma"],
|
||||||
|
[".xlsxds","xlsxds"],
|
||||||
|
[".sqlds","sqlds"],
|
||||||
|
[".tmpl.js","tmpl"],
|
||||||
|
[".tmpl.css","tmpl"],
|
||||||
|
[".html.tmpl","tmpl"],
|
||||||
|
[".bcrud", "bricks_crud"],
|
||||||
|
[".tmpl","tmpl"],
|
||||||
|
[".app","app"],
|
||||||
|
[".bui","bui"],
|
||||||
|
[".ui","bui"],
|
||||||
|
[".dspy","dspy"],
|
||||||
|
[".md","md"]
|
||||||
|
],
|
||||||
|
"rsakey":{
|
||||||
|
"privatekey":"$[workdir]$/conf/rsa_private_key.pem",
|
||||||
|
"publickey":"$[workdir]$/conf/rsa_public_key.pem"
|
||||||
|
},
|
||||||
|
"session_max_time":3000,
|
||||||
|
"session_issue_time":2500,
|
||||||
|
"session_redis_notuse":{
|
||||||
|
"url":"redis://127.0.0.1:6379"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2545
data/Emilia_ZH_EN_pinyin/vocab.txt
Normal file
2545
data/Emilia_ZH_EN_pinyin/vocab.txt
Normal file
File diff suppressed because it is too large
Load Diff
1127
data/librispeech_pc_test_clean_cross_sentence.lst
Normal file
1127
data/librispeech_pc_test_clean_cross_sentence.lst
Normal file
File diff suppressed because it is too large
Load Diff
79
install
Executable file
79
install
Executable file
@ -0,0 +1,79 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import codecs
|
||||||
|
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print(f'Usage:\n{sys.argv[0]} venvname')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
user = os.getlogin()
|
||||||
|
home = os.environ.get('HOME')
|
||||||
|
try:
|
||||||
|
os.mkdir(f'{home}/ve')
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
venv = sys.argv[1]
|
||||||
|
port = int(sys.argv[2])
|
||||||
|
if not os.path.exists(f'{home}/{venv}'):
|
||||||
|
os.system(f'python3 -m venv ~/{venv}')
|
||||||
|
pwd = os.getcwd()
|
||||||
|
name = os.path.basename(pwd)
|
||||||
|
if os.path.exists(f'./app/{name}.py'):
|
||||||
|
print('env exists')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
dirs = f'./app ./conf ./files ./wwwroot ./script ./logs'.split(' ')
|
||||||
|
for d in dirs:
|
||||||
|
try:
|
||||||
|
os.mkdir(d)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
files=f'app/{name}.py conf/config.json files/README.md wwwroot/index.dspy'.split(' ')
|
||||||
|
for f in files:
|
||||||
|
os.system(f'touch {f}')
|
||||||
|
|
||||||
|
service = f"""[Unit]
|
||||||
|
Description={name} service
|
||||||
|
Wants=systemd-networkd.service
|
||||||
|
Requires=nginx.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=forking
|
||||||
|
ExecStart=su - {user} -c "{pwd}/script/{name}.sh"
|
||||||
|
ExecStop=su - ymq "{home}/bin/killname {name}.py"
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
"""
|
||||||
|
|
||||||
|
with codecs.open(f'./script/{name}.service', 'w', 'utf-8') as f:
|
||||||
|
f.write(service)
|
||||||
|
|
||||||
|
with codecs.open(f'./script/{name}.sh', 'w', 'utf-8') as f:
|
||||||
|
f.write(f"""#!/usr/bin/bash
|
||||||
|
|
||||||
|
killname {pwd}/app/{name}.py
|
||||||
|
{home}/{venv}/bin/python {pwd}/app/{name}.py -w {pwd} > {pwd}/logs/stderr.log 2>&1 &
|
||||||
|
exit 0
|
||||||
|
""")
|
||||||
|
|
||||||
|
with codecs.open(f'./script/install.sh', 'w', 'utf-8') as f:
|
||||||
|
f.write(f"""#!/usr/bin/bash
|
||||||
|
sudo cp {name}.service /etc/systemd/system
|
||||||
|
sudo systemctl enable {name}.service
|
||||||
|
sudo systemctl start {name}
|
||||||
|
""")
|
||||||
|
|
||||||
|
if not os.path.exists(f'{home}/bin'):
|
||||||
|
os.mkdir(f'{home}/bin')
|
||||||
|
if not os.path.exists(f'{home}/bin/killname'):
|
||||||
|
with codecs.open(f'{home}/bin/killname', 'w', 'utf-8') as f:
|
||||||
|
f.write("""#!/usr/bin/bash
|
||||||
|
|
||||||
|
ps -ef|grep "$1"|grep -v grep|awk '{print("kill -9", $2)}'|sh
|
||||||
|
""")
|
||||||
|
os.system(f'chmod +x {pwd}/bin/*')
|
||||||
|
os.system(f'{pwd}/script/install.sh')
|
||||||
|
|
13
script/f5tts.service
Normal file
13
script/f5tts.service
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=f5tts service
|
||||||
|
Documention=f5tts service to control f5tts service start or stoop
|
||||||
|
Wants=systemd-networkd.service
|
||||||
|
Requires=nginx.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=forking
|
||||||
|
ExecStart=su - ymq -c "/d/ymq/py/f5tts/run.sh f5tts.py"
|
||||||
|
ExecStop=su - ymq "/d/ymq/bin/killname f5tts.py"
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
BIN
tests/out.wav
Normal file
BIN
tests/out.wav
Normal file
Binary file not shown.
BIN
tests/ref_audio/test_en_1_ref_short.wav
Normal file
BIN
tests/ref_audio/test_en_1_ref_short.wav
Normal file
Binary file not shown.
BIN
tests/ref_audio/test_zh_1_ref_short.wav
Normal file
BIN
tests/ref_audio/test_zh_1_ref_short.wav
Normal file
Binary file not shown.
15
wwwroot/api/inference/index.dspy
Normal file
15
wwwroot/api/inference/index.dspy
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
async def g():
|
||||||
|
async for d in infer_stream(params_kw.prompt):
|
||||||
|
nd = d.get('audio')
|
||||||
|
if nd:
|
||||||
|
yield nd
|
||||||
|
try:
|
||||||
|
resp = await stream_response(request, g, content_type='audio/mpeg')
|
||||||
|
return resp
|
||||||
|
except Exception as e:
|
||||||
|
exc = format_exc()
|
||||||
|
exception(f'{e=}\n{exc}')
|
||||||
|
return {
|
||||||
|
"status":"error",
|
||||||
|
"message":str(e)
|
||||||
|
}
|
@ -1,44 +0,0 @@
|
|||||||
import sys
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
|
|
||||||
from appPublic.dictObject import DictObject
|
|
||||||
from appPublic.zmq_reqrep import ZmqRequester
|
|
||||||
from appPublic.jsonConfig import getConfig
|
|
||||||
from appPublic.uniqueID import getID
|
|
||||||
|
|
||||||
zmq_url = "tcp://127.0.0.1:9999"
|
|
||||||
from time import time
|
|
||||||
|
|
||||||
class F5TTSClient:
|
|
||||||
def __init__(self, zmq_url):
|
|
||||||
self.zmq_url = zmq_url
|
|
||||||
self.requester = ZmqRequester(self.zmq_url)
|
|
||||||
|
|
||||||
def generate(self, prompt):
|
|
||||||
d = {
|
|
||||||
"prompt":prompt,
|
|
||||||
"reqid":getID()
|
|
||||||
}
|
|
||||||
msg = json.dumps(d)
|
|
||||||
resp = self.requester.send(msg)
|
|
||||||
if resp != None:
|
|
||||||
ret = json.loads(resp)
|
|
||||||
print(f'response={ret}')
|
|
||||||
else:
|
|
||||||
print(f'response is None')
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
print(f'running {self.zmq_url}')
|
|
||||||
while True:
|
|
||||||
print('input audio_file:')
|
|
||||||
af = input()
|
|
||||||
if len(af) > 0:
|
|
||||||
self.generate(af)
|
|
||||||
print('ended ...')
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
workdir = os.getcwd()
|
|
||||||
config = getConfig(workdir)
|
|
||||||
asr = ASRClient(config.zmq_url or zmq_url)
|
|
||||||
asr.run()
|
|
Loading…
Reference in New Issue
Block a user