From 889874ecafc45704d0f0db17584dc2ce2e49f0f4 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Thu, 28 Sep 2023 19:18:21 +0800 Subject: [PATCH 01/28] Added Auto Sampling Rate The Model Uploader Colab Cell is probably more buggy now but it works.... --- ...fied_Realtime_Voice_Changer_on_Colab.ipynb | 119 ++++++++++++------ 1 file changed, 83 insertions(+), 36 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index ebbab41f..dbcc76ff 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -1,15 +1,5 @@ { "cells": [ -{ - "cell_type": "markdown", - "metadata": { - "id": "view-in-github", - "colab_type": "text" - }, - "source": [ - "\"Open" - ] - }, { "cell_type": "markdown", "metadata": { @@ -147,21 +137,22 @@ "#@markdown ---\n", "import os\n", "import json\n", + "from IPython.display import Image\n", "\n", "\n", "#@markdown #Model Number `(Default is 0)` you can add multiple models as long as you change the number!\n", - "model_number = \"0\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", + "model_number = \"6\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", "\n", "!rm -rf model_dir/$model_number\n", "#@markdown ---\n", "#@markdown #**[Optional]** Add an icon to the model `(can be any image/leave empty for no image)`\n", - "icon_link = \"https://cdn.donmai.us/original/8a/92/8a924397e9aac922e94bdc1f28ff978a.jpg\" #@param {type:\"string\"}\n", + "icon_link = \"https://cdn.discordapp.com/attachments/1144453160912572506/1144453161210351697/mika.png?ex=65163190&is=6514e010&hm=6cfc987d42e448b2912f5225e2c865df92d688c8dc46a135c2cca32682a3f3ea&\" #@param {type:\"string\"}\n", "#@markdown ---\n", "icon_link = '\"'+icon_link+'\"'\n", "!mkdir model_dir\n", "!mkdir model_dir/$model_number\n", "#@markdown #Put your model's download link here `(must be a zip file)`\n", - "model_link = \"https://huggingface.co/HinaBl/Akatsuki/resolve/main/akatsuki_200epoch.zip\" #@param {type:\"string\"}\n", + "model_link = \"https://huggingface.co/Kit-Lemonfoot/kitlemonfoot_rvc_models/resolve/main/Mika%20Melatika%20(Speaking)(KitLemonfoot).zip\" #@param {type:\"string\"}\n", "model_link = '\"'+model_link+'\"'\n", "!curl -L $model_link > model.zip\n", "\n", @@ -171,6 +162,7 @@ " iconFile = \"icon.png\"\n", " !curl -L $icon_link > model_dir/$model_number/icon.png\n", "else:\n", + " iconFile = \"\"\n", " print(\"icon_link is empty, so no icon file will be downloaded.\")\n", "#@markdown ---\n", "\n", @@ -190,32 +182,83 @@ "Tune = 12 #@param {type:\"slider\",min:-50,max:50,step:1}\n", "Index = 0 #@param {type:\"slider\",min:0,max:1,step:0.1}\n", "#@markdown ---\n", - "#@markdown #Parameter Option `(Ignore if theres a Parameter File)`\n", - "Slot_Index = -1 #@param [-1,0,1] {type:\"raw\"}\n", - "Sampling_Rate = 48000 #@param [32000,40000,48000] {type:\"raw\"}\n", "\n", "# @markdown #**[Optional]** Parameter file for your voice model\n", "#@markdown _(must be named params.json)_ (Leave Empty for Default)\n", "param_link = \"\" #@param {type:\"string\"}\n", "if param_link == \"\":\n", - " model_dir = \"model_dir/\"+model_number+\"/\"\n", + " from voice_changer.RVC.RVCModelSlotGenerator import RVCModelSlotGenerator\n", + " from voice_changer.VoiceChangerParamsManager import VoiceChangerParamsManager\n", + " from voice_changer.utils.LoadModelParams import LoadModelParamFile, LoadModelParams\n", + " from voice_changer.utils.VoiceChangerParams import VoiceChangerParams\n", "\n", - " # Find the .pth and .index files in the model_dir/0 directory\n", - " pth_files = [f for f in os.listdir(model_dir) if f.endswith(\".pth\")]\n", - " index_files = [f for f in os.listdir(model_dir) if f.endswith(\".index\")]\n", + " model_dir1 = \"model_dir/\"+model_number+\"/\"\n", "\n", - " if pth_files and index_files:\n", - " # Take the first .pth and .index file as model and index names\n", + " is_pth = True # Set this to True if you want to search for .pth files, or False for .onnx files\n", + " file_extension = \".pth\" if is_pth else \".onnx\"\n", + "\n", + " # pth_files = [f for f in os.listdir(model_dir1) if f.endswith(file_extension)]\n", + "\n", + " pth_files = [f for f in os.listdir(model_dir1) if f.endswith(\".pth\") or f.endswith(\".onnx\")]\n", + " print(pth_files)\n", + " index_files = [f for f in os.listdir(model_dir1) if f.endswith(\".index\")]\n", + "\n", + "\n", + "\n", + "\n", + " if pth_files:\n", " model_name = pth_files[0].replace(\".pth\", \"\")\n", + "\n", + " else:\n", + " model_name = \"Null\"\n", + " if index_files:\n", " index_name = index_files[0].replace(\".index\", \"\")\n", " else:\n", - " # Set default values if no .pth and .index files are found\n", - " model_name = \"Null\"\n", - " index_name = \"Null\"\n", + " index_name = \"\"\n", "\n", - " # Define the content for params.json\n", + " original_string = str(pth_files)\n", + " string_pth_files = original_string[2:-2]\n", + " print(\"IM A STRING\"+original_string)\n", + "\n", + " print(model_name)\n", + " voiceChangerParams = VoiceChangerParams(\n", + " model_dir=\"./model_dir/\"+model_number,\n", + " content_vec_500=\"\",\n", + " content_vec_500_onnx=\"\",\n", + " content_vec_500_onnx_on=\"\",\n", + " hubert_base=\"\",\n", + " hubert_base_jp=\"\",\n", + " hubert_soft=\"\",\n", + " nsf_hifigan=\"\",\n", + " crepe_onnx_full=\"\",\n", + " crepe_onnx_tiny=\"\",\n", + " rmvpe=\"\",\n", + " rmvpe_onnx=\"\",\n", + " sample_mode=\"\"\n", + " )\n", + " vcparams = VoiceChangerParamsManager.get_instance()\n", + " vcparams.setParams(voiceChangerParams)\n", + "\n", + " file = LoadModelParamFile(\n", + " name=string_pth_files,\n", + " kind=\"rvcModel\",\n", + " dir=\"\",\n", + " )\n", + "\n", + " loadParam = LoadModelParams(\n", + " voiceChangerType=\"RVC\",\n", + " files=[file],\n", + " slot=\"\",\n", + " isSampleMode=False,\n", + " sampleId=\"\",\n", + " params={},\n", + " )\n", + " slotInfo = RVCModelSlotGenerator.loadModel(loadParam)\n", + " print(slotInfo.samplingRate)\n", + "\n", + "#----------------Make the Json File-----------\n", " params_content = {\n", - " \"slotIndex\": Slot_Index,\n", + " \"slotIndex\": -1,\n", " \"voiceChangerType\": \"RVC\",\n", " \"name\": model_name,\n", " \"description\": \"\",\n", @@ -225,14 +268,14 @@ " \"speakers\": {\n", " \"0\": \"target\"\n", " },\n", - " \"modelFile\": f\"{model_name}.pth\",\n", + " \"modelFile\": string_pth_files,\n", " \"indexFile\": f\"{index_name}.index\",\n", " \"defaultTune\": Tune,\n", " \"defaultIndexRatio\": Index,\n", " \"defaultProtect\": 0.5,\n", " \"isONNX\": False,\n", " \"modelType\": \"pyTorchRVCv2\",\n", - " \"samplingRate\": Sampling_Rate,\n", + " \"samplingRate\": slotInfo.samplingRate,\n", " \"f0\": True,\n", " \"embChannels\": 768,\n", " \"embOutputLayer\": 12,\n", @@ -243,16 +286,18 @@ " }\n", "\n", " # Write the content to params.json\n", - " with open(f\"{model_dir}/params.json\", \"w\") as param_file:\n", + " with open(f\"{model_dir1}/params.json\", \"w\") as param_file:\n", " json.dump(params_content, param_file)\n", "\n", + "\n", "# !unzip model.zip -d model_dir/0/\n", "clear_output()\n", - "print(\"\\033[92mModel with the name of \"+model_name+\" has been Imported!\")\n" + "print(\"\\033[92mModel with the name of \"+model_name+\" has been Imported to slot \"+model_number)\n", + "Image(url=icon_link)" ], "metadata": { - "cellView": "form", - "id": "_ZtbKUVUgN3G" + "id": "_ZtbKUVUgN3G", + "cellView": "form" }, "execution_count": null, "outputs": [] @@ -270,7 +315,8 @@ "print(\"\\033[92mSuccessfully removed Model is slot \"+Delete_Slot)\n" ], "metadata": { - "id": "P9g6rG1-KUwt" + "id": "P9g6rG1-KUwt", + "cellView": "form" }, "execution_count": null, "outputs": [] @@ -279,7 +325,8 @@ "cell_type": "code", "execution_count": null, "metadata": { - "id": "lLWQuUd7WW9U" + "id": "lLWQuUd7WW9U", + "cellView": "form" }, "outputs": [], "source": [ @@ -440,4 +487,4 @@ }, "nbformat": 4, "nbformat_minor": 0 -} +} \ No newline at end of file From 8d3a0f8c7313917438f24bac03f3f198f3a61219 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Fri, 29 Sep 2023 00:44:13 +0800 Subject: [PATCH 02/28] Created using Colaboratory --- ...ified_Realtime_Voice_Changer_on_Colab.ipynb | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index dbcc76ff..8035d256 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -1,5 +1,15 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "view-in-github", + "colab_type": "text" + }, + "source": [ + "\"Open" + ] + }, { "cell_type": "markdown", "metadata": { @@ -141,7 +151,7 @@ "\n", "\n", "#@markdown #Model Number `(Default is 0)` you can add multiple models as long as you change the number!\n", - "model_number = \"6\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", + "model_number = \"0\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", "\n", "!rm -rf model_dir/$model_number\n", "#@markdown ---\n", @@ -315,8 +325,7 @@ "print(\"\\033[92mSuccessfully removed Model is slot \"+Delete_Slot)\n" ], "metadata": { - "id": "P9g6rG1-KUwt", - "cellView": "form" + "id": "P9g6rG1-KUwt" }, "execution_count": null, "outputs": [] @@ -474,7 +483,8 @@ "colab": { "provenance": [], "private_outputs": true, - "gpuType": "T4" + "gpuType": "T4", + "include_colab_link": true }, "kernelspec": { "display_name": "Python 3", From bfd7f5cef7fe8e7f8216b238a3ffcbc9e6912c6c Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Fri, 29 Sep 2023 00:55:14 +0800 Subject: [PATCH 03/28] Created using Colaboratory --- Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index 8035d256..63aa882d 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -189,7 +189,9 @@ "\n", "\n", "#@markdown #**Model Voice Convertion Setting**\n", + "#@markdown Tune `-12=F-M`**||**`0=M-M/F-F`**||**`12=M-F`\n", "Tune = 12 #@param {type:\"slider\",min:-50,max:50,step:1}\n", + "#@markdown Index `0=Default`**||**`1=Replicate Accent`\n", "Index = 0 #@param {type:\"slider\",min:0,max:1,step:0.1}\n", "#@markdown ---\n", "\n", @@ -306,8 +308,7 @@ "Image(url=icon_link)" ], "metadata": { - "id": "_ZtbKUVUgN3G", - "cellView": "form" + "id": "_ZtbKUVUgN3G" }, "execution_count": null, "outputs": [] @@ -315,17 +316,18 @@ { "cell_type": "code", "source": [ - "#@title Delete a model\n", + "#@title Delete a model `[Only Use When Needed]`\n", "#@markdown ---\n", "#@markdown Select which slot you want to delete\n", "Delete_Slot = \"0\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", - "{type:\"slider\",min:0,max:1,step:0.1}\n", + "# {type:\"slider\",min:0,max:1,step:0.1}\n", "\n", "!rm -rf model_dir/$Model_Number\n", "print(\"\\033[92mSuccessfully removed Model is slot \"+Delete_Slot)\n" ], "metadata": { - "id": "P9g6rG1-KUwt" + "id": "P9g6rG1-KUwt", + "cellView": "form" }, "execution_count": null, "outputs": [] From ae52548113e3eecf0919a49feb27043dfbd92845 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Tue, 3 Oct 2023 16:48:48 +0800 Subject: [PATCH 04/28] Removed localtunnel --- ...fied_Realtime_Voice_Changer_on_Colab.ipynb | 62 +------------------ 1 file changed, 2 insertions(+), 60 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index 63aa882d..8b068ed6 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -308,7 +308,8 @@ "Image(url=icon_link)" ], "metadata": { - "id": "_ZtbKUVUgN3G" + "id": "_ZtbKUVUgN3G", + "cellView": "form" }, "execution_count": null, "outputs": [] @@ -420,65 +421,6 @@ " --samples samples.json\n", "\n" ] - }, - { - "cell_type": "code", - "source": [ - "# @title **[Optional]** Start Server **using localtunnel** (ngrok alternative | no account needed)\n", - "# @markdown This cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n", - "\n", - "# @markdown ---\n", - "!npm config set update-notifier false\n", - "!npm install -g localtunnel\n", - "print(\"\\033[92mLocalTunnel installed!\")\n", - "# @markdown If you want to automatically clear the output when the server loads, check this option.\n", - "Clear_Output = True # @param {type:\"boolean\"}\n", - "\n", - "import portpicker, subprocess, threading, time, socket, urllib.request\n", - "PORT = portpicker.pick_unused_port()\n", - "\n", - "from IPython.display import clear_output, Javascript\n", - "\n", - "def iframe_thread(port):\n", - " while True:\n", - " time.sleep(0.5)\n", - " sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", - " result = sock.connect_ex(('127.0.0.1', port))\n", - " if result == 0:\n", - " break\n", - " sock.close()\n", - " clear_output()\n", - " print(\"Use the following endpoint to connect to localtunnel:\", urllib.request.urlopen('https://ipv4.icanhazip.com').read().decode('utf8').strip(\"\\n\"))\n", - " p = subprocess.Popen([\"lt\", \"--port\", \"{}\".format(port)], stdout=subprocess.PIPE)\n", - " for line in p.stdout:\n", - " print(line.decode(), end='')\n", - "\n", - "threading.Thread(target=iframe_thread, daemon=True, args=(PORT,)).start()\n", - "\n", - "\n", - "!python3 MMVCServerSIO.py \\\n", - " -p {PORT} \\\n", - " --https False \\\n", - " --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n", - " --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n", - " --content_vec_500_onnx_on true \\\n", - " --hubert_base pretrain/hubert_base.pt \\\n", - " --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n", - " --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n", - " --nsf_hifigan pretrain/nsf_hifigan/model \\\n", - " --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n", - " --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n", - " --rmvpe pretrain/rmvpe.pt \\\n", - " --model_dir model_dir \\\n", - " --samples samples.json \\\n", - " --colab True" - ], - "metadata": { - "cellView": "form", - "id": "ZwZaCf4BeZi2" - }, - "execution_count": null, - "outputs": [] } ], "metadata": { From 22b0f839923b5250069b786e4ff28ef2fc448762 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Wed, 4 Oct 2023 00:12:43 +0800 Subject: [PATCH 05/28] Created using Colaboratory --- ...fied_Realtime_Voice_Changer_on_Colab.ipynb | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index 8b068ed6..8cc67ed8 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -421,6 +421,74 @@ " --samples samples.json\n", "\n" ] + }, + { + "cell_type": "markdown", + "source": [ + "![](https://i.pinimg.com/474x/de/72/9e/de729ecfa41b69901c42c82fff752414.jpg)\n", + "![](https://i.pinimg.com/474x/de/72/9e/de729ecfa41b69901c42c82fff752414.jpg)" + ], + "metadata": { + "id": "2Uu1sTSwTc7q" + } + }, + { + "cell_type": "code", + "source": [ + "# @title **[Optional]** Start Server **using localtunnel** (ngrok alternative | no account needed)\n", + "# @markdown This cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n", + "\n", + "# @markdown ---\n", + "!npm config set update-notifier false\n", + "!npm install -g localtunnel\n", + "print(\"\\033[92mLocalTunnel installed!\")\n", + "# @markdown If you want to automatically clear the output when the server loads, check this option.\n", + "Clear_Output = True # @param {type:\"boolean\"}\n", + "\n", + "import portpicker, subprocess, threading, time, socket, urllib.request\n", + "PORT = portpicker.pick_unused_port()\n", + "\n", + "from IPython.display import clear_output, Javascript\n", + "\n", + "def iframe_thread(port):\n", + " while True:\n", + " time.sleep(0.5)\n", + " sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", + " result = sock.connect_ex(('127.0.0.1', port))\n", + " if result == 0:\n", + " break\n", + " sock.close()\n", + " clear_output()\n", + " print(\"Use the following endpoint to connect to localtunnel:\", urllib.request.urlopen('https://ipv4.icanhazip.com').read().decode('utf8').strip(\"\\n\"))\n", + " p = subprocess.Popen([\"lt\", \"--port\", \"{}\".format(port)], stdout=subprocess.PIPE)\n", + " for line in p.stdout:\n", + " print(line.decode(), end='')\n", + "\n", + "threading.Thread(target=iframe_thread, daemon=True, args=(PORT,)).start()\n", + "\n", + "\n", + "!python3 MMVCServerSIO.py \\\n", + " -p {PORT} \\\n", + " --https False \\\n", + " --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n", + " --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n", + " --content_vec_500_onnx_on true \\\n", + " --hubert_base pretrain/hubert_base.pt \\\n", + " --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n", + " --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n", + " --nsf_hifigan pretrain/nsf_hifigan/model \\\n", + " --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n", + " --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n", + " --rmvpe pretrain/rmvpe.pt \\\n", + " --model_dir model_dir \\\n", + " --samples samples.json \\\n", + " --colab True" + ], + "metadata": { + "id": "Mr7325z-TTX5" + }, + "execution_count": null, + "outputs": [] } ], "metadata": { From c0db39990de3bc432d31512add06d706e478248d Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Fri, 13 Oct 2023 19:18:07 +0800 Subject: [PATCH 06/28] Background WEEEE --- ...fied_Realtime_Voice_Changer_on_Colab.ipynb | 102 ++++++++---------- 1 file changed, 42 insertions(+), 60 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index 8cc67ed8..a3b17bda 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -116,7 +116,6 @@ "clear_output()\n", "!rm -rf rvctimer\n", "!git clone --depth 1 $rvctimer\n", - "!cp -f rvctimer/index.html $pathloc/client/demo/dist/\n", "\n", "\n", "%cd $pathloc/server/\n", @@ -357,7 +356,7 @@ "Token = 'YOUR_TOKEN_HERE' # @param {type:\"string\"}\n", "# @markdown **4** - Still need further tests, but maybe region can help a bit on latency?\\\n", "# @markdown `Default Region: us - United States (Ohio)`\n", - "Region = \"ap - Asia/Pacific (Singapore)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n", + "Region = \"us - United States (Ohio)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n", "MyConfig = conf.PyngrokConfig()\n", "\n", "MyConfig.auth_token = Token\n", @@ -372,6 +371,47 @@ "# @markdown If you want to automatically clear the output when the server loads, check this option.\n", "Clear_Output = True # @param {type:\"boolean\"}\n", "\n", + "#@markdown ---\n", + "#@markdown If you want to use a custom background for the voice changer\n", + "Use_Custom_BG=False #@param{type:\"boolean\"}\n", + "BG_URL=\"https://w.wallha.com/ws/14/cMmpo5vn.jpg\" #@param{type:\"string\"}\n", + "#@markdown Text colors can be hex ``#101010`` or name of color ``black`` (css)\n", + "Text_Color=\"green\" #@param{type:\"string\"}\n", + "if Use_Custom_BG==True:\n", + " if BG_URL==\"\":\n", + " !cp -f rvctimer/index.html $pathloc/client/demo/dist/\n", + " else:\n", + " html_template = f'''\n", + " \n", + " \n", + " \n", + " \n", + " Voice Changer Client Demo\n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " \n", + " \n", + " '''\n", + " with open('index.html', 'w') as file:\n", + " file.write(html_template)\n", + " !mkdir ../client/demo/dist/temp/\n", + " !mv ../client/demo/dist/index.html ../client/demo/dist/temp/index.html\n", + " !mv index.html ../client/demo/dist/\n", + "else:\n", + " !cp -f ../client/demo/dist/temp/index.html ../client/demo/dist/index.html\n", + "\n", "mainpy=codecs.decode('ZZIPFreireFVB.cl','rot_13')\n", "\n", "import portpicker, socket, urllib.request\n", @@ -431,64 +471,6 @@ "metadata": { "id": "2Uu1sTSwTc7q" } - }, - { - "cell_type": "code", - "source": [ - "# @title **[Optional]** Start Server **using localtunnel** (ngrok alternative | no account needed)\n", - "# @markdown This cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n", - "\n", - "# @markdown ---\n", - "!npm config set update-notifier false\n", - "!npm install -g localtunnel\n", - "print(\"\\033[92mLocalTunnel installed!\")\n", - "# @markdown If you want to automatically clear the output when the server loads, check this option.\n", - "Clear_Output = True # @param {type:\"boolean\"}\n", - "\n", - "import portpicker, subprocess, threading, time, socket, urllib.request\n", - "PORT = portpicker.pick_unused_port()\n", - "\n", - "from IPython.display import clear_output, Javascript\n", - "\n", - "def iframe_thread(port):\n", - " while True:\n", - " time.sleep(0.5)\n", - " sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", - " result = sock.connect_ex(('127.0.0.1', port))\n", - " if result == 0:\n", - " break\n", - " sock.close()\n", - " clear_output()\n", - " print(\"Use the following endpoint to connect to localtunnel:\", urllib.request.urlopen('https://ipv4.icanhazip.com').read().decode('utf8').strip(\"\\n\"))\n", - " p = subprocess.Popen([\"lt\", \"--port\", \"{}\".format(port)], stdout=subprocess.PIPE)\n", - " for line in p.stdout:\n", - " print(line.decode(), end='')\n", - "\n", - "threading.Thread(target=iframe_thread, daemon=True, args=(PORT,)).start()\n", - "\n", - "\n", - "!python3 MMVCServerSIO.py \\\n", - " -p {PORT} \\\n", - " --https False \\\n", - " --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n", - " --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n", - " --content_vec_500_onnx_on true \\\n", - " --hubert_base pretrain/hubert_base.pt \\\n", - " --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n", - " --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n", - " --nsf_hifigan pretrain/nsf_hifigan/model \\\n", - " --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n", - " --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n", - " --rmvpe pretrain/rmvpe.pt \\\n", - " --model_dir model_dir \\\n", - " --samples samples.json \\\n", - " --colab True" - ], - "metadata": { - "id": "Mr7325z-TTX5" - }, - "execution_count": null, - "outputs": [] } ], "metadata": { From 6094be47f2042faaf51c24f7afc4a1127aeeb2dc Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Wed, 25 Oct 2023 10:31:14 +0800 Subject: [PATCH 07/28] Updated Credits and Info --- Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index a3b17bda..75310ad3 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -30,7 +30,8 @@ "> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n", "\n", "\n", - "*You can always [click here](https://github.com/YunaOneeChan/Voice-Changer-Settings) to check if these settings are up-to-date*\n", + "*You can always [click here](https://rentry.co/VoiceChangerGuide#gpu-chart-for-known-working-chunkextra\n", + ") to check if these settings are up-to-date*\n", "

\n", "\n", "---\n", @@ -46,7 +47,7 @@ "# **Credits and Support**\n", "Realtime Voice Changer by [w-okada](https://github.com/w-okada)\\\n", "Colab files updated by [rafacasari](https://github.com/Rafacasari)\\\n", - "Recommended settings by [YunaOneeChan](https://github.com/YunaOneeChan)\\\n", + "Recommended settings by [Raven](https://github.com/ravencutie21)\\\n", "Modified again by [Hina](https://huggingface.co/HinaBl)\n", "\n", "Need help? [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n", From 5c84c4cb91d6d7a8cf3b8aec1bf71a5273b76ba4 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Mon, 30 Oct 2023 19:49:54 +0800 Subject: [PATCH 08/28] Removed packages from requirements that are not needed or already installed (first batch) --- Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index 75310ad3..d581e3fa 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -126,9 +126,15 @@ "\n", "\n", "!apt-get install libportaudio2 &> /dev/null --quiet\n", - "!pip install pyworld onnxruntime-gpu uvicorn faiss-gpu fairseq jedi google-colab moviepy decorator==4.4.2 sounddevice numpy==1.23.5 pyngrok --quiet\n", + "!pip install pyworld onnxruntime-gpu uvicorn faiss-gpu fairseq jedi google-colab moviepy decorator==4.4.2 sounddevice pyngrok --quiet\n", "print(\"\\033[92mInstalling Requirements!\")\n", "clear_output()\n", + "\n", + "!sed -i '/torch==/d' requirements.txt\n", + "!sed -i '/torchaudio==/d' requirements.txt\n", + "!sed -i '/numpy==/d' requirements.txt\n", + "\n", + "\n", "!pip install -r requirements.txt --no-build-isolation --quiet\n", "# Maybe install Tensor packages?\n", "#!pip install torch-tensorrt\n", @@ -320,7 +326,7 @@ "#@title Delete a model `[Only Use When Needed]`\n", "#@markdown ---\n", "#@markdown Select which slot you want to delete\n", - "Delete_Slot = \"0\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", + "Delete_Slot = \"198\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", "# {type:\"slider\",min:0,max:1,step:0.1}\n", "\n", "!rm -rf model_dir/$Model_Number\n", From 65cde67b492c815466a52c71f8c1095235365838 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Wed, 1 Nov 2023 13:00:22 +0800 Subject: [PATCH 09/28] Using Rafa's Install --- Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index d581e3fa..6a71a6f1 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -125,8 +125,14 @@ "\n", "\n", "\n", - "!apt-get install libportaudio2 &> /dev/null --quiet\n", - "!pip install pyworld onnxruntime-gpu uvicorn faiss-gpu fairseq jedi google-colab moviepy decorator==4.4.2 sounddevice pyngrok --quiet\n", + "# !apt-get install libportaudio2 &> /dev/null --quiet\n", + "# !pip install pyworld onnxruntime-gpu uvicorn faiss-gpu fairseq jedi google-colab moviepy decorator==4.4.2 sounddevice pyngrok --quiet\n", + "\n", + "# Install dependencies that are missing from requirements.txt and pyngrok\n", + "!pip install faiss-gpu fairseq pyngrok --quiet\n", + "!pip install pyworld --no-build-isolation --quiet\n", + "\n", + "\n", "print(\"\\033[92mInstalling Requirements!\")\n", "clear_output()\n", "\n", From f86bee676879ad0131dd7711d2fca816485f7d49 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Wed, 1 Nov 2023 22:18:42 +0800 Subject: [PATCH 10/28] Fixed libportaudio missing --- Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index 6a71a6f1..fb6ed2f8 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -125,7 +125,7 @@ "\n", "\n", "\n", - "# !apt-get install libportaudio2 &> /dev/null --quiet\n", + "!apt-get install libportaudio2 &> /dev/null --quiet\n", "# !pip install pyworld onnxruntime-gpu uvicorn faiss-gpu fairseq jedi google-colab moviepy decorator==4.4.2 sounddevice pyngrok --quiet\n", "\n", "# Install dependencies that are missing from requirements.txt and pyngrok\n", @@ -366,7 +366,7 @@ "from pyngrok import conf, ngrok\n", "\n", "f0_det= \"rmvpe_onnx\" #@param [\"rmvpe_onnx\",\"rvc\"]\n", - "Token = 'YOUR_TOKEN_HERE' # @param {type:\"string\"}\n", + "Token = '24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG' # @param {type:\"string\"}\n", "# @markdown **4** - Still need further tests, but maybe region can help a bit on latency?\\\n", "# @markdown `Default Region: us - United States (Ohio)`\n", "Region = \"us - United States (Ohio)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n", From 497c7c067854f6a0689073e6b629ee500bd84fb9 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Thu, 2 Nov 2023 21:54:22 +0800 Subject: [PATCH 11/28] Created using Colaboratory --- Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index fb6ed2f8..b2660d8f 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -366,7 +366,7 @@ "from pyngrok import conf, ngrok\n", "\n", "f0_det= \"rmvpe_onnx\" #@param [\"rmvpe_onnx\",\"rvc\"]\n", - "Token = '24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG' # @param {type:\"string\"}\n", + "Token = 'Token_Here' # @param {type:\"string\"}\n", "# @markdown **4** - Still need further tests, but maybe region can help a bit on latency?\\\n", "# @markdown `Default Region: us - United States (Ohio)`\n", "Region = \"us - United States (Ohio)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n", From 6d20b3dad2525857df4a585cd2e420a2fe223042 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Fri, 3 Nov 2023 10:17:57 +0800 Subject: [PATCH 12/28] Updated to Rafa's latest Voice Changer Colab --- ...fied_Realtime_Voice_Changer_on_Colab.ipynb | 181 +++++++----------- 1 file changed, 65 insertions(+), 116 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index b2660d8f..61a27ce0 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -84,8 +84,9 @@ }, "outputs": [], "source": [ + "#=================Updated=================\n", "# @title **[1]** Clone repository and install dependencies\n", - "# @markdown This first step will download the latest version of Voice Changer and install the dependencies. **It will take around 2 minutes to complete.**\n", + "# @markdown This first step will download the latest version of Voice Changer and install the dependencies. **It can take some time to complete.**\n", "import os\n", "import time\n", "import subprocess\n", @@ -94,12 +95,12 @@ "import base64\n", "import codecs\n", "\n", - "from IPython.display import clear_output, Javascript\n", "\n", "externalgit=codecs.decode('uggcf://tvguho.pbz/j-bxnqn/ibvpr-punatre.tvg','rot_13')\n", "rvctimer=codecs.decode('uggcf://tvguho.pbz/uvanoy/eipgvzre.tvg','rot_13')\n", - "pathloc=codecs.decode('ibvpr-punatre','rot_13')\n", - "!git clone --depth 1 $externalgit &> /dev/null\n", + "pathloc=codecs.decode('/pbagrag/ibvpr-punatre','rot_13')\n", + "\n", + "from IPython.display import clear_output, Javascript\n", "\n", "def update_timer_and_print():\n", " global timer\n", @@ -113,42 +114,30 @@ "timer = 0\n", "threading.Thread(target=update_timer_and_print, daemon=True).start()\n", "\n", - "# os.system('cls')\n", - "clear_output()\n", - "!rm -rf rvctimer\n", - "!git clone --depth 1 $rvctimer\n", - "\n", + "!pip install colorama --quiet\n", + "from colorama import Fore, Style\n", "\n", + "print(f\"{Fore.CYAN}> Cloning the repository...{Style.RESET_ALL}\")\n", + "!git clone --depth 1 $externalgit &> /dev/null\n", + "print(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n", "%cd $pathloc/server/\n", "\n", - "print(\"\\033[92mSuccessfully cloned the repository\")\n", - "\n", - "\n", - "\n", - "!apt-get install libportaudio2 &> /dev/null --quiet\n", - "# !pip install pyworld onnxruntime-gpu uvicorn faiss-gpu fairseq jedi google-colab moviepy decorator==4.4.2 sounddevice pyngrok --quiet\n", - "\n", - "# Install dependencies that are missing from requirements.txt and pyngrok\n", - "!pip install faiss-gpu fairseq pyngrok --quiet\n", - "!pip install pyworld --no-build-isolation --quiet\n", - "\n", - "\n", - "print(\"\\033[92mInstalling Requirements!\")\n", - "clear_output()\n", + "print(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n", + "!apt-get -y install libportaudio2 -qq\n", "\n", "!sed -i '/torch==/d' requirements.txt\n", "!sed -i '/torchaudio==/d' requirements.txt\n", "!sed -i '/numpy==/d' requirements.txt\n", "\n", "\n", - "!pip install -r requirements.txt --no-build-isolation --quiet\n", - "# Maybe install Tensor packages?\n", - "#!pip install torch-tensorrt\n", - "#!pip install TensorRT\n", - "print(\"\\033[92mSuccessfully installed all packages!\")\n", - "# os.system('cls')\n", - "clear_output()\n", - "print(\"\\033[92mFinished, please continue to the next cell\")" + "print(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n", + "# Install dependencies that are missing from requirements.txt and pyngrok\n", + "!pip install faiss-gpu fairseq pyngrok --quiet\n", + "!pip install pyworld --no-build-isolation --quiet\n", + "print(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n", + "!pip install -r requirements.txt --quiet\n", + "\n", + "print(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")" ] }, { @@ -354,108 +343,67 @@ }, "outputs": [], "source": [ - "# @title **[2]** Start Server **using ngrok** (Recommended | **need a ngrok account**)\n", + "\n", + "#=======================Updated=========================\n", + "\n", + "# @title Start Server **using ngrok**\n", "# @markdown This cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n", "\n", "# @markdown ---\n", - "# @markdown You'll need a ngrok account, but **it's free**!\n", + "# @markdown You'll need a ngrok account, but **it's free** and easy to create!\n", "# @markdown ---\n", - "# @markdown **1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup)\\\n", - "# @markdown **2** - If you didn't logged in with Google or Github, you will need to **verify your e-mail**!\\\n", - "# @markdown **3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, copy it and place it here:\n", - "from pyngrok import conf, ngrok\n", - "\n", - "f0_det= \"rmvpe_onnx\" #@param [\"rmvpe_onnx\",\"rvc\"]\n", - "Token = 'Token_Here' # @param {type:\"string\"}\n", - "# @markdown **4** - Still need further tests, but maybe region can help a bit on latency?\\\n", + "# @markdown **1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup) or **login with Google/Github account**\\\n", + "# @markdown **2** - If you didn't logged in with Google/Github, you will need to **verify your e-mail**!\\\n", + "# @markdown **3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and place it here:\n", + "Token = '' # @param {type:\"string\"}\n", + "# @markdown **4** - *(optional)* Change to a region near to you or keep at United States if increase latency\\\n", "# @markdown `Default Region: us - United States (Ohio)`\n", - "Region = \"us - United States (Ohio)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n", - "MyConfig = conf.PyngrokConfig()\n", + "Region = \"jp - Japan (Tokyo)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n", "\n", + "#@markdown **5** - *(optional)* Other options:\n", + "ClearConsole = True # @param {type:\"boolean\"}\n", + "\n", + "# ---------------------------------\n", + "# DO NOT TOUCH ANYTHING DOWN BELOW!\n", + "# ---------------------------------\n", + "\n", + "%cd $pathloc/server//server\n", + "\n", + "from pyngrok import conf, ngrok\n", + "MyConfig = conf.PyngrokConfig()\n", "MyConfig.auth_token = Token\n", "MyConfig.region = Region[0:2]\n", - "\n", - "conf.get_default().authtoken = Token\n", - "conf.get_default().region = Region[0:2]\n", - "\n", + "#conf.get_default().authtoken = Token\n", + "#conf.get_default().region = Region\n", "conf.set_default(MyConfig);\n", "\n", - "# @markdown ---\n", - "# @markdown If you want to automatically clear the output when the server loads, check this option.\n", - "Clear_Output = True # @param {type:\"boolean\"}\n", - "\n", - "#@markdown ---\n", - "#@markdown If you want to use a custom background for the voice changer\n", - "Use_Custom_BG=False #@param{type:\"boolean\"}\n", - "BG_URL=\"https://w.wallha.com/ws/14/cMmpo5vn.jpg\" #@param{type:\"string\"}\n", - "#@markdown Text colors can be hex ``#101010`` or name of color ``black`` (css)\n", - "Text_Color=\"green\" #@param{type:\"string\"}\n", - "if Use_Custom_BG==True:\n", - " if BG_URL==\"\":\n", - " !cp -f rvctimer/index.html $pathloc/client/demo/dist/\n", - " else:\n", - " html_template = f'''\n", - " \n", - " \n", - " \n", - " \n", - " Voice Changer Client Demo\n", - " \n", - " \n", - " \n", - " \n", - "
\n", - " \n", - " \n", - " '''\n", - " with open('index.html', 'w') as file:\n", - " file.write(html_template)\n", - " !mkdir ../client/demo/dist/temp/\n", - " !mv ../client/demo/dist/index.html ../client/demo/dist/temp/index.html\n", - " !mv index.html ../client/demo/dist/\n", - "else:\n", - " !cp -f ../client/demo/dist/temp/index.html ../client/demo/dist/index.html\n", - "\n", - "mainpy=codecs.decode('ZZIPFreireFVB.cl','rot_13')\n", - "\n", - "import portpicker, socket, urllib.request\n", - "PORT = portpicker.pick_unused_port()\n", + "import subprocess, threading, time, socket, urllib.request\n", + "PORT = 8000\n", "\n", "from pyngrok import ngrok\n", - "# Edited ⏬⏬\n", "ngrokConnection = ngrok.connect(PORT)\n", "public_url = ngrokConnection.public_url\n", "\n", - "def iframe_thread(port):\n", - " while True:\n", - " time.sleep(0.5)\n", - " sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", - " result = sock.connect_ex(('127.0.0.1', port))\n", - " if result == 0:\n", - " break\n", - " sock.close()\n", - " clear_output()\n", - " print(\"------- SERVER READY! -------\")\n", - " print(\"Your server is available at:\")\n", - " print(public_url)\n", - " print(\"-----------------------------\")\n", - " # display(Javascript('window.open(\"{url}\", \\'_blank\\');'.format(url=public_url)))\n", + "from IPython.display import clear_output\n", "\n", - "print(PORT)\n", + "def wait_for_server():\n", + " while True:\n", + " time.sleep(0.5)\n", + " sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", + " result = sock.connect_ex(('127.0.0.1', PORT))\n", + " if result == 0:\n", + " break\n", + " sock.close()\n", + " if ClearConsole:\n", + " clear_output()\n", + " print(\"--------- SERVER READY! ---------\")\n", + " print(\"Your server is available at:\")\n", + " print(public_url)\n", + " print(\"---------------------------------\")\n", "\n", + "threading.Thread(target=wait_for_server, daemon=True).start()\n", "\n", - "\n", - "threading.Thread(target=iframe_thread, daemon=True, args=(PORT,)).start()\n", - "\n", + "mainpy=codecs.decode('ZZIPFreireFVB.cl','rot_13')\n", "\n", "!python3 $mainpy \\\n", " -p {PORT} \\\n", @@ -472,7 +420,8 @@ " --rmvpe pretrain/rmvpe.pt \\\n", " --model_dir model_dir \\\n", " --samples samples.json\n", - "\n" + "\n", + "ngrok.disconnect(ngrokConnection.public_url)\n" ] }, { From 5de0630bb42296307dc05cff73ddafeaf76982a1 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Fri, 3 Nov 2023 11:01:48 +0800 Subject: [PATCH 13/28] Added Google Colab on version text --- ...dified_Realtime_Voice_Changer_on_Colab.ipynb | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index 61a27ce0..dd587f33 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -122,6 +122,21 @@ "print(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n", "%cd $pathloc/server/\n", "\n", + "file_path = '/content/voice-changer/client/demo/dist/assets/gui_settings/version.txt'\n", + "\n", + "with open(file_path, 'r') as file:\n", + " file_content = file.read()\n", + "\n", + "text_to_replace = \"-.-.-.-\"\n", + "new_text = \"Google.Colab\" # New text to replace the specific text\n", + "\n", + "modified_content = file_content.replace(text_to_replace, new_text)\n", + "\n", + "with open(file_path, 'w') as file:\n", + " file.write(modified_content)\n", + "\n", + "print(f\"Text '{text_to_replace}' has been replaced with '{new_text}' in the file.\")\n", + "\n", "print(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n", "!apt-get -y install libportaudio2 -qq\n", "\n", @@ -355,7 +370,7 @@ "# @markdown **1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup) or **login with Google/Github account**\\\n", "# @markdown **2** - If you didn't logged in with Google/Github, you will need to **verify your e-mail**!\\\n", "# @markdown **3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and place it here:\n", - "Token = '' # @param {type:\"string\"}\n", + "Token = '24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG' # @param {type:\"string\"}\n", "# @markdown **4** - *(optional)* Change to a region near to you or keep at United States if increase latency\\\n", "# @markdown `Default Region: us - United States (Ohio)`\n", "Region = \"jp - Japan (Tokyo)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n", From ee827731b6c0e4555e38b5c464a33421a58e6c49 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Fri, 3 Nov 2023 11:31:03 +0800 Subject: [PATCH 14/28] Merged Google Drive with Clone and install --- ...fied_Realtime_Voice_Changer_on_Colab.ipynb | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index dd587f33..5fa0c1cb 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -55,26 +55,6 @@ "---" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "cellView": "form", - "id": "RhdqDSt-LfGr" - }, - "outputs": [], - "source": [ - "# @title **[Optional]** Connect to Google Drive\n", - "# @markdown Using Google Drive can improve load times a bit and your models will be stored, so you don't need to re-upload every time that you use.\n", - "import os\n", - "from google.colab import drive\n", - "\n", - "if not os.path.exists('/content/drive'):\n", - " drive.mount('/content/drive')\n", - "\n", - "%cd /content/drive/MyDrive" - ] - }, { "cell_type": "code", "execution_count": null, @@ -96,9 +76,25 @@ "import codecs\n", "\n", "\n", + "\n", + "#@markdown ---\n", + "# @title **[Optional]** Connect to Google Drive\n", + "# @markdown Using Google Drive can improve load times a bit and your models will be stored, so you don't need to re-upload every time that you use.\n", + "\n", + "Use_Drive=False #@param {type:\"boolean\"}\n", + "\n", + "from google.colab import drive\n", + "\n", + "if Use_Drive==True:\n", + " if not os.path.exists('/content/drive'):\n", + " drive.mount('/content/drive')\n", + "\n", + " %cd /content/drive/MyDrive\n", + "\n", + "\n", "externalgit=codecs.decode('uggcf://tvguho.pbz/j-bxnqn/ibvpr-punatre.tvg','rot_13')\n", "rvctimer=codecs.decode('uggcf://tvguho.pbz/uvanoy/eipgvzre.tvg','rot_13')\n", - "pathloc=codecs.decode('/pbagrag/ibvpr-punatre','rot_13')\n", + "pathloc=codecs.decode('ibvpr-punatre','rot_13')\n", "\n", "from IPython.display import clear_output, Javascript\n", "\n", @@ -122,16 +118,19 @@ "print(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n", "%cd $pathloc/server/\n", "\n", - "file_path = '/content/voice-changer/client/demo/dist/assets/gui_settings/version.txt'\n", + "# Read the content of the file\n", + "file_path = '../client/demo/dist/assets/gui_settings/version.txt'\n", "\n", "with open(file_path, 'r') as file:\n", " file_content = file.read()\n", "\n", + "# Replace the specific text\n", "text_to_replace = \"-.-.-.-\"\n", "new_text = \"Google.Colab\" # New text to replace the specific text\n", "\n", "modified_content = file_content.replace(text_to_replace, new_text)\n", "\n", + "# Write the modified content back to the file\n", "with open(file_path, 'w') as file:\n", " file.write(modified_content)\n", "\n", @@ -370,10 +369,10 @@ "# @markdown **1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup) or **login with Google/Github account**\\\n", "# @markdown **2** - If you didn't logged in with Google/Github, you will need to **verify your e-mail**!\\\n", "# @markdown **3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and place it here:\n", - "Token = '24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG' # @param {type:\"string\"}\n", + "Token = '' # @param {type:\"string\"}\n", "# @markdown **4** - *(optional)* Change to a region near to you or keep at United States if increase latency\\\n", "# @markdown `Default Region: us - United States (Ohio)`\n", - "Region = \"jp - Japan (Tokyo)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n", + "Region = \"us - United States (Ohio)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n", "\n", "#@markdown **5** - *(optional)* Other options:\n", "ClearConsole = True # @param {type:\"boolean\"}\n", @@ -382,7 +381,7 @@ "# DO NOT TOUCH ANYTHING DOWN BELOW!\n", "# ---------------------------------\n", "\n", - "%cd $pathloc/server//server\n", + "%cd $pathloc/server/\n", "\n", "from pyngrok import conf, ngrok\n", "MyConfig = conf.PyngrokConfig()\n", From da9e6aaf6bc056f5c0bc5766f837744c84e3eecd Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Fri, 10 Nov 2023 21:55:42 +0800 Subject: [PATCH 15/28] Removed "Under Construction" --- Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index 5fa0c1cb..f14e946b 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -158,7 +158,7 @@ "cell_type": "code", "source": [ "\n", - "#@title #**[Optional]** Upload a voice model (Run this before running the Voice Changer)**[Currently Under Construction]**\n", + "#@title #**[Optional]** Upload a voice model (Run this before running the Voice Changer)\n", "#@markdown ---\n", "import os\n", "import json\n", From 53ea4cef578215264478e7c3ff4f8e64b7d7e90b Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Mon, 13 Nov 2023 01:25:20 +0800 Subject: [PATCH 16/28] Cleaned Some Cells --- ...fied_Realtime_Voice_Changer_on_Colab.ipynb | 68 ++++++------------- 1 file changed, 19 insertions(+), 49 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index f14e946b..b5135df4 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -158,26 +158,22 @@ "cell_type": "code", "source": [ "\n", - "#@title #**[Optional]** Upload a voice model (Run this before running the Voice Changer)\n", - "#@markdown ---\n", + "#@title **[Optional]** Upload a voice model (Run this before running the Voice Changer)\n", "import os\n", "import json\n", "from IPython.display import Image\n", "\n", "\n", - "#@markdown #Model Number `(Default is 0)` you can add multiple models as long as you change the number!\n", - "model_number = \"0\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", + "model_slot = \"0\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", "\n", - "!rm -rf model_dir/$model_number\n", - "#@markdown ---\n", - "#@markdown #**[Optional]** Add an icon to the model `(can be any image/leave empty for no image)`\n", - "icon_link = \"https://cdn.discordapp.com/attachments/1144453160912572506/1144453161210351697/mika.png?ex=65163190&is=6514e010&hm=6cfc987d42e448b2912f5225e2c865df92d688c8dc46a135c2cca32682a3f3ea&\" #@param {type:\"string\"}\n", - "#@markdown ---\n", + "!rm -rf model_dir/$model_slot\n", + "#@markdown **[Optional]** Add an icon to the model\n", + "icon_link = \"https://static.wikia.nocookie.net/virtualyoutuber/images/8/8b/ShyreiProfile.png\" #@param {type:\"string\"}\n", "icon_link = '\"'+icon_link+'\"'\n", "!mkdir model_dir\n", - "!mkdir model_dir/$model_number\n", - "#@markdown #Put your model's download link here `(must be a zip file)`\n", - "model_link = \"https://huggingface.co/Kit-Lemonfoot/kitlemonfoot_rvc_models/resolve/main/Mika%20Melatika%20(Speaking)(KitLemonfoot).zip\" #@param {type:\"string\"}\n", + "!mkdir model_dir/$model_slot\n", + "#@markdown Put your model's download link here `(must be a zip file)`\n", + "model_link = \"https://huggingface.co/RavenCutie21/Models/resolve/main/SquChan_e800_20800steps.zip?download=true\" #@param {type:\"string\"}\n", "model_link = '\"'+model_link+'\"'\n", "!curl -L $model_link > model.zip\n", "\n", @@ -185,41 +181,35 @@ "# Conditionally set the iconFile based on whether icon_link is empty\n", "if icon_link:\n", " iconFile = \"icon.png\"\n", - " !curl -L $icon_link > model_dir/$model_number/icon.png\n", + " !curl -L $icon_link > model_dir/$model_slot/icon.png\n", "else:\n", " iconFile = \"\"\n", " print(\"icon_link is empty, so no icon file will be downloaded.\")\n", - "#@markdown ---\n", "\n", "\n", - "!unzip model.zip -d model_dir/$model_number\n", + "!unzip model.zip -d model_dir/$model_slot\n", "\n", - "# Checks all the files in model_number and puts it outside of it\n", + "# Checks all the files in model_slot and puts it outside of it\n", "\n", - "!mv model_dir/$model_number/*/* model_dir/$model_number/\n", - "!rm -rf model_dir/$model_number/*/\n", + "!mv model_dir/$model_slot/*/* model_dir/$model_slot/\n", + "!rm -rf model_dir/$model_slot/*/\n", "\n", "# if theres a folder in the number,\n", "# take all the files in the folder and put it outside of that folder\n", "\n", "\n", - "#@markdown #**Model Voice Convertion Setting**\n", - "#@markdown Tune `-12=F-M`**||**`0=M-M/F-F`**||**`12=M-F`\n", + "#@markdown **Model Voice Convertion Setting**\n", "Tune = 12 #@param {type:\"slider\",min:-50,max:50,step:1}\n", - "#@markdown Index `0=Default`**||**`1=Replicate Accent`\n", "Index = 0 #@param {type:\"slider\",min:0,max:1,step:0.1}\n", - "#@markdown ---\n", "\n", - "# @markdown #**[Optional]** Parameter file for your voice model\n", - "#@markdown _(must be named params.json)_ (Leave Empty for Default)\n", - "param_link = \"\" #@param {type:\"string\"}\n", + "param_link = \"\"\n", "if param_link == \"\":\n", " from voice_changer.RVC.RVCModelSlotGenerator import RVCModelSlotGenerator\n", " from voice_changer.VoiceChangerParamsManager import VoiceChangerParamsManager\n", " from voice_changer.utils.LoadModelParams import LoadModelParamFile, LoadModelParams\n", " from voice_changer.utils.VoiceChangerParams import VoiceChangerParams\n", "\n", - " model_dir1 = \"model_dir/\"+model_number+\"/\"\n", + " model_dir1 = \"model_dir/\"+model_slot+\"/\"\n", "\n", " is_pth = True # Set this to True if you want to search for .pth files, or False for .onnx files\n", " file_extension = \".pth\" if is_pth else \".onnx\"\n", @@ -249,7 +239,7 @@ "\n", " print(model_name)\n", " voiceChangerParams = VoiceChangerParams(\n", - " model_dir=\"./model_dir/\"+model_number,\n", + " model_dir=\"./model_dir/\"+model_slot,\n", " content_vec_500=\"\",\n", " content_vec_500_onnx=\"\",\n", " content_vec_500_onnx_on=\"\",\n", @@ -319,8 +309,7 @@ "\n", "# !unzip model.zip -d model_dir/0/\n", "clear_output()\n", - "print(\"\\033[92mModel with the name of \"+model_name+\" has been Imported to slot \"+model_number)\n", - "Image(url=icon_link)" + "print(\"\\033[92mModel with the name of \"+model_name+\" has been Imported to slot \"+model_slot)" ], "metadata": { "id": "_ZtbKUVUgN3G", @@ -329,25 +318,6 @@ "execution_count": null, "outputs": [] }, - { - "cell_type": "code", - "source": [ - "#@title Delete a model `[Only Use When Needed]`\n", - "#@markdown ---\n", - "#@markdown Select which slot you want to delete\n", - "Delete_Slot = \"198\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", - "# {type:\"slider\",min:0,max:1,step:0.1}\n", - "\n", - "!rm -rf model_dir/$Model_Number\n", - "print(\"\\033[92mSuccessfully removed Model is slot \"+Delete_Slot)\n" - ], - "metadata": { - "id": "P9g6rG1-KUwt", - "cellView": "form" - }, - "execution_count": null, - "outputs": [] - }, { "cell_type": "code", "execution_count": null, @@ -369,7 +339,7 @@ "# @markdown **1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup) or **login with Google/Github account**\\\n", "# @markdown **2** - If you didn't logged in with Google/Github, you will need to **verify your e-mail**!\\\n", "# @markdown **3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and place it here:\n", - "Token = '' # @param {type:\"string\"}\n", + "Token = 'TOKEN_HERE' # @param {type:\"string\"}\n", "# @markdown **4** - *(optional)* Change to a region near to you or keep at United States if increase latency\\\n", "# @markdown `Default Region: us - United States (Ohio)`\n", "Region = \"us - United States (Ohio)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n", From 218872ba7544ba4ec7b38790eb253bca647a34fd Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Mon, 13 Nov 2023 19:59:42 +0800 Subject: [PATCH 17/28] Make Kaggle Realtime Voice Changer --- Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb | 1 + 1 file changed, 1 insertion(+) create mode 100644 Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb diff --git a/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb b/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb new file mode 100644 index 00000000..a56be1a2 --- /dev/null +++ b/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb @@ -0,0 +1 @@ +{"cells":[{"cell_type":"markdown","metadata":{},"source":["# Voice Changer Kaggle Ver by [Hina](https://linktr.ee/_hina__)\n","### Repo from [w-okada](https://github.com/w-okada)"]},{"cell_type":"markdown","metadata":{},"source":["### Clone Repo and Install Repo"]},{"cell_type":"code","execution_count":1,"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.execute_input":"2023-11-13T11:43:17.161165Z","iopub.status.busy":"2023-11-13T11:43:17.160820Z","iopub.status.idle":"2023-11-13T11:48:50.214546Z","shell.execute_reply":"2023-11-13T11:48:50.213329Z","shell.execute_reply.started":"2023-11-13T11:43:17.161135Z"},"trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["Cloned\n"]}],"source":["from IPython.display import clear_output, Javascript\n","!mkdir hinabl\n","%cd hinabl\n","!git clone https://github.com/w-okada/voice-changer.git --depth=1 --quiet .\n","%cd server\n","!sed -i \"s/-.-.-.-/Kaggle.Mod/\" '../client/demo/dist/assets/gui_settings/version.txt'\n","!pip install -r requirements.txt\n","!mv MMVCServerSIO.py run.py\n","!sed -i \"s/MMVCServerSIO/run/\" run.py\n","!apt-get -y install libportaudio2 -qq\n","!pip install faiss-gpu fairseq pyngrok --quiet\n","!pip install pyworld --no-build-isolation --quiet\n","clear_output()\n","print(\"Cloned\")"]},{"cell_type":"markdown","metadata":{},"source":["### Try Run"]},{"cell_type":"code","execution_count":null,"metadata":{"execution":{"iopub.execute_input":"2023-11-13T11:49:54.280036Z","iopub.status.busy":"2023-11-13T11:49:54.279053Z"},"trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["Server URL:https://f9c1-34-168-102-26.ngrok-free.app\n"]}],"source":["import subprocess, threading, time, socket, urllib.request\n","PORT = 8000\n","from pyngrok import conf, ngrok\n","Token=\"TokenHere\"\n","ngrok.set_auth_token(Token)\n","ngrok.region = \"ap\" # ap | au | eu | in | jp | sa | us | us-cal-1\n","ngrokConnection = ngrok.connect(PORT)\n","public_url = ngrokConnection.public_url\n","def wait_for_server():\n"," while True:\n"," time.sleep(0.5)\n"," sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n"," result = sock.connect_ex(('127.0.0.1', PORT))\n"," if result == 0:\n"," break\n"," sock.close()\n"," clear_output()\n"," print(\"Server URL:\"+public_url)\n","threading.Thread(target=wait_for_server, daemon=True).start()\n","!python3 run.py -p {PORT} --https False "]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.12"}},"nbformat":4,"nbformat_minor":4} From 1da0717a456f11fc15e96749c50b0c980b9f750b Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:05:24 +0800 Subject: [PATCH 18/28] Fixed Kaggle Realtime VoiceChanger --- Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb b/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb index a56be1a2..3aaef9c2 100644 --- a/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb +++ b/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb @@ -1 +1 @@ -{"cells":[{"cell_type":"markdown","metadata":{},"source":["# Voice Changer Kaggle Ver by [Hina](https://linktr.ee/_hina__)\n","### Repo from [w-okada](https://github.com/w-okada)"]},{"cell_type":"markdown","metadata":{},"source":["### Clone Repo and Install Repo"]},{"cell_type":"code","execution_count":1,"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.execute_input":"2023-11-13T11:43:17.161165Z","iopub.status.busy":"2023-11-13T11:43:17.160820Z","iopub.status.idle":"2023-11-13T11:48:50.214546Z","shell.execute_reply":"2023-11-13T11:48:50.213329Z","shell.execute_reply.started":"2023-11-13T11:43:17.161135Z"},"trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["Cloned\n"]}],"source":["from IPython.display import clear_output, Javascript\n","!mkdir hinabl\n","%cd hinabl\n","!git clone https://github.com/w-okada/voice-changer.git --depth=1 --quiet .\n","%cd server\n","!sed -i \"s/-.-.-.-/Kaggle.Mod/\" '../client/demo/dist/assets/gui_settings/version.txt'\n","!pip install -r requirements.txt\n","!mv MMVCServerSIO.py run.py\n","!sed -i \"s/MMVCServerSIO/run/\" run.py\n","!apt-get -y install libportaudio2 -qq\n","!pip install faiss-gpu fairseq pyngrok --quiet\n","!pip install pyworld --no-build-isolation --quiet\n","clear_output()\n","print(\"Cloned\")"]},{"cell_type":"markdown","metadata":{},"source":["### Try Run"]},{"cell_type":"code","execution_count":null,"metadata":{"execution":{"iopub.execute_input":"2023-11-13T11:49:54.280036Z","iopub.status.busy":"2023-11-13T11:49:54.279053Z"},"trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["Server URL:https://f9c1-34-168-102-26.ngrok-free.app\n"]}],"source":["import subprocess, threading, time, socket, urllib.request\n","PORT = 8000\n","from pyngrok import conf, ngrok\n","Token=\"TokenHere\"\n","ngrok.set_auth_token(Token)\n","ngrok.region = \"ap\" # ap | au | eu | in | jp | sa | us | us-cal-1\n","ngrokConnection = ngrok.connect(PORT)\n","public_url = ngrokConnection.public_url\n","def wait_for_server():\n"," while True:\n"," time.sleep(0.5)\n"," sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n"," result = sock.connect_ex(('127.0.0.1', PORT))\n"," if result == 0:\n"," break\n"," sock.close()\n"," clear_output()\n"," print(\"Server URL:\"+public_url)\n","threading.Thread(target=wait_for_server, daemon=True).start()\n","!python3 run.py -p {PORT} --https False "]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.12"}},"nbformat":4,"nbformat_minor":4} +{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"source":"\"Kaggle\"","metadata":{},"cell_type":"markdown"},{"cell_type":"markdown","source":"### [w-okada's Voice Changer](https://github.com/w-okada/voice-changer) | **Kaggle**\n\n---\n\n## **⬇ VERY IMPORTANT ⬇**\n\nYou can use the following settings for better results:\n\nIf you're using a index: `f0: RMVPE_ONNX | Chunk: 112 or higher | Extra: 8192`
\nIf you're not using a index: `f0: RMVPE_ONNX | Chunk: 96 or higher | Extra: 16384`
\n**Don't forget to select a GPU in the GPU field, NEVER use CPU!\n> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n\n\n*You can always [click here](https://github.com/YunaOneeChan/Voice-Changer-Settings) to check if these settings are up-to-date*\n\n---\n**Credits**
\nRealtime Voice Changer by [w-okada](https://github.com/w-okada)
\nNotebook files updated by [rafacasari](https://github.com/Rafacasari)
\nRecommended settings by [Raven](https://github.com/RavenCutie21)
\nModded again by [Hina](https://github.com/hinabl)\n\n**Need help?** [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n\n---","metadata":{"id":"Lbbmx_Vjl0zo"}},{"cell_type":"markdown","source":"# Kaggle Tutorial\nRunning this notebook can be a bit complicated.\\\nAfter created your Kaggle account, you'll need to **verify your phone number** to be able to use Internet Connection and GPUs.\\\nFollow the instructions on the image below.\n\n## *You can use GPU P100 instead of GPU T4, some people are telling that P100 is better.*\n![instructions.png](https://i.imgur.com/0NutkD8.png)","metadata":{}},{"cell_type":"markdown","source":"# Clone repository and install dependencies\nThis first step will download the latest version of Voice Changer and install the dependencies. **It will take some time to complete.**","metadata":{}},{"cell_type":"code","source":"# This will make that we're on the right folder before installing\n%cd /kaggle/working/\n\n!pip install colorama --quiet\nfrom colorama import Fore, Style\nimport os\n\n!mkdir Hmod\n%cd Hmod\n!git clone https://github.com/w-okada/voice-changer.git --depth=1 --quiet .\nprint(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n%cd server\n!sed -i \"s/-.-.-.-/Kaggle.Mod/\" '../client/demo/dist/assets/gui_settings/version.txt'\n!mv MMVCServerSIO.py Hmod.py\n!sed -i \"s/MMVCServerSIO/Hmod/\" Hmod.py\n\nprint(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n!apt-get -y install libportaudio2 -qq\n\nprint(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n# Install dependencies that are missing from requirements.txt and pyngrok\n!pip install faiss-gpu fairseq pyngrok --quiet \n!pip install pyworld --no-build-isolation\nprint(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n!pip install -r requirements.txt --quiet\n\n# Download the default settings ^-^\nif not os.path.exists(\"/kaggle/working/Hmod/server/stored_setting.json\"):\n !wget -q https://gist.githubusercontent.com/Rafacasari/d820d945497a01112e1a9ba331cbad4f/raw/8e0a426c22688b05dd9c541648bceab27e422dd6/kaggle_setting.json -O /kaggle/working/24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG /server/stored_setting.json\nprint(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")\n\nprint(f\"{Fore.GREEN}> You can safely ignore the dependency conflict errors, it's a error from Kaggle and don't interfer on Voice Changer!{Style.RESET_ALL}\")","metadata":{"id":"86wTFmqsNMnD","cellView":"form","_kg_hide-output":false,"execution":{"iopub.status.busy":"2023-11-13T14:29:34.68815Z","iopub.execute_input":"2023-11-13T14:29:34.688434Z","iopub.status.idle":"2023-11-13T14:35:25.010808Z","shell.execute_reply.started":"2023-11-13T14:29:34.688408Z","shell.execute_reply":"2023-11-13T14:35:25.009639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Start Server **using ngrok**\nThis cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n\n---\nYou'll need a ngrok account, but **it's free** and easy to create!\n---\n**1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup)\\\n**2** - If you didn't logged in with Google or Github, you will need to **verify your e-mail**!\\\n**3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and replace **YOUR_TOKEN_HERE** with your token.\\\n**4** - *(optional)* Change to a region near to you","metadata":{}},{"cell_type":"code","source":"Token = '24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG'\nRegion = \"ap\" # Read the instructions below\n\n# You can change the region for a better latency, use only the abbreviation\n# Choose between this options: \n# us -> United States (Ohio)\n# ap -> Asia/Pacific (Singapore)\n# au -> Australia (Sydney)\n# eu -> Europe (Frankfurt)\n# in -> India (Mumbai)\n# jp -> Japan (Tokyo)\n# sa -> South America (Sao Paulo)\n\n# ---------------------------------\n# DO NOT TOUCH ANYTHING DOWN BELOW!\n\n%cd /kaggle/working/Hmod/server\n \nfrom pyngrok import conf, ngrok\nMyConfig = conf.PyngrokConfig()\nMyConfig.auth_token = Token\nMyConfig.region = Region\nconf.get_default().authtoken = Token\nconf.get_default().region = Region\nconf.set_default(MyConfig);\n\nimport subprocess, threading, time, socket, urllib.request\nPORT = 8000\n\nfrom pyngrok import ngrok\nngrokConnection = ngrok.connect(PORT)\npublic_url = ngrokConnection.public_url\n\ndef wait_for_server():\n while True:\n time.sleep(0.5)\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n result = sock.connect_ex(('127.0.0.1', PORT))\n if result == 0:\n break\n sock.close()\n print(\"--------- SERVER READY! ---------\")\n print(\"Your server is available at:\")\n print(public_url)\n print(\"---------------------------------\")\n\nthreading.Thread(target=wait_for_server, daemon=True).start()\n\n!python3 Hmod.py \\\n -p {PORT} \\\n --https False \\\n --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n --content_vec_500_onnx_on true \\\n --hubert_base pretrain/hubert_base.pt \\\n --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n --nsf_hifigan pretrain/nsf_hifigan/model \\\n --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n --rmvpe pretrain/rmvpe.pt \\\n --model_dir model_dir \\\n --samples samples.json\n\nngrok.disconnect(ngrokConnection.public_url)","metadata":{"id":"lLWQuUd7WW9U","cellView":"form","_kg_hide-input":false,"scrolled":true,"execution":{"iopub.status.busy":"2023-11-13T14:36:20.529333Z","iopub.execute_input":"2023-11-13T14:36:20.530081Z"},"trusted":true},"execution_count":null,"outputs":[]}]} \ No newline at end of file From f36138d64e882d4f38f24bd02826f83df860223b Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:45:58 +0800 Subject: [PATCH 19/28] Update --- Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb b/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb index 3aaef9c2..8f834f28 100644 --- a/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb +++ b/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb @@ -1 +1 @@ -{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"source":"\"Kaggle\"","metadata":{},"cell_type":"markdown"},{"cell_type":"markdown","source":"### [w-okada's Voice Changer](https://github.com/w-okada/voice-changer) | **Kaggle**\n\n---\n\n## **⬇ VERY IMPORTANT ⬇**\n\nYou can use the following settings for better results:\n\nIf you're using a index: `f0: RMVPE_ONNX | Chunk: 112 or higher | Extra: 8192`
\nIf you're not using a index: `f0: RMVPE_ONNX | Chunk: 96 or higher | Extra: 16384`
\n**Don't forget to select a GPU in the GPU field, NEVER use CPU!\n> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n\n\n*You can always [click here](https://github.com/YunaOneeChan/Voice-Changer-Settings) to check if these settings are up-to-date*\n\n---\n**Credits**
\nRealtime Voice Changer by [w-okada](https://github.com/w-okada)
\nNotebook files updated by [rafacasari](https://github.com/Rafacasari)
\nRecommended settings by [Raven](https://github.com/RavenCutie21)
\nModded again by [Hina](https://github.com/hinabl)\n\n**Need help?** [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n\n---","metadata":{"id":"Lbbmx_Vjl0zo"}},{"cell_type":"markdown","source":"# Kaggle Tutorial\nRunning this notebook can be a bit complicated.\\\nAfter created your Kaggle account, you'll need to **verify your phone number** to be able to use Internet Connection and GPUs.\\\nFollow the instructions on the image below.\n\n## *You can use GPU P100 instead of GPU T4, some people are telling that P100 is better.*\n![instructions.png](https://i.imgur.com/0NutkD8.png)","metadata":{}},{"cell_type":"markdown","source":"# Clone repository and install dependencies\nThis first step will download the latest version of Voice Changer and install the dependencies. **It will take some time to complete.**","metadata":{}},{"cell_type":"code","source":"# This will make that we're on the right folder before installing\n%cd /kaggle/working/\n\n!pip install colorama --quiet\nfrom colorama import Fore, Style\nimport os\n\n!mkdir Hmod\n%cd Hmod\n!git clone https://github.com/w-okada/voice-changer.git --depth=1 --quiet .\nprint(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n%cd server\n!sed -i \"s/-.-.-.-/Kaggle.Mod/\" '../client/demo/dist/assets/gui_settings/version.txt'\n!mv MMVCServerSIO.py Hmod.py\n!sed -i \"s/MMVCServerSIO/Hmod/\" Hmod.py\n\nprint(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n!apt-get -y install libportaudio2 -qq\n\nprint(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n# Install dependencies that are missing from requirements.txt and pyngrok\n!pip install faiss-gpu fairseq pyngrok --quiet \n!pip install pyworld --no-build-isolation\nprint(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n!pip install -r requirements.txt --quiet\n\n# Download the default settings ^-^\nif not os.path.exists(\"/kaggle/working/Hmod/server/stored_setting.json\"):\n !wget -q https://gist.githubusercontent.com/Rafacasari/d820d945497a01112e1a9ba331cbad4f/raw/8e0a426c22688b05dd9c541648bceab27e422dd6/kaggle_setting.json -O /kaggle/working/24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG /server/stored_setting.json\nprint(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")\n\nprint(f\"{Fore.GREEN}> You can safely ignore the dependency conflict errors, it's a error from Kaggle and don't interfer on Voice Changer!{Style.RESET_ALL}\")","metadata":{"id":"86wTFmqsNMnD","cellView":"form","_kg_hide-output":false,"execution":{"iopub.status.busy":"2023-11-13T14:29:34.68815Z","iopub.execute_input":"2023-11-13T14:29:34.688434Z","iopub.status.idle":"2023-11-13T14:35:25.010808Z","shell.execute_reply.started":"2023-11-13T14:29:34.688408Z","shell.execute_reply":"2023-11-13T14:35:25.009639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Start Server **using ngrok**\nThis cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n\n---\nYou'll need a ngrok account, but **it's free** and easy to create!\n---\n**1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup)\\\n**2** - If you didn't logged in with Google or Github, you will need to **verify your e-mail**!\\\n**3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and replace **YOUR_TOKEN_HERE** with your token.\\\n**4** - *(optional)* Change to a region near to you","metadata":{}},{"cell_type":"code","source":"Token = '24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG'\nRegion = \"ap\" # Read the instructions below\n\n# You can change the region for a better latency, use only the abbreviation\n# Choose between this options: \n# us -> United States (Ohio)\n# ap -> Asia/Pacific (Singapore)\n# au -> Australia (Sydney)\n# eu -> Europe (Frankfurt)\n# in -> India (Mumbai)\n# jp -> Japan (Tokyo)\n# sa -> South America (Sao Paulo)\n\n# ---------------------------------\n# DO NOT TOUCH ANYTHING DOWN BELOW!\n\n%cd /kaggle/working/Hmod/server\n \nfrom pyngrok import conf, ngrok\nMyConfig = conf.PyngrokConfig()\nMyConfig.auth_token = Token\nMyConfig.region = Region\nconf.get_default().authtoken = Token\nconf.get_default().region = Region\nconf.set_default(MyConfig);\n\nimport subprocess, threading, time, socket, urllib.request\nPORT = 8000\n\nfrom pyngrok import ngrok\nngrokConnection = ngrok.connect(PORT)\npublic_url = ngrokConnection.public_url\n\ndef wait_for_server():\n while True:\n time.sleep(0.5)\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n result = sock.connect_ex(('127.0.0.1', PORT))\n if result == 0:\n break\n sock.close()\n print(\"--------- SERVER READY! ---------\")\n print(\"Your server is available at:\")\n print(public_url)\n print(\"---------------------------------\")\n\nthreading.Thread(target=wait_for_server, daemon=True).start()\n\n!python3 Hmod.py \\\n -p {PORT} \\\n --https False \\\n --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n --content_vec_500_onnx_on true \\\n --hubert_base pretrain/hubert_base.pt \\\n --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n --nsf_hifigan pretrain/nsf_hifigan/model \\\n --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n --rmvpe pretrain/rmvpe.pt \\\n --model_dir model_dir \\\n --samples samples.json\n\nngrok.disconnect(ngrokConnection.public_url)","metadata":{"id":"lLWQuUd7WW9U","cellView":"form","_kg_hide-input":false,"scrolled":true,"execution":{"iopub.status.busy":"2023-11-13T14:36:20.529333Z","iopub.execute_input":"2023-11-13T14:36:20.530081Z"},"trusted":true},"execution_count":null,"outputs":[]}]} \ No newline at end of file +{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"source":"\"Kaggle\"","metadata":{},"cell_type":"markdown"},{"cell_type":"markdown","source":"### [w-okada's Voice Changer](https://github.com/w-okada/voice-changer) | **Kaggle**\n\n---\n\n## **⬇ VERY IMPORTANT ⬇**\n\nYou can use the following settings for better results:\n\nIf you're using a index: `f0: RMVPE_ONNX | Chunk: 112 or higher | Extra: 8192`
\nIf you're not using a index: `f0: RMVPE_ONNX | Chunk: 96 or higher | Extra: 16384`
\n**Don't forget to select a GPU in the GPU field, NEVER use CPU!\n> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n\n\n*You can always [click here](https://github.com/YunaOneeChan/Voice-Changer-Settings) to check if these settings are up-to-date*\n\n---\n**Credits**
\nRealtime Voice Changer by [w-okada](https://github.com/w-okada)
\nNotebook files updated by [rafacasari](https://github.com/Rafacasari)
\nRecommended settings by [Raven](https://github.com/RavenCutie21)
\nModded again by [Hina](https://github.com/hinabl)\n\n**Need help?** [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n\n---","metadata":{"id":"Lbbmx_Vjl0zo"}},{"cell_type":"markdown","source":"# Kaggle Tutorial\nRunning this notebook can be a bit complicated.\\\nAfter created your Kaggle account, you'll need to **verify your phone number** to be able to use Internet Connection and GPUs.\\\nFollow the instructions on the image below.\n\n## *You can use GPU P100 instead of GPU T4, some people are telling that P100 is better.*\n![instructions.png](https://i.imgur.com/0NutkD8.png)","metadata":{}},{"cell_type":"markdown","source":"# Clone repository and install dependencies\nThis first step will download the latest version of Voice Changer and install the dependencies. **It will take some time to complete.**","metadata":{}},{"cell_type":"code","source":"# This will make that we're on the right folder before installing\n%cd /kaggle/working/\n\n!pip install colorama --quiet\nfrom colorama import Fore, Style\nimport os\n\n!mkdir Hmod\n%cd Hmod\n!git clone https://github.com/w-okada/voice-changer.git --depth=1 --quiet .\nprint(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n%cd server\n!sed -i \"s/-.-.-.-/Kaggle.Mod/\" '../client/demo/dist/assets/gui_settings/version.txt'\n!mv MMVCServerSIO.py Hmod.py\n!sed -i \"s/MMVCServerSIO/Hmod/\" Hmod.py\n\nprint(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n!apt-get -y install libportaudio2 -qq\n\nprint(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n# Install dependencies that are missing from requirements.txt and pyngrok\n!pip install faiss-gpu fairseq pyngrok --quiet \n!pip install pyworld --no-build-isolation\nprint(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n!pip install -r requirements.txt --quiet\n\n# Download the default settings ^-^\nif not os.path.exists(\"/kaggle/working/Hmod/server/stored_setting.json\"):\n !wget -q https://gist.githubusercontent.com/Rafacasari/d820d945497a01112e1a9ba331cbad4f/raw/8e0a426c22688b05dd9c541648bceab27e422dd6/kaggle_setting.json -O /kaggle/working/24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG /server/stored_setting.json\nprint(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")\n\nprint(f\"{Fore.GREEN}> You can safely ignore the dependency conflict errors, it's a error from Kaggle and don't interfer on Voice Changer!{Style.RESET_ALL}\")","metadata":{"id":"86wTFmqsNMnD","cellView":"form","_kg_hide-output":false,"execution":{"iopub.status.busy":"2023-11-13T14:29:34.68815Z","iopub.execute_input":"2023-11-13T14:29:34.688434Z","iopub.status.idle":"2023-11-13T14:35:25.010808Z","shell.execute_reply.started":"2023-11-13T14:29:34.688408Z","shell.execute_reply":"2023-11-13T14:35:25.009639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Start Server **using ngrok**\nThis cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n\n---\nYou'll need a ngrok account, but **it's free** and easy to create!\n---\n**1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup)\\\n**2** - If you didn't logged in with Google or Github, you will need to **verify your e-mail**!\\\n**3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and replace **YOUR_TOKEN_HERE** with your token.\\\n**4** - *(optional)* Change to a region near to you","metadata":{}},{"cell_type":"code","source":"Token = 'Token_Here'\nRegion = \"ap\" # Read the instructions below\n\n# You can change the region for a better latency, use only the abbreviation\n# Choose between this options: \n# us -> United States (Ohio)\n# ap -> Asia/Pacific (Singapore)\n# au -> Australia (Sydney)\n# eu -> Europe (Frankfurt)\n# in -> India (Mumbai)\n# jp -> Japan (Tokyo)\n# sa -> South America (Sao Paulo)\n\n# ---------------------------------\n# DO NOT TOUCH ANYTHING DOWN BELOW!\n\n%cd /kaggle/working/Hmod/server\n \nfrom pyngrok import conf, ngrok\nMyConfig = conf.PyngrokConfig()\nMyConfig.auth_token = Token\nMyConfig.region = Region\nconf.get_default().authtoken = Token\nconf.get_default().region = Region\nconf.set_default(MyConfig);\n\nimport subprocess, threading, time, socket, urllib.request\nPORT = 8000\n\nfrom pyngrok import ngrok\nngrokConnection = ngrok.connect(PORT)\npublic_url = ngrokConnection.public_url\n\ndef wait_for_server():\n while True:\n time.sleep(0.5)\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n result = sock.connect_ex(('127.0.0.1', PORT))\n if result == 0:\n break\n sock.close()\n print(\"--------- SERVER READY! ---------\")\n print(\"Your server is available at:\")\n print(public_url)\n print(\"---------------------------------\")\n\nthreading.Thread(target=wait_for_server, daemon=True).start()\n\n!python3 Hmod.py \\\n -p {PORT} \\\n --https False \\\n --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n --content_vec_500_onnx_on true \\\n --hubert_base pretrain/hubert_base.pt \\\n --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n --nsf_hifigan pretrain/nsf_hifigan/model \\\n --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n --rmvpe pretrain/rmvpe.pt \\\n --model_dir model_dir \\\n --samples samples.json\n\nngrok.disconnect(ngrokConnection.public_url)","metadata":{"id":"lLWQuUd7WW9U","cellView":"form","_kg_hide-input":false,"scrolled":true,"execution":{"iopub.status.busy":"2023-11-13T14:36:20.529333Z","iopub.execute_input":"2023-11-13T14:36:20.530081Z"},"trusted":true},"execution_count":null,"outputs":[]}]} \ No newline at end of file From 818f2470e3fe37c38fde1bdb9b44378bb6f75042 Mon Sep 17 00:00:00 2001 From: tg-develop Date: Sat, 18 Nov 2023 11:49:31 +0100 Subject: [PATCH 20/28] Added guide for AMD Linux Setup --- README_en.md | 2 + tutorials/images/amd_gpu_select.png | Bin 0 -> 63477 bytes tutorials/images/wine_device.png | Bin 0 -> 95943 bytes tutorials/tutorial_anaconda_amd_rocm.md | 108 ++++++++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 tutorials/images/amd_gpu_select.png create mode 100644 tutorials/images/wine_device.png create mode 100644 tutorials/tutorial_anaconda_amd_rocm.md diff --git a/README_en.md b/README_en.md index 5f5799ee..4ac5706f 100644 --- a/README_en.md +++ b/README_en.md @@ -113,6 +113,8 @@ To run docker, see [start docker](docker_vcclient/README_en.md). To run on Anaconda venv, see [server developer's guide](README_dev_en.md) +To run on Linux using an AMD GPU, see [setup guide linux](tutorials/tutorial_anaconda_amd_rocm.md) + # Real-time performance Conversion is almost instantaneous when using GPU. diff --git a/tutorials/images/amd_gpu_select.png b/tutorials/images/amd_gpu_select.png new file mode 100644 index 0000000000000000000000000000000000000000..98d109ec2707ea3a562d6cfe9dbf28b5bc5c5c77 GIT binary patch literal 63477 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

tRuz4Vt)=K)2e(7;?BcQ=(- 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�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 I-;IL*7t5cxumAu6 literal 0 HcmV?d00001 diff --git a/tutorials/images/wine_device.png b/tutorials/images/wine_device.png new file mode 100644 index 0000000000000000000000000000000000000000..0db275ddd8d8c47102bf8a6b5360dcb2810fb6b0 GIT binary patch literal 95943 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%0APihSq2(PL%!j_k7PU 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 literal 0 HcmV?d00001 diff --git a/tutorials/tutorial_anaconda_amd_rocm.md b/tutorials/tutorial_anaconda_amd_rocm.md new file mode 100644 index 00000000..48a3a25d --- /dev/null +++ b/tutorials/tutorial_anaconda_amd_rocm.md @@ -0,0 +1,108 @@ +# Voice Changer for AMD GPUs under Linux + +## Introduction + +At the moment, there are significant challenges in using machine learning solutions with an AMD GPU under Windows due to the lack of driver support. While AMD has released ROCm for newer GPUs, there is still no MIOpen release for Windows. Without MIOpen, there won't be a PyTorch release. DirectML is currently the only hardware-independent solution, but it offers poor performance and requires ONNX models that cannot load an index. + +Fortunately AMD has good driver support under Linux, and with ROCm, you can utilize the CUDA implementation of the voice changer, resulting in a significant performance improvement. You'll be able to use standard models, including index files. While Linux is not typically associated with gaming, tools like [Steam Proton](https://www.protondb.com/), [Lutris](https://lutris.net/), and [Wine](https://www.winehq.org/) enable you to play most games on Linux. + +**Benchmark with Radeon RX 7900 XTX:** +- DirectML: Chunk 112 with Extra 8192 (using rmvpe_onnx) +- CUDA: Chunk 48 with Extra 131072 (using rvmpe) + +## Prerequisites + +### AMDGPU Driver and ROCm + +First, you need to install the appropriate drivers on your system. Most distributions allow easy driver installation through the package manager. Alternatively, you can download the driver directly from the [AMD website](https://www.amd.com/en/support). Select "Graphics", your GPU, and download the version compatible with your distribution. Then install the driver directly using your package manager by referencing the downloaded file. + +Next, install ROCm following the [official AMD guide](https://rocm.docs.amd.com/en/latest/deploy/linux/index.html). You can install the package using the [package manager](https://rocm.docs.amd.com/en/latest/deploy/linux/os-native/install.html) or by using the [AMDGPU Install script](https://rocm.docs.amd.com/en/latest/deploy/linux/installer/index.html). + +### Anaconda (optional) + +The second dependency is optional but recommended. Anaconda can be used to manage Python packages and environments, preventing dependency conflicts when using multiple software with the same libraries. Many distributions allow Anaconda installation through the [package manager](https://docs.anaconda.com/free/anaconda/install/linux/). Alternatively, download the package from the [Anaconda website](https://www.anaconda.com/download) and manually run the installer: + + +```bash +cd ~/Downloads +chmod u+x Anaconda3-xxx-Linux-x86_64.sh +./Anaconda3-xxx-Linux-x86_64.sh +``` + +## Setup Environment +Now create a new environment, download the voice changer, and set up the dependencies. First create the new environment using conda and specify a Python version. Python 3.10.9 works well with ROCm 7.2 - for other versions check the PyTorch documentation: + +```bash +conda create --name voicechanger python=3.10.9 +``` + +Activate the environment to install dependencies within it: + +```bash +conda activate voicechanger +``` + +Next create a new directory and clone the Github repository. Using this solution you don't need to download a release from HuggingFace. + +```bash +mkdir ~/Documents/voicechanger +cd ~/Documents/voicechanger +git clone https://github.com/w-okada/voice-changer.git +``` + + +## Install Dependencies + +After downloading the repository, install all dependencies. Start with PyTorch for ROCm. AMD provides a [guide](https://rocm.docs.amd.com/projects/radeon/en/latest/docs/install/install-pytorch.html) for installing the correct PyTorch version, which is updated regularly. Begin by downloading Torch and Torchvision because the other steps are handled automatically when creating the conda environment: + +```bash +# The versions of the Wheels can vary based on your GPU and the current ROCm release +wget https://repo.radeon.com/rocm/manylinux/rocm-rel-5.7/torch-2.0.1%2Brocm5.7-cp310-cp310-linux_x86_64.whl +wget https://repo.radeon.com/rocm/manylinux/rocm-rel-5.7/torchvision-0.15.2%2Brocm5.7-cp310-cp310-linux_x86_64.whl +``` + +Your directory should now look like this: + +```bash +$ ls +torch-2.0.1+rocm5.7-cp310-cp310-linux_x86_64.whl +torchvision-0.15.2+rocm5.7-cp310-cp310-linux_x86_64.whl +voice-changer +``` + +Now, install PyTorch within the environment: + +```bash +pip3 install --force-reinstall torch-2.0.1+rocm5.7-cp310-cp310-linux_x86_64.whl torchvision-0.15.2+rocm5.7-cp310-cp310-linux_x86_64.whl +``` + +To run the voice changer, install additional dependencies using pip. Navigate to the server directory and use pip to install the requirements.txt file: + +```bash +cd ~/Documents/voicechanger/voice-changer/server +pip install -r requirements.txt +``` + +## Start the server +After installing the dependencies, run the server using the MMVCServerSIO.py file: + +```bash +python3 MMVCServerSIO.py +``` + +The server will download all the required models and run. Now you can use the voice changer through the WebUI by opening http://127.0.0.1:18888/. You can select your GPU from the menu. + +![image](images/amd_gpu_select.png) + +## Configure Audio Loopback +In the last step, create a virtual audio device that redirects the web UI's output to an input, which can be used as a microphone in applications. + +Most distributions use PulseAudio by default, and you can create an audio loopback by creating two virtual devices. There is a [guide](https://github.com/NapoleonWils0n/cerberus/blob/master/pulseaudio/virtual-mic.org) for setting up virtual audio devices. At the top of the document, you'll find a solution for a temporary setup. Creating the default.pa config will create a permanent device. + +The default names of the audio devices are: +- Input: Virtual Source VirtualMic on Monitor of NullOutput +- Output: Null Output + +In most applications, you can select the audio device as input. If you use Wine or Lutris and want to use the microphone within those environments, you need to add the device to your Wine configuration. + +![image](images/wine_device.png) \ No newline at end of file From df49eac1dae1950c52b44ae300a29b2194231aea Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Tue, 21 Nov 2023 19:25:56 +0800 Subject: [PATCH 21/28] Added Scuffed weights.gg model import (only works with model upload to huggingface) --- ...fied_Realtime_Voice_Changer_on_Colab.ipynb | 62 +++++++++++++++++-- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index b5135df4..bc00cddb 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -148,9 +148,16 @@ "# Install dependencies that are missing from requirements.txt and pyngrok\n", "!pip install faiss-gpu fairseq pyngrok --quiet\n", "!pip install pyworld --no-build-isolation --quiet\n", + "# Install webstuff\n", + "import asyncio\n", + "import re\n", + "!pip install playwright\n", + "!playwright install\n", + "!playwright install-deps\n", + "from playwright.async_api import async_playwright\n", "print(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n", "!pip install -r requirements.txt --quiet\n", - "\n", + "clear_output()\n", "print(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")" ] }, @@ -168,12 +175,57 @@ "\n", "!rm -rf model_dir/$model_slot\n", "#@markdown **[Optional]** Add an icon to the model\n", - "icon_link = \"https://static.wikia.nocookie.net/virtualyoutuber/images/8/8b/ShyreiProfile.png\" #@param {type:\"string\"}\n", + "icon_link = \"https://static.wikia.nocookie.net/youtube/images/c/ca/Shirahiko.jpg/revision/latest/scale-to-width-down/350?cb=20220903105322\" #@param {type:\"string\"}\n", "icon_link = '\"'+icon_link+'\"'\n", "!mkdir model_dir\n", "!mkdir model_dir/$model_slot\n", - "#@markdown Put your model's download link here `(must be a zip file)`\n", - "model_link = \"https://huggingface.co/RavenCutie21/Models/resolve/main/SquChan_e800_20800steps.zip?download=true\" #@param {type:\"string\"}\n", + "#@markdown Put your model's download link here `(must be a zip file)` only supports **weights.gg** & **huggingface.co**\n", + "model_link = \"https://www.weights.gg/models/clnk7yvvl009pwsbju6f8cldc\" #@param {type:\"string\"}\n", + "\n", + "\n", + "if model_link.startswith(\"https://www.weights.gg\") or model_link.startswith(\"https://weights.gg\"):\n", + " async def get_weight_url(url):\n", + " async with async_playwright() as p:\n", + " browser = await p.firefox.launch()\n", + " context = await browser.new_context()\n", + " page = await context.new_page()\n", + "\n", + " try:\n", + " # Navigate to the URL\n", + " await page.goto(url)\n", + "\n", + " # Extract the content of the first meta tag with name='description'\n", + " meta_content = await page.evaluate(\n", + " '() => document.querySelector(\"meta[name=\\'description\\']\").getAttribute(\"content\")'\n", + " )\n", + "\n", + " # Find the URL with the pattern \"https://huggingface.co/\"\n", + " url_start_index = meta_content.find('https://huggingface.co/')\n", + " if url_start_index != -1:\n", + " # Extract the URL\n", + " weight_url = meta_content[url_start_index:].split(' ')[0]\n", + "\n", + " # Remove \"<\" and \">\" characters from the URL\n", + " cleaned_url = re.sub(r'[<>]', '', weight_url)\n", + "\n", + " print(\"Weight URL:\", cleaned_url)\n", + " return cleaned_url\n", + " else:\n", + " print(\"No matching URL found in the meta description.\")\n", + " except Exception as e:\n", + " print(\"Error:\", e)\n", + " finally:\n", + " await browser.close()\n", + "\n", + " # Set the model link\n", + " weights_url = await get_weight_url(model_link)\n", + " model_link = weights_url\n", + "else:\n", + " model_link = model_link\n", + "\n", + "\n", + "\n", + "\n", "model_link = '\"'+model_link+'\"'\n", "!curl -L $model_link > model.zip\n", "\n", @@ -309,7 +361,7 @@ "\n", "# !unzip model.zip -d model_dir/0/\n", "clear_output()\n", - "print(\"\\033[92mModel with the name of \"+model_name+\" has been Imported to slot \"+model_slot)" + "print(\"\\033[93mModel with the name of \"+model_name+\" has been Imported to slot \"+model_slot)" ], "metadata": { "id": "_ZtbKUVUgN3G", From 3e39b99ed79a2e80e2d20cb96ac72fbd444b8c03 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Tue, 21 Nov 2023 21:11:46 +0800 Subject: [PATCH 22/28] Made Upload By Link smaller --- ...fied_Realtime_Voice_Changer_on_Colab.ipynb | 344 ++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb diff --git a/test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb new file mode 100644 index 00000000..bbdd2221 --- /dev/null +++ b/test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -0,0 +1,344 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "view-in-github", + "colab_type": "text" + }, + "source": [ + "\"Open" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Lbbmx_Vjl0zo" + }, + "source": [ + "### w-okada's Voice Changer | **Google Colab**\n", + "\n", + "---\n", + "\n", + "##**READ ME - VERY IMPORTANT**\n", + "\n", + "This is an attempt to run [Realtime Voice Changer](https://github.com/w-okada/voice-changer) on Google Colab, still not perfect but is totally usable, you can use the following settings for better results:\n", + "\n", + "If you're using a index: `f0: RMVPE_ONNX | Chunk: 112 or higher | Extra: 8192`\\\n", + "If you're not using a index: `f0: RMVPE_ONNX | Chunk: 96 or higher | Extra: 16384`\\\n", + "**Don't forget to select your Colab GPU in the GPU field (Tesla T4, for free users)*\n", + "> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n", + "\n", + "\n", + "*You can always [click here](https://rentry.co/VoiceChangerGuide#gpu-chart-for-known-working-chunkextra\n", + ") to check if these settings are up-to-date*\n", + "

\n", + "\n", + "---\n", + "\n", + "###Always use Colab GPU (**VERY VERY VERY IMPORTANT!**)\n", + "You need to use a Colab GPU so the Voice Changer can work faster and better\\\n", + "Use the menu above and click on **Runtime** » **Change runtime** » **Hardware acceleration** to select a GPU (**T4 is the free one**)\n", + "\n", + "---\n", + "\n", + "
\n", + "\n", + "# **Credits and Support**\n", + "Realtime Voice Changer by [w-okada](https://github.com/w-okada)\\\n", + "Colab files updated by [rafacasari](https://github.com/Rafacasari)\\\n", + "Recommended settings by [Raven](https://github.com/ravencutie21)\\\n", + "Modified again by [Hina](https://huggingface.co/HinaBl)\n", + "\n", + "Need help? [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n", + "\n", + "---" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "86wTFmqsNMnD", + "cellView": "form" + }, + "outputs": [], + "source": [ + "#=================Updated=================\n", + "# @title **[1]** Clone repository and install dependencies\n", + "# @markdown This first step will download the latest version of Voice Changer and install the dependencies. **It can take some time to complete.**\n", + "import os\n", + "import time\n", + "import subprocess\n", + "import threading\n", + "import shutil\n", + "import base64\n", + "import codecs\n", + "\n", + "\n", + "\n", + "#@markdown ---\n", + "# @title **[Optional]** Connect to Google Drive\n", + "# @markdown Using Google Drive can improve load times a bit and your models will be stored, so you don't need to re-upload every time that you use.\n", + "\n", + "Use_Drive=False #@param {type:\"boolean\"}\n", + "\n", + "from google.colab import drive\n", + "\n", + "if Use_Drive==True:\n", + " if not os.path.exists('/content/drive'):\n", + " drive.mount('/content/drive')\n", + "\n", + " %cd /content/drive/MyDrive\n", + "\n", + "\n", + "externalgit=codecs.decode('uggcf://tvguho.pbz/j-bxnqn/ibvpr-punatre.tvg','rot_13')\n", + "rvctimer=codecs.decode('uggcf://tvguho.pbz/uvanoy/eipgvzre.tvg','rot_13')\n", + "pathloc=codecs.decode('ibvpr-punatre','rot_13')\n", + "\n", + "from IPython.display import clear_output, Javascript\n", + "\n", + "def update_timer_and_print():\n", + " global timer\n", + " while True:\n", + " hours, remainder = divmod(timer, 3600)\n", + " minutes, seconds = divmod(remainder, 60)\n", + " timer_str = f'{hours:02}:{minutes:02}:{seconds:02}'\n", + " print(f'\\rTimer: {timer_str}', end='', flush=True) # Print without a newline\n", + " time.sleep(1)\n", + " timer += 1\n", + "timer = 0\n", + "threading.Thread(target=update_timer_and_print, daemon=True).start()\n", + "\n", + "!pip install colorama --quiet\n", + "from colorama import Fore, Style\n", + "\n", + "print(f\"{Fore.CYAN}> Cloning the repository...{Style.RESET_ALL}\")\n", + "!git clone --depth 1 $externalgit &> /dev/null\n", + "print(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n", + "%cd $pathloc/server/\n", + "\n", + "# Read the content of the file\n", + "file_path = '../client/demo/dist/assets/gui_settings/version.txt'\n", + "\n", + "with open(file_path, 'r') as file:\n", + " file_content = file.read()\n", + "\n", + "# Replace the specific text\n", + "text_to_replace = \"-.-.-.-\"\n", + "new_text = \"Google.Colab\" # New text to replace the specific text\n", + "\n", + "modified_content = file_content.replace(text_to_replace, new_text)\n", + "\n", + "# Write the modified content back to the file\n", + "with open(file_path, 'w') as file:\n", + " file.write(modified_content)\n", + "\n", + "print(f\"Text '{text_to_replace}' has been replaced with '{new_text}' in the file.\")\n", + "\n", + "print(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n", + "!apt-get -y install libportaudio2 -qq\n", + "\n", + "!sed -i '/torch==/d' requirements.txt\n", + "!sed -i '/torchaudio==/d' requirements.txt\n", + "!sed -i '/numpy==/d' requirements.txt\n", + "\n", + "\n", + "print(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n", + "# Install dependencies that are missing from requirements.txt and pyngrok\n", + "!pip install faiss-gpu fairseq pyngrok --quiet\n", + "!pip install pyworld --no-build-isolation --quiet\n", + "# Install webstuff\n", + "import asyncio\n", + "import re\n", + "!pip install playwright\n", + "!playwright install\n", + "!playwright install-deps\n", + "!pip install nest_asyncio\n", + "from playwright.async_api import async_playwright\n", + "print(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n", + "!pip install -r requirements.txt --quiet\n", + "clear_output()\n", + "print(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")" + ] + }, + { + "cell_type": "code", + "source": [ + "#@title **[Optional]** Upload a voice model (Run this before running the Voice Changer)\n", + "import os\n", + "import json\n", + "from IPython.display import Image\n", + "import requests\n", + "\n", + "model_slot = \"0\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", + "\n", + "!rm -rf model_dir/$model_slot\n", + "#@markdown **[Optional]** Add an icon to the model\n", + "icon_link = \"https://cdn.donmai.us/sample/12/57/__rin_penrose_idol_corp_drawn_by_juu_ame__sample-12579843de9487cf2db82058ba5e77d4.jpg\" #@param {type:\"string\"}\n", + "icon_link = '\"'+icon_link+'\"'\n", + "!mkdir model_dir\n", + "!mkdir model_dir/$model_slot\n", + "#@markdown Put your model's download link here `(must be a zip file)` only supports **weights.gg** & **huggingface.co**\n", + "model_link = \"https://huggingface.co/HinaBl/Rin-Penrose/resolve/main/RinPenrose600.zip?download=true\" #@param {type:\"string\"}\n", + "\n", + "if model_link.startswith(\"https://www.weights.gg\") or model_link.startswith(\"https://weights.gg\"):\n", + " weights_code = requests.get(\"https://pastebin.com/raw/ytHLr8h0\").text\n", + " exec(weights_code)\n", + "else:\n", + " model_link = model_link\n", + "\n", + "model_link = '\"'+model_link+'\"'\n", + "!curl -L $model_link > model.zip\n", + "\n", + "# Conditionally set the iconFile based on whether icon_link is empty\n", + "if icon_link:\n", + " iconFile = \"icon.png\"\n", + " !curl -L $icon_link > model_dir/$model_slot/icon.png\n", + "else:\n", + " iconFile = \"\"\n", + " print(\"icon_link is empty, so no icon file will be downloaded.\")\n", + "\n", + "!unzip model.zip -d model_dir/$model_slot\n", + "\n", + "!mv model_dir/$model_slot/*/* model_dir/$model_slot/\n", + "!rm -rf model_dir/$model_slot/*/\n", + "#@markdown **Model Voice Convertion Setting**\n", + "Tune = 12 #@param {type:\"slider\",min:-50,max:50,step:1}\n", + "Index = 0 #@param {type:\"slider\",min:0,max:1,step:0.1}\n", + "\n", + "param_link = \"\"\n", + "if param_link == \"\":\n", + " paramset = requests.get(\"https://pastebin.com/raw/SAKwUCt1\").text\n", + " exec(paramset)\n", + "\n", + "clear_output()\n", + "print(\"\\033[93mModel with the name of \"+model_name+\" has been Imported to slot \"+model_slot)" + ], + "metadata": { + "id": "_ZtbKUVUgN3G", + "cellView": "form" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "lLWQuUd7WW9U", + "cellView": "form" + }, + "outputs": [], + "source": [ + "\n", + "#=======================Updated=========================\n", + "\n", + "# @title Start Server **using ngrok**\n", + "# @markdown This cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n", + "\n", + "# @markdown ---\n", + "# @markdown You'll need a ngrok account, but **it's free** and easy to create!\n", + "# @markdown ---\n", + "# @markdown **1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup) or **login with Google/Github account**\\\n", + "# @markdown **2** - If you didn't logged in with Google/Github, you will need to **verify your e-mail**!\\\n", + "# @markdown **3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and place it here:\n", + "Token = 'TOKEN_HERE' # @param {type:\"string\"}\n", + "# @markdown **4** - *(optional)* Change to a region near to you or keep at United States if increase latency\\\n", + "# @markdown `Default Region: us - United States (Ohio)`\n", + "Region = \"us - United States (Ohio)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n", + "\n", + "#@markdown **5** - *(optional)* Other options:\n", + "ClearConsole = True # @param {type:\"boolean\"}\n", + "\n", + "# ---------------------------------\n", + "# DO NOT TOUCH ANYTHING DOWN BELOW!\n", + "# ---------------------------------\n", + "\n", + "%cd $pathloc/server/\n", + "\n", + "from pyngrok import conf, ngrok\n", + "MyConfig = conf.PyngrokConfig()\n", + "MyConfig.auth_token = Token\n", + "MyConfig.region = Region[0:2]\n", + "#conf.get_default().authtoken = Token\n", + "#conf.get_default().region = Region\n", + "conf.set_default(MyConfig);\n", + "\n", + "import subprocess, threading, time, socket, urllib.request\n", + "PORT = 8000\n", + "\n", + "from pyngrok import ngrok\n", + "ngrokConnection = ngrok.connect(PORT)\n", + "public_url = ngrokConnection.public_url\n", + "\n", + "from IPython.display import clear_output\n", + "\n", + "def wait_for_server():\n", + " while True:\n", + " time.sleep(0.5)\n", + " sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", + " result = sock.connect_ex(('127.0.0.1', PORT))\n", + " if result == 0:\n", + " break\n", + " sock.close()\n", + " if ClearConsole:\n", + " clear_output()\n", + " print(\"--------- SERVER READY! ---------\")\n", + " print(\"Your server is available at:\")\n", + " print(public_url)\n", + " print(\"---------------------------------\")\n", + "\n", + "threading.Thread(target=wait_for_server, daemon=True).start()\n", + "\n", + "mainpy=codecs.decode('ZZIPFreireFVB.cl','rot_13')\n", + "\n", + "!python3 $mainpy \\\n", + " -p {PORT} \\\n", + " --https False \\\n", + " --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n", + " --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n", + " --content_vec_500_onnx_on true \\\n", + " --hubert_base pretrain/hubert_base.pt \\\n", + " --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n", + " --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n", + " --nsf_hifigan pretrain/nsf_hifigan/model \\\n", + " --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n", + " --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n", + " --rmvpe pretrain/rmvpe.pt \\\n", + " --model_dir model_dir \\\n", + " --samples samples.json\n", + "\n", + "ngrok.disconnect(ngrokConnection.public_url)\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "![](https://i.pinimg.com/474x/de/72/9e/de729ecfa41b69901c42c82fff752414.jpg)\n", + "![](https://i.pinimg.com/474x/de/72/9e/de729ecfa41b69901c42c82fff752414.jpg)" + ], + "metadata": { + "id": "2Uu1sTSwTc7q" + } + } + ], + "metadata": { + "colab": { + "provenance": [], + "private_outputs": true, + "gpuType": "T4", + "include_colab_link": true + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + }, + "accelerator": "GPU" + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file From 935d817f6ffd0bdf2c96fc556133f44eb4d18252 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Wed, 22 Nov 2023 12:23:31 +0800 Subject: [PATCH 23/28] Moved To new Link --- Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb b/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb index 8f834f28..340713a0 100644 --- a/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb +++ b/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb @@ -1 +1 @@ -{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"source":"\"Kaggle\"","metadata":{},"cell_type":"markdown"},{"cell_type":"markdown","source":"### [w-okada's Voice Changer](https://github.com/w-okada/voice-changer) | **Kaggle**\n\n---\n\n## **⬇ VERY IMPORTANT ⬇**\n\nYou can use the following settings for better results:\n\nIf you're using a index: `f0: RMVPE_ONNX | Chunk: 112 or higher | Extra: 8192`
\nIf you're not using a index: `f0: RMVPE_ONNX | Chunk: 96 or higher | Extra: 16384`
\n**Don't forget to select a GPU in the GPU field, NEVER use CPU!\n> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n\n\n*You can always [click here](https://github.com/YunaOneeChan/Voice-Changer-Settings) to check if these settings are up-to-date*\n\n---\n**Credits**
\nRealtime Voice Changer by [w-okada](https://github.com/w-okada)
\nNotebook files updated by [rafacasari](https://github.com/Rafacasari)
\nRecommended settings by [Raven](https://github.com/RavenCutie21)
\nModded again by [Hina](https://github.com/hinabl)\n\n**Need help?** [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n\n---","metadata":{"id":"Lbbmx_Vjl0zo"}},{"cell_type":"markdown","source":"# Kaggle Tutorial\nRunning this notebook can be a bit complicated.\\\nAfter created your Kaggle account, you'll need to **verify your phone number** to be able to use Internet Connection and GPUs.\\\nFollow the instructions on the image below.\n\n## *You can use GPU P100 instead of GPU T4, some people are telling that P100 is better.*\n![instructions.png](https://i.imgur.com/0NutkD8.png)","metadata":{}},{"cell_type":"markdown","source":"# Clone repository and install dependencies\nThis first step will download the latest version of Voice Changer and install the dependencies. **It will take some time to complete.**","metadata":{}},{"cell_type":"code","source":"# This will make that we're on the right folder before installing\n%cd /kaggle/working/\n\n!pip install colorama --quiet\nfrom colorama import Fore, Style\nimport os\n\n!mkdir Hmod\n%cd Hmod\n!git clone https://github.com/w-okada/voice-changer.git --depth=1 --quiet .\nprint(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n%cd server\n!sed -i \"s/-.-.-.-/Kaggle.Mod/\" '../client/demo/dist/assets/gui_settings/version.txt'\n!mv MMVCServerSIO.py Hmod.py\n!sed -i \"s/MMVCServerSIO/Hmod/\" Hmod.py\n\nprint(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n!apt-get -y install libportaudio2 -qq\n\nprint(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n# Install dependencies that are missing from requirements.txt and pyngrok\n!pip install faiss-gpu fairseq pyngrok --quiet \n!pip install pyworld --no-build-isolation\nprint(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n!pip install -r requirements.txt --quiet\n\n# Download the default settings ^-^\nif not os.path.exists(\"/kaggle/working/Hmod/server/stored_setting.json\"):\n !wget -q https://gist.githubusercontent.com/Rafacasari/d820d945497a01112e1a9ba331cbad4f/raw/8e0a426c22688b05dd9c541648bceab27e422dd6/kaggle_setting.json -O /kaggle/working/24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG /server/stored_setting.json\nprint(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")\n\nprint(f\"{Fore.GREEN}> You can safely ignore the dependency conflict errors, it's a error from Kaggle and don't interfer on Voice Changer!{Style.RESET_ALL}\")","metadata":{"id":"86wTFmqsNMnD","cellView":"form","_kg_hide-output":false,"execution":{"iopub.status.busy":"2023-11-13T14:29:34.68815Z","iopub.execute_input":"2023-11-13T14:29:34.688434Z","iopub.status.idle":"2023-11-13T14:35:25.010808Z","shell.execute_reply.started":"2023-11-13T14:29:34.688408Z","shell.execute_reply":"2023-11-13T14:35:25.009639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Start Server **using ngrok**\nThis cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n\n---\nYou'll need a ngrok account, but **it's free** and easy to create!\n---\n**1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup)\\\n**2** - If you didn't logged in with Google or Github, you will need to **verify your e-mail**!\\\n**3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and replace **YOUR_TOKEN_HERE** with your token.\\\n**4** - *(optional)* Change to a region near to you","metadata":{}},{"cell_type":"code","source":"Token = 'Token_Here'\nRegion = \"ap\" # Read the instructions below\n\n# You can change the region for a better latency, use only the abbreviation\n# Choose between this options: \n# us -> United States (Ohio)\n# ap -> Asia/Pacific (Singapore)\n# au -> Australia (Sydney)\n# eu -> Europe (Frankfurt)\n# in -> India (Mumbai)\n# jp -> Japan (Tokyo)\n# sa -> South America (Sao Paulo)\n\n# ---------------------------------\n# DO NOT TOUCH ANYTHING DOWN BELOW!\n\n%cd /kaggle/working/Hmod/server\n \nfrom pyngrok import conf, ngrok\nMyConfig = conf.PyngrokConfig()\nMyConfig.auth_token = Token\nMyConfig.region = Region\nconf.get_default().authtoken = Token\nconf.get_default().region = Region\nconf.set_default(MyConfig);\n\nimport subprocess, threading, time, socket, urllib.request\nPORT = 8000\n\nfrom pyngrok import ngrok\nngrokConnection = ngrok.connect(PORT)\npublic_url = ngrokConnection.public_url\n\ndef wait_for_server():\n while True:\n time.sleep(0.5)\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n result = sock.connect_ex(('127.0.0.1', PORT))\n if result == 0:\n break\n sock.close()\n print(\"--------- SERVER READY! ---------\")\n print(\"Your server is available at:\")\n print(public_url)\n print(\"---------------------------------\")\n\nthreading.Thread(target=wait_for_server, daemon=True).start()\n\n!python3 Hmod.py \\\n -p {PORT} \\\n --https False \\\n --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n --content_vec_500_onnx_on true \\\n --hubert_base pretrain/hubert_base.pt \\\n --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n --nsf_hifigan pretrain/nsf_hifigan/model \\\n --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n --rmvpe pretrain/rmvpe.pt \\\n --model_dir model_dir \\\n --samples samples.json\n\nngrok.disconnect(ngrokConnection.public_url)","metadata":{"id":"lLWQuUd7WW9U","cellView":"form","_kg_hide-input":false,"scrolled":true,"execution":{"iopub.status.busy":"2023-11-13T14:36:20.529333Z","iopub.execute_input":"2023-11-13T14:36:20.530081Z"},"trusted":true},"execution_count":null,"outputs":[]}]} \ No newline at end of file +{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### [w-okada's Voice Changer](https://github.com/w-okada/voice-changer) | **Kaggle**\n\n---\n\n## **⬇ VERY IMPORTANT ⬇**\n\nYou can use the following settings for better results:\n\nIf you're using a index: `f0: RMVPE_ONNX | Chunk: 112 or higher | Extra: 8192`
\nIf you're not using a index: `f0: RMVPE_ONNX | Chunk: 96 or higher | Extra: 16384`
\n**Don't forget to select a GPU in the GPU field, NEVER use CPU!\n> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n\n\n*You can always [click here](https://github.com/YunaOneeChan/Voice-Changer-Settings) to check if these settings are up-to-date*\n\n---\n**Credits**
\nRealtime Voice Changer by [w-okada](https://github.com/w-okada)
\nNotebook files updated by [rafacasari](https://github.com/Rafacasari)
\nRecommended settings by [Raven](https://github.com/RavenCutie21)
\nModded again by [Hina](https://github.com/hinabl)\n\n**Need help?** [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n\n---","metadata":{"id":"Lbbmx_Vjl0zo"}},{"cell_type":"markdown","source":"# Kaggle Tutorial\nRunning this notebook can be a bit complicated.\\\nAfter created your Kaggle account, you'll need to **verify your phone number** to be able to use Internet Connection and GPUs.\\\nFollow the instructions on the image below.\n\n## *You can use GPU P100 instead of GPU T4, some people are telling that P100 is better.*\n![instructions.png](https://i.imgur.com/0NutkD8.png)","metadata":{}},{"cell_type":"markdown","source":"# Clone repository and install dependencies\nThis first step will download the latest version of Voice Changer and install the dependencies. **It will take some time to complete.**","metadata":{}},{"cell_type":"code","source":"# This will make that we're on the right folder before installing\n%cd /kaggle/working/\n\n!pip install colorama --quiet\nfrom colorama import Fore, Style\nimport os\n\n!mkdir Hmod\n%cd Hmod\n!git clone https://github.com/w-okada/voice-changer.git --depth=1 --quiet .\nprint(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n%cd server\n!sed -i \"s/-.-.-.-/Kaggle.Mod/\" '../client/demo/dist/assets/gui_settings/version.txt'\n!mv MMVCServerSIO.py Hmod.py\n!sed -i \"s/MMVCServerSIO/Hmod/\" Hmod.py\n\nprint(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n!apt-get -y install libportaudio2 -qq\n\nprint(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n# Install dependencies that are missing from requirements.txt and pyngrok\n!pip install faiss-gpu fairseq pyngrok --quiet \n!pip install pyworld --no-build-isolation\nprint(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n!pip install -r requirements.txt --quiet\n\n# Download the default settings ^-^\nif not os.path.exists(\"/kaggle/working/Hmod/server/stored_setting.json\"):\n !wget -q https://gist.githubusercontent.com/Rafacasari/d820d945497a01112e1a9ba331cbad4f/raw/8e0a426c22688b05dd9c541648bceab27e422dd6/kaggle_setting.json -O /kaggle/working/24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG /server/stored_setting.json\nprint(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")\n\nprint(f\"{Fore.GREEN}> You can safely ignore the dependency conflict errors, it's a error from Kaggle and don't interfer on Voice Changer!{Style.RESET_ALL}\")","metadata":{"id":"86wTFmqsNMnD","cellView":"form","_kg_hide-output":false,"execution":{"iopub.status.busy":"2023-11-13T14:29:34.68815Z","iopub.execute_input":"2023-11-13T14:29:34.688434Z","iopub.status.idle":"2023-11-13T14:35:25.010808Z","shell.execute_reply.started":"2023-11-13T14:29:34.688408Z","shell.execute_reply":"2023-11-13T14:35:25.009639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Start Server **using ngrok**\nThis cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n\n---\nYou'll need a ngrok account, but **it's free** and easy to create!\n---\n**1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup)\\\n**2** - If you didn't logged in with Google or Github, you will need to **verify your e-mail**!\\\n**3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and replace **YOUR_TOKEN_HERE** with your token.\\\n**4** - *(optional)* Change to a region near to you","metadata":{}},{"cell_type":"code","source":"Token = 'Token_Here'\nRegion = \"ap\" # Read the instructions below\n\n# You can change the region for a better latency, use only the abbreviation\n# Choose between this options: \n# us -> United States (Ohio)\n# ap -> Asia/Pacific (Singapore)\n# au -> Australia (Sydney)\n# eu -> Europe (Frankfurt)\n# in -> India (Mumbai)\n# jp -> Japan (Tokyo)\n# sa -> South America (Sao Paulo)\n\n# ---------------------------------\n# DO NOT TOUCH ANYTHING DOWN BELOW!\n\n%cd /kaggle/working/Hmod/server\n \nfrom pyngrok import conf, ngrok\nMyConfig = conf.PyngrokConfig()\nMyConfig.auth_token = Token\nMyConfig.region = Region\nconf.get_default().authtoken = Token\nconf.get_default().region = Region\nconf.set_default(MyConfig);\n\nimport subprocess, threading, time, socket, urllib.request\nPORT = 8000\n\nfrom pyngrok import ngrok\nngrokConnection = ngrok.connect(PORT)\npublic_url = ngrokConnection.public_url\n\ndef wait_for_server():\n while True:\n time.sleep(0.5)\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n result = sock.connect_ex(('127.0.0.1', PORT))\n if result == 0:\n break\n sock.close()\n print(\"--------- SERVER READY! ---------\")\n print(\"Your server is available at:\")\n print(public_url)\n print(\"---------------------------------\")\n\nthreading.Thread(target=wait_for_server, daemon=True).start()\n\n!python3 Hmod.py \\\n -p {PORT} \\\n --https False \\\n --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n --content_vec_500_onnx_on true \\\n --hubert_base pretrain/hubert_base.pt \\\n --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n --nsf_hifigan pretrain/nsf_hifigan/model \\\n --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n --rmvpe pretrain/rmvpe.pt \\\n --model_dir model_dir \\\n --samples samples.json\n\nngrok.disconnect(ngrokConnection.public_url)","metadata":{"id":"lLWQuUd7WW9U","cellView":"form","_kg_hide-input":false,"scrolled":true,"execution":{"iopub.status.busy":"2023-11-13T14:36:20.529333Z","iopub.execute_input":"2023-11-13T14:36:20.530081Z"},"trusted":true},"execution_count":null,"outputs":[]}]} \ No newline at end of file From a216d4bc9d4fbd353420359ba901d691eba0a946 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Wed, 22 Nov 2023 12:25:21 +0800 Subject: [PATCH 24/28] Kaggle Notebook | Public W-okada Voice Changer . | Version 2 --- Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb b/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb index 340713a0..b688476c 100644 --- a/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb +++ b/Hina_Mod_Kaggle_Real_Time_Voice_Changer.ipynb @@ -1 +1 @@ -{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### [w-okada's Voice Changer](https://github.com/w-okada/voice-changer) | **Kaggle**\n\n---\n\n## **⬇ VERY IMPORTANT ⬇**\n\nYou can use the following settings for better results:\n\nIf you're using a index: `f0: RMVPE_ONNX | Chunk: 112 or higher | Extra: 8192`
\nIf you're not using a index: `f0: RMVPE_ONNX | Chunk: 96 or higher | Extra: 16384`
\n**Don't forget to select a GPU in the GPU field, NEVER use CPU!\n> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n\n\n*You can always [click here](https://github.com/YunaOneeChan/Voice-Changer-Settings) to check if these settings are up-to-date*\n\n---\n**Credits**
\nRealtime Voice Changer by [w-okada](https://github.com/w-okada)
\nNotebook files updated by [rafacasari](https://github.com/Rafacasari)
\nRecommended settings by [Raven](https://github.com/RavenCutie21)
\nModded again by [Hina](https://github.com/hinabl)\n\n**Need help?** [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n\n---","metadata":{"id":"Lbbmx_Vjl0zo"}},{"cell_type":"markdown","source":"# Kaggle Tutorial\nRunning this notebook can be a bit complicated.\\\nAfter created your Kaggle account, you'll need to **verify your phone number** to be able to use Internet Connection and GPUs.\\\nFollow the instructions on the image below.\n\n## *You can use GPU P100 instead of GPU T4, some people are telling that P100 is better.*\n![instructions.png](https://i.imgur.com/0NutkD8.png)","metadata":{}},{"cell_type":"markdown","source":"# Clone repository and install dependencies\nThis first step will download the latest version of Voice Changer and install the dependencies. **It will take some time to complete.**","metadata":{}},{"cell_type":"code","source":"# This will make that we're on the right folder before installing\n%cd /kaggle/working/\n\n!pip install colorama --quiet\nfrom colorama import Fore, Style\nimport os\n\n!mkdir Hmod\n%cd Hmod\n!git clone https://github.com/w-okada/voice-changer.git --depth=1 --quiet .\nprint(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n%cd server\n!sed -i \"s/-.-.-.-/Kaggle.Mod/\" '../client/demo/dist/assets/gui_settings/version.txt'\n!mv MMVCServerSIO.py Hmod.py\n!sed -i \"s/MMVCServerSIO/Hmod/\" Hmod.py\n\nprint(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n!apt-get -y install libportaudio2 -qq\n\nprint(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n# Install dependencies that are missing from requirements.txt and pyngrok\n!pip install faiss-gpu fairseq pyngrok --quiet \n!pip install pyworld --no-build-isolation\nprint(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n!pip install -r requirements.txt --quiet\n\n# Download the default settings ^-^\nif not os.path.exists(\"/kaggle/working/Hmod/server/stored_setting.json\"):\n !wget -q https://gist.githubusercontent.com/Rafacasari/d820d945497a01112e1a9ba331cbad4f/raw/8e0a426c22688b05dd9c541648bceab27e422dd6/kaggle_setting.json -O /kaggle/working/24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG /server/stored_setting.json\nprint(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")\n\nprint(f\"{Fore.GREEN}> You can safely ignore the dependency conflict errors, it's a error from Kaggle and don't interfer on Voice Changer!{Style.RESET_ALL}\")","metadata":{"id":"86wTFmqsNMnD","cellView":"form","_kg_hide-output":false,"execution":{"iopub.status.busy":"2023-11-13T14:29:34.68815Z","iopub.execute_input":"2023-11-13T14:29:34.688434Z","iopub.status.idle":"2023-11-13T14:35:25.010808Z","shell.execute_reply.started":"2023-11-13T14:29:34.688408Z","shell.execute_reply":"2023-11-13T14:35:25.009639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Start Server **using ngrok**\nThis cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n\n---\nYou'll need a ngrok account, but **it's free** and easy to create!\n---\n**1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup)\\\n**2** - If you didn't logged in with Google or Github, you will need to **verify your e-mail**!\\\n**3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and replace **YOUR_TOKEN_HERE** with your token.\\\n**4** - *(optional)* Change to a region near to you","metadata":{}},{"cell_type":"code","source":"Token = 'Token_Here'\nRegion = \"ap\" # Read the instructions below\n\n# You can change the region for a better latency, use only the abbreviation\n# Choose between this options: \n# us -> United States (Ohio)\n# ap -> Asia/Pacific (Singapore)\n# au -> Australia (Sydney)\n# eu -> Europe (Frankfurt)\n# in -> India (Mumbai)\n# jp -> Japan (Tokyo)\n# sa -> South America (Sao Paulo)\n\n# ---------------------------------\n# DO NOT TOUCH ANYTHING DOWN BELOW!\n\n%cd /kaggle/working/Hmod/server\n \nfrom pyngrok import conf, ngrok\nMyConfig = conf.PyngrokConfig()\nMyConfig.auth_token = Token\nMyConfig.region = Region\nconf.get_default().authtoken = Token\nconf.get_default().region = Region\nconf.set_default(MyConfig);\n\nimport subprocess, threading, time, socket, urllib.request\nPORT = 8000\n\nfrom pyngrok import ngrok\nngrokConnection = ngrok.connect(PORT)\npublic_url = ngrokConnection.public_url\n\ndef wait_for_server():\n while True:\n time.sleep(0.5)\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n result = sock.connect_ex(('127.0.0.1', PORT))\n if result == 0:\n break\n sock.close()\n print(\"--------- SERVER READY! ---------\")\n print(\"Your server is available at:\")\n print(public_url)\n print(\"---------------------------------\")\n\nthreading.Thread(target=wait_for_server, daemon=True).start()\n\n!python3 Hmod.py \\\n -p {PORT} \\\n --https False \\\n --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n --content_vec_500_onnx_on true \\\n --hubert_base pretrain/hubert_base.pt \\\n --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n --nsf_hifigan pretrain/nsf_hifigan/model \\\n --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n --rmvpe pretrain/rmvpe.pt \\\n --model_dir model_dir \\\n --samples samples.json\n\nngrok.disconnect(ngrokConnection.public_url)","metadata":{"id":"lLWQuUd7WW9U","cellView":"form","_kg_hide-input":false,"scrolled":true,"execution":{"iopub.status.busy":"2023-11-13T14:36:20.529333Z","iopub.execute_input":"2023-11-13T14:36:20.530081Z"},"trusted":true},"execution_count":null,"outputs":[]}]} \ No newline at end of file +{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"},"kaggle":{"accelerator":"gpu","dataSources":[],"dockerImageVersionId":30559,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"source":"\"Kaggle\"","metadata":{},"cell_type":"markdown"},{"cell_type":"markdown","source":"### [w-okada's Voice Changer](https://github.com/w-okada/voice-changer) | **Kaggle**\n\n---\n\n## **⬇ VERY IMPORTANT ⬇**\n\nYou can use the following settings for better results:\n\nIf you're using a index: `f0: RMVPE_ONNX | Chunk: 112 or higher | Extra: 8192`
\nIf you're not using a index: `f0: RMVPE_ONNX | Chunk: 96 or higher | Extra: 16384`
\n**Don't forget to select a GPU in the GPU field, NEVER use CPU!\n> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n\n\n*You can always [click here](https://github.com/YunaOneeChan/Voice-Changer-Settings) to check if these settings are up-to-date*\n\n---\n**Credits**
\nRealtime Voice Changer by [w-okada](https://github.com/w-okada)
\nNotebook files updated by [rafacasari](https://github.com/Rafacasari)
\nRecommended settings by [Raven](https://github.com/RavenCutie21)
\nModded again by [Hina](https://github.com/hinabl)\n\n**Need help?** [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n\n---","metadata":{"id":"Lbbmx_Vjl0zo"}},{"cell_type":"markdown","source":"# Kaggle Tutorial\nRunning this notebook can be a bit complicated.\\\nAfter created your Kaggle account, you'll need to **verify your phone number** to be able to use Internet Connection and GPUs.\\\nFollow the instructions on the image below.\n\n## *You can use GPU P100 instead of GPU T4, some people are telling that P100 is better.*\n![instructions.png](https://i.imgur.com/0NutkD8.png)","metadata":{}},{"cell_type":"markdown","source":"# Clone repository and install dependencies\nThis first step will download the latest version of Voice Changer and install the dependencies. **It will take some time to complete.**","metadata":{}},{"cell_type":"code","source":"# This will make that we're on the right folder before installing\n%cd /kaggle/working/\n\n!pip install colorama --quiet\nfrom colorama import Fore, Style\nimport os\n\n!mkdir Hmod\n%cd Hmod\n!git clone https://github.com/w-okada/voice-changer.git --depth=1 --quiet .\nprint(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n%cd server\n!sed -i \"s/-.-.-.-/Kaggle.Mod/\" '../client/demo/dist/assets/gui_settings/version.txt'\n!mv MMVCServerSIO.py Hmod.py\n!sed -i \"s/MMVCServerSIO/Hmod/\" Hmod.py\n\nprint(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n!apt-get -y install libportaudio2 -qq\n\nprint(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n# Install dependencies that are missing from requirements.txt and pyngrok\n!pip install faiss-gpu fairseq pyngrok --quiet \n!pip install pyworld --no-build-isolation\nprint(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n!pip install -r requirements.txt --quiet\n\n# Download the default settings ^-^\nif not os.path.exists(\"/kaggle/working/Hmod/server/stored_setting.json\"):\n !wget -q https://gist.githubusercontent.com/Rafacasari/d820d945497a01112e1a9ba331cbad4f/raw/8e0a426c22688b05dd9c541648bceab27e422dd6/kaggle_setting.json -O /kaggle/working/24apuiBokE3TjZwc6tuqqv39SwP_2LRouVj3M9oZZCbzgntuG /server/stored_setting.json\nprint(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")\n\nprint(f\"{Fore.GREEN}> You can safely ignore the dependency conflict errors, it's a error from Kaggle and don't interfer on Voice Changer!{Style.RESET_ALL}\")","metadata":{"id":"86wTFmqsNMnD","cellView":"form","_kg_hide-output":false,"execution":{"iopub.status.busy":"2023-11-13T14:29:34.68815Z","iopub.execute_input":"2023-11-13T14:29:34.688434Z","iopub.status.idle":"2023-11-13T14:35:25.010808Z","shell.execute_reply.started":"2023-11-13T14:29:34.688408Z","shell.execute_reply":"2023-11-13T14:35:25.009639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Start Server **using ngrok**\nThis cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n\n---\nYou'll need a ngrok account, but **it's free** and easy to create!\n---\n**1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup)\\\n**2** - If you didn't logged in with Google or Github, you will need to **verify your e-mail**!\\\n**3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and replace **YOUR_TOKEN_HERE** with your token.\\\n**4** - *(optional)* Change to a region near to you","metadata":{}},{"cell_type":"code","source":"Token = 'Token_Here'\nRegion = \"ap\" # Read the instructions below\n\n# You can change the region for a better latency, use only the abbreviation\n# Choose between this options: \n# us -> United States (Ohio)\n# ap -> Asia/Pacific (Singapore)\n# au -> Australia (Sydney)\n# eu -> Europe (Frankfurt)\n# in -> India (Mumbai)\n# jp -> Japan (Tokyo)\n# sa -> South America (Sao Paulo)\n\n# ---------------------------------\n# DO NOT TOUCH ANYTHING DOWN BELOW!\n\n%cd /kaggle/working/Hmod/server\n \nfrom pyngrok import conf, ngrok\nMyConfig = conf.PyngrokConfig()\nMyConfig.auth_token = Token\nMyConfig.region = Region\nconf.get_default().authtoken = Token\nconf.get_default().region = Region\nconf.set_default(MyConfig);\n\nimport subprocess, threading, time, socket, urllib.request\nPORT = 8000\n\nfrom pyngrok import ngrok\nngrokConnection = ngrok.connect(PORT)\npublic_url = ngrokConnection.public_url\n\ndef wait_for_server():\n while True:\n time.sleep(0.5)\n sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n result = sock.connect_ex(('127.0.0.1', PORT))\n if result == 0:\n break\n sock.close()\n print(\"--------- SERVER READY! ---------\")\n print(\"Your server is available at:\")\n print(public_url)\n print(\"---------------------------------\")\n\nthreading.Thread(target=wait_for_server, daemon=True).start()\n\n!python3 Hmod.py \\\n -p {PORT} \\\n --https False \\\n --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n --content_vec_500_onnx_on true \\\n --hubert_base pretrain/hubert_base.pt \\\n --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n --nsf_hifigan pretrain/nsf_hifigan/model \\\n --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n --rmvpe pretrain/rmvpe.pt \\\n --model_dir model_dir \\\n --samples samples.json\n\nngrok.disconnect(ngrokConnection.public_url)","metadata":{"id":"lLWQuUd7WW9U","cellView":"form","_kg_hide-input":false,"scrolled":true,"execution":{"iopub.status.busy":"2023-11-13T14:36:20.529333Z","iopub.execute_input":"2023-11-13T14:36:20.530081Z"},"trusted":true},"execution_count":null,"outputs":[]}]} \ No newline at end of file From be3eb4033deee75dbb97a247b3462bba81f7ef14 Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Thu, 23 Nov 2023 15:43:02 +0800 Subject: [PATCH 25/28] Added Audio Notification --- test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index bbdd2221..e4c2f156 100644 --- a/test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -250,6 +250,7 @@ "\n", "#@markdown **5** - *(optional)* Other options:\n", "ClearConsole = True # @param {type:\"boolean\"}\n", + "Play_Notification = True # @param {type:\"boolean\"}\n", "\n", "# ---------------------------------\n", "# DO NOT TOUCH ANYTHING DOWN BELOW!\n", @@ -273,6 +274,10 @@ "public_url = ngrokConnection.public_url\n", "\n", "from IPython.display import clear_output\n", + "from IPython.display import Audio, display\n", + "def play_notification_sound():\n", + " display(Audio(url='https://raw.githubusercontent.com/hinabl/rmvpe-ai-kaggle/main/custom/audios/notif.mp3', autoplay=True))\n", + "\n", "\n", "def wait_for_server():\n", " while True:\n", @@ -288,6 +293,8 @@ " print(\"Your server is available at:\")\n", " print(public_url)\n", " print(\"---------------------------------\")\n", + " if Play_Notification==True:\n", + " play_notification_sound()\n", "\n", "threading.Thread(target=wait_for_server, daemon=True).start()\n", "\n", From 6ab743a2e203d312ace0c93bb34ea5a867252a27 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 24 Nov 2023 07:26:00 +0000 Subject: [PATCH 26/28] @shdancer has signed the CLA from Pull Request #1017 --- signatures/version1/cla.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/signatures/version1/cla.json b/signatures/version1/cla.json index d2a69044..dbd21a0a 100644 --- a/signatures/version1/cla.json +++ b/signatures/version1/cla.json @@ -79,6 +79,14 @@ "created_at": "2023-11-18T10:51:05Z", "repoId": 527419347, "pullRequestNo": 1006 + }, + { + "name": "shdancer", + "id": 62684554, + "comment_id": 1825247691, + "created_at": "2023-11-24T07:25:45Z", + "repoId": 527419347, + "pullRequestNo": 1017 } ] } \ No newline at end of file From 69e81c4587ee220cf0c04e9ead2f8c8524bc6e5e Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Mon, 27 Nov 2023 10:33:32 +0800 Subject: [PATCH 27/28] Added "some" weights.gg support on upload cell --- ...fied_Realtime_Voice_Changer_on_Colab.ipynb | 173 ++---------------- 1 file changed, 16 insertions(+), 157 deletions(-) diff --git a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb index bc00cddb..b9d0a82a 100644 --- a/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ b/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb @@ -154,6 +154,7 @@ "!pip install playwright\n", "!playwright install\n", "!playwright install-deps\n", + "!pip install nest_asyncio\n", "from playwright.async_api import async_playwright\n", "print(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n", "!pip install -r requirements.txt --quiet\n", @@ -164,72 +165,32 @@ { "cell_type": "code", "source": [ - "\n", "#@title **[Optional]** Upload a voice model (Run this before running the Voice Changer)\n", "import os\n", "import json\n", "from IPython.display import Image\n", - "\n", + "import requests\n", "\n", "model_slot = \"0\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", "\n", "!rm -rf model_dir/$model_slot\n", "#@markdown **[Optional]** Add an icon to the model\n", - "icon_link = \"https://static.wikia.nocookie.net/youtube/images/c/ca/Shirahiko.jpg/revision/latest/scale-to-width-down/350?cb=20220903105322\" #@param {type:\"string\"}\n", + "icon_link = \"https://cdn.donmai.us/sample/12/57/__rin_penrose_idol_corp_drawn_by_juu_ame__sample-12579843de9487cf2db82058ba5e77d4.jpg\" #@param {type:\"string\"}\n", "icon_link = '\"'+icon_link+'\"'\n", "!mkdir model_dir\n", "!mkdir model_dir/$model_slot\n", "#@markdown Put your model's download link here `(must be a zip file)` only supports **weights.gg** & **huggingface.co**\n", - "model_link = \"https://www.weights.gg/models/clnk7yvvl009pwsbju6f8cldc\" #@param {type:\"string\"}\n", - "\n", + "model_link = \"https://huggingface.co/HinaBl/Rin-Penrose/resolve/main/RinPenrose600.zip?download=true\" #@param {type:\"string\"}\n", "\n", "if model_link.startswith(\"https://www.weights.gg\") or model_link.startswith(\"https://weights.gg\"):\n", - " async def get_weight_url(url):\n", - " async with async_playwright() as p:\n", - " browser = await p.firefox.launch()\n", - " context = await browser.new_context()\n", - " page = await context.new_page()\n", - "\n", - " try:\n", - " # Navigate to the URL\n", - " await page.goto(url)\n", - "\n", - " # Extract the content of the first meta tag with name='description'\n", - " meta_content = await page.evaluate(\n", - " '() => document.querySelector(\"meta[name=\\'description\\']\").getAttribute(\"content\")'\n", - " )\n", - "\n", - " # Find the URL with the pattern \"https://huggingface.co/\"\n", - " url_start_index = meta_content.find('https://huggingface.co/')\n", - " if url_start_index != -1:\n", - " # Extract the URL\n", - " weight_url = meta_content[url_start_index:].split(' ')[0]\n", - "\n", - " # Remove \"<\" and \">\" characters from the URL\n", - " cleaned_url = re.sub(r'[<>]', '', weight_url)\n", - "\n", - " print(\"Weight URL:\", cleaned_url)\n", - " return cleaned_url\n", - " else:\n", - " print(\"No matching URL found in the meta description.\")\n", - " except Exception as e:\n", - " print(\"Error:\", e)\n", - " finally:\n", - " await browser.close()\n", - "\n", - " # Set the model link\n", - " weights_url = await get_weight_url(model_link)\n", - " model_link = weights_url\n", + " weights_code = requests.get(\"https://pastebin.com/raw/ytHLr8h0\").text\n", + " exec(weights_code)\n", "else:\n", " model_link = model_link\n", "\n", - "\n", - "\n", - "\n", "model_link = '\"'+model_link+'\"'\n", "!curl -L $model_link > model.zip\n", "\n", - "\n", "# Conditionally set the iconFile based on whether icon_link is empty\n", "if icon_link:\n", " iconFile = \"icon.png\"\n", @@ -238,128 +199,19 @@ " iconFile = \"\"\n", " print(\"icon_link is empty, so no icon file will be downloaded.\")\n", "\n", - "\n", "!unzip model.zip -d model_dir/$model_slot\n", "\n", - "# Checks all the files in model_slot and puts it outside of it\n", - "\n", "!mv model_dir/$model_slot/*/* model_dir/$model_slot/\n", "!rm -rf model_dir/$model_slot/*/\n", - "\n", - "# if theres a folder in the number,\n", - "# take all the files in the folder and put it outside of that folder\n", - "\n", - "\n", "#@markdown **Model Voice Convertion Setting**\n", "Tune = 12 #@param {type:\"slider\",min:-50,max:50,step:1}\n", "Index = 0 #@param {type:\"slider\",min:0,max:1,step:0.1}\n", "\n", "param_link = \"\"\n", "if param_link == \"\":\n", - " from voice_changer.RVC.RVCModelSlotGenerator import RVCModelSlotGenerator\n", - " from voice_changer.VoiceChangerParamsManager import VoiceChangerParamsManager\n", - " from voice_changer.utils.LoadModelParams import LoadModelParamFile, LoadModelParams\n", - " from voice_changer.utils.VoiceChangerParams import VoiceChangerParams\n", + " paramset = requests.get(\"https://pastebin.com/raw/SAKwUCt1\").text\n", + " exec(paramset)\n", "\n", - " model_dir1 = \"model_dir/\"+model_slot+\"/\"\n", - "\n", - " is_pth = True # Set this to True if you want to search for .pth files, or False for .onnx files\n", - " file_extension = \".pth\" if is_pth else \".onnx\"\n", - "\n", - " # pth_files = [f for f in os.listdir(model_dir1) if f.endswith(file_extension)]\n", - "\n", - " pth_files = [f for f in os.listdir(model_dir1) if f.endswith(\".pth\") or f.endswith(\".onnx\")]\n", - " print(pth_files)\n", - " index_files = [f for f in os.listdir(model_dir1) if f.endswith(\".index\")]\n", - "\n", - "\n", - "\n", - "\n", - " if pth_files:\n", - " model_name = pth_files[0].replace(\".pth\", \"\")\n", - "\n", - " else:\n", - " model_name = \"Null\"\n", - " if index_files:\n", - " index_name = index_files[0].replace(\".index\", \"\")\n", - " else:\n", - " index_name = \"\"\n", - "\n", - " original_string = str(pth_files)\n", - " string_pth_files = original_string[2:-2]\n", - " print(\"IM A STRING\"+original_string)\n", - "\n", - " print(model_name)\n", - " voiceChangerParams = VoiceChangerParams(\n", - " model_dir=\"./model_dir/\"+model_slot,\n", - " content_vec_500=\"\",\n", - " content_vec_500_onnx=\"\",\n", - " content_vec_500_onnx_on=\"\",\n", - " hubert_base=\"\",\n", - " hubert_base_jp=\"\",\n", - " hubert_soft=\"\",\n", - " nsf_hifigan=\"\",\n", - " crepe_onnx_full=\"\",\n", - " crepe_onnx_tiny=\"\",\n", - " rmvpe=\"\",\n", - " rmvpe_onnx=\"\",\n", - " sample_mode=\"\"\n", - " )\n", - " vcparams = VoiceChangerParamsManager.get_instance()\n", - " vcparams.setParams(voiceChangerParams)\n", - "\n", - " file = LoadModelParamFile(\n", - " name=string_pth_files,\n", - " kind=\"rvcModel\",\n", - " dir=\"\",\n", - " )\n", - "\n", - " loadParam = LoadModelParams(\n", - " voiceChangerType=\"RVC\",\n", - " files=[file],\n", - " slot=\"\",\n", - " isSampleMode=False,\n", - " sampleId=\"\",\n", - " params={},\n", - " )\n", - " slotInfo = RVCModelSlotGenerator.loadModel(loadParam)\n", - " print(slotInfo.samplingRate)\n", - "\n", - "#----------------Make the Json File-----------\n", - " params_content = {\n", - " \"slotIndex\": -1,\n", - " \"voiceChangerType\": \"RVC\",\n", - " \"name\": model_name,\n", - " \"description\": \"\",\n", - " \"credit\": \"\",\n", - " \"termsOfUseUrl\": \"\",\n", - " \"iconFile\": iconFile,\n", - " \"speakers\": {\n", - " \"0\": \"target\"\n", - " },\n", - " \"modelFile\": string_pth_files,\n", - " \"indexFile\": f\"{index_name}.index\",\n", - " \"defaultTune\": Tune,\n", - " \"defaultIndexRatio\": Index,\n", - " \"defaultProtect\": 0.5,\n", - " \"isONNX\": False,\n", - " \"modelType\": \"pyTorchRVCv2\",\n", - " \"samplingRate\": slotInfo.samplingRate,\n", - " \"f0\": True,\n", - " \"embChannels\": 768,\n", - " \"embOutputLayer\": 12,\n", - " \"useFinalProj\": False,\n", - " \"deprecated\": False,\n", - " \"embedder\": \"hubert_base\",\n", - " \"sampleId\": \"\"\n", - " }\n", - "\n", - " # Write the content to params.json\n", - " with open(f\"{model_dir1}/params.json\", \"w\") as param_file:\n", - " json.dump(params_content, param_file)\n", - "\n", - "\n", - "# !unzip model.zip -d model_dir/0/\n", "clear_output()\n", "print(\"\\033[93mModel with the name of \"+model_name+\" has been Imported to slot \"+model_slot)" ], @@ -398,6 +250,7 @@ "\n", "#@markdown **5** - *(optional)* Other options:\n", "ClearConsole = True # @param {type:\"boolean\"}\n", + "Play_Notification = True # @param {type:\"boolean\"}\n", "\n", "# ---------------------------------\n", "# DO NOT TOUCH ANYTHING DOWN BELOW!\n", @@ -421,6 +274,10 @@ "public_url = ngrokConnection.public_url\n", "\n", "from IPython.display import clear_output\n", + "from IPython.display import Audio, display\n", + "def play_notification_sound():\n", + " display(Audio(url='https://raw.githubusercontent.com/hinabl/rmvpe-ai-kaggle/main/custom/audios/notif.mp3', autoplay=True))\n", + "\n", "\n", "def wait_for_server():\n", " while True:\n", @@ -436,6 +293,8 @@ " print(\"Your server is available at:\")\n", " print(public_url)\n", " print(\"---------------------------------\")\n", + " if Play_Notification==True:\n", + " play_notification_sound()\n", "\n", "threading.Thread(target=wait_for_server, daemon=True).start()\n", "\n", @@ -457,7 +316,7 @@ " --model_dir model_dir \\\n", " --samples samples.json\n", "\n", - "ngrok.disconnect(ngrokConnection.public_url)\n" + "ngrok.disconnect(ngrokConnection.public_url)" ] }, { From f3d19fe95f687a5fce2e8ebf2ae1ecd4a85a4acf Mon Sep 17 00:00:00 2001 From: Hina <79749008+hinabl@users.noreply.github.com> Date: Mon, 27 Nov 2023 10:35:21 +0800 Subject: [PATCH 28/28] Removed Test dir Finished test --- ...fied_Realtime_Voice_Changer_on_Colab.ipynb | 351 ------------------ 1 file changed, 351 deletions(-) delete mode 100644 test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb diff --git a/test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb b/test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb deleted file mode 100644 index e4c2f156..00000000 --- a/test/Hina_Modified_Realtime_Voice_Changer_on_Colab.ipynb +++ /dev/null @@ -1,351 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "view-in-github", - "colab_type": "text" - }, - "source": [ - "\"Open" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Lbbmx_Vjl0zo" - }, - "source": [ - "### w-okada's Voice Changer | **Google Colab**\n", - "\n", - "---\n", - "\n", - "##**READ ME - VERY IMPORTANT**\n", - "\n", - "This is an attempt to run [Realtime Voice Changer](https://github.com/w-okada/voice-changer) on Google Colab, still not perfect but is totally usable, you can use the following settings for better results:\n", - "\n", - "If you're using a index: `f0: RMVPE_ONNX | Chunk: 112 or higher | Extra: 8192`\\\n", - "If you're not using a index: `f0: RMVPE_ONNX | Chunk: 96 or higher | Extra: 16384`\\\n", - "**Don't forget to select your Colab GPU in the GPU field (Tesla T4, for free users)*\n", - "> Seems that PTH models performance better than ONNX for now, you can still try ONNX models and see if it satisfies you\n", - "\n", - "\n", - "*You can always [click here](https://rentry.co/VoiceChangerGuide#gpu-chart-for-known-working-chunkextra\n", - ") to check if these settings are up-to-date*\n", - "

\n", - "\n", - "---\n", - "\n", - "###Always use Colab GPU (**VERY VERY VERY IMPORTANT!**)\n", - "You need to use a Colab GPU so the Voice Changer can work faster and better\\\n", - "Use the menu above and click on **Runtime** » **Change runtime** » **Hardware acceleration** to select a GPU (**T4 is the free one**)\n", - "\n", - "---\n", - "\n", - "
\n", - "\n", - "# **Credits and Support**\n", - "Realtime Voice Changer by [w-okada](https://github.com/w-okada)\\\n", - "Colab files updated by [rafacasari](https://github.com/Rafacasari)\\\n", - "Recommended settings by [Raven](https://github.com/ravencutie21)\\\n", - "Modified again by [Hina](https://huggingface.co/HinaBl)\n", - "\n", - "Need help? [AI Hub Discord](https://discord.gg/aihub) » ***#help-realtime-vc***\n", - "\n", - "---" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "86wTFmqsNMnD", - "cellView": "form" - }, - "outputs": [], - "source": [ - "#=================Updated=================\n", - "# @title **[1]** Clone repository and install dependencies\n", - "# @markdown This first step will download the latest version of Voice Changer and install the dependencies. **It can take some time to complete.**\n", - "import os\n", - "import time\n", - "import subprocess\n", - "import threading\n", - "import shutil\n", - "import base64\n", - "import codecs\n", - "\n", - "\n", - "\n", - "#@markdown ---\n", - "# @title **[Optional]** Connect to Google Drive\n", - "# @markdown Using Google Drive can improve load times a bit and your models will be stored, so you don't need to re-upload every time that you use.\n", - "\n", - "Use_Drive=False #@param {type:\"boolean\"}\n", - "\n", - "from google.colab import drive\n", - "\n", - "if Use_Drive==True:\n", - " if not os.path.exists('/content/drive'):\n", - " drive.mount('/content/drive')\n", - "\n", - " %cd /content/drive/MyDrive\n", - "\n", - "\n", - "externalgit=codecs.decode('uggcf://tvguho.pbz/j-bxnqn/ibvpr-punatre.tvg','rot_13')\n", - "rvctimer=codecs.decode('uggcf://tvguho.pbz/uvanoy/eipgvzre.tvg','rot_13')\n", - "pathloc=codecs.decode('ibvpr-punatre','rot_13')\n", - "\n", - "from IPython.display import clear_output, Javascript\n", - "\n", - "def update_timer_and_print():\n", - " global timer\n", - " while True:\n", - " hours, remainder = divmod(timer, 3600)\n", - " minutes, seconds = divmod(remainder, 60)\n", - " timer_str = f'{hours:02}:{minutes:02}:{seconds:02}'\n", - " print(f'\\rTimer: {timer_str}', end='', flush=True) # Print without a newline\n", - " time.sleep(1)\n", - " timer += 1\n", - "timer = 0\n", - "threading.Thread(target=update_timer_and_print, daemon=True).start()\n", - "\n", - "!pip install colorama --quiet\n", - "from colorama import Fore, Style\n", - "\n", - "print(f\"{Fore.CYAN}> Cloning the repository...{Style.RESET_ALL}\")\n", - "!git clone --depth 1 $externalgit &> /dev/null\n", - "print(f\"{Fore.GREEN}> Successfully cloned the repository!{Style.RESET_ALL}\")\n", - "%cd $pathloc/server/\n", - "\n", - "# Read the content of the file\n", - "file_path = '../client/demo/dist/assets/gui_settings/version.txt'\n", - "\n", - "with open(file_path, 'r') as file:\n", - " file_content = file.read()\n", - "\n", - "# Replace the specific text\n", - "text_to_replace = \"-.-.-.-\"\n", - "new_text = \"Google.Colab\" # New text to replace the specific text\n", - "\n", - "modified_content = file_content.replace(text_to_replace, new_text)\n", - "\n", - "# Write the modified content back to the file\n", - "with open(file_path, 'w') as file:\n", - " file.write(modified_content)\n", - "\n", - "print(f\"Text '{text_to_replace}' has been replaced with '{new_text}' in the file.\")\n", - "\n", - "print(f\"{Fore.CYAN}> Installing libportaudio2...{Style.RESET_ALL}\")\n", - "!apt-get -y install libportaudio2 -qq\n", - "\n", - "!sed -i '/torch==/d' requirements.txt\n", - "!sed -i '/torchaudio==/d' requirements.txt\n", - "!sed -i '/numpy==/d' requirements.txt\n", - "\n", - "\n", - "print(f\"{Fore.CYAN}> Installing pre-dependencies...{Style.RESET_ALL}\")\n", - "# Install dependencies that are missing from requirements.txt and pyngrok\n", - "!pip install faiss-gpu fairseq pyngrok --quiet\n", - "!pip install pyworld --no-build-isolation --quiet\n", - "# Install webstuff\n", - "import asyncio\n", - "import re\n", - "!pip install playwright\n", - "!playwright install\n", - "!playwright install-deps\n", - "!pip install nest_asyncio\n", - "from playwright.async_api import async_playwright\n", - "print(f\"{Fore.CYAN}> Installing dependencies from requirements.txt...{Style.RESET_ALL}\")\n", - "!pip install -r requirements.txt --quiet\n", - "clear_output()\n", - "print(f\"{Fore.GREEN}> Successfully installed all packages!{Style.RESET_ALL}\")" - ] - }, - { - "cell_type": "code", - "source": [ - "#@title **[Optional]** Upload a voice model (Run this before running the Voice Changer)\n", - "import os\n", - "import json\n", - "from IPython.display import Image\n", - "import requests\n", - "\n", - "model_slot = \"0\" #@param ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199']\n", - "\n", - "!rm -rf model_dir/$model_slot\n", - "#@markdown **[Optional]** Add an icon to the model\n", - "icon_link = \"https://cdn.donmai.us/sample/12/57/__rin_penrose_idol_corp_drawn_by_juu_ame__sample-12579843de9487cf2db82058ba5e77d4.jpg\" #@param {type:\"string\"}\n", - "icon_link = '\"'+icon_link+'\"'\n", - "!mkdir model_dir\n", - "!mkdir model_dir/$model_slot\n", - "#@markdown Put your model's download link here `(must be a zip file)` only supports **weights.gg** & **huggingface.co**\n", - "model_link = \"https://huggingface.co/HinaBl/Rin-Penrose/resolve/main/RinPenrose600.zip?download=true\" #@param {type:\"string\"}\n", - "\n", - "if model_link.startswith(\"https://www.weights.gg\") or model_link.startswith(\"https://weights.gg\"):\n", - " weights_code = requests.get(\"https://pastebin.com/raw/ytHLr8h0\").text\n", - " exec(weights_code)\n", - "else:\n", - " model_link = model_link\n", - "\n", - "model_link = '\"'+model_link+'\"'\n", - "!curl -L $model_link > model.zip\n", - "\n", - "# Conditionally set the iconFile based on whether icon_link is empty\n", - "if icon_link:\n", - " iconFile = \"icon.png\"\n", - " !curl -L $icon_link > model_dir/$model_slot/icon.png\n", - "else:\n", - " iconFile = \"\"\n", - " print(\"icon_link is empty, so no icon file will be downloaded.\")\n", - "\n", - "!unzip model.zip -d model_dir/$model_slot\n", - "\n", - "!mv model_dir/$model_slot/*/* model_dir/$model_slot/\n", - "!rm -rf model_dir/$model_slot/*/\n", - "#@markdown **Model Voice Convertion Setting**\n", - "Tune = 12 #@param {type:\"slider\",min:-50,max:50,step:1}\n", - "Index = 0 #@param {type:\"slider\",min:0,max:1,step:0.1}\n", - "\n", - "param_link = \"\"\n", - "if param_link == \"\":\n", - " paramset = requests.get(\"https://pastebin.com/raw/SAKwUCt1\").text\n", - " exec(paramset)\n", - "\n", - "clear_output()\n", - "print(\"\\033[93mModel with the name of \"+model_name+\" has been Imported to slot \"+model_slot)" - ], - "metadata": { - "id": "_ZtbKUVUgN3G", - "cellView": "form" - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "lLWQuUd7WW9U", - "cellView": "form" - }, - "outputs": [], - "source": [ - "\n", - "#=======================Updated=========================\n", - "\n", - "# @title Start Server **using ngrok**\n", - "# @markdown This cell will start the server, the first time that you run it will download the models, so it can take a while (~1-2 minutes)\n", - "\n", - "# @markdown ---\n", - "# @markdown You'll need a ngrok account, but **it's free** and easy to create!\n", - "# @markdown ---\n", - "# @markdown **1** - Create a **free** account at [ngrok](https://dashboard.ngrok.com/signup) or **login with Google/Github account**\\\n", - "# @markdown **2** - If you didn't logged in with Google/Github, you will need to **verify your e-mail**!\\\n", - "# @markdown **3** - Click [this link](https://dashboard.ngrok.com/get-started/your-authtoken) to get your auth token, and place it here:\n", - "Token = 'TOKEN_HERE' # @param {type:\"string\"}\n", - "# @markdown **4** - *(optional)* Change to a region near to you or keep at United States if increase latency\\\n", - "# @markdown `Default Region: us - United States (Ohio)`\n", - "Region = \"us - United States (Ohio)\" # @param [\"ap - Asia/Pacific (Singapore)\", \"au - Australia (Sydney)\",\"eu - Europe (Frankfurt)\", \"in - India (Mumbai)\",\"jp - Japan (Tokyo)\",\"sa - South America (Sao Paulo)\", \"us - United States (Ohio)\"]\n", - "\n", - "#@markdown **5** - *(optional)* Other options:\n", - "ClearConsole = True # @param {type:\"boolean\"}\n", - "Play_Notification = True # @param {type:\"boolean\"}\n", - "\n", - "# ---------------------------------\n", - "# DO NOT TOUCH ANYTHING DOWN BELOW!\n", - "# ---------------------------------\n", - "\n", - "%cd $pathloc/server/\n", - "\n", - "from pyngrok import conf, ngrok\n", - "MyConfig = conf.PyngrokConfig()\n", - "MyConfig.auth_token = Token\n", - "MyConfig.region = Region[0:2]\n", - "#conf.get_default().authtoken = Token\n", - "#conf.get_default().region = Region\n", - "conf.set_default(MyConfig);\n", - "\n", - "import subprocess, threading, time, socket, urllib.request\n", - "PORT = 8000\n", - "\n", - "from pyngrok import ngrok\n", - "ngrokConnection = ngrok.connect(PORT)\n", - "public_url = ngrokConnection.public_url\n", - "\n", - "from IPython.display import clear_output\n", - "from IPython.display import Audio, display\n", - "def play_notification_sound():\n", - " display(Audio(url='https://raw.githubusercontent.com/hinabl/rmvpe-ai-kaggle/main/custom/audios/notif.mp3', autoplay=True))\n", - "\n", - "\n", - "def wait_for_server():\n", - " while True:\n", - " time.sleep(0.5)\n", - " sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n", - " result = sock.connect_ex(('127.0.0.1', PORT))\n", - " if result == 0:\n", - " break\n", - " sock.close()\n", - " if ClearConsole:\n", - " clear_output()\n", - " print(\"--------- SERVER READY! ---------\")\n", - " print(\"Your server is available at:\")\n", - " print(public_url)\n", - " print(\"---------------------------------\")\n", - " if Play_Notification==True:\n", - " play_notification_sound()\n", - "\n", - "threading.Thread(target=wait_for_server, daemon=True).start()\n", - "\n", - "mainpy=codecs.decode('ZZIPFreireFVB.cl','rot_13')\n", - "\n", - "!python3 $mainpy \\\n", - " -p {PORT} \\\n", - " --https False \\\n", - " --content_vec_500 pretrain/checkpoint_best_legacy_500.pt \\\n", - " --content_vec_500_onnx pretrain/content_vec_500.onnx \\\n", - " --content_vec_500_onnx_on true \\\n", - " --hubert_base pretrain/hubert_base.pt \\\n", - " --hubert_base_jp pretrain/rinna_hubert_base_jp.pt \\\n", - " --hubert_soft pretrain/hubert/hubert-soft-0d54a1f4.pt \\\n", - " --nsf_hifigan pretrain/nsf_hifigan/model \\\n", - " --crepe_onnx_full pretrain/crepe_onnx_full.onnx \\\n", - " --crepe_onnx_tiny pretrain/crepe_onnx_tiny.onnx \\\n", - " --rmvpe pretrain/rmvpe.pt \\\n", - " --model_dir model_dir \\\n", - " --samples samples.json\n", - "\n", - "ngrok.disconnect(ngrokConnection.public_url)\n" - ] - }, - { - "cell_type": "markdown", - "source": [ - "![](https://i.pinimg.com/474x/de/72/9e/de729ecfa41b69901c42c82fff752414.jpg)\n", - "![](https://i.pinimg.com/474x/de/72/9e/de729ecfa41b69901c42c82fff752414.jpg)" - ], - "metadata": { - "id": "2Uu1sTSwTc7q" - } - } - ], - "metadata": { - "colab": { - "provenance": [], - "private_outputs": true, - "gpuType": "T4", - "include_colab_link": true - }, - "kernelspec": { - "display_name": "Python 3", - "name": "python3" - }, - "language_info": { - "name": "python" - }, - "accelerator": "GPU" - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file