Merge pull request #93 from w-okada/dev

Dev
This commit is contained in:
w-okada 2022-11-11 02:07:29 +09:00 committed by GitHub
commit 30323b875c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 875 additions and 295 deletions

View File

@ -0,0 +1,293 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"collapsed_sections": [],
"authorship_tag": "ABX9TyNeYcg5YiUjFhkeVj9OycIp",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
},
"gpuClass": "standard"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/github/w-okada/voice-changer/blob/dev/MMVCTrainerFrontendDemo.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"source": [
"Voice Changer Simple (デモ版)\n",
"---\n",
"\n",
"このートはVoice ChangerをColab上で動かすデモ版です。\n",
"\n",
"正式版はローカルPCのDocker上で動かすアプリケーションです。\n",
"\n",
"正式版は、多くの場合より少ないタイムラグで滑らかに音声を変換できます。\n",
"\n",
"詳細な使用方法はこちらの[リポジトリ](https://github.com/w-okada/voice-changer)からご確認ください。\n"
],
"metadata": {
"id": "Lbbmx_Vjl0zo"
}
},
{
"cell_type": "markdown",
"source": [
"# GPUを確認\n",
"GPUを用いたほうが高速に処理が行えます。\n",
"\n",
"下記のコマンドでGPUが確認できない場合は、上のメニューから\n",
"\n",
"「ランタイム」→「ランタイムの変更」→「ハードウェア アクセラレータ」\n",
"\n",
"でGPUを選択してください。"
],
"metadata": {
"id": "oUKi1NYMmXrr"
}
},
{
"cell_type": "code",
"source": [
"# (1) GPUの確認\n",
"!nvidia-smi"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "vV1t7PBRm-o6",
"outputId": "15081c48-84f0-4798-be64-38cf15c28966"
},
"execution_count": 1,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.\n",
"\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"# リポジトリのクローン\n",
"リポジトリをクローンします"
],
"metadata": {
"id": "sLBfykjBnjWc"
}
},
{
"cell_type": "code",
"source": [
"# (2) リポジトリのクローン\n",
"!git clone --depth 1 https://github.com/isletennos/MMVC_Trainer.git -b v1.3.1.3 /MMVC_Trainer\n",
"!git clone --depth 1 https://github.com/w-okada/voice-changer.git -b dev\n",
"%cd voice-changer/demo/\n",
"\n",
"!cp ../template/setting_mmvc_colab.json ../frontend/dist/assets/setting.json"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "86wTFmqsNMnD",
"outputId": "5151e168-15ec-4e4e-b50c-07867876294e"
},
"execution_count": 2,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"fatal: destination path '/MMVC_Trainer' already exists and is not an empty directory.\n",
"fatal: destination path 'voice-changer' already exists and is not an empty directory.\n",
"/content/voice-changer/demo\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"# モジュールのインストール\n",
"\n",
"必要なモジュールをインストールします。"
],
"metadata": {
"id": "8Na2PbLZSWgZ"
}
},
{
"cell_type": "code",
"source": [
"# (3) 設定ファイルの確認\n",
"!apt-get install -y espeak libsndfile1-dev &> /dev/null\n",
"!pip install unidecode &> /dev/null\n",
"!pip install phonemizer &> /dev/null\n",
"!pip install retry &> /dev/null\n",
"!pip install python-socketio &> /dev/null\n",
"!pip install fastapi &> /dev/null\n",
"!pip install python-multipart &> /dev/null\n",
"!pip install uvicorn &> /dev/null\n",
"!pip install websockets &> /dev/null\n",
"!pip install pyOpenSSL &> /dev/null\n",
"!pip install pyopenjtalk==0.2.0 &> /dev/null\n"
],
"metadata": {
"id": "LwZAAuqxX7yY"
},
"execution_count": 3,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"# サーバの起動\n",
"\n",
"サーバを起動します。(4-1)\n",
"\n",
"サーバの起動状況を確認します。(4-2) \n",
"\n",
"このセルは繰り返し実行することになるのでCtrl+Retでセルを実行してください。\n",
"\n",
"下記のようなテキストが表示されたら起動完了です。\n",
"\n",
"**`DEBUG:asyncio:Using selector: EpollSelector`**\n",
"\n",
"```\n",
" Phase name:__main__\n",
" PHASE3:__main__\n",
" PHASE1:__main__\n",
"Start MMVC SocketIO Server\n",
" CONFIG:None, MODEL:None\n",
"DEBUG:asyncio:Using selector: EpollSelector\n",
"```\n",
"\n"
],
"metadata": {
"id": "-_2OcN9Borke"
}
},
{
"cell_type": "code",
"source": [
"!mkdir -p /MMVC_Trainer/info\n",
"!mkdir -p /MMVC_Trainer/logs"
],
"metadata": {
"id": "pwUQ0_RzGK_g"
},
"execution_count": 4,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# (4-1) サーバの起動\n",
"import random\n",
"PORT = 10000 + random.randint(1, 9999)\n",
"LOG_FILE = f\"LOG_FILE_{PORT}\"\n",
"\n",
"get_ipython().system_raw(f'python3 MMVCServerSIO.py -p {PORT} --colab True >{LOG_FILE} 2>&1 &')\n",
"#print(f\"PORT:{PORT}, LOG_FILE:{LOG_FILE}\")"
],
"metadata": {
"id": "G-nMdPxEW1rc"
},
"execution_count": 5,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# (4-2) サーバの起動確認\n",
"!sleep 5\n",
"!tail -20 {LOG_FILE}"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "chu06KpAjEK6",
"outputId": "26995bdf-063e-43ee-84fd-4aecc7e7b7e6"
},
"execution_count": 6,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"\u001b[32m Phase name:__main__\u001b[0m\n",
"\u001b[32m PHASE3:__main__\u001b[0m\n",
"\u001b[32m PHASE1:__main__\u001b[0m\n",
"\u001b[17mStart MMVC SocketIO Server\u001b[0m\n",
"\u001b[34m CONFIG:None, MODEL:None\u001b[0m\n",
"DEBUG:asyncio:Using selector: EpollSelector\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"# プロキシを起動\n",
"ウェブサーバへのアクセスをするためのプロキシを起動します。\n",
"\n",
"表示されたURLをクリックして開くと別タブでアプリが開きます。\n",
"\n",
"Colabなので、ロードにある程度時間がかかります(30秒くらい)。"
],
"metadata": {
"id": "WhxcFLQEpctq"
}
},
{
"cell_type": "code",
"source": [
"# (5) プロキシを起動\n",
"from google.colab.output import eval_js\n",
"proxy = eval_js( \"google.colab.kernel.proxyPort(\" + str(PORT) + \")\" )\n",
"print(f\"{proxy}trainer/\")"
],
"metadata": {
"id": "nkRjZm95l87C",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "845d1582-d776-4154-984c-e256dcce6b38"
},
"execution_count": 7,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"https://ffm3z64cmhr-496ff2e9c6d22116-12768-colab.googleusercontent.com/trainer/\n"
]
}
]
}
]
}

View File

@ -5,7 +5,7 @@
"colab": {
"provenance": [],
"collapsed_sections": [],
"authorship_tag": "ABX9TyNuz5ToQB/hiwJTFCBOyGT/",
"authorship_tag": "ABX9TyP6Wv8fttT+X2Op6MmqB/kg",
"include_colab_link": true
},
"kernelspec": {
@ -82,7 +82,7 @@
"base_uri": "https://localhost:8080/"
},
"id": "Eihm8H2X-7wm",
"outputId": "e51016e6-7f6e-4b95-8822-a4713017a6a6"
"outputId": "76331fb1-5ef8-40e6-a381-258b5e425853"
},
"execution_count": 1,
"outputs": [
@ -122,7 +122,7 @@
"cell_type": "code",
"source": [
"# (2) リポジトリのクローン\n",
"!git clone https://github.com/w-okada/voice-changer.git\n",
"!git clone --depth 1 https://github.com/w-okada/voice-changer.git -b ver_1.0\n",
"%cd voice-changer/docs/\n"
],
"metadata": {
@ -130,7 +130,7 @@
"base_uri": "https://localhost:8080/"
},
"id": "86wTFmqsNMnD",
"outputId": "63e02151-2e55-49f3-8219-ba16cbb28233"
"outputId": "40471833-d720-41c9-f4a7-ac15fbf18e14"
},
"execution_count": 3,
"outputs": [
@ -139,12 +139,22 @@
"name": "stdout",
"text": [
"Cloning into 'voice-changer'...\n",
"remote: Enumerating objects: 499, done.\u001b[K\n",
"remote: Counting objects: 100% (83/83), done.\u001b[K\n",
"remote: Compressing objects: 100% (65/65), done.\u001b[K\n",
"remote: Total 499 (delta 26), reused 30 (delta 18), pack-reused 416\u001b[K\n",
"Receiving objects: 100% (499/499), 21.10 MiB | 13.43 MiB/s, done.\n",
"Resolving deltas: 100% (253/253), done.\n",
"remote: Enumerating objects: 81, done.\u001b[K\n",
"remote: Counting objects: 100% (81/81), done.\u001b[K\n",
"remote: Compressing objects: 100% (68/68), done.\u001b[K\n",
"remote: Total 81 (delta 12), reused 53 (delta 5), pack-reused 0\u001b[K\n",
"Unpacking objects: 100% (81/81), done.\n",
"Note: checking out 'f8823cb7e2025f13227f5918408cceda224bf9f0'.\n",
"\n",
"You are in 'detached HEAD' state. You can look around, make experimental\n",
"changes and commit them, and you can discard any commits you make in this\n",
"state without impacting any branches by performing another checkout.\n",
"\n",
"If you want to create a new branch to retain commits you create, you may\n",
"do so (now or later) by using -b with the checkout command again. Example:\n",
"\n",
" git checkout -b <new-branch-name>\n",
"\n",
"/content/voice-changer/docs\n"
]
}
@ -184,7 +194,7 @@
"base_uri": "https://localhost:8080/"
},
"id": "rpWUobjlBCNF",
"outputId": "0dd8bbc1-dd1e-47fe-fef6-fbc22540dc7a"
"outputId": "285e0259-16af-4932-e78b-bec94f337e9c"
},
"execution_count": 5,
"outputs": [
@ -244,7 +254,7 @@
"base_uri": "https://localhost:8080/"
},
"id": "LwZAAuqxX7yY",
"outputId": "627e09e8-bc64-4110-ce0a-5b3f84e8bf1d"
"outputId": "ea2b3b39-d571-4d47-a38b-d0e657a335cd"
},
"execution_count": 6,
"outputs": [
@ -254,20 +264,20 @@
"text": [
"Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n",
"Requirement already satisfied: flask in /usr/local/lib/python3.7/dist-packages (1.1.4)\n",
"Requirement already satisfied: Jinja2<3.0,>=2.10.1 in /usr/local/lib/python3.7/dist-packages (from flask) (2.11.3)\n",
"Requirement already satisfied: Werkzeug<2.0,>=0.15 in /usr/local/lib/python3.7/dist-packages (from flask) (1.0.1)\n",
"Requirement already satisfied: click<8.0,>=5.1 in /usr/local/lib/python3.7/dist-packages (from flask) (7.1.2)\n",
"Requirement already satisfied: itsdangerous<2.0,>=0.24 in /usr/local/lib/python3.7/dist-packages (from flask) (1.1.0)\n",
"Requirement already satisfied: Werkzeug<2.0,>=0.15 in /usr/local/lib/python3.7/dist-packages (from flask) (1.0.1)\n",
"Requirement already satisfied: Jinja2<3.0,>=2.10.1 in /usr/local/lib/python3.7/dist-packages (from flask) (2.11.3)\n",
"Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib/python3.7/dist-packages (from Jinja2<3.0,>=2.10.1->flask) (2.0.1)\n",
"Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n",
"Collecting flask_cors\n",
" Downloading Flask_Cors-3.0.10-py2.py3-none-any.whl (14 kB)\n",
"Requirement already satisfied: Flask>=0.9 in /usr/local/lib/python3.7/dist-packages (from flask_cors) (1.1.4)\n",
"Requirement already satisfied: Six in /usr/local/lib/python3.7/dist-packages (from flask_cors) (1.15.0)\n",
"Requirement already satisfied: itsdangerous<2.0,>=0.24 in /usr/local/lib/python3.7/dist-packages (from Flask>=0.9->flask_cors) (1.1.0)\n",
"Requirement already satisfied: Flask>=0.9 in /usr/local/lib/python3.7/dist-packages (from flask_cors) (1.1.4)\n",
"Requirement already satisfied: Werkzeug<2.0,>=0.15 in /usr/local/lib/python3.7/dist-packages (from Flask>=0.9->flask_cors) (1.0.1)\n",
"Requirement already satisfied: click<8.0,>=5.1 in /usr/local/lib/python3.7/dist-packages (from Flask>=0.9->flask_cors) (7.1.2)\n",
"Requirement already satisfied: itsdangerous<2.0,>=0.24 in /usr/local/lib/python3.7/dist-packages (from Flask>=0.9->flask_cors) (1.1.0)\n",
"Requirement already satisfied: Jinja2<3.0,>=2.10.1 in /usr/local/lib/python3.7/dist-packages (from Flask>=0.9->flask_cors) (2.11.3)\n",
"Requirement already satisfied: click<8.0,>=5.1 in /usr/local/lib/python3.7/dist-packages (from Flask>=0.9->flask_cors) (7.1.2)\n",
"Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib/python3.7/dist-packages (from Jinja2<3.0,>=2.10.1->Flask>=0.9->flask_cors) (2.0.1)\n",
"Installing collected packages: flask-cors\n",
"Successfully installed flask-cors-3.0.10\n"
@ -333,25 +343,25 @@
"base_uri": "https://localhost:8080/"
},
"id": "chu06KpAjEK6",
"outputId": "a42873c4-2826-4b54-f497-01adb1683875"
"outputId": "6f5cbed9-65a7-4570-f58a-5447e402947c"
},
"execution_count": 8,
"execution_count": 10,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[2022-09-13 22:45:22,054] INFO in recorderServer: START APP\n",
"[2022-11-08 19:11:17,679] INFO in recorderServer: START APP\n",
" * Serving Flask app \"recorderServer\" (lazy loading)\n",
" * Environment: production\n",
" WARNING: This is a development server. Do not use it in a production deployment.\n",
" Use a production WSGI server instead.\n",
" * Debug mode: on\n",
"[2022-09-13 22:45:22,062] INFO in _internal: * Running on http://0.0.0.0:8018/ (Press CTRL+C to quit)\n",
"[2022-09-13 22:45:22,063] INFO in _internal: * Restarting with stat\n",
"[2022-09-13 22:45:22,238] INFO in recorderServer: START APP\n",
"[2022-09-13 22:45:22,244] WARNING in _internal: * Debugger is active!\n",
"[2022-09-13 22:45:22,268] INFO in _internal: * Debugger PIN: 334-166-753\n"
"[2022-11-08 19:11:17,696] INFO in _internal: * Running on http://0.0.0.0:8018/ (Press CTRL+C to quit)\n",
"[2022-11-08 19:11:17,697] INFO in _internal: * Restarting with stat\n",
"[2022-11-08 19:11:17,893] INFO in recorderServer: START APP\n",
"[2022-11-08 19:11:17,900] WARNING in _internal: * Debugger is active!\n",
"[2022-11-08 19:11:17,930] INFO in _internal: * Debugger PIN: 225-344-519\n"
]
}
]
@ -384,9 +394,9 @@
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "768df0ee-9499-430b-ab4f-c602311114ae"
"outputId": "7d2664b8-945c-4ee6-b49f-51f7f96cf388"
},
"execution_count": 9,
"execution_count": 11,
"outputs": [
{
"output_type": "display_data",
@ -443,7 +453,7 @@
"metadata": {
"id": "3PhrmCD2LaCH"
},
"execution_count": 43,
"execution_count": null,
"outputs": []
},
{
@ -469,7 +479,7 @@
"id": "f5l6ggSyACLs",
"outputId": "4db3571a-46e6-4fd9-c560-628cf4af9284"
},
"execution_count": 57,
"execution_count": null,
"outputs": [
{
"output_type": "stream",
@ -492,7 +502,7 @@
"metadata": {
"id": "UEVb2GGZSesY"
},
"execution_count": 71,
"execution_count": null,
"outputs": []
},
{
@ -542,7 +552,7 @@
"id": "L8UsVp3dDs4R",
"outputId": "5d640caf-87b0-45a6-aa0c-76295e537f6a"
},
"execution_count": 73,
"execution_count": null,
"outputs": [
{
"output_type": "stream",

View File

@ -20,9 +20,23 @@ from datetime import datetime
import torch
import numpy as np
from mods.ssl import create_self_signed_cert
from mods.VoiceChanger import VoiceChanger
# from mods.Whisper import Whisper
# File Uploader
from mods.FileUploader import upload_file, concat_file_chunks
# Trainer Rest Internal
from mods.Trainer_Speakers import mod_get_speakers
from mods.Trainer_Speaker import mod_delete_speaker
from mods.Trainer_Speaker_Voices import mod_get_speaker_voices
from mods.Trainer_Speaker_Voice import mod_get_speaker_voice
from mods.Trainer_MultiSpeakerSetting import mod_get_multi_speaker_setting, mod_post_multi_speaker_setting
from mods.Trainer_Models import mod_get_models
from mods.Trainer_Model import mod_get_model, mod_delete_model
from mods.Trainer_Training import mod_post_pre_training, mod_post_start_training, mod_post_stop_training, mod_get_related_files, mod_get_tail_training_log
class UvicornSuppressFilter(logging.Filter):
def filter(self, record):
@ -131,6 +145,24 @@ args = parser.parse_args()
printMessage(f"Phase name:{__name__}", level=2)
thisFilename = os.path.basename(__file__)[:-3]
from typing import Callable, List
from fastapi import Body, FastAPI, HTTPException, Request, Response
from fastapi.exceptions import RequestValidationError
from fastapi.routing import APIRoute
class ValidationErrorLoggingRoute(APIRoute):
def get_route_handler(self) -> Callable:
original_route_handler = super().get_route_handler()
async def custom_route_handler(request: Request) -> Response:
try:
return await original_route_handler(request)
except Exception as exc:
print("Exception", request.url, str(exc))
body = await request.body()
detail = {"errors": exc.errors(), "body": body.decode()}
raise HTTPException(status_code=422, detail=detail)
return custom_route_handler
if __name__ == thisFilename or args.colab == True:
printMessage(f"PHASE3:{__name__}", level=2)
@ -139,6 +171,7 @@ if __name__ == thisFilename or args.colab == True:
MODEL = args.m
app_fastapi = FastAPI()
app_fastapi.router.route_class = ValidationErrorLoggingRoute
app_fastapi.add_middleware(
CORSMiddleware,
allow_origins=["*"],
@ -149,6 +182,10 @@ if __name__ == thisFilename or args.colab == True:
app_fastapi.mount("/front", StaticFiles(directory="../frontend/dist", html=True), name="static")
app_fastapi.mount("/trainer", StaticFiles(directory="../frontend/dist", html=True), name="static")
app_fastapi.mount("/recorder", StaticFiles(directory="../frontend/dist", html=True), name="static")
sio = socketio.AsyncServer(
async_mode='asgi',
cors_allowed_origins='*'
@ -178,36 +215,20 @@ if __name__ == thisFilename or args.colab == True:
return {"result": "Index"}
UPLOAD_DIR = "model_upload_dir"
############
# File Uploder
# ##########
UPLOAD_DIR = "upload_dir"
os.makedirs(UPLOAD_DIR, exist_ok=True)
# Can colab receive post request "ONLY" at root path?
@app_fastapi.post("/upload_model_file")
async def upload_file(configFile:UploadFile = File(...), modelFile: UploadFile = File(...)):
if configFile and modelFile:
for file in [modelFile, configFile]:
filename = file.filename
fileobj = file.file
upload_dir = open(os.path.join(UPLOAD_DIR, filename),'wb+')
shutil.copyfileobj(fileobj, upload_dir)
upload_dir.close()
namespace.loadModel(os.path.join(UPLOAD_DIR, configFile.filename), os.path.join(UPLOAD_DIR, modelFile.filename))
return {"uploaded files": f"{configFile.filename}, {modelFile.filename} "}
return {"Error": "uploaded file is not found."}
MODEL_DIR = "/MMVC_Trainer/logs"
os.makedirs(MODEL_DIR, exist_ok=True)
@app_fastapi.post("/upload_file")
async def post_upload_file(
file:UploadFile = File(...),
filename: str = Form(...)
):
if file and filename:
fileobj = file.file
upload_dir = open(os.path.join(UPLOAD_DIR, filename),'wb+')
shutil.copyfileobj(fileobj, upload_dir)
upload_dir.close()
return {"uploaded files": f"{filename} "}
return {"Error": "uploaded file is not found."}
return upload_file(UPLOAD_DIR, file, filename)
@app_fastapi.post("/load_model")
async def post_load_model(
@ -216,33 +237,40 @@ if __name__ == thisFilename or args.colab == True:
configFilename: str = Form(...)
):
target_file_name = modelFilename
with open(os.path.join(UPLOAD_DIR, target_file_name), "ab") as target_file:
for i in range(modelFilenameChunkNum):
filename = f"{modelFilename}_{i}"
chunk_file_path = os.path.join(UPLOAD_DIR,filename)
stored_chunk_file = open(chunk_file_path, 'rb')
target_file.write(stored_chunk_file.read())
stored_chunk_file.close()
os.unlink(chunk_file_path)
target_file.close()
print(f'File saved to: {target_file_name}')
modelFilePath = concat_file_chunks(UPLOAD_DIR, modelFilename, modelFilenameChunkNum,UPLOAD_DIR)
print(f'File saved to: {modelFilePath}')
configFilePath = os.path.join(UPLOAD_DIR, configFilename)
print(f'Load: {configFilename}, {target_file_name}')
namespace.loadModel(os.path.join(UPLOAD_DIR, configFilename), os.path.join(UPLOAD_DIR, target_file_name))
return {"File saved to": f"{target_file_name}"}
namespace.loadModel(configFilePath, modelFilePath)
return {"load": f"{modelFilePath}, {configFilePath}"}
@app_fastapi.post("/load_model_for_train")
async def post_load_model_for_train(
modelGFilename: str = Form(...),
modelGFilenameChunkNum: int = Form(...),
modelDFilename: str = Form(...),
modelDFilenameChunkNum: int = Form(...),
):
modelGFilePath = concat_file_chunks(UPLOAD_DIR, modelGFilename, modelGFilenameChunkNum, MODEL_DIR)
modelDFilePath = concat_file_chunks(UPLOAD_DIR, modelDFilename, modelDFilenameChunkNum,MODEL_DIR)
return {"File saved": f"{modelGFilePath}, {modelDFilePath}"}
@app_fastapi.post("/extract_voices")
async def post_load_model(
zipFilename: str = Form(...),
zipFileChunkNum: int = Form(...),
):
zipFilePath = concat_file_chunks(UPLOAD_DIR, zipFilename, zipFileChunkNum, UPLOAD_DIR)
shutil.unpack_archive(zipFilePath, "/MMVC_Trainer/dataset/textful/")
return {"Zip file unpacked": f"{zipFilePath}"}
@app_fastapi.get("/transcribe")
def get_transcribe():
try:
namespace.transcribe()
except Exception as e:
print("TRANSCRIBE PROCESSING!!!! EXCEPTION!!!", e)
print(traceback.format_exc())
return str(e)
############
# Voice Changer
# ##########
@app_fastapi.post("/test")
async def post_test(voice:VoiceModel):
try:
@ -284,6 +312,68 @@ if __name__ == thisFilename or args.colab == True:
return str(e)
# Trainer REST API ※ ColabがTop直下のパスにしかPOSTを投げれないようなので"REST風"
@app_fastapi.get("/get_speakers")
async def get_speakers():
return mod_get_speakers()
@app_fastapi.delete("/delete_speaker")
async def delete_speaker(speaker:str= Form(...)):
return mod_delete_speaker(speaker)
@app_fastapi.get("/get_speaker_voices")
async def get_speaker_voices(speaker:str):
return mod_get_speaker_voices(speaker)
@app_fastapi.get("/get_speaker_voice")
async def get_speaker_voices(speaker:str, voice:str):
return mod_get_speaker_voice(speaker, voice)
@app_fastapi.get("/get_multi_speaker_setting")
async def get_multi_speaker_setting():
return mod_get_multi_speaker_setting()
@app_fastapi.post("/post_multi_speaker_setting")
async def post_multi_speaker_setting(setting: str = Form(...)):
return mod_post_multi_speaker_setting(setting)
@app_fastapi.get("/get_models")
async def get_models():
return mod_get_models()
@app_fastapi.get("/get_model")
async def get_model(model:str):
return mod_get_model(model)
@app_fastapi.delete("/delete_model")
async def delete_model(model:str= Form(...)):
return mod_delete_model(model)
@app_fastapi.post("/post_pre_training")
async def post_pre_training(batch:int= Form(...)):
return mod_post_pre_training(batch)
@app_fastapi.post("/post_start_training")
async def post_start_training():
print("POST START TRAINING..")
return mod_post_start_training()
@app_fastapi.post("/post_stop_training")
async def post_stop_training():
print("POST STOP TRAINING..")
return mod_post_stop_training()
@app_fastapi.get("/get_related_files")
async def get_related_files():
return mod_get_related_files()
@app_fastapi.get("/get_tail_training_log")
async def get_tail_training_log(num:int):
return mod_get_tail_training_log(num)
if __name__ == '__mp_main__':
printMessage(f"PHASE2:{__name__}", level=2)

27
demo/mods/FileUploader.py Executable file
View File

@ -0,0 +1,27 @@
import os, shutil
from fastapi import UploadFile
# UPLOAD_DIR = "model_upload_dir"
def upload_file(upload_dirname:str, file:UploadFile, filename: str):
if file and filename:
fileobj = file.file
upload_dir = open(os.path.join(upload_dirname, filename),'wb+')
shutil.copyfileobj(fileobj, upload_dir)
upload_dir.close()
return {"uploaded files": f"{filename} "}
return {"Error": "uploaded file is not found."}
def concat_file_chunks(upload_dirname:str, filename:str, chunkNum:int, dest_dirname:str):
target_file_name = os.path.join(dest_dirname, filename)
with open(target_file_name, "ab") as target_file:
for i in range(chunkNum):
chunkName = f"{filename}_{i}"
chunk_file_path = os.path.join(upload_dirname, chunkName)
stored_chunk_file = open(chunk_file_path, 'rb')
target_file.write(stored_chunk_file.read())
stored_chunk_file.close()
os.unlink(chunk_file_path)
target_file.close()
return target_file_name

13
demo/mods/Trainer_Model.py Executable file
View File

@ -0,0 +1,13 @@
from fastapi.responses import FileResponse
import os
def mod_get_model(modelFile:str):
modelPath = os.path.join("/MMVC_Trainer/logs", modelFile)
return FileResponse(path=modelPath)
def mod_delete_model(modelFile:str):
modelPath = os.path.join("/MMVC_Trainer/logs", modelFile)
os.unlink(modelPath)
return {"Model deleted": f"{modelFile}"}

21
demo/mods/Trainer_Models.py Executable file
View File

@ -0,0 +1,21 @@
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
from trainer_mods.files import get_file_list
import os
def mod_get_models():
gModels = get_file_list(f'/MMVC_Trainer/logs/G*.pth')
dModels = get_file_list(f'/MMVC_Trainer/logs/D*.pth')
models = []
models.extend(gModels)
models.extend(dModels)
models = [ os.path.basename(x) for x in models]
models = sorted(models)
data = {
"models":models
}
json_compatible_item_data = jsonable_encoder(data)
return JSONResponse(content=json_compatible_item_data)

View File

@ -0,0 +1,26 @@
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
import os
MULTI_SPEAKER_SETTING_PATH = "/MMVC_Trainer/dataset/multi_speaker_correspondence.txt"
def mod_get_multi_speaker_setting():
data = {}
if os.path.isfile(MULTI_SPEAKER_SETTING_PATH) == False:
with open(MULTI_SPEAKER_SETTING_PATH, "w") as f:
f.write("")
f.flush()
f.close()
with open(MULTI_SPEAKER_SETTING_PATH, "r") as f:
setting = f.read()
data["multi_speaker_setting"] = setting
json_compatible_item_data = jsonable_encoder(data)
return JSONResponse(content=json_compatible_item_data)
def mod_post_multi_speaker_setting(setting:str):
with open(MULTI_SPEAKER_SETTING_PATH, "w") as f:
f.write(setting)
f.flush()
f.close()
return {"Write Multispeaker setting": f"{setting}"}

15
demo/mods/Trainer_Speaker.py Executable file
View File

@ -0,0 +1,15 @@
import shutil
from mods.Trainer_MultiSpeakerSetting import MULTI_SPEAKER_SETTING_PATH
def mod_delete_speaker(speaker:str):
shutil.rmtree(f"/MMVC_Trainer/dataset/textful/{speaker}")
with open(MULTI_SPEAKER_SETTING_PATH, "r") as f:
setting = f.readlines()
filtered = filter(lambda x: x.startswith(f"{speaker}|")==False, setting)
with open(MULTI_SPEAKER_SETTING_PATH, "w") as f:
f.writelines(list(filtered))
f.flush()
f.close()
return {"Speaker deleted": f"{speaker}"}

View File

@ -0,0 +1,28 @@
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
import os, base64
def mod_get_speaker_voice(speaker:str, voice:str):
wav_file = f'/MMVC_Trainer/dataset/textful/{speaker}/wav/{voice}.wav'
text_file = f'/MMVC_Trainer/dataset/textful/{speaker}/text/{voice}.txt'
readable_text_file = f'/MMVC_Trainer/dataset/textful/{speaker}/readable_text/{voice}.txt'
data = {}
if os.path.exists(wav_file):
with open(wav_file, "rb") as f:
wav_data = f.read()
wav_data_base64 = base64.b64encode(wav_data).decode('utf-8')
data["wav"] = wav_data_base64
if os.path.exists(text_file):
with open(text_file, "r") as f:
text_data = f.read()
data["text"] = text_data
if os.path.exists(readable_text_file):
with open(readable_text_file, "r") as f:
text_data = f.read()
data["readable_text"] = text_data
json_compatible_item_data = jsonable_encoder(data)
return JSONResponse(content=json_compatible_item_data)

View File

@ -0,0 +1,22 @@
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
from trainer_mods.files import get_file_list
import os
def mod_get_speaker_voices(speaker:str):
voices = get_file_list(f'/MMVC_Trainer/dataset/textful/{speaker}/wav/*.wav')
texts = get_file_list(f'/MMVC_Trainer/dataset/textful/{speaker}/text/*.txt')
readable_texts = get_file_list(f'/MMVC_Trainer/dataset/textful/{speaker}/readable_text/*.txt')
items = voices
items.extend(texts)
items.extend(readable_texts)
items = [ os.path.splitext(os.path.basename(x))[0] for x in items]
items = sorted(set(items))
data = {
"voices":items
}
json_compatible_item_data = jsonable_encoder(data)
return JSONResponse(content=json_compatible_item_data)

15
demo/mods/Trainer_Speakers.py Executable file
View File

@ -0,0 +1,15 @@
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
from trainer_mods.files import get_dir_list
import os
# CreateはFileUploaderで実装。
def mod_get_speakers():
os.makedirs("/MMVC_Trainer/dataset/textful", exist_ok=True)
speakers = get_dir_list("/MMVC_Trainer/dataset/textful/")
data = {
"speakers":sorted(speakers)
}
json_compatible_item_data = jsonable_encoder(data)
return JSONResponse(content=json_compatible_item_data)

167
demo/mods/Trainer_Training.py Executable file
View File

@ -0,0 +1,167 @@
import subprocess,os
from trainer_mods.files import get_file_list
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
LOG_DIR = "/MMVC_Trainer/info"
train_proc = None
SUCCESS = 0
ERROR = -1
### Submodule for Pre train
def sync_exec(cmd:str, log_path:str):
shortCmdStr = cmd[:20]
try:
with open(log_path, 'w') as log_file:
proc = subprocess.run(cmd, shell=True, text=True, stdout=log_file, stderr=log_file, cwd="/MMVC_Trainer")
print(f"{shortCmdStr} returncode:{proc.returncode}")
if proc.returncode != 0:
print(f"{shortCmdStr} exception:")
return (ERROR, f"returncode:{proc.returncode}")
except Exception as e:
print(f"{shortCmdStr} exception:", str(e))
return (ERROR, str(e))
return (SUCCESS, "success")
def sync_exec_with_stdout(cmd:str, log_path:str):
shortCmdStr = cmd[:20]
try:
with open(log_path, 'w') as log_file:
proc = subprocess.run(cmd, shell=True, text=True, stdout=subprocess.PIPE,
stderr=log_file, cwd="/MMVC_Trainer")
print(f"STDOUT{shortCmdStr}",proc.stdout)
except Exception as e:
print(f"{shortCmdStr} exception:", str(e))
return (ERROR, str(e))
return (SUCCESS, proc.stdout)
def create_dataset():
cmd = "python3 create_dataset_jtalk.py -f train_config -s 24000 -m dataset/multi_speaker_correspondence.txt"
log_file = os.path.join(LOG_DIR, "log_create_dataset_jtalk.txt")
res = sync_exec(cmd, log_file)
return res
def set_batch_size(batch:int):
cmd = "sed -i 's/\"batch_size\": [0-9]*/\"batch_size\": " + str(batch) + "/' /MMVC_Trainer/configs/baseconfig.json"
log_file = os.path.join(LOG_DIR, "log_set_batch_size.txt")
res = sync_exec(cmd, log_file)
return res
def set_dummy_device_count():
cmd = 'sed -ie "s/torch.cuda.device_count()/1/" /MMVC_Trainer/train_ms.py'
log_file = os.path.join(LOG_DIR, "log_set_dummy_device_count.txt")
res = sync_exec(cmd, log_file)
return res
### Submodule for Train
def exec_training():
global train_proc
log_file = os.path.join(LOG_DIR, "training.txt")
# トレーニング開始確認(二重起動回避)
if train_proc != None:
status = train_proc.poll()
if status != None:
print("Training have ended.", status)
train_proc = None
else:
print("Training have stated.")
return (ERROR, "Training have started")
try:
with open(log_file, 'w') as log_file:
cmd = 'python3 train_ms.py -c configs/train_config.json -m ./'
print("exec:",cmd)
train_proc = subprocess.Popen("exec "+cmd, shell=True, text=True, stdout=log_file, stderr=log_file, cwd="/MMVC_Trainer")
print("Training stated")
print(f"returncode:{train_proc.returncode}")
except Exception as e:
print("start training exception:", str(e))
return (ERROR, str(e))
return (SUCCESS, "success")
def stop_training():
global train_proc
if train_proc == None:
print("Training have not stated.")
return (ERROR, "Training have not stated.")
status = train_proc.poll()
if status != None:
print("Training have already ended.", status)
train_proc = None
return (ERROR, "Training have already ended. " + status)
else:
train_proc.kill()
print("Training have stoped.")
return (SUCCESS, "success")
### Main
def mod_post_pre_training(batch:int):
res = set_batch_size(batch)
if res[0] == ERROR:
return {"result":"failed", "detail": f"Preprocess(set_batch_size) failed. {res[1]}"}
res = set_dummy_device_count()
if res[0] == ERROR:
return {"result":"failed", "detail": f"Preprocess(set_dummy_device_count) failed. {res[1]}"}
res = create_dataset()
if res[0] == ERROR:
return {"result":"failed", "detail": f"Preprocess failed(create_dataset). {res[1]}"}
return {"result":"success", "detail": f"Preprocess succeeded. {res[1]}"}
def mod_post_start_training():
res = exec_training()
if res[0] == ERROR:
return {"result":"failed", "detail": f"Start training failed. {res[1]}"}
return {"result":"success", "detail": f"Start training succeeded. {res[1]}"}
def mod_post_stop_training():
res = stop_training()
if res[0] == ERROR:
return {"result":"failed", "detail": f"Stop training failed. {res[1]}"}
return {"result":"success", "detail": f"Stop training succeeded. {res[1]}"}
### DEBUG
def mod_get_related_files():
files = get_file_list(os.path.join(LOG_DIR,"*"))
files.extend([
"/MMVC_Trainer/dataset/multi_speaker_correspondence.txt",
"/MMVC_Trainer/train_ms.py",
])
files.extend(
get_file_list("/MMVC_Trainer/configs/*")
)
res = []
for f in files:
size = os.path.getsize(f)
data = ""
if size < 1024*1024:
with open(f, "r") as input:
data = input.read()
res.append({
"name":f,
"size":size,
"data":data
})
json_compatible_item_data = jsonable_encoder(res)
return JSONResponse(content=json_compatible_item_data)
def mod_get_tail_training_log(num:int):
training_log_file = os.path.join(LOG_DIR, "training.txt")
res = sync_exec(f"cat {training_log_file} | sed -e 's/.*\r//' > /tmp/out","/dev/null")
cmd = f'tail -n {num} /tmp/out'
res = sync_exec_with_stdout(cmd, "/dev/null")
if res[0] == ERROR:
return {"result":"failed", "detail": f"Tail training log failed. {res[1]}"}
return {"result":"success", "detail":res[1]}

19
demo/trainer_mods/files.py Executable file
View File

@ -0,0 +1,19 @@
import os,glob
def get_file_list(top_dir):
for root, dirs, files in os.walk(top_dir):
for dir in dirs:
dirPath = os.path.join(root, dir)
print(f'dirPath = {dirPath}')
for file in files:
filePath = os.path.join(root, file)
print(f'filePath = {filePath}')
def get_dir_list(top_dir):
return os.listdir(top_dir)
def get_file_list(top_dir):
return glob.glob(top_dir)

View File

@ -1,4 +1,4 @@
FROM dannadori/voice-changer-internal:20221104_061809 as front
FROM dannadori/voice-changer-internal:20221109_051139 as front
FROM debian:bullseye-slim as base
ARG DEBIAN_FRONTEND=noninteractive
@ -60,7 +60,6 @@ COPY --from=base --chmod=777 /usr/local/lib/python3.9/dist-packages /usr/local/l
COPY --from=front --chmod=777 /MMVC_Trainer /MMVC_Trainer
RUN chmod 0777 /MMVC_Trainer
WORKDIR /MMVC_Trainer
ADD /setup.sh /MMVC_Trainer/
ADD /exec.sh /MMVC_Trainer/
@ -69,6 +68,10 @@ COPY --from=front --chmod=777 /voice-changer-internal/frontend/dist /voice-chang
COPY --from=front --chmod=777 /voice-changer-internal/voice-change-service /voice-changer-internal/voice-change-service
RUN chmod 0777 /voice-changer-internal/voice-change-service
## 歴史的な経緯でsetup.shをMMVC_Trainerに置いているのでそこを起動時のWORKDIRにしている。
WORKDIR /MMVC_Trainer
# ##### Soft VC
# COPY --from=front /hubert /hubert
# COPY --from=front /acoustic-model /acoustic-model

View File

@ -39,16 +39,17 @@ if [ "${MODE}" = "MMVC" ] ; then
# python3 MMVCServerSIO.py $PARAMS 2>stderr.txt
# fi
echo "MMVCを起動します"
python3 MMVCServerSIO.py $PARAMS 2>stderr.txt
python3 MMVCServerSIO.py $PARAMS #2>stderr.txt
elif [ "${MODE}" = "MMVC_TRAIN" ] ; then
python3 create_dataset_jtalk.py -f train_config -s 24000 -m dataset/multi_speaker_correspondence.txt
# date_tag=`date +%Y%m%d%H%M%S`
sed -ie 's/80000/8000/' train_ms.py
sed -ie "s/\"batch_size\": 10/\"batch_size\": $batch_size/" configs/train_config.json
sed -ie "s/torch.cuda.device_count()/1/" train_ms.py
python3 -m tensorboard.main --logdir logs --port 6006 --host 0.0.0.0 &
python3 train_ms.py $PARAMS
cd /voice-changer-internal/voice-change-service
# python3 create_dataset_jtalk.py -f train_config -s 24000 -m dataset/multi_speaker_correspondence.txt
# # date_tag=`date +%Y%m%d%H%M%S`
# sed -ie 's/80000/8000/' train_ms.py
# sed -ie "s/\"batch_size\": 10/\"batch_size\": $batch_size/" configs/train_config.json
# sed -ie "s/torch.cuda.device_count()/1/" train_ms.py
python3 -m tensorboard.main --logdir /MMVC_Trainer/logs --port 6006 --host 0.0.0.0 &
python3 MMVCServerSIO.py $PARAMS
# if ${resume_flag}; then
# echo "トレーニング再開。バッチサイズ: ${batch_size}。"
# python3 train_ms.py -c configs/train_config.json -m vc

View File

@ -3,11 +3,12 @@
# 参考:https://programwiz.org/2022/03/22/how-to-write-shell-script-for-option-parsing/
set -eu
echo "1"
# 実行ユーザ作成
USER_ID=${LOCAL_UID:-9001}
GROUP_ID=${LOCAL_GID:-9001}
echo "2"
echo "exec with [UID : $USER_ID, GID: $GROUP_ID]"
useradd -u $USER_ID -o -m user
groupmod -g $GROUP_ID user

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-help-circle"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>

After

Width:  |  Height:  |  Size: 365 B

BIN
docs/assets/icons/zun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -2,6 +2,9 @@
"app_title": "voice-recorder",
"storage_type":"local",
"use_mel_spectrogram":true,
"current_text":"ITA-emotion",
"current_text_index":0,
"sample_rate":48000,
"text": [
{
"title": "ITA-emotion",

File diff suppressed because one or more lines are too long

View File

@ -5,12 +5,6 @@
(c) 2013-2017 Mozilla, Apache License 2.0
*/
/*!
* Font Awesome Free 6.1.2 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
/*!
* The buffer module from node.js, for the browser.
*
@ -19,7 +13,7 @@
*/
/*!
* wavesurfer.js 6.2.0 (2022-05-16)
* wavesurfer.js 6.4.0 (2022-11-05)
* https://wavesurfer-js.org
* @license BSD-3-Clause
*/

4
frontend/dist/assets/setting_recorder.json vendored Executable file
View File

@ -0,0 +1,4 @@
{
"app_title": "recorder",
"majar_mode": "docker"
}

4
frontend/dist/assets/setting_trainer.json vendored Executable file
View File

@ -0,0 +1,4 @@
{
"app_title": "trainer",
"majar_mode": "docker"
}

View File

@ -1 +1 @@
<!doctype html><html lang="ja" style="width:100%;height:100%;overflow:hidden"><head><meta charset="utf-8"/><title>voice recorder</title><script defer="defer" src="index.js"></script></head><body style="width:100%;height:100%;margin:0"><div id="app" style="width:100%;height:100%"></div><noscript><strong>javascriptを有効にしてください</strong></noscript></body></html>
<!doctype html><html lang="ja" style="width:100%;height:100%;overflow:hidden"><head><meta charset="utf-8"/><title>Realtime Voice Changer (Train/VC)</title><script defer="defer" src="index.js"></script></head><body style="width:100%;height:100%;margin:0"><div id="app" style="width:100%;height:100%"></div><noscript><strong>javascriptを有効にしてください</strong></noscript></body></html>

File diff suppressed because one or more lines are too long

View File

@ -4,7 +4,7 @@
"description": "",
"main": "index.js",
"scripts": {
"build:docker": "date +%Y%m%d%H%M%S > trainer/dummy && DOCKER_BUILDKIT=1 docker build -f trainer/Dockerfile trainer/ -t voice-changer",
"build:docker": "date +%Y%m%d%H%M%S > docker/dummy && DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile docker/ -t voice-changer",
"copy:frontend":"docker run -v `pwd`/frontend/dist:/frontend/dist --entrypoint /bin/bash -ti voice-changer -c \"cp -r /voice-changer-internal/frontend/dist/* /frontend/dist\"",
"copy:backend":"docker run -v `pwd`/demo:/demo --entrypoint /bin/bash -ti voice-changer -c \"cp -r /voice-changer-internal/voice-change-service/* /demo/\"",
"create:demo":"run-p copy:frontend copy:backend",

View File

@ -1,20 +1,21 @@
#!/bin/bash
set -eu
DOCKER_IMAGE=dannadori/voice-changer:20221104_062009
#DOCKER_IMAGE=voice-changer
#DOCKER_IMAGE=dannadori/voice-changer:20221108_105937
DOCKER_IMAGE=voice-changer
MODE=$1
PARAMS=${@:2:($#-1)}
### DEFAULT VAR ###
DEFAULT_EX_PORT=18888
DEFAULT_EX_TB_PORT=16006
DEFAULT_USE_GPU=on # on|off
# DEFAULT_VERBOSE=off # on|off
### ENV VAR ###
EX_PORT=${EX_PORT:-${DEFAULT_EX_PORT}}
EX_TB_PORT=${EX_TB_PORT:-${DEFAULT_EX_TB_PORT}}
USE_GPU=${USE_GPU:-${DEFAULT_USE_GPU}}
# VERBOSE=${VERBOSE:-${DEFAULT_VERBOSE}}
@ -30,16 +31,16 @@ if [ "${MODE}" = "MMVC_TRAIN" ]; then
echo "トレーニングを開始します"
docker run -it --gpus all --shm-size=128M \
-v `pwd`/exp/${name}/dataset:/MMVC_Trainer/dataset \
-v `pwd`/exp/${name}/logs:/MMVC_Trainer/logs \
-v `pwd`/exp/${name}/filelists:/MMVC_Trainer/filelists \
-v `pwd`/vc_resources:/resources \
-v `pwd`/work_dir/logs:/MMVC_Trainer/logs \
-v `pwd`/work_dir/dataset:/MMVC_Trainer/dataset \
-v `pwd`/work_dir/info:/MMVC_Trainer/info \
-e LOCAL_UID=$(id -u $USER) \
-e LOCAL_GID=$(id -g $USER) \
-e EX_PORT=${EX_PORT} -e EX_TB_PORT=${EX_TB_PORT} \
-e EX_IP="`hostname -I`" \
-e EX_PORT=${EX_PORT} \
-e VERBOSE=${VERBOSE} \
-p ${EX_PORT}:6006 $DOCKER_IMAGE "$@"
-p ${EX_PORT}:8080 -p ${EX_TB_PORT}:6006 \
$DOCKER_IMAGE "$@"
elif [ "${MODE}" = "MMVC" ]; then
if [ "${USE_GPU}" = "on" ]; then

View File

@ -1,53 +0,0 @@
#!/bin/bash
EXP_NAME=$1
echo $EXP_NAME
# (A)
mkdir -p exp/${EXP_NAME}/logs
mkdir -p exp/${EXP_NAME}/filelists
mkdir -p exp/${EXP_NAME}/dataset
echo "00_myvoice|107" > exp/${EXP_NAME}/dataset/multi_speaker_correspondence.txt
echo "01_target_zundamon|100" >> exp/${EXP_NAME}/dataset/multi_speaker_correspondence.txt
echo "02_target_tsumugi|103" >> exp/${EXP_NAME}/dataset/multi_speaker_correspondence.txt
echo "03_target_metan|102" >> exp/${EXP_NAME}/dataset/multi_speaker_correspondence.txt
echo "04_target_ksora|101" >> exp/${EXP_NAME}/dataset/multi_speaker_correspondence.txt
# (B) トレーニングデータ作成
# (B-0) my voice
mkdir -p exp/${EXP_NAME}/dataset/textful/00_myvoice/text
mkdir -p exp/${EXP_NAME}/dataset/textful/00_myvoice/wav
cp dataset/00_myvoice/wav/* exp/${EXP_NAME}/dataset/textful/00_myvoice/wav/
cp dataset/00_myvoice/text/* exp/${EXP_NAME}/dataset/textful/00_myvoice/text/
# (B-1) ずんだもん
mkdir -p exp/${EXP_NAME}/dataset/textful/01_target_zundamon/
unzip -j dataset/1225_zundamon.zip 1225_zundamon/wav/* -d exp/${EXP_NAME}/dataset/textful/01_target_zundamon/wav/
unzip -j dataset/1225_zundamon.zip 1225_zundamon/text/* -d exp/${EXP_NAME}/dataset/textful/01_target_zundamon/text/
# (B-2) 春日部つむぎ
mkdir -p exp/${EXP_NAME}/dataset/textful/02_target_tsumugi/
unzip -j dataset/344_tsumugi.zip 344_tsumugi/wav/* -d exp/${EXP_NAME}/dataset/textful/02_target_tsumugi/wav/
unzip -j dataset/344_tsumugi.zip 344_tsumugi/text/* -d exp/${EXP_NAME}/dataset/textful/02_target_tsumugi/text/
# (B-3) 四国めたん
mkdir -p exp/${EXP_NAME}/dataset/textful/03_target_metan/
unzip -j dataset/459_methane.zip 459_methane/wav/* -d exp/${EXP_NAME}/dataset/textful/03_target_metan/wav/
unzip -j dataset/459_methane.zip 459_methane/text/* -d exp/${EXP_NAME}/dataset/textful/03_target_metan/text/
# (B-4) 九州そら
mkdir -p exp/${EXP_NAME}/dataset/textful/04_target_ksora/
unzip -j dataset/912_sora.zip 912_sora/wav/* -d exp/${EXP_NAME}/dataset/textful/04_target_ksora/wav/
unzip -j dataset/912_sora.zip 912_sora/text/* -d exp/${EXP_NAME}/dataset/textful/04_target_ksora/text/
## 004_expまで。
# echo $1
# mkdir -p ${EXP_NAME}/00_myvoice/text
# mkdir -p ${EXP_NAME}/00_myvoice/wav
# mkdir -p ${EXP_NAME}/logs
# mkdir -p ${EXP_NAME}/filelists

View File

@ -1,133 +0,0 @@
#!/bin/bash
# 参考:https://programwiz.org/2022/03/22/how-to-write-shell-script-for-option-parsing/
set -eu
echo "------"
echo "$@"
echo "------"
usage() {
echo "
usage:
For training
$0 [-t] [-b batch_size] [-r]
-t: flag for training mode
-b: batch_size.
-r: flag for resuming training.
For changing voice
$0 [-v] [-c config] [-m model]
-v: flag for voice change mode
-c: config
-m: model name
For help
$0 [-h]
-h: show this help
" >&2
}
warn () {
echo "! ! ! $1 ! ! !"
exit 1
}
training_flag=false
batch_size=10
resume_flag=false
voice_change_flag=false
config=
model=
escape_flag=false
# オプション解析
while getopts tb:rvc:m:hx OPT; do
case $OPT in
t)
training_flag=true
;;
b)
batch_size="$OPTARG"
;;
r)
resume_flag=true
;;
v)
voice_change_flag=true
;;
c)
config="$OPTARG"
;;
m)
model="$OPTARG"
;;
h | \?)
usage && exit 1
;;
x)
escape_flag=true
esac
done
# ## コマンドライン引数から、オプション引数分を削除
# # shift $((OPTIND - 1))
# # モード解析
# if $training_flag && $voice_change_flag; then
# warn "-tトレーニングモード と -vボイチェンモードは同時に指定できません。"
# exit 1
# elif $training_flag; then
# echo "■■■ ト レ ー ニ ン グ モ ー ド ■■■"
# elif $voice_change_flag; then
# echo "■■■ ボ イ チ ェ ン モ ー ド ■■■"
# elif $escape_flag; then
# /bin/bash
# else
# warn "-tトレーニングモード と -vボイチェンモードのいずれかを指定してください。"
# exit 1
# fi
if $training_flag; then
python3 create_dataset_jtalk.py -f train_config -s 24000 -m dataset/multi_speaker_correspondence.txt
# date_tag=`date +%Y%m%d%H%M%S`
sed -ie 's/80000/8000/' train_ms.py
sed -ie "s/\"batch_size\": 10/\"batch_size\": $batch_size/" configs/train_config.json
sed -ie "s/torch.cuda.device_count()/1/" train_ms.py
python3 -m tensorboard.main --logdir logs --port 6006 --host 0.0.0.0 &
if ${resume_flag}; then
echo "トレーニング再開。バッチサイズ: ${batch_size}"
python3 train_ms.py -c configs/train_config.json -m vc
else
echo "トレーニング開始。バッチサイズ: ${batch_size}"
python3 train_ms.py -c configs/train_config.json -m vc -fg fine_model/G_180000.pth -fd fine_model/D_180000.pth
fi
fi
if $voice_change_flag; then
if [[ -z "$config" ]]; then
warn "コンフィグファイル(-c)を指定してください"
fi
if [[ -z "$model" ]]; then
warn "モデルファイル(-m)を指定してください"
fi
cd /voice-changer-internal/voice-change-service
cp -r /resources/* .
if [[ -e ./setting.json ]]; then
cp ./setting.json ../frontend/dist/assets/setting.json
fi
echo "-----------!!"
echo $config $model
echo $model
python3 serverSIO.py -p 8080 -c $config -m $model --https True --httpsSelfSigned True
fi

5
work_dir/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*
!.gitignore
!logs
!info
!dataset

3
work_dir/dataset/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*
!.gitignore
!textful