Closed shikichrome closed 6 months ago
https://store.steampowered.com/app/2488350/_/?l=schinese 多分だが、これを使うんだろうな。ただ、俺はこれに金をかけることはない。 中国語圏の話やアプリは知らんから、言葉で説明してもらえるのが一番だが、APIなら、俺はこんな感じでたたいてるぞー
Gradio APIをたたくのが難点だけど、改造してFastAPIのほうをたたくようにしていいし、 ChatGPTのレスポンスを読ませてもよいし、APIならその上も行ける…
import re
import os
from gradio_client import Client
import re
from gradio_client import Client
import string
output_folder = "./OuPuti3/"
os.makedirs(output_folder, exist_ok=True)
client = Client("http://127.0.0.1:7860")
result = client.predict(
"jvnv-F1", # Literal['jvnv-F1', 'jvnv-F2', 'jvnv-M1', 'jvnv-M2', 'Rinne', 'tukuyomi'] in 'モデル一覧' Dropdown component
api_name="/update_model_files_gr"
)
print(result)
result = client.predict(
"jvnv-F1", # Literal['jvnv-F1', 'jvnv-F2', 'jvnv-M1', 'jvnv-M2', 'Rinne', 'tukuyomi'] in 'モデル一覧' Dropdown component
"'model_assets\jvnv-F1\jvnv-F1.safetensors", # Literal['model_assets\jvnv-F1\jvnv-F1.safetensors'] in 'モデルファイル' Dropdown component
api_name="/load_model_gr"
)
print(result)
#result = client.predict(
# "jvnv-F1", # Literal['jvnv-F1', 'jvnv-F2', 'jvnv-M1', 'jvnv-M2', 'Rinne', 'tukuyomi'] in 'モデル一覧' Dropdown component
# "model_assets\jvnv-F1\jvnv-F1.safetensors", # Literal['model_assets\jvnv-F1\jvnv-F1.safetensors'] in 'モデルファイル' Dropdown component
# api_name="/load_model_gr"
#)
#print(result)
result = client.predict(
"プリセットから選ぶ", # Literal['プリセットから選ぶ', '音声ファイルを入力'] in 'スタイルの指定方法' Radio component
api_name="/gr_util"
)
print(result)
# '。'を改行に変換する関数
def replace_period_with_newline(text):
return text.replace('。', '。\n')
# かっこの削除を行う関数
def remove_parentheses(text):
# 正規表現を使用してかっこの部分を削除する
clean_text = re.sub(r'\([^)]*\)', '', text)
return clean_text
def remove_alphabets_and_spaces(text):
# 正規表現パターンを使用してアルファベットと空白を削除する
return re.sub(r'[a-zA-Za-zA-Z]', '', text).replace(' ', '').replace(' ', '')
def remove_symbols(text):
specified_symbols = "-,.?!_\\|[]{}^~!\"#$&'()–"
return ''.join(char for char in text if char not in specified_symbols)
def process_text(text):
"""
テキストに対して処理を行う関数。
Parameters:
text (str): 処理するテキスト
Returns:
str: 処理後のテキスト
"""
result = ""
inside_brackets = False
current_word = ""
for char in text:
if char in ['(', '(']: # 全角のかっこも追加
inside_brackets = True
current_word = ""
elif char in [')', ')']: # 全角のかっこも追加
inside_brackets = False
if len(current_word) >= 5:
result += current_word
current_word = ""
result += char
elif inside_brackets:
current_word += char
else:
result += char
return result.replace(")","").replace(")","")
client = Client("http://127.0.0.1:7860/")
""" def predict_text(text):
output = client.predict(
text, # テキスト
"JP", # 言語
None, # ファイルパス
0.4, # SDP比率
0.6, # ノイズ
0.8, # ノイズ_W
1.1, # 長さ
True, # 改行で分けて生成
0.2, # 改行ごとに挟む無音の長さ(秒)
"", # アシストテキスト
1, # アシストテキストの強さ
False, # アシストテキストを使う
"Neutral", # スタイル
5, # スタイルの強さ
"", # アクセント調整
False, # アクセント調整を使う
"tsukuyomi-chan", # 話者
api_name="/tts_fn"
)
return output[1] """
def predict_text(text):
output = client.predict(
"jvnv-F1", # モデル
"model_assets\jvnv-F1-jp\jvnv-F1-jp_e160_s14000.safetensors", # モデルファイル
text+"-~", # テキスト
"JP", # 言語
None, # ファイルパス
0.5, # SDP比率
0.6, # ノイズ
0.8, # ノイズ_W
1.1, # 長さ
True, # 改行で分けて生成
0.5, # 改行ごとに挟む無音の長さ(秒)
"", # アシストテキスト
0.6, # アシストテキストの強さ
False, # アシストテキストを使う
"Neutral", # スタイル
5, # スタイルの強さ
text, # アクセント調整
False, # アクセント調整を使う
"jvnv-F1-jp", # 話者
api_name="/tts_fn"
)
return output[1]
def copy_file_to_output_folder(file_path, output_folder):
# ファイル名を取得
file_name = os.path.basename(file_path)
# 出力フォルダーにコピーするパスを設定
destination_path = os.path.join(output_folder, file_name)
# ファイルをコピーする
with open(file_path, 'rb') as source_file, open(destination_path, 'wb') as destination_file:
destination_file.write(source_file.read())
# テキストを処理してwavファイルとして保存する関数
def process_and_save_text(text, output_folder, i):
ntext=remove_alphabets_and_spaces(text)
cntext=remove_symbols(ntext)
context=process_text(cntext)
patOh=predict_text(context)
file_name = f"text_{i}.wav"
destination_path = os.path.join(output_folder, file_name)
# wavファイルとして保存する
with open(patOh, 'rb') as source_file, open(destination_path, 'wb') as destination_file:
destination_file.write(source_file.read())
# データセットの文章を分割して処理する
for i in range(100): # 100の部分はデータセットのサイズに応じて適切な値に変更してください
print(i)
# ファイルパスを設定
file_path = f"C:/WorkSpace/folder/{i}.txt"
# ファイルを開いてテキストを読み込む
with open(file_path, 'r', encoding='utf-8') as f:
text = f.read()
# 処理して保存する
process_and_save_text(text, output_folder, i)
FastAPIだとこんな感じ?
import requests
import json
import tkinter as tk
from tkinter import ttk
import tempfile
import os
import subprocess
def play_audio(audio_path):
if os.name == 'nt': # Windows
os.startfile(audio_path)
elif os.name == 'posix': # macOS / Linux
subprocess.run(['xdg-open', audio_path])
def send_request():
url = 'http://127.0.0.1:5000/voice' # FastAPIエンドポイントを指定
params = {
"text": text_entry.get() ,
"model_id": 0,
"speaker_id": 0,
"sdp_ratio": 0.5,
"noise": 0.6,
"noisew": 0.8,
"length": 1.1,
"language": "JP",
"auto_split": True,
"split_interval": 0.5,
"assist_text": "すいません、よくわかりません",
"assist_text_weight": 0.6,
"style": "Neutral",
"style_weight": 5
}
response = requests.get(url, params=params)
if response.status_code == 200:
audio_data = response.content
# 一時ファイルに音声データを保存
with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as f:
f.write(audio_data)
temp_audio_path = f.name
# 音声再生
play_audio(temp_audio_path)
print("音声データを再生しました。")
else:
print("リクエストが失敗しました。ステータスコード:", response.status_code)
# GUIを作成
root = tk.Tk()
root.title("TTSリクエスト送信")
root.geometry("400x200")
# テキスト入力フィールド
text_label = ttk.Label(root, text="テキスト:")
text_label.grid(row=0, column=0, padx=5, pady=5)
text_entry = ttk.Entry(root, width=40)
text_entry.grid(row=0, column=1, padx=5, pady=5)
# 送信ボタン
send_button = ttk.Button(root, text="送信", command=send_request)
send_button.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="WE")
root.mainloop()
動画のようにするなら…こうかな?
import requests
import tempfile
import os
import subprocess
import datetime
def play_audio(audio_path):
if os.name == 'nt': # Windows
os.startfile(audio_path)
elif os.name == 'posix': # macOS / Linux
subprocess.run(['xdg-open', audio_path])
def send_request():
current_time = datetime.datetime.now()
current_hour = current_time.hour
current_minute = current_time.minute
current_second = current_time.second
time_str = f"{current_hour}時{current_minute}分{current_second}秒になりました。"
url = 'http://127.0.0.1:5000/voice' # FastAPIエンドポイントを指定
params = {
"text": time_str,
"model_id": 0,
"speaker_id": "0",
"sdp_ratio": 0.5,
"noise": 0.6,
"noisew": 0.8,
"length": 1.1,
"language": "JP",
"auto_split": True,
"split_interval": 0.5,
"assist_text": "あぁん、そこ!とってもいいのぉー!",
"assist_text_weight": 0.6,
"style": "Neutral",
"style_weight": 5
}
response = requests.get(url, params=params)
if response.status_code == 200:
audio_data = response.content
# 一時ファイルに音声データを保存
with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as f:
f.write(audio_data)
temp_audio_path = f.name
# 音声再生
play_audio(temp_audio_path)
print("音声データを再生しました。")
else:
print("リクエストが失敗しました。ステータスコード:", response.status_code)
# 定期的に現在の時間を取得して読み上げる
while True:
send_request()
time.sleep(3600) # 1時間ごとに実行
import requests import json import tkinter as tk from tkinter import ttk import tempfile import os import subprocess def play_audio(audio_path): if os.name == 'nt': # Windows os.startfile(audio_path) elif os.name == 'posix': # macOS / Linux subprocess.run(['xdg-open', audio_path]) def send_request(): url = 'http://127.0.0.1:5000/voice' # FastAPIエンドポイントを指定 params = { "text": text_entry.get() , "model_id": 0, "speaker_id": 0, "sdp_ratio": 0.5, "noise": 0.6, "noisew": 0.8, "length": 1.1, "language": "JP", "auto_split": True, "split_interval": 0.5, "assist_text": "すいません、よくわかりません", "assist_text_weight": 0.6, "style": "Neutral", "style_weight": 5 } response = requests.get(url, params=params) if response.status_code == 200: audio_data = response.content # 一時ファイルに音声データを保存 with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as f: f.write(audio_data) temp_audio_path = f.name # 音声再生 play_audio(temp_audio_path) print("音声データを再生しました。") else: print("リクエストが失敗しました。ステータスコード:", response.status_code) # GUIを作成 root = tk.Tk() root.title("TTSリクエスト送信") root.geometry("400x200") # テキスト入力フィールド text_label = ttk.Label(root, text="テキスト:") text_label.grid(row=0, column=0, padx=5, pady=5) text_entry = ttk.Entry(root, width=40) text_entry.grid(row=0, column=1, padx=5, pady=5) # 送信ボタン send_button = ttk.Button(root, text="送信", command=send_request) send_button.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="WE") root.mainloop()
これをもともとのFastAPI.pyに入れたらいい感じですかな?←プログラミングわからない素人
これは新しくPythonファイルを作成してから、そこに入れて、実行してもらう感じです。
App.batと同じディレクトリでファイルを作成して実行するなら、run.pyファイルを作成したのちに、run.batを作って、つぎのコードを。っていう必要はなかったわ
chcp 65001 > NUL
@echo off
pushd %~dp0
echo Running run.py...
venv\Scripts\python run.py
if %errorlevel% neq 0 ( pause & popd & exit /b %errorlevel% )
popd
pause
import requests
import tempfile
import os
import subprocess
import datetime
import random
import time
def play_audio(audio_path):
if os.name == 'nt': # Windows
os.startfile(audio_path)
elif os.name == 'posix': # macOS / Linux
subprocess.run(['xdg-open', audio_path])
def send_request(text):
url = 'http://127.0.0.1:5000/voice' # FastAPIエンドポイントを指定
params = {
"text": text,
"model_id": 0,
"speaker_id": "0",
"sdp_ratio": 0.5,
"noise": 0.6,
"noisew": 0.8,
"length": 1.1,
"language": "JP",
"auto_split": True,
"split_interval": 0.5,
"assist_text": "あぁん、そこ!とってもいいのぉー!",
"assist_text_weight": 0.6,
"style": "Neutral",
"style_weight": 5
}
response = requests.get(url, params=params)
if response.status_code == 200:
audio_data = response.content
# 一時ファイルに音声データを保存
with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as f:
f.write(audio_data)
temp_audio_path = f.name
# 音声再生
play_audio(temp_audio_path)
print("音声データを再生しました。")
else:
print("リクエストが失敗しました。ステータスコード:", response.status_code)
def roll_d100():
return random.randint(1, 100)
# 定型文リスト
phrases = [
"こんにちは。",
"おはようございます。",
"こんばんは。",
"今日もいい天気ですね。",
"いつもありがとうございます。",
"お疲れ様です。",
"よろしくお願いします。",
"おめでとうございます。"
]
# 定期的に現在の時間を取得して読み上げる
while True:
roll_result = roll_d100()
if roll_result <= 3:
random_phrase = random.choice(phrases)
send_request(random_phrase)
time.sleep(60) # 1分ごとに実行
一分に一回、3パーセントの確率で定型文を読むよ
これで解決なら閉じちゃってください
時間お知らせの音声が出てきましたが......そのソフトに読み込ませるURLはどこからとればいいでしょうか....本当に何度もありがとうございます
なら今度はこれを作って実行して。
chcp 65001 > NUL
@echo off
pushd %~dp0
echo Running server_fastapi.py...
venv\Scripts\python server_fastapi.py
if %errorlevel% neq 0 ( pause & popd & exit /b %errorlevel% )
popd
pause
これを実行すると、URLが出てくると思う。ちなみに、定型分と時間のコードはあのままで動作します。
chcp 65001 > NUL @echo off pushd %~dp0 echo Running server_fastapi.py... venv\Scripts\python server_fastapi.py if %errorlevel% neq 0 ( pause & popd & exit /b %errorlevel% ) popd pause
.pyで別で作りましたが一瞬でとじました
あー、ごめん。それは
run.bat
^^^
行けるかな...?
ご参考までにそのURLのいれるところのコード見せますね... { "name":"New VITS-API Site", "kind":"VITS_API_SITE", "type":"VITS_API_SITE", "src":"item.json", "url":"http://127.0.0.1:23456/voice/vits?id={{id}}&text={{text}}&format={{format}}&length={{length}}&noise={{noise}}&noisew={{noisew}}&sdp_ratio={{sdp_ratio}}&api_key={{api_key}}", "speakers":[ { "id":0, "name":"朗读者1" }, { "id":1, "name":"朗读者2" } ], "langs":["中文Chinese[ZH]","日本语Japanese[JA]","英文English[EN]"], "format":"wav", "needApiKey":false, "length":"1", "noise":"0.50", "noisew":"0.90", "sdp_ratio":"0.20", "tag":"VITS_API_SITE" }
ためしにURL入れるところにhttp://127.0.0.1:5000/voice/vits?id={{id}}&text={{text}}&format={{format}}&length={{length}}&noise={{noise}}&noisew={{noisew}}&sdp_ratio={{sdp_ratio}}&api_key={{api_key}}",入れてみた
これをどうして欲しいのかはわからないけど、私が提供したコードは多分server_fastapi.pyさえ動いてれば動作すると思うよ
問題は解決しましたか?受験が控えてるのにこっちが気になってしまいまして...
ああ、申し訳ございません....せっかくいっぱい書いていただけたのに分からないかもしれません.... 今の目的はAPIを通してDigital Mateに読み込ませることであって...でもやり方全然わからなくて...
なんか、目的を間違えていたようで申し訳ないんですが... digital mateのいろんなタイミングのスクショをください。 例えば、新しいキャラを選択?作成?するところなど
ボイスのAPI追加画面だとこちらです
他のAPIサイトのデータ参考です { "name":"AI-Hobbyist原/星语音合成(Bert-VITS2)", "kind":"VITS_API_SITE", "type":"VITS_API_SITE", "src":"item.json", "action":"post", "postFormat":"{\"text\":\"{{text}}\",\"speaker\":\"{{speakerName}}\",\"sdp_ratio\":{{sdp_ratio}},\"noise\": {{noise}},\"noisew\": {{noisew}}, \"length\": {{length}}, \"token\": \"{{api_key}}\" }", "responseType":"json", "responseJsonKey":"audio", "url":"https://tts.ai-lab.top", "langs":[], "defaultLang":"", "format":"wav", "api_key":"a07a9f7b6e74a5537b62ce8eb990e571", "needApiKey":true, "length":"1", "noise":"0.50", "noisew":"0.90", "sdp_ratio":"0.20", "hint":"【注意】开加速器或梯子可能会减慢语音下载速度。点击这里注册账号获取自己的ApiKey", "hintLink":"https://tts.ai-hobbyist.org/", "tag":"VITS_API_SITE", "speakers":["anzai","「信使」","「公子」","「博士」","「大肉丸」","「女士」","「散兵」","「白老先生」","七七","三月七","上杉","丹吉尔","丹恒","丹枢","丽莎","久利须","久岐忍","九条裟罗","九条镰治","云堇","五郎","伊利亚斯","伊迪娅","优菈","伦纳德","佐西摩斯","佩拉","停云","元太","克列门特","克拉拉","克罗索","八重神子","公输师傅","凝光","凯亚","凯瑟琳","刃","刻晴","北斗","半夏","博易","博来","卡波特","卡维","卡芙卡","卢卡","可可利亚","可莉","史瓦罗","吴船长","哲平","嘉玛","嘉良","回声海螺","坎蒂丝","埃勒曼","埃尔欣根","埃德","埃泽","埃洛伊","埃舍尔","塔杰·拉德卡尼","塞塔蕾","塞琉斯","夏洛蒂","多莉","夜兰","大慈树王","大毫","天叔","天目十五","奥兹","奥列格","女士","妮露","姬子","娜塔莎","娜维娅","安柏","安西","宛烟","宵宫","岩明","巴达维","布洛妮娅","希儿","希露瓦","帕姆","帕斯卡","常九爷","康纳","开拓者(女)","开拓者(男)","式大将","彦卿","影","德沃沙克","恕筠","恶龙","悦","慧心","戴因斯雷布","托克","托马","拉赫曼","拉齐","掇星攫辰天君","提纳里","斯坦利","斯科特","旁白","早柚","昆钧","明曦","景元","晴霓","杜拉夫","杰帕德","松浦","林尼","枫原万叶","柊千里","查尔斯","柯莱","桑博","欧菲妮","毗伽尔","沙扎曼","派蒙","流浪者","浣溪","浮游水蕈兽·元素生命","海妮耶","海芭夏","深渊使徒","深渊法师","温迪","烟绯","爱德琳","爱贝尔","玛乔丽","玛塞勒","玛格丽特","玲可","珊瑚","珊瑚宫心海","珐露珊","班尼特","琳妮特","琴","瑶瑶","瓦尔特","甘雨","田铁嘴","申鹤","留云借风真君","白术","白露","百闻","知易","石头","砂糖","神里绫人","神里绫华","空","符玄","笼钓瓶一心","米卡","素裳","纯水精灵?","纳比尔","纳西妲","绮良良","绿芙蓉","罗刹","罗莎莉亚","羽生田千鹤","老孟","胡桃","舒伯特","艾丝妲","艾伯特","艾尔海森","艾文","艾莉丝","芙宁娜","芭芭拉","荒泷一斗","荧","莎拉","莫塞伊思","莫娜","莱依拉","莺儿","菲米尼","菲谢尔","萍姥姥","萨赫哈蒂","萨齐因","蒂玛乌斯","虎克","螺丝咕姆","行秋","西拉杰","言笑","诺艾尔","费斯曼","赛诺","辛焱","达达利亚","迈勒斯","迈蒙","迪卢克","迪奥娜","迪娜泽黛","迪希雅","那维莱特","重云","金人会长","钟离","银狼","镜流","长生","阿佩普","阿兰","阿圆","阿娜耶","阿守","阿尔卡米","阿巴图伊","阿扎尔","阿拉夫","阿晃","阿洛瓦","阿祇","阿贝多","陆行岩本真蕈·元素生命","雷泽","雷电将军","霄翰","霍夫曼","青镞","青雀","香菱","驭空","魈","鹿野奈奈","鹿野院平藏","黑塔","龙二"] }
Traceback (most recent call last): File "E:\python\lib\asyncio\events.py", line 80, in _run self._context.run(self._callback, *self._args) File "E:\python\lib\asyncio\proactor_events.py", line 162, in _call_connection_lost self._sock.shutdown(socket.SHUT_RDWR) ConnectionResetError: [WinError 10054] 既存の接続はリモート ホストに強制的に切断されました。 無理っぽいかも
それ、server_fastapi.pyは起動してるか?
はい起動しています
じゃあ、ファイアウォールを殺しましょう。 消し方はネットで調べてください
ちょっとできましたかも!でもDigital Mate通してGPTの返事を拾うの無理でした
GPTの返事ならSteamのQ&Aとかを読めば分かると思うので、解決?
なんか既に設定されている返事なら読み上げれるけど、GPTのにできません....色々とありがとうございます
あ、できました。ありがとうございます!!
vits-simple-apiみたいに別のソフトからローカルURLを入れるだけで 自動的に喋らせることはできますか? https://www.bilibili.com/video/BV1W841117RL/?vd_source=dfeacb548ad2bc5554d7f5a06b641c71 動画のこれに応用したいと思っていますが.... やり方がわからなくて、すみません