diff --git a/demo/MMVCServerSIO.py b/demo/MMVCServerSIO.py index 3ab31362..f83a45f5 100755 --- a/demo/MMVCServerSIO.py +++ b/demo/MMVCServerSIO.py @@ -150,6 +150,8 @@ if __name__ == thisFilename or args.colab == True: return {"result": "Index"} + UPLOAD_DIR = "model_upload_dir" + os.makedirs(UPLOAD_DIR) # Can colab receive post request "ONLY" at root path? @app_fastapi.post("/upload_model_file") async def upload_file(configFile:UploadFile = File(...), modelFile: UploadFile = File(...)): @@ -157,37 +159,51 @@ if __name__ == thisFilename or args.colab == True: for file in [modelFile, configFile]: filename = file.filename fileobj = file.file - upload_dir = open(os.path.join(".", filename),'wb+') + upload_dir = open(os.path.join(UPLOAD_DIR, filename),'wb+') shutil.copyfileobj(fileobj, upload_dir) upload_dir.close() - namespace.loadModel(configFile.filename, modelFile.filename) + namespace.loadModel(os.path.join(UPLOAD_DIR, configFile.filename), os.path.join(UPLOAD_DIR, modelFile.filename)) return {"uploaded files": f"{configFile.filename}, {modelFile.filename} "} return {"Error": "uploaded file is not found."} - @app_fastapi.get("/resumable") - async def get_resumble(): - print("GET REQUSET") - raise HTTPException(status_code=404, detail="Not found") - return 'OK' - - @app_fastapi.post("/resumable") - async def post_resumble( + @app_fastapi.post("/upload_file") + async def post_upload_file( file:UploadFile = File(...), filename: str = Form(...) ): - print("resumableFilename", filename) if file and filename: - filename = file.filename + "_" + filename fileobj = file.file - upload_dir = open(os.path.join(".", filename),'wb+') + upload_dir = open(os.path.join(UPLOAD_DIR, filename),'wb+') shutil.copyfileobj(fileobj, upload_dir) upload_dir.close() return {"uploaded files": f"{filename} "} return {"Error": "uploaded file is not found."} - return 'OK' + + @app_fastapi.post("/load_model") + async def post_load_model( + modelFilename: str = Form(...), + modelFilenameChunkNum: int = Form(...), + configFilename: str = Form(...) + ): + + target_file_name = modelFilename + with open(os.path.join(UPLOAD_DIR, target_file_name), "ab") as target_file: + for i in range(modelFilenameChunkNum): + filename = f"{modelFilename}_{i}" + chunk_file_path = os.path.join(UPLOAD_DIR,filename) + stored_chunk_file = open(chunk_file_path, 'rb') + target_file.write(stored_chunk_file.read()) + stored_chunk_file.close() + os.unlink(chunk_file_path) + target_file.close() + print(f'File saved to: {target_file_name}') + + print(f'Load: {configFilename}, {target_file_name}') + namespace.loadModel(os.path.join(UPLOAD_DIR, configFilename), os.path.join(UPLOAD_DIR, target_file_name)) + return {"File saved to": f"{target_file_name}"} @app_fastapi.post("/test") diff --git a/frontend/dist/index.js b/frontend/dist/index.js index 4fcd77a6..53692c7b 100755 --- a/frontend/dist/index.js +++ b/frontend/dist/index.js @@ -3913,7 +3913,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"fetchTextResource\": () => (/* binding */ fetchTextResource),\n/* harmony export */ \"postVoice\": () => (/* binding */ postVoice),\n/* harmony export */ \"uploadModelProps\": () => (/* binding */ uploadModelProps),\n/* harmony export */ \"uploadModelPropsResumable\": () => (/* binding */ uploadModelPropsResumable)\n/* harmony export */ });\n/* provided dependency */ var Buffer = __webpack_require__(/*! buffer */ \"./node_modules/buffer/index.js\")[\"Buffer\"];\n// import Resumable from 'resumablejs'\n// import { file } from \"jszip\";\nconst fetchTextResource = async (url) => {\n const res = await fetch(url, {\n method: \"GET\"\n });\n const text = res.text();\n return text;\n};\nconst postVoice = async (url, gpu, srcId, dstId, timestamp, buffer) => {\n const obj = {\n gpu, srcId, dstId, timestamp, buffer: Buffer.from(buffer).toString('base64')\n };\n const body = JSON.stringify(obj);\n const res = await fetch(`${url}`, {\n method: \"POST\",\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json'\n },\n body: body\n });\n const receivedJson = await res.json();\n const changedVoiceBase64 = receivedJson[\"changedVoiceBase64\"];\n const buf = Buffer.from(changedVoiceBase64, \"base64\");\n const ab = new ArrayBuffer(buf.length);\n // console.log(\"RECIV\", buf.length)\n const view = new Uint8Array(ab);\n for (let i = 0; i < buf.length; ++i) {\n view[i] = buf[i];\n }\n return ab;\n};\nconst uploadModelProps = (modelFile, configFile, onprogress) => {\n const req = new XMLHttpRequest();\n const formData = new FormData();\n formData.append(\"modelFile\", modelFile);\n formData.append(\"configFile\", configFile);\n req.upload.onprogress = (ev) => {\n const progress = Math.ceil(ev.loaded / ev.total * 10000 / 100);\n console.log(\"Progress:\", ev.loaded, ev.total, progress);\n onprogress(progress, ev.loaded == ev.total);\n };\n req.upload.onloadend = (ev) => {\n console.log(\"Progress[END!]:\", ev.loaded, ev.total, Math.ceil(ev.loaded / ev.total * 10000 / 100));\n onprogress(100, true);\n };\n req.open(\"POST\", '/upload_model_file');\n req.send(formData);\n};\nconst uploadModelPropsResumable = async (modelFile, _configFile, _onprogress) => {\n const size = 1024 * 1024;\n // const size = modelFile.size / 10;\n const fileChunks = [];\n let index = 0; // index値\n for (let cur = 0; cur < modelFile.size; cur += size) {\n fileChunks.push({\n hash: index++,\n chunk: modelFile.slice(cur, cur + size),\n });\n }\n console.log(\"FILE_CHUNKS:\", fileChunks);\n while (true) {\n const promises = [];\n for (let i = 0; i < 10; i++) {\n const chunk = fileChunks.shift();\n if (!chunk) {\n break;\n }\n const p = new Promise((resolve) => {\n const formData = new FormData();\n formData.append(\"file\", chunk.chunk);\n formData.append(\"filename\", \"file_\" + chunk.hash);\n const request = new Request('/resumable', {\n method: 'POST',\n body: formData,\n });\n fetch(request).then(async (response) => {\n console.log(await response.text());\n resolve();\n });\n });\n promises.push(p);\n }\n await Promise.all(promises);\n }\n // for (const x of fileChunks) {\n // console.log(\"SEND CHUNK:\", x.hash)\n // const p = new Promise((resolve, _reject) => {\n // // const req = new XMLHttpRequest();\n // const formData = new FormData();\n // formData.append(\"file\", x.chunk);\n // formData.append(\"filename\", \"file_\" + x.hash);\n // // req.upload.onprogress = (ev: ProgressEvent) => {\n // // const progress = Math.ceil(ev.loaded / ev.total * 10000 / 100)\n // // console.log(\"Progress:\", ev.loaded, ev.total, progress)\n // // // onprogress(progress, ev.loaded == ev.total)\n // // }\n // // req.upload.onloadend = (ev: ProgressEvent) => {\n // // console.log(\"Progress[END!]:\", ev.loaded, ev.total, Math.ceil(ev.loaded / ev.total * 10000 / 100))\n // // resolve()\n // // // onprogress(100, true)\n // // }\n // // req.open(\"POST\", '/resumable');\n // // req.send(formData);\n // const request = new Request('/resumable', {\n // method: 'POST',\n // body: formData,\n // });\n // fetch(request).then(async (response) => {\n // console.log(await response.text())\n // })\n // resolve()\n // })\n // console.log(\"SEND CHUNK wait:\", x.hash)\n // await p;\n // console.log(\"SEND CHUNK done:\", x.hash)\n // }\n // const res = new Resumable({\n // target: '/resumable',\n // // chunkSize: 100 * 1024,\n // simultaneousUploads: 1,\n // })\n // res.on(\"progress\", () => {\n // console.log(\"PROGRESS:\", res.progress)\n // })\n // res.on(\"uploadStart\", () => {\n // console.log(\"uploadStart:\")\n // })\n // res.on(\"fileSuccess\", (file: Resumable.ResumableFile) => {\n // console.log(\"fileSuccess:\", file)\n // })\n // res.on(\"fileAdded\", () => {\n // console.log(\"fileAdded:\")\n // })\n // res.on(\"fileError\", () => {\n // console.log(\"fileError:\")\n // })\n // res.addFile(modelFile)\n // res.addFile(_configFile)\n // console.log(\"send\", res.files, res.getSize())\n // res.upload()\n};\n\n\n//# sourceURL=webpack://voice-changer-internal/./frontend/src/001_clients_and_managers/002_ResourceLoader.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"fetchTextResource\": () => (/* binding */ fetchTextResource),\n/* harmony export */ \"postVoice\": () => (/* binding */ postVoice),\n/* harmony export */ \"uploadModelProps\": () => (/* binding */ uploadModelProps),\n/* harmony export */ \"uploadModelPropsResumable\": () => (/* binding */ uploadModelPropsResumable)\n/* harmony export */ });\n/* provided dependency */ var Buffer = __webpack_require__(/*! buffer */ \"./node_modules/buffer/index.js\")[\"Buffer\"];\n// import Resumable from 'resumablejs'\n// import { file } from \"jszip\";\nconst fetchTextResource = async (url) => {\n const res = await fetch(url, {\n method: \"GET\"\n });\n const text = res.text();\n return text;\n};\nconst postVoice = async (url, gpu, srcId, dstId, timestamp, buffer) => {\n const obj = {\n gpu, srcId, dstId, timestamp, buffer: Buffer.from(buffer).toString('base64')\n };\n const body = JSON.stringify(obj);\n const res = await fetch(`${url}`, {\n method: \"POST\",\n headers: {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json'\n },\n body: body\n });\n const receivedJson = await res.json();\n const changedVoiceBase64 = receivedJson[\"changedVoiceBase64\"];\n const buf = Buffer.from(changedVoiceBase64, \"base64\");\n const ab = new ArrayBuffer(buf.length);\n // console.log(\"RECIV\", buf.length)\n const view = new Uint8Array(ab);\n for (let i = 0; i < buf.length; ++i) {\n view[i] = buf[i];\n }\n return ab;\n};\nconst uploadModelProps = (modelFile, configFile, onprogress) => {\n const req = new XMLHttpRequest();\n const formData = new FormData();\n formData.append(\"modelFile\", modelFile);\n formData.append(\"configFile\", configFile);\n req.upload.onprogress = (ev) => {\n const progress = Math.ceil(ev.loaded / ev.total * 10000 / 100);\n console.log(\"Progress:\", ev.loaded, ev.total, progress);\n onprogress(progress, ev.loaded == ev.total);\n };\n req.upload.onloadend = (ev) => {\n console.log(\"Progress[END!]:\", ev.loaded, ev.total, Math.ceil(ev.loaded / ev.total * 10000 / 100));\n onprogress(100, true);\n };\n req.open(\"POST\", '/upload_model_file');\n req.send(formData);\n};\nconst uploadModelPropsResumable = async (modelFile, configFile, _onprogress) => {\n const size = 1024 * 1024;\n // const size = modelFile.size / 10;\n const fileChunks = [];\n let index = 0; // index値\n for (let cur = 0; cur < modelFile.size; cur += size) {\n fileChunks.push({\n hash: index++,\n chunk: modelFile.slice(cur, cur + size),\n });\n }\n const chunkNum = fileChunks.length;\n console.log(\"FILE_CHUNKS:\", chunkNum, fileChunks);\n while (true) {\n const promises = [];\n for (let i = 0; i < 10; i++) {\n const chunk = fileChunks.shift();\n if (!chunk) {\n break;\n }\n const p = new Promise((resolve) => {\n const formData = new FormData();\n formData.append(\"file\", chunk.chunk);\n formData.append(\"filename\", `${modelFile.name}_${chunk.hash}`);\n const request = new Request('/upload_file', {\n method: 'POST',\n body: formData,\n });\n fetch(request).then(async (response) => {\n console.log(await response.text());\n resolve();\n });\n });\n promises.push(p);\n }\n await Promise.all(promises);\n if (fileChunks.length == 0) {\n break;\n }\n }\n console.log(\"model uploaded\");\n const configP = new Promise((resolve) => {\n const formData = new FormData();\n formData.append(\"file\", configFile);\n formData.append(\"filename\", configFile.name);\n const request = new Request('/upload_file', {\n method: 'POST',\n body: formData,\n });\n fetch(request).then(async (response) => {\n console.log(await response.text());\n resolve();\n });\n });\n await configP;\n console.log(\"config uploaded\");\n const loadP = new Promise((resolve) => {\n const formData = new FormData();\n formData.append(\"modelFilename\", modelFile.name);\n formData.append(\"modelFilenameChunkNum\", \"\" + chunkNum);\n formData.append(\"configFilename\", configFile.name);\n const request = new Request('/load_model', {\n method: 'POST',\n body: formData,\n });\n fetch(request).then(async (response) => {\n console.log(await response.text());\n resolve();\n });\n });\n await loadP;\n console.log(\"model loaded\");\n // for (const x of fileChunks) {\n // console.log(\"SEND CHUNK:\", x.hash)\n // const p = new Promise((resolve, _reject) => {\n // // const req = new XMLHttpRequest();\n // const formData = new FormData();\n // formData.append(\"file\", x.chunk);\n // formData.append(\"filename\", \"file_\" + x.hash);\n // // req.upload.onprogress = (ev: ProgressEvent) => {\n // // const progress = Math.ceil(ev.loaded / ev.total * 10000 / 100)\n // // console.log(\"Progress:\", ev.loaded, ev.total, progress)\n // // // onprogress(progress, ev.loaded == ev.total)\n // // }\n // // req.upload.onloadend = (ev: ProgressEvent) => {\n // // console.log(\"Progress[END!]:\", ev.loaded, ev.total, Math.ceil(ev.loaded / ev.total * 10000 / 100))\n // // resolve()\n // // // onprogress(100, true)\n // // }\n // // req.open(\"POST\", '/resumable');\n // // req.send(formData);\n // const request = new Request('/resumable', {\n // method: 'POST',\n // body: formData,\n // });\n // fetch(request).then(async (response) => {\n // console.log(await response.text())\n // })\n // resolve()\n // })\n // console.log(\"SEND CHUNK wait:\", x.hash)\n // await p;\n // console.log(\"SEND CHUNK done:\", x.hash)\n // }\n // const res = new Resumable({\n // target: '/resumable',\n // // chunkSize: 100 * 1024,\n // simultaneousUploads: 1,\n // })\n // res.on(\"progress\", () => {\n // console.log(\"PROGRESS:\", res.progress)\n // })\n // res.on(\"uploadStart\", () => {\n // console.log(\"uploadStart:\")\n // })\n // res.on(\"fileSuccess\", (file: Resumable.ResumableFile) => {\n // console.log(\"fileSuccess:\", file)\n // })\n // res.on(\"fileAdded\", () => {\n // console.log(\"fileAdded:\")\n // })\n // res.on(\"fileError\", () => {\n // console.log(\"fileError:\")\n // })\n // res.addFile(modelFile)\n // res.addFile(_configFile)\n // console.log(\"send\", res.files, res.getSize())\n // res.upload()\n};\n\n\n//# sourceURL=webpack://voice-changer-internal/./frontend/src/001_clients_and_managers/002_ResourceLoader.ts?"); /***/ }), diff --git a/trainer/Dockerfile b/trainer/Dockerfile index d1940f8b..d0769f55 100644 --- a/trainer/Dockerfile +++ b/trainer/Dockerfile @@ -1,4 +1,4 @@ -FROM dannadori/voice-changer-internal:20221030_212136 as front +FROM dannadori/voice-changer-internal:20221030_223546 as front FROM debian:bullseye-slim as base ARG DEBIAN_FRONTEND=noninteractive