Compare commits
10 Commits
c8c6bc5770
...
master
@@ -31,6 +31,6 @@ weights/
|
||||
pretrained/
|
||||
|
||||
# Next.js workspace exclusions
|
||||
frontend-next/node_modules/
|
||||
frontend-next/.next/
|
||||
frontend-next/out/
|
||||
frontend/node_modules/
|
||||
frontend/.next/
|
||||
frontend/out/
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
# 🤖 ONNX VC - Agent Guidelines & Architecture Map
|
||||
|
||||
This file serves as a guide for AI agents (Gemini, Claude, Cursor, etc.) working on the ONNX Voice Changer repository. It explains the project architecture, directory structure, core conventions, and how to maintain the codebase.
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Technology Stack
|
||||
1. **Backend:** Python 3.10+, WebSocket (using `websockets`), ONNX Runtime, NumPy, PyTorch (only for RVC export).
|
||||
2. **Frontend:** Next.js 15 (App Router), React 19, TypeScript, Tailwind CSS, Lucide React, Framer Motion.
|
||||
3. **Voice Conversion:** Retrieval-based Voice Conversion (RVC) models accelerated via ONNX Runtime (CPU, CUDA, DirectML).
|
||||
|
||||
---
|
||||
|
||||
## 📁 Repository Structure
|
||||
* [/server.py](file:///M:/Users/ahmad/project/onnx-voice-changer/server.py) — The main WebSocket API server.
|
||||
* [/frontend/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend) — Next.js 15 client dashboard app.
|
||||
* [/frontend-deprecated/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend-deprecated) — Legacy static single-page web files (HTML/CSS/JS). Do not modify.
|
||||
* [/docs/](file:///M:/Users/ahmad/project/onnx-voice-changer/docs) — Holds localized README documentation files (Indonesian, Spanish, Japanese, Chinese).
|
||||
* [/lib/](file:///M:/Users/ahmad/project/onnx-voice-changer/lib) — RVC models and export scripts (e.g. `export_onnx.py`).
|
||||
* [/weights/](file:///M:/Users/ahmad/project/onnx-voice-changer/weights) — Character voice models (e.g., `weights/HuTao/HuTao.onnx`).
|
||||
* [/pretrained/](file:///M:/Users/ahmad/project/onnx-voice-changer/pretrained) — Holds the pre-trained `vec-768-layer-12.onnx` ContentVec model.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Core Architecture & Conventions
|
||||
|
||||
### 1. Pure API Backend (No Static Hosting)
|
||||
* **Rule:** The Python backend (`server.py`) operates **strictly as a WebSocket API**.
|
||||
* **Do NOT** configure Python to serve frontend static pages, build files, or index HTML.
|
||||
* The Next.js frontend client runs independently (via `npm run dev` or a separate production server).
|
||||
|
||||
### 2. WebSocket Audio Pipeline
|
||||
* Audio chunks are sent to and from the server as **binary WebSocket messages** containing raw `Float32` PCM audio data.
|
||||
* Configuration changes, telemetry, and status controls are handled using **JSON WebSocket messages** sent in the same connection.
|
||||
* Always check the message payload type (binary vs. string JSON text) in `server.py`.
|
||||
|
||||
### 3. Digital Signal Processing (DSP) Staging
|
||||
* Audio preprocessing is handled on the server side:
|
||||
1. **Low-Cut Filter:** Active Butterworth 1st order high-pass filter at 80Hz to eliminate AC hum.
|
||||
2. **Noise Gate:** Threshold-based silence gate to bypass inference when the user is silent.
|
||||
3. **Gain Controls:** Input and output gain staging before and after inference.
|
||||
* Ensure all DSP math is optimized using `numpy` arrays to maintain low latency.
|
||||
|
||||
### 4. RVC ONNX Export
|
||||
* PyTorch RVC models (`.pth`) must be converted to ONNX (`.onnx`) before inference.
|
||||
* Always use [/lib/export_onnx.py](file:///M:/Users/ahmad/project/onnx-voice-changer/lib/export_onnx.py) for conversion:
|
||||
```bash
|
||||
python lib/export_onnx.py --model_name <CharacterFolder>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Frontend Design Guidelines
|
||||
* **Responsive Layout:** Must support mobile and desktop views, utilizing a collapsible sidebar.
|
||||
* **Themes & Accent Colors:** Supports dark/light mode toggling, with a custom accent color system (Purple, Blue, Emerald, Rose, Amber) stored in state.
|
||||
* **i18n Translation:** Do not hardcode English/Indonesian strings. Ensure all labels, warnings, and messages are registered in [translations.ts](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend/src/utils/translations.ts).
|
||||
|
||||
---
|
||||
|
||||
## 🏃 Useful Development Commands
|
||||
|
||||
### Running Backend
|
||||
```bash
|
||||
python server.py --host 127.0.0.1 --port 8765 --device cuda
|
||||
```
|
||||
|
||||
### Running Frontend Dev Server
|
||||
```bash
|
||||
cd frontend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Building Frontend Production Server
|
||||
```bash
|
||||
cd frontend
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf
|
||||
of the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if distributed along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the Work text from the License, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of the purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2026 Kanara Technology
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,5 +1,7 @@
|
||||
# 🎙️ ONNX VC - Standalone Real-Time Voice Changer
|
||||
|
||||
🌐 **Languages:** [English](README.md) | [Bahasa Indonesia](docs/README.id.md) | [Español](docs/README.es.md) | [日本語](docs/README.ja.md) | [简体中文](docs/README.zh.md)
|
||||
|
||||
A high-performance, low-latency, real-time AI voice conversion system powered by **ONNX Runtime** and **Retrieval-based Voice Conversion (RVC)**. Features a premium dashboard built with **Next.js App Router**, **TypeScript**, and **Tailwind CSS**, supporting full internationalization.
|
||||
|
||||
---
|
||||
@@ -37,11 +39,11 @@ graph TD
|
||||
---
|
||||
|
||||
## 📁 Repository Structure
|
||||
* [server.py](file:///M:/Users/ahmad/project/onnx-voice-changer/server.py) — The main WebSocket backend and static HTTP server managing connection loops, audio resampling, and model execution.
|
||||
* [server.py](file:///M:/Users/ahmad/project/onnx-voice-changer/server.py) — The main WebSocket backend server managing connection loops, audio resampling, and model execution.
|
||||
* [start.bat](file:///M:/Users/ahmad/project/onnx-voice-changer/start.bat) — Windows launcher batch file that automatically resolves the Python virtual environment and executes the server.
|
||||
* [requirements.txt](file:///M:/Users/ahmad/project/onnx-voice-changer/requirements.txt) — Python dependencies list.
|
||||
* [frontend-next/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend-next) — The development workspace for the frontend client (Next.js, TypeScript).
|
||||
* [frontend/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend) — Statically exported and optimized assets served by [server.py](file:///M:/Users/ahmad/project/onnx-voice-changer/server.py) backend.
|
||||
* [frontend/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend) — The frontend client workspace built with Next.js (TypeScript, Tailwind CSS).
|
||||
* [frontend-deprecated/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend-deprecated) — The old deprecated frontend code.
|
||||
* [lib/](file:///M:/Users/ahmad/project/onnx-voice-changer/lib) — Core package containing inference models, ONNX conversion scripts, and prediction tools.
|
||||
* [weights/](file:///M:/Users/ahmad/project/onnx-voice-changer/weights) — Directory for character voice model weights (e.g. `weights/HuTao/`).
|
||||
* [pretrained/](file:///M:/Users/ahmad/project/onnx-voice-changer/pretrained) — Directory containing base pre-trained models.
|
||||
@@ -53,7 +55,7 @@ graph TD
|
||||
### 📋 Prerequisites
|
||||
* **Python 3.10+**
|
||||
* **FFmpeg** installed and added to the system PATH (Required for audio processing utilities).
|
||||
* **Node.js 18+** & **npm** (Only required if you want to modify and compile the frontend workspace).
|
||||
* **Node.js 18+** & **npm** (Required to run the Next.js frontend client).
|
||||
* (Optional) **NVIDIA CUDA Toolkit** (v11.x/12.x) and **cuDNN** for GPU execution acceleration.
|
||||
|
||||
---
|
||||
@@ -111,35 +113,27 @@ To run character models on ONNX Runtime, you must place your standard PyTorch RV
|
||||
---
|
||||
|
||||
### 🖥️ 4. Running the Frontend Client
|
||||
Since the Python backend operates purely as a WebSocket API service, you must run the Next.js frontend client separately.
|
||||
The frontend client runs as a standalone Next.js development server or built production server.
|
||||
|
||||
#### Option A: Development Server (Quick & Recommended)
|
||||
1. Navigate to the frontend directory:
|
||||
```bash
|
||||
cd frontend-next
|
||||
cd frontend
|
||||
```
|
||||
2. Install npm dependencies:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
3. Spin up the dev server:
|
||||
3. Start the development server:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
Open your browser and navigate to **`http://localhost:3000`**.
|
||||
|
||||
#### Option B: Compiled Static Production Web Server
|
||||
1. Navigate to `frontend-next` and build the application:
|
||||
Alternatively, to build and run the production server:
|
||||
```bash
|
||||
cd frontend-next
|
||||
npm install
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
*Note: This will compile static pages and copy them into the root `/frontend` folder.*
|
||||
2. Serve the compiled output using a static file server of your choice:
|
||||
- Using Node: `npx serve ../frontend -p 3000`
|
||||
- Using Python: `python -m http.server 3000 --directory ../frontend`
|
||||
Open **`http://localhost:3000`** in your browser.
|
||||
|
||||
---
|
||||
|
||||
@@ -160,7 +154,7 @@ python server.py --host 127.0.0.1 --port 8765 --device cuda
|
||||
| `--model` | Target folder name in `weights/` to load directly upon startup. | `None` |
|
||||
|
||||
### Step 2: Open the Frontend Dashboard
|
||||
Make sure your frontend client is running (via `npm run dev` or a static server on `http://localhost:3000`), open it in your browser, and it will automatically connect to the WebSocket API backend.
|
||||
Make sure your frontend client is running (via `npm run dev` or `npm run start` on `http://localhost:3000`), open it in your browser, and it will automatically connect to the WebSocket API backend.
|
||||
|
||||
---
|
||||
|
||||
@@ -169,3 +163,14 @@ To achieve low latency without output artifacts, the audio processing utilizes:
|
||||
1. **Sliding Window Context Buffer:** Keeps a short historical buffer of the audio to feed the model the required context frames while minimizing output audio delay.
|
||||
2. **Convolution Padding Fadeout:** 120ms of trailing silent padding is temporarily appended to input segments to avoid edge-fading anomalies inherent to RVC convolutional steps.
|
||||
3. **Linear Resampling:** Low-overhead linear interpolation for quick sample rate adaptation.
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Credits & Acknowledgements
|
||||
* **Made with ❤️ by [Kanara Technology](https://github.com/kanaratechnologyindonesia)** (Mirror: [git.kanara.tech](https://git.kanara.tech/kanara))
|
||||
* Powered by [ONNX Runtime](https://onnxruntime.ai/) and [Retrieval-based Voice Conversion (RVC)](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI)
|
||||
|
||||
---
|
||||
|
||||
## 📄 License
|
||||
This project is licensed under the Apache License 2.0. See the [LICENSE](file:///M:/Users/ahmad/project/onnx-voice-changer/LICENSE) file for details.
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
# 🎙️ ONNX VC - Standalone Real-Time Voice Changer
|
||||
|
||||
🌐 **Idiomas:** [English](../README.md) | [Bahasa Indonesia](README.id.md) | [Español](README.es.md) | [日本語](README.ja.md) | [简体中文](README.zh.md)
|
||||
|
||||
Un sistema de conversión de voz por IA en tiempo real, de alto rendimiento y baja latencia, impulsado por **ONNX Runtime** y **Retrieval-based Voice Conversion (RVC)**. Cuenta con un panel de control premium desarrollado con **Next.js App Router**, **TypeScript** y **Tailwind CSS**, con soporte para internacionalización completa.
|
||||
|
||||
---
|
||||
|
||||
## ✨ Características Clave
|
||||
* **🚀 Canal de Audio WebSocket (Audio Pipeline):** Transferencia de audio en tiempo real mediante conexiones WebSocket binarias (PCM float32 sin procesar) para una latencia mínima.
|
||||
* **⚡ Aceleración ONNX Multi-Backend:** Soporta proveedores de ejecución que incluyen NVIDIA `CUDA`, AMD/Intel `DirectML` y CPU como respaldo.
|
||||
* **🌐 Localización Universal:** Interfaz completamente traducible que soporta inglés, indonesio, japonés, chino y español.
|
||||
* **🎨 Panel de Control Premium:** Entorno de trabajo responsivo construido con React 19, Radix UI, Framer Motion y Tailwind CSS.
|
||||
* **🎼 Canal DSP de Alta Fidelidad:**
|
||||
* **Filtro de Corte Bajo (Low-Cut Filter):** Filtro de paso alto Butterworth activo de primer orden a 80 Hz para eliminar el zumbido de CA y los ruidos de fondo.
|
||||
* **Puerta de Ruido (Noise Gate):** Supresión de ruido basada en umbral para omitir la inferencia durante el silencio (ahorrando ciclos de CPU/GPU).
|
||||
* **Controles de Ganancia:** Control de ganancia digital independiente de entrada y salida.
|
||||
* **🧠 Extracción Avanzada de Tono:** Predicción de tono optimizada a 16 kHz utilizando el modelo RMVPE (Retrieval-based Minimum Vocal Pitch Estimation).
|
||||
* **🌐 Arquitectura de Enrutamiento Dual:** Permite enrutar el audio a través del navegador web (Web Audio API) o directamente mediante el hardware de audio local del servidor (utilizando `sounddevice`).
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Arquitectura del Sistema
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Micrófono / Navegador Web] -->|Web Audio API| B(Conexión WebSocket)
|
||||
B -->|Fragmento de PCM Float32 sin procesar| C[Backend de server.py]
|
||||
C -->|1. Filtro de paso alto 80Hz| D[Tahap DSP]
|
||||
D -->|2. Ganancia y puerta de ruido| D
|
||||
D -->|3. Remuestreo a 16kHz| E[Hubert/ContentVec ONNX]
|
||||
D -->|4. Estimación de tono RMVPE| F[Predictor de tono]
|
||||
E --> G[Inferencia del modelo RVC ONNX]
|
||||
F --> G
|
||||
G -->|Fragmentos de audio de destino| H(Conexión WebSocket)
|
||||
H -->|Reproducir audio| I[Altavoces del navegador / Dispositivo de audio]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📁 Estructura del Repositorio
|
||||
* [server.py](file:///M:/Users/ahmad/project/onnx-voice-changer/server.py) — El servidor backend WebSocket principal que gestiona los bucles de conexión, el remuestreo de audio y la ejecución del modelo.
|
||||
* [start.bat](file:///M:/Users/ahmad/project/onnx-voice-changer/start.bat) — Archivo por lotes ejecutable para Windows que inicializa automáticamente el entorno virtual de Python y ejecuta el servidor.
|
||||
* [requirements.txt](file:///M:/Users/ahmad/project/onnx-voice-changer/requirements.txt) — Lista de dependencias de Python.
|
||||
* [frontend/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend) — El espacio de trabajo del cliente frontend construido con Next.js (TypeScript, Tailwind CSS).
|
||||
* [frontend-deprecated/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend-deprecated) — Código frontend antiguo ya en desuso.
|
||||
* [lib/](file:///M:/Users/ahmad/project/onnx-voice-changer/lib) — Paquete central que contiene los modelos de inferencia, scripts de conversión a ONNX y herramientas de predicción.
|
||||
* [weights/](file:///M:/Users/ahmad/project/onnx-voice-changer/weights) — Directorio para los archivos de peso de los modelos de voz de personajes (ej. `weights/HuTao/`).
|
||||
* [pretrained/](file:///M:/Users/ahmad/project/onnx-voice-changer/pretrained) — Directorio que contiene los modelos base preentrenados.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Instalación y Configuración
|
||||
|
||||
### 📋 Requisitos Previos
|
||||
* **Python 3.10+**
|
||||
* **FFmpeg** instalado y agregado al PATH del sistema (necesario para las utilidades de procesamiento de audio).
|
||||
* **Node.js 18+** y **npm** (necesario para ejecutar el cliente frontend Next.js).
|
||||
* (Opcional) **NVIDIA CUDA Toolkit** (v11.x/12.x) y **cuDNN** para aceleración de ejecución en GPU.
|
||||
|
||||
---
|
||||
|
||||
### 📦 1. Instalación del Backend de Python
|
||||
1. Clone este repositorio en su directorio local.
|
||||
2. Inicialice y active un entorno virtual:
|
||||
```bash
|
||||
python -m venv venv
|
||||
# En Windows:
|
||||
.\venv\Scripts\activate
|
||||
# En Linux/macOS:
|
||||
source venv/bin/activate
|
||||
```
|
||||
3. Instale las dependencias requeridas:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 📥 2. Descargar ContentVec Preentrenado (Requerido)
|
||||
El modelo requiere un modelo base ContentVec para generar las características del hablante a partir de los fragmentos de voz.
|
||||
1. Descargue el modelo `vec-768-layer-12.onnx` desde Hugging Face:
|
||||
👉 **[Descargar vec-768-layer-12.onnx](https://huggingface.co/DogManTC/test-rvc-onnx/blob/main/vec-768-layer-12.onnx)**
|
||||
2. Guarde el archivo descargado dentro del directorio `pretrained/`:
|
||||
```
|
||||
pretrained/
|
||||
└── vec-768-layer-12.onnx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔄 3. Configuración y Exportación de Modelos RVC a ONNX
|
||||
Para ejecutar modelos de personajes en ONNX Runtime, debe colocar sus modelos RVC estándar de PyTorch (`.pth`) bajo el directorio `weights/` y convertirlos.
|
||||
|
||||
1. Cree una subcarpeta bajo `weights/` con el nombre de su personaje (ej. `HuTao`):
|
||||
```
|
||||
weights/
|
||||
└── HuTao/
|
||||
└── HuTao.pth
|
||||
```
|
||||
2. Ejecute el script de conversión a ONNX pasando el nombre de la carpeta del modelo:
|
||||
```bash
|
||||
python lib/export_onnx.py --model_name HuTao
|
||||
```
|
||||
3. El script buscará automáticamente el archivo `.pth` dentro de `weights/HuTao/` y exportará el archivo `HuTao.onnx` correspondiente en el mismo directorio:
|
||||
```
|
||||
weights/
|
||||
└── HuTao/
|
||||
├── HuTao.pth
|
||||
└── HuTao.onnx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🖥️ 4. Ejecución del Cliente Frontend
|
||||
El cliente frontend se ejecuta como un servidor de desarrollo independiente de Next.js o como un servidor de producción compilado.
|
||||
|
||||
1. Navegue al directorio frontend:
|
||||
```bash
|
||||
cd frontend
|
||||
```
|
||||
2. Instale las dependencias de npm:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
3. Inicie el servidor de desarrollo:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
Abra su navegador y acceda a **`http://localhost:3000`**.
|
||||
|
||||
Alternativamente, para compilar y ejecutar el servidor de producción:
|
||||
```bash
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏃 Funcionamiento del Cambiador de Voz
|
||||
|
||||
### Paso 1: Iniciar el Backend WebSocket de Python
|
||||
Ejecute el servidor desde su terminal (puerto predeterminado `8765`):
|
||||
```bash
|
||||
python server.py --host 127.0.0.1 --port 8765 --device cuda
|
||||
```
|
||||
|
||||
#### ⚙️ Argumentos de Línea de Comandos
|
||||
| Argumento | Descripción | Predeterminado |
|
||||
|---|---|---|
|
||||
| `--host` | La dirección a la que se enlaza el servidor WebSocket. | `127.0.0.1` |
|
||||
| `--port` | Puerto de comunicación WebSocket. | `8765` |
|
||||
| `--device` | El dispositivo de ejecución de ONNX Runtime (`cpu`, `cuda`, `dml`). | `cuda` |
|
||||
| `--model` | Nombre de la carpeta de destino en `weights/` para cargar directamente al inicio. | `None` |
|
||||
|
||||
### Paso 2: Abrir el Panel de Control Frontend
|
||||
Asegúrese de que su cliente frontend esté ejecutándose (a través de `npm run dev` o `npm run start` en `http://localhost:3000`), ábralo en su navegador y este se conectará automáticamente al backend de la API WebSocket.
|
||||
|
||||
---
|
||||
|
||||
## 🔊 Detalles de DSP de Audio
|
||||
Para lograr una latencia baja sin artefactos de salida, el procesamiento de audio utiliza:
|
||||
1. **Búfer de Contexto de Ventana Deslizante:** Mantiene un búfer histórico corto de audio para alimentar al modelo con los fragmentos de contexto necesarios, minimizando el retraso de la salida de audio.
|
||||
2. **Desvanecimiento por Relleno de Convolución:** Se añade temporalmente un relleno silencioso de 120 ms al final de los segmentos de entrada para evitar anomalías de desvanecimiento en los bordes, inherentes a los pasos de convolución RVC.
|
||||
3. **Remuestreo Lineal:** Interpolación lineal de bajo costo computacional para una rápida adaptación de la frecuencia de muestreo.
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Créditos y Agradecimientos
|
||||
* **Hecho con ❤️ por [Kanara Technology](https://github.com/kanaratechnologyindonesia)** (Espejo: [git.kanara.tech](https://git.kanara.tech/kanara))
|
||||
* Impulsado por [ONNX Runtime](https://onnxruntime.ai/) y [Retrieval-based Voice Conversion (RVC)](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI)
|
||||
|
||||
---
|
||||
|
||||
## 📄 Licencia
|
||||
Este proyecto está licenciado bajo la Apache License 2.0. Consulte el archivo [LICENSE](file:///M:/Users/ahmad/project/onnx-voice-changer/LICENSE) para más detalles.
|
||||
@@ -0,0 +1,176 @@
|
||||
# 🎙️ ONNX VC - Standalone Real-Time Voice Changer
|
||||
|
||||
🌐 **Bahasa:** [English](../README.md) | [Bahasa Indonesia](README.id.md) | [Español](README.es.md) | [日本語](README.ja.md) | [简体中文](README.zh.md)
|
||||
|
||||
Sistem konversi suara AI real-time berkinerja tinggi dan latensi rendah yang ditenagai oleh **ONNX Runtime** dan **Retrieval-based Voice Conversion (RVC)**. Dilengkapi dengan dashboard premium yang dibuat menggunakan **Next.js App Router**, **TypeScript**, dan **Tailwind CSS**, serta mendukung internasionalisasi penuh.
|
||||
|
||||
---
|
||||
|
||||
## ✨ Fitur Utama
|
||||
* **🚀 WebSocket Audio Pipeline:** Pengiriman audio streaming menggunakan koneksi WebSocket biner (raw PCM float32) untuk overhead minimal.
|
||||
* **⚡ Akselerasi ONNX Multi-Backend:** Mendukung execution providers termasuk NVIDIA `CUDA`, AMD/Intel `DirectML`, dan fallback `CPU`.
|
||||
* **🌐 Universal Localisation:** Antarmuka yang dapat diterjemahkan sepenuhnya, mendukung Bahasa Inggris, Indonesia, Jepang, Mandarin, dan Spanyol.
|
||||
* **🎨 Dashboard Premium**: Halaman kerja responsif yang dibangun menggunakan React 19, Radix UI, Framer Motion, dan Tailwind CSS.
|
||||
* **🎼 DSP Pipeline dengan Kualitas Tinggi:**
|
||||
* **Low-Cut Filter:** Butterworth high-pass filter orde pertama aktif pada frekuensi 80Hz untuk menghilangkan hum AC dan gemuruh.
|
||||
* **Noise Gate:** Penekanan derau berbasis ambang batas (threshold) untuk melewati inferensi saat hening (menghemat siklus CPU/GPU).
|
||||
* **Gain Controls:** Pengaturan gain digital input/output independen.
|
||||
* **🧠 Ekstraksi Pitch Canggih:** Prediksi pitch 16kHz yang dioptimalkan menggunakan model RMVPE (Retrieval-based Minimum Vocal Pitch Estimation).
|
||||
* **🌐 Arsitektur Dual Routing:** Mendukung perutean audio melalui browser web (Web Audio API) atau langsung melalui perangkat keras audio lokal server (menggunakan `sounddevice`).
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Arsitektur Sistem
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Mikrofon / Browser Web] -->|Web Audio API| B(Koneksi WebSocket)
|
||||
B -->|Chunk PCM Float32 Mentah| C[Backend server.py]
|
||||
C -->|1. High-Pass Filter 80Hz| D[Tahap DSP]
|
||||
D -->|2. Gain & Noise Gate| D
|
||||
D -->|3. Resample ke 16kHz| E[Hubert/ContentVec ONNX]
|
||||
D -->|4. Estimasi Pitch RMVPE| F[Prediktor Pitch]
|
||||
E --> G[Inferensi Model ONNX RVC]
|
||||
F --> G
|
||||
G -->|Chunk Audio Target| H(Koneksi WebSocket)
|
||||
H -->|Putar Audio| I[Speaker Browser / Perangkat Audio]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📁 Struktur Repositori
|
||||
* [server.py](file:///M:/Users/ahmad/project/onnx-voice-changer/server.py) — Server backend WebSocket utama yang mengelola loop koneksi, resampling audio, dan eksekusi model.
|
||||
* [start.bat](file:///M:/Users/ahmad/project/onnx-voice-changer/start.bat) — File batch peluncur Windows yang secara otomatis menyiapkan environment virtual Python dan menjalankan server.
|
||||
* [requirements.txt](file:///M:/Users/ahmad/project/onnx-voice-changer/requirements.txt) — Daftar dependensi Python.
|
||||
* [frontend/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend) — Ruang kerja klien frontend yang dibangun dengan Next.js (TypeScript, Tailwind CSS).
|
||||
* [frontend-deprecated/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend-deprecated) — Kode frontend lama yang sudah usang.
|
||||
* [lib/](file:///M:/Users/ahmad/project/onnx-voice-changer/lib) — Paket inti yang berisi model inferensi, skrip konversi ONNX, dan alat prediksi.
|
||||
* [weights/](file:///M:/Users/ahmad/project/onnx-voice-changer/weights) — Direktori untuk bobot model suara karakter (contoh: `weights/HuTao/`).
|
||||
* [pretrained/](file:///M:/Users/ahmad/project/onnx-voice-changer/pretrained) — Direktori yang berisi model dasar pra-terlatih.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Instalasi & Pengaturan
|
||||
|
||||
### 📋 Prasyarat
|
||||
* **Python 3.10+**
|
||||
* **FFmpeg** terinstal dan ditambahkan ke PATH sistem (Diperlukan untuk pemrosesan audio).
|
||||
* **Node.js 18+** & **npm** (Diperlukan untuk menjalankan klien frontend Next.js).
|
||||
* (Opsional) **NVIDIA CUDA Toolkit** (v11.x/12.x) dan **cuDNN** untuk akselerasi eksekusi GPU.
|
||||
|
||||
---
|
||||
|
||||
### 📦 1. Instalasi Backend Python
|
||||
1. Klon repositori ini ke direktori lokal Anda.
|
||||
2. Inisialisasi dan aktifkan virtual environment:
|
||||
```bash
|
||||
python -m venv venv
|
||||
# Di Windows:
|
||||
.\venv\Scripts\activate
|
||||
# Di Linux/macOS:
|
||||
source venv/bin/activate
|
||||
```
|
||||
3. Instal dependensi yang diperlukan:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 📥 2. Unduh Pre-trained ContentVec (Diperlukan)
|
||||
Model ini memerlukan model dasar ContentVec untuk menghasilkan fitur pembicara dari potongan suara.
|
||||
1. Unduh model `vec-768-layer-12.onnx` dari Hugging Face:
|
||||
👉 **[Unduh vec-768-layer-12.onnx](https://huggingface.co/DogManTC/test-rvc-onnx/blob/main/vec-768-layer-12.onnx)**
|
||||
2. Simpan file yang diunduh di dalam direktori `pretrained/`:
|
||||
```
|
||||
pretrained/
|
||||
└── vec-768-layer-12.onnx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔄 3. Siapkan & Ekspor Model RVC ke ONNX
|
||||
Untuk menjalankan model karakter pada ONNX Runtime, Anda harus menempatkan model RVC PyTorch standar Anda (`.pth`) di bawah direktori `weights/` dan mengonversinya.
|
||||
|
||||
1. Buat sub-folder di bawah `weights/` yang dinamai sesuai karakter Anda (contoh: `HuTao`):
|
||||
```
|
||||
weights/
|
||||
└── HuTao/
|
||||
└── HuTao.pth
|
||||
```
|
||||
2. Jalankan skrip konversi ONNX dengan memasukkan nama folder model:
|
||||
```bash
|
||||
python lib/export_onnx.py --model_name HuTao
|
||||
```
|
||||
3. Skrip akan secara otomatis mencari file `.pth` di dalam `weights/HuTao/` dan mengekspor file `HuTao.onnx` yang sesuai di dalam direktori yang sama:
|
||||
```
|
||||
weights/
|
||||
└── HuTao/
|
||||
├── HuTao.pth
|
||||
└── HuTao.onnx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🖥️ 4. Menjalankan Klien Frontend
|
||||
Klien frontend berjalan sebagai server pengembangan Next.js mandiri atau server produksi yang telah di-build.
|
||||
|
||||
1. Navigasi ke direktori frontend:
|
||||
```bash
|
||||
cd frontend
|
||||
```
|
||||
2. Instal dependensi npm:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
3. Jalankan server pengembangan:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
Buka browser Anda dan arahkan ke **`http://localhost:3000`**.
|
||||
|
||||
Atau, untuk membuat build dan menjalankan server produksi:
|
||||
```bash
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏃 Menjalankan Pengubah Suara
|
||||
|
||||
### Langkah 1: Mulai Backend WebSocket Python
|
||||
Jalankan server menggunakan terminal Anda (default ke port `8765`):
|
||||
```bash
|
||||
python server.py --host 127.0.0.1 --port 8765 --device cuda
|
||||
```
|
||||
|
||||
#### ⚙️ Argumen Baris Perintah
|
||||
| Argumen | Deskripsi | Default |
|
||||
|---|---|---|
|
||||
| `--host` | Alamat yang diikat oleh server WebSocket. | `127.0.0.1` |
|
||||
| `--port` | Port komunikasi WebSocket. | `8765` |
|
||||
| `--device` | Perangkat eksekusi ONNX Runtime (`cpu`, `cuda`, `dml`). | `cuda` |
|
||||
| `--model` | Nama folder target di `weights/` untuk dimuat langsung saat memulai. | `None` |
|
||||
|
||||
### Langkah 2: Buka Dashboard Frontend
|
||||
Pastikan klien frontend Anda berjalan (via `npm run dev` atau `npm run start` pada `http://localhost:3000`), buka di browser Anda, dan klien akan terhubung secara otomatis ke backend WebSocket API.
|
||||
|
||||
---
|
||||
|
||||
## 🔊 Detail DSP Audio
|
||||
Untuk mencapai latensi rendah tanpa artifak output, pemrosesan audio menggunakan:
|
||||
1. **Buffer Konteks Sliding Window:** Mempertahankan buffer historis pendek dari audio untuk memberikan frame konteks yang diperlukan ke model sambil meminimalkan penundaan audio output.
|
||||
2. **Fadeout Padding Konvolusi:** Padding senyap trailing sebesar 120ms ditambahkan sementara ke segmen input untuk menghindari anomali memudar di tepi yang melekat pada langkah konvolusional RVC.
|
||||
3. **Resampling Linear:** Penggunaan overhead rendah resampling linear untuk adaptasi laju sampel yang cepat.
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Kredit & Penghargaan
|
||||
* **Dibuat dengan ❤️ oleh [Kanara Technology](https://github.com/kanaratechnologyindonesia)** (Mirror: [git.kanara.tech](https://git.kanara.tech/kanara))
|
||||
* Ditenagai oleh [ONNX Runtime](https://onnxruntime.ai/) dan [Retrieval-based Voice Conversion (RVC)](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI)
|
||||
|
||||
---
|
||||
|
||||
## 📄 Lisensi
|
||||
Proyek ini dilisensikan di bawah Apache License 2.0. Lihat file [LICENSE](file:///M:/Users/ahmad/project/onnx-voice-changer/LICENSE) untuk informasi lebih lanjut.
|
||||
@@ -0,0 +1,176 @@
|
||||
# 🎙️ ONNX VC - Standalone Real-Time Voice Changer
|
||||
|
||||
🌐 **言語:** [English](../README.md) | [Bahasa Indonesia](README.id.md) | [Español](README.es.md) | [日本語](README.ja.md) | [简体中文](README.zh.md)
|
||||
|
||||
**ONNX Runtime**と**Retrieval-based Voice Conversion (RVC)**を搭載した、高性能・低遅延のリアルタイムAI音声変換システム。**Next.js App Router**、**TypeScript**、**Tailwind CSS**で構築されたプレミアムなダッシュボードを備え、完全な多言語対応をサポートしています。
|
||||
|
||||
---
|
||||
|
||||
## ✨ 主な機能
|
||||
* **🚀 WebSocketオーディオパイプライン:** 遅延を最小限に抑えるため、バイナリWebSocket接続(生のPCM float32)を使用したストリーミングオーディオ転送。
|
||||
* **⚡ マルチバックエンドONNXアクセラレーション:** NVIDIA `CUDA`、AMD/Intel `DirectML`、およびフォールバック用の`CPU`を含む実行プロバイダーをサポート。
|
||||
* **🌐 ユニバーサルローカライズ:** 英語、インドネシア語、日本語、中国語、スペイン語をサポートする完全翻訳可能なインターフェース。
|
||||
* **🎨 プレミアムダッシュボード:** React 19、Radix UI、Framer Motion、Tailwind CSSを使用して構築された完全レスポンシブなワークスペース。
|
||||
* **🎼 高忠実度DSPパイプライン:**
|
||||
* **ローカットフィルター:** ACハム音や低周波ノイズを除去する80Hzのアクティブ1次バターワースハイパスフィルター。
|
||||
* **ノイズゲート:** 無音時のインフェレンスをスキップ(CPU/GPUサイクルを節約)するためのしきい値ベースのノイズ抑制。
|
||||
* **ゲインコントロール:** 独立した入力/出力デジタルゲインスタージ。
|
||||
* **🧠 高度なピッチ抽出:** RMVPE(Retrieval-based Minimum Vocal Pitch Estimation)モデルを使用した、最適化された16kHzピッチ予測。
|
||||
* **🌐 デュアルルーティングアーキテクチャ:** Webブラウザ(Web Audio API)経由、またはサーバーのローカルオーディオハードウェア(`sounddevice`を使用)経由でのオーディオルーティングをサポート。
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ システムアーキテクチャ
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[マイク / Webブラウザ] -->|Web Audio API| B(WebSocket接続)
|
||||
B -->|生のFloat32 PCMチャンク| C[server.py バックエンド]
|
||||
C -->|1. ハイパスフィルター 80Hz| D[DSP段階]
|
||||
D -->|2. ゲイン&ノイズゲート| D
|
||||
D -->|3. 16kHzへのリサンプリング| E[Hubert/ContentVec ONNX]
|
||||
D -->|4. ピッチ推定 RMVPE| F[ピッチ予測器]
|
||||
E --> G[RVC ONNXモデル推論]
|
||||
F --> G
|
||||
G -->|ターゲットオーディオチャンク| H(WebSocket接続)
|
||||
H -->|オーディオ再生| I[ブラウザスピーカー / オーディオデバイス]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📁 リポジトリ構成
|
||||
* [server.py](file:///M:/Users/ahmad/project/onnx-voice-changer/server.py) — 接続ループ、オーディオリサンプリング、およびモデル実行を管理するメインのWebSocketバックエンドサーバー。
|
||||
* [start.bat](file:///M:/Users/ahmad/project/onnx-voice-changer/start.bat) — Pythonの仮想環境を自動的に解決し、サーバーを実行するWindowsランチャーバッチファイル。
|
||||
* [requirements.txt](file:///M:/Users/ahmad/project/onnx-voice-changer/requirements.txt) — Pythonの依存関係リスト。
|
||||
* [frontend/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend) — Next.js(TypeScript、Tailwind CSS)で構築されたフロントエンドクライアントワークスペース。
|
||||
* [frontend-deprecated/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend-deprecated) — 非推奨の古いフロントエンドコード。
|
||||
* [lib/](file:///M:/Users/ahmad/project/onnx-voice-changer/lib) — 推論モデル、ONNX変換スクリプト、および予測ツールを含むコアパッケージ。
|
||||
* [weights/](file:///M:/Users/ahmad/project/onnx-voice-changer/weights) — キャラクターボイスモデルの重み用のディレクトリ(例: `weights/HuTao/`)。
|
||||
* [pretrained/](file:///M:/Users/ahmad/project/onnx-voice-changer/pretrained) — ベースとなる事前学習済みモデルを含むディレクトリ。
|
||||
|
||||
---
|
||||
|
||||
## 🚀 インストールとセットアップ
|
||||
|
||||
### 📋 前提条件
|
||||
* **Python 3.10+**
|
||||
* **FFmpeg** がインストールされ、システム環境変数 PATH に追加されていること(音声処理ユーティリティに必要)。
|
||||
* **Node.js 18+** & **npm**(Next.jsフロントエンドクライアントの実行に必要)。
|
||||
* (オプション)GPU実行アクセラレーション用の **NVIDIA CUDA Toolkit** (v11.x/12.x) および **cuDNN**。
|
||||
|
||||
---
|
||||
|
||||
### 📦 1. Pythonバックエンドのインストール
|
||||
1. このリポジトリをローカルディレクトリにクローンします。
|
||||
2. 仮想環境を初期化して有効化します:
|
||||
```bash
|
||||
python -m venv venv
|
||||
# Windowsの場合:
|
||||
.\venv\Scripts\activate
|
||||
# Linux/macOSの場合:
|
||||
source venv/bin/activate
|
||||
```
|
||||
3. 必要な依存関係をインストールします:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 📥 2. 事前学習済みContentVecのダウンロード(必須)
|
||||
音声チャンクから話者特徴を生成するために、ContentVecベースモデルが必要です。
|
||||
1. Hugging Faceから`vec-768-layer-12.onnx`モデルをダウンロードします:
|
||||
👉 **[vec-768-layer-12.onnxをダウンロード](https://huggingface.co/DogManTC/test-rvc-onnx/blob/main/vec-768-layer-12.onnx)**
|
||||
2. ダウンロードしたファイルを`pretrained/`ディレクトリ内に保存します:
|
||||
```
|
||||
pretrained/
|
||||
└── vec-768-layer-12.onnx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔄 3. RVCモデルのセットアップとONNXへのエクスポート
|
||||
ONNX Runtimeでキャラクターモデルを実行するには、標準のPyTorch RVCモデル(`.pth`)を`weights/`ディレクトリに配置し、変換する必要があります。
|
||||
|
||||
1. `weights/`の下にキャラクター名(例: `HuTao`)のサブフォルダを作成します:
|
||||
```
|
||||
weights/
|
||||
└── HuTao/
|
||||
└── HuTao.pth
|
||||
```
|
||||
2. モデルのフォルダ名を指定してONNX変換スクリプトを実行します:
|
||||
```bash
|
||||
python lib/export_onnx.py --model_name HuTao
|
||||
```
|
||||
3. スクリプトは`weights/HuTao/`内の`.pth`ファイルを自動的に探索し、同じディレクトリ内に対応する`HuTao.onnx`ファイルをエクスポートします:
|
||||
```
|
||||
weights/
|
||||
└── HuTao/
|
||||
├── HuTao.pth
|
||||
└── HuTao.onnx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🖥️ 4. フロントエンドクライアントの実行
|
||||
フロントエンドクライアントは、スタンドアロンのNext.js開発サーバーまたはビルド済みの本番サーバーとして実行されます。
|
||||
|
||||
1. フロントエンドディレクトリに移動します:
|
||||
```bash
|
||||
cd frontend
|
||||
```
|
||||
2. npm依存関係をインストールします:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
3. 開発サーバーを起動します:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
ブラウザを開き、**`http://localhost:3000`**にアクセスします。
|
||||
|
||||
または、本番サーバーをビルドして実行する場合:
|
||||
```bash
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏃 ボイスチェンジャーの実行
|
||||
|
||||
### ステップ 1:Python WebSocketバックエンドの起動
|
||||
ターミナルを使用してサーバーを実行します(デフォルトポートは`8765`):
|
||||
```bash
|
||||
python server.py --host 127.0.0.1 --port 8765 --device cuda
|
||||
```
|
||||
|
||||
#### ⚙️ コマンドライン引数
|
||||
| 引数 | 説明 | デフォルト |
|
||||
|---|---|---|
|
||||
| `--host` | WebSocketサーバーがバインドするアドレス。 | `127.0.0.1` |
|
||||
| `--port` | WebSocket通信ポート。 | `8765` |
|
||||
| `--device` | ONNX Runtimeの実行デバイス(`cpu`、`cuda`、`dml`)。 | `cuda` |
|
||||
| `--model` | 起動時に直接読み込む`weights/`内のターゲットフォルダ名。 | `None` |
|
||||
|
||||
### ステップ 2:フロントエンドダッシュボードを開く
|
||||
フロントエンドクライアントが実行されていること(`npm run dev`または`http://localhost:3000`での`npm run start`経由)を確認し、ブラウザで開くと、自動的にWebSocket APIバックエンドに接続されます。
|
||||
|
||||
---
|
||||
|
||||
## 🔊 オーディオDSPの詳細
|
||||
出力アーティファクトなしで低遅延を実現するために、オーディオ処理では以下を使用しています:
|
||||
1. **スライディングウィンドウコンテキストバッファ:** 出力オーディオの遅延を最小限に抑えながら、モデルに必要なコンテキストフレームを供給するために、オーディオの短い履歴バッファを保持します。
|
||||
2. **畳み込みパディングフェードアウト:** RVCの畳み込みステップに固有のエッジフェード異常を回避するために、120msの末尾の無音パディングが入力セグメントに一時的に追加されます。
|
||||
3. **線形リサンプリング:** 素早いサンプリングレート適応のための低オーバーヘッドの線形補間。
|
||||
|
||||
---
|
||||
|
||||
## 🤝 クレジットと謝辞
|
||||
* **[Kanara Technology](https://github.com/kanaratechnologyindonesia)** (ミラー: [git.kanara.tech](https://git.kanara.tech/kanara)) **により ❤️ を込めて制作されました**
|
||||
* [ONNX Runtime](https://onnxruntime.ai/) および [Retrieval-based Voice Conversion (RVC)](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI) を使用しています
|
||||
|
||||
---
|
||||
|
||||
## 📄 ライセンス
|
||||
このプロジェクトは Apache License 2.0 の下でライセンスされています。詳細は [LICENSE](file:///M:/Users/ahmad/project/onnx-voice-changer/LICENSE) ファイルを参照してください。
|
||||
@@ -0,0 +1,176 @@
|
||||
# 🎙️ ONNX VC - Standalone Real-Time Voice Changer
|
||||
|
||||
🌐 **语言:** [English](../README.md) | [Bahasa Indonesia](README.id.md) | [Español](README.es.md) | [日本語](README.ja.md) | [简体中文](README.zh.md)
|
||||
|
||||
基于 **ONNX Runtime** 和 **检索式语音转换 (RVC)** 构建的高性能、低延迟实时 AI 变声系统。配有使用 **Next.js App Router**、**TypeScript** 和 **Tailwind CSS** 构建的高级仪表板,支持完整的国际化。
|
||||
|
||||
---
|
||||
|
||||
## ✨ 核心功能
|
||||
* **🚀 WebSocket 音频传输管道:** 使用二进制 WebSocket 连接(原始 PCM float32)进行流式音频传输,确保最低的系统开销。
|
||||
* **⚡ 多后端 ONNX 加速:** 支持包括 NVIDIA `CUDA`、AMD/Intel `DirectML` 以及备用 `CPU` 在内的多种执行提供程序。
|
||||
* **🌐 通用本地化:** 支持英文、印尼文、日文、中文和西班牙文的完全可翻译界面。
|
||||
* **🎨 高级仪表板:** 使用 React 19、Radix UI、Framer Motion 和 Tailwind CSS 构建的完全响应式工作区。
|
||||
* **🎼 高保真 DSP 处理管道:**
|
||||
* **低切滤波器:** 80Hz 处的主动一阶巴特沃斯高通滤波器,用以消除交流蜂鸣声和隆隆声。
|
||||
* **噪声门:** 基于阈值的噪声抑制,可在静音期间绕过推理(以节省 CPU/GPU 周期)。
|
||||
* **增益控制:** 独立输入/输出数字增益级。
|
||||
* **🧠 先进的基频提取:** 使用 RMVPE (Retrieval-based Minimum Vocal Pitch Estimation) 模型优化 16kHz 基频预测。
|
||||
* **🌐 双路由架构:** 支持通过 Web 浏览器(Web Audio API)或直接通过服务器的本地音频硬件(使用 `sounddevice`)进行音频路由。
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 系统架构
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[麦克风 / Web 浏览器] -->|Web Audio API| B(WebSocket 连接)
|
||||
B -->|原始 Float32 PCM 块| C[server.py 后端]
|
||||
C -->|1. 高通滤波器 80Hz| D[DSP 阶段]
|
||||
D -->|2. 增益与噪声门| D
|
||||
D -->|3. 重采样至 16kHz| E[Hubert/ContentVec ONNX]
|
||||
D -->|4. 基频估计 RMVPE| F[基频预测器]
|
||||
E --> G[RVC ONNX 模型推理]
|
||||
F --> G
|
||||
G -->|目标音频块| H(WebSocket 连接)
|
||||
H -->|播放音频| I[浏览器扬声器 / 音频设备]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📁 仓库结构
|
||||
* [server.py](file:///M:/Users/ahmad/project/onnx-voice-changer/server.py) — 主要的 WebSocket 后端服务器,用于管理连接循环、音频重采样和模型执行。
|
||||
* [start.bat](file:///M:/Users/ahmad/project/onnx-voice-changer/start.bat) — Windows 启动批处理文件,可自动解析 Python 虚拟环境并执行服务器。
|
||||
* [requirements.txt](file:///M:/Users/ahmad/project/onnx-voice-changer/requirements.txt) — Python 依赖列表。
|
||||
* [frontend/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend) — 使用 Next.js(TypeScript, Tailwind CSS)构建的前端客户端工作区。
|
||||
* [frontend-deprecated/](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend-deprecated) — 已弃用的旧前端代码。
|
||||
* [lib/](file:///M:/Users/ahmad/project/onnx-voice-changer/lib) — 核心包,包含推理模型、ONNX 转换脚本和预测工具。
|
||||
* [weights/](file:///M:/Users/ahmad/project/onnx-voice-changer/weights) — 角色声音模型权重目录(例如 `weights/HuTao/`)。
|
||||
* [pretrained/](file:///M:/Users/ahmad/project/onnx-voice-changer/pretrained) — 包含基础预训练模型的目录。
|
||||
|
||||
---
|
||||
|
||||
## 🚀 安装与设置
|
||||
|
||||
### 📋 准备工作
|
||||
* **Python 3.10+**
|
||||
* 已安装 **FFmpeg** 并添加到系统 PATH 中(音频处理工具所必需)。
|
||||
* **Node.js 18+** 和 **npm**(运行 Next.js 前端客户端所必需)。
|
||||
* (可选)用于 GPU 执行加速的 **NVIDIA CUDA Toolkit** (v11.x/12.x) 和 **cuDNN**。
|
||||
|
||||
---
|
||||
|
||||
### 📦 1. Python 后端安装
|
||||
1. 将此仓库克隆到您的本地目录。
|
||||
2. 初始化并激活虚拟环境:
|
||||
```bash
|
||||
python -m venv venv
|
||||
# 在 Windows 下:
|
||||
.\venv\Scripts\activate
|
||||
# 在 Linux/macOS 下:
|
||||
source venv/bin/activate
|
||||
```
|
||||
3. 安装所需依赖:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 📥 2. 下载预训练 ContentVec(必需)
|
||||
该模型需要 ContentVec 基础模型以从声音块生成说话者特征。
|
||||
1. 从 Hugging Face 下载 `vec-768-layer-12.onnx` 模型:
|
||||
👉 **[下载 vec-768-layer-12.onnx](https://huggingface.co/DogManTC/test-rvc-onnx/blob/main/vec-768-layer-12.onnx)**
|
||||
2. 将下载的文件保存到 `pretrained/` 目录中:
|
||||
```
|
||||
pretrained/
|
||||
└── vec-768-layer-12.onnx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔄 3. 设置并导出 RVC 模型为 ONNX
|
||||
要在 ONNX Runtime 上运行角色模型,您必须将标准 PyTorch RVC模型(`.pth`)放入 `weights/` 目录并进行转换。
|
||||
|
||||
1. 在 `weights/` 下创建一个以您的角色命名的子文件夹(例如 `HuTao`):
|
||||
```
|
||||
weights/
|
||||
└── HuTao/
|
||||
└── HuTao.pth
|
||||
```
|
||||
2. 通过传递模型的文件夹名称来运行 ONNX 转换脚本:
|
||||
```bash
|
||||
python lib/export_onnx.py --model_name HuTao
|
||||
```
|
||||
3. 脚本将自动在 `weights/HuTao/` 中搜索 `.pth` 文件,并在同一目录下导出相应的 `HuTao.onnx` 文件:
|
||||
```
|
||||
weights/
|
||||
└── HuTao/
|
||||
├── HuTao.pth
|
||||
└── HuTao.onnx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🖥️ 4. 运行前端客户端
|
||||
前端客户端可以作为独立的 Next.js 开发服务器或编译后的生产服务器运行。
|
||||
|
||||
1. 进入前端目录:
|
||||
```bash
|
||||
cd frontend
|
||||
```
|
||||
2. 安装 npm 依赖项:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
3. 启动开发服务器:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
打开浏览器并访问 **`http://localhost:3000`**。
|
||||
|
||||
或者,构建并运行生产服务器:
|
||||
```bash
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏃 运行变声器
|
||||
|
||||
### 步骤 1:启动 Python WebSocket 后端
|
||||
使用终端运行服务器(默认为端口 `8765`):
|
||||
```bash
|
||||
python server.py --host 127.0.0.1 --port 8765 --device cuda
|
||||
```
|
||||
|
||||
#### ⚙️ 命令行参数
|
||||
| 参数 | 说明 | 默认值 |
|
||||
|---|---|---|
|
||||
| `--host` | WebSocket 服务器绑定的地址。 | `127.0.0.1` |
|
||||
| `--port` | WebSocket 通信端口。 | `8765` |
|
||||
| `--device` | ONNX Runtime 执行设备(`cpu`、`cuda`、`dml`)。 | `cuda` |
|
||||
| `--model` | 启动时直接加载的 `weights/` 中的目标文件夹名称。 | `None` |
|
||||
|
||||
### 步骤 2:打开前端仪表板
|
||||
确保您的前端客户端正在运行(通过 `npm run dev` 或在 `http://localhost:3000` 上运行 `npm run start`),在浏览器中打开它,它将自动连接到 WebSocket API 后端。
|
||||
|
||||
---
|
||||
|
||||
## 音频 DSP 细节
|
||||
为了在没有输出伪影的情况下实现低延迟,音频处理利用了:
|
||||
1. **滑动窗口上下文缓冲区:** 保持较短的音频历史缓冲区,以向模型提供所需的上下文帧,同时最小化输出音频延迟。
|
||||
2. **卷积填充淡出:** 在输入片段中临时追加 120ms 的尾随静音填充,以避免 RVC 卷积步骤中固有的边缘淡入淡出异常。
|
||||
3. **线性重采样:** 低开销的线性插值,可快速适应采样率。
|
||||
|
||||
---
|
||||
|
||||
## 🤝 鸣谢与贡献
|
||||
* **由 [Kanara Technology](https://github.com/kanaratechnologyindonesia)** (镜像: [git.kanara.tech](https://git.kanara.tech/kanara)) **用 ❤️ 制作**
|
||||
* 基于 [ONNX Runtime](https://onnxruntime.ai/) 和 [Retrieval-based Voice Conversion (RVC)](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI)
|
||||
|
||||
---
|
||||
|
||||
## 📄 许可证
|
||||
本项目采用 Apache 2.0 许可证进行授权。详情请参阅 [LICENSE](file:///M:/Users/ahmad/project/onnx-voice-changer/LICENSE) 文件。
|
||||
@@ -0,0 +1,41 @@
|
||||
# ⚠️ Deprecated Frontend
|
||||
|
||||
This directory contains the original, legacy single-page static HTML/CSS/JS frontend application for the ONNX Voice Changer.
|
||||
|
||||
---
|
||||
|
||||
## 🚫 Status: Deprecated
|
||||
This frontend is **no longer maintained or active**.
|
||||
|
||||
### Why?
|
||||
1. **Upgraded Dashboard:** The voice changer client has been completely refactored and rewritten as a premium **Next.js 15 (TypeScript & Tailwind CSS)** application, which is now located in the main [/frontend](file:///M:/Users/ahmad/project/onnx-voice-changer/frontend) workspace.
|
||||
2. **Pure API Backend:** The Python backend (`server.py`) has been simplified to run as a pure WebSocket API backend and no longer hosts static files.
|
||||
|
||||
---
|
||||
|
||||
## 📂 Files Included
|
||||
* `index.html` — The legacy single-page layout.
|
||||
* `styles.css` — Legacy stylesheets.
|
||||
* `app.js` — Legacy Audio DSP processing and WebSocket integration.
|
||||
|
||||
---
|
||||
|
||||
## 🏃 Running the Deprecated Client (Reference Only)
|
||||
If you still want to run this legacy frontend for reference, you can serve this directory using any static file server:
|
||||
|
||||
### Option A: Using Python
|
||||
```bash
|
||||
python -m http.server 3000
|
||||
```
|
||||
|
||||
### Option B: Using Node (npx)
|
||||
```bash
|
||||
npx serve . -p 3000
|
||||
```
|
||||
|
||||
After serving, open **`http://localhost:3000`** in your browser. Ensure the Python WebSocket backend (`server.py`) is running on port `8765`.
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Credits & Acknowledgements
|
||||
* **Made with ❤️ by [Kanara Technology](https://github.com/kanaratechnologyindonesia)** (Mirror: [git.kanara.tech](https://git.kanara.tech/kanara))
|
||||
@@ -1,36 +0,0 @@
|
||||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
||||
@@ -1,50 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const srcDir = path.join(__dirname, 'out');
|
||||
const destDir = path.join(__dirname, '..', 'frontend');
|
||||
|
||||
function copyDirSync(src, dest) {
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
const entries = fs.readdirSync(src, { withFileTypes: true });
|
||||
|
||||
for (let entry of entries) {
|
||||
const srcPath = path.join(src, entry.name);
|
||||
const destPath = path.join(dest, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
copyDirSync(srcPath, destPath);
|
||||
} else {
|
||||
fs.copyFileSync(srcPath, destPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cleanDirSync(dir) {
|
||||
if (!fs.existsSync(dir)) return;
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
for (let entry of entries) {
|
||||
if (entry.name === '.git' || entry.name === '.antigravitycli') continue;
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
fs.rmSync(fullPath, { recursive: true, force: true });
|
||||
} else {
|
||||
fs.unlinkSync(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('Wiping old static files in frontend/ ...');
|
||||
cleanDirSync(destDir);
|
||||
|
||||
console.log('Copying static Next.js assets to frontend/ ...');
|
||||
if (fs.existsSync(srcDir)) {
|
||||
copyDirSync(srcDir, destDir);
|
||||
console.log('Build output synchronization successful!');
|
||||
} else {
|
||||
console.error('Error: "out/" directory not found. Compile the Next.js build first.');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Synchronization failed:', err);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
# 🎨 ONNX VC - Frontend Client Dashboard
|
||||
|
||||
The premium user dashboard for the **ONNX VC (Real-Time Voice Changer)**. Built using **Next.js 15 (App Router)**, **React 19**, **TypeScript**, and **Tailwind CSS**, providing a high-fidelity control panel for real-time AI voice conversion.
|
||||
|
||||
---
|
||||
|
||||
## ✨ Key Features
|
||||
* **🌐 Complete Internationalization (i18n):** Supports English, Indonesian, Spanish, Japanese, and Chinese.
|
||||
* **🌓 Dark Mode & Custom Themes:** Seamless dark/light theme switching with custom accent colors (Purple, Blue, Emerald, Rose, Amber).
|
||||
* **📊 Dual Waveform Visualizer:** Displays real-time input and output audio waveform graphs side-by-side in a single row for compact, effective monitoring.
|
||||
* **📱 Collapsible Sidebar:** Optimized UI layout with a smooth collapsible sidebar for managing settings.
|
||||
* **🎛️ Interactive DSP Controls:** Easily adjust input/output gain staging, active 80Hz low-cut filters, noise gates, and pitch transposition.
|
||||
* **⚙️ Dual Routing Toggle:** Switch between browser-side routing (Web Audio API) and server-side hardware routing (`sounddevice`).
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
### 📋 Prerequisites
|
||||
* **Node.js 18+**
|
||||
* **npm**, **yarn**, or **pnpm** package manager
|
||||
|
||||
### 📦 Installation
|
||||
Navigate to this directory and install the project dependencies:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### 🏃 Running the Development Server
|
||||
Start the Next.js local development server:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
Open **[http://localhost:3000](http://localhost:3000)** in your web browser.
|
||||
|
||||
### 🏗️ Building for Production
|
||||
To build the application for optimized production performance:
|
||||
```bash
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔌 WebSocket Connection
|
||||
The frontend connects to the Python WebSocket backend to stream binary audio chunks and receive converted audio.
|
||||
* **Default backend URL:** `ws://127.0.0.1:8765`
|
||||
* Ensure your backend `server.py` is running before starting voice conversion from the dashboard.
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Credits & Acknowledgements
|
||||
* **Made with ❤️ by [Kanara Technology](https://github.com/kanaratechnologyindonesia)** (Mirror: [git.kanara.tech](https://git.kanara.tech/kanara))
|
||||
* Powered by [Next.js](https://nextjs.org/) and [Tailwind CSS](https://tailwindcss.com/)
|
||||
@@ -1,9 +0,0 @@
|
||||
1:"$Sreact.fragment"
|
||||
2:I[47257,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"ClientPageRoot"]
|
||||
3:I[52683,["/_next/static/chunks/0dbhjjzl8qfwv.js","/_next/static/chunks/01yjdu1pd4sew.js"],"default"]
|
||||
6:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"OutletBoundary"]
|
||||
7:"$Sreact.suspense"
|
||||
0:{"rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/01yjdu1pd4sew.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
4:{}
|
||||
5:"$0:rsc:props:children:0:props:serverProvidedParams:params"
|
||||
8:null
|
||||
@@ -1,20 +0,0 @@
|
||||
1:"$Sreact.fragment"
|
||||
2:I[39756,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
3:I[37457,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
4:I[47257,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"ClientPageRoot"]
|
||||
5:I[52683,["/_next/static/chunks/0dbhjjzl8qfwv.js","/_next/static/chunks/01yjdu1pd4sew.js"],"default"]
|
||||
8:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"OutletBoundary"]
|
||||
9:"$Sreact.suspense"
|
||||
b:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"ViewportBoundary"]
|
||||
d:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"MetadataBoundary"]
|
||||
f:I[68027,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default",1]
|
||||
:HL["/_next/static/chunks/0~n~ndg8g34g9.css","style"]
|
||||
:HL["/_next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
||||
:HL["/_next/static/media/caa3a2e1cccd8315-s.p.09~u27dqhyhd6.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
||||
0:{"P":null,"c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0~n~ndg8g34g9.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/0dbhjjzl8qfwv.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable h-full antialiased","children":["$","body",null,{"className":"min-h-full flex flex-col","children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L4",null,{"Component":"$5","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@6","$@7"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/01yjdu1pd4sew.js","async":true,"nonce":"$undefined"}]],["$","$L8",null,{"children":["$","$9",null,{"name":"Next.MetadataOutlet","children":"$@a"}]}]]}],{},null,false,null]},null,false,null],["$","$1","h",{"children":[null,["$","$Lb",null,{"children":"$Lc"}],["$","div",null,{"hidden":true,"children":["$","$Ld",null,{"children":["$","$9",null,{"name":"Next.Metadata","children":"$Le"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$f",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0~n~ndg8g34g9.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
6:{}
|
||||
7:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
|
||||
c:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
||||
10:I[27201,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"IconMark"]
|
||||
a:null
|
||||
e:[["$","title","0",{"children":"🎙️ ONNX VC - Real-Time AI Voice Changer"}],["$","meta","1",{"name":"description","content":"ONNX VC - Pengubah suara real-time berbasis AI berlatensi ultra-rendah dengan ONNX Runtime."}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L10","3",{}]]
|
||||
@@ -1,6 +0,0 @@
|
||||
1:"$Sreact.fragment"
|
||||
2:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"ViewportBoundary"]
|
||||
3:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"MetadataBoundary"]
|
||||
4:"$Sreact.suspense"
|
||||
5:I[27201,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"IconMark"]
|
||||
0:{"rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"🎙️ ONNX VC - Real-Time AI Voice Changer"}],["$","meta","1",{"name":"description","content":"ONNX VC - Pengubah suara real-time berbasis AI berlatensi ultra-rendah dengan ONNX Runtime."}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L5","3",{}]]}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
@@ -1,5 +0,0 @@
|
||||
1:"$Sreact.fragment"
|
||||
2:I[39756,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
3:I[37457,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
:HL["/_next/static/chunks/0~n~ndg8g34g9.css","style"]
|
||||
0:{"rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0~n~ndg8g34g9.css","precedence":"next"}],["$","script","script-0",{"src":"/_next/static/chunks/0dbhjjzl8qfwv.js","async":true}]],["$","html",null,{"lang":"en","className":"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable h-full antialiased","children":["$","body",null,{"className":"min-h-full flex flex-col","children":["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
@@ -1,4 +0,0 @@
|
||||
:HL["/_next/static/chunks/0~n~ndg8g34g9.css","style"]
|
||||
:HL["/_next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
||||
:HL["/_next/static/media/caa3a2e1cccd8315-s.p.09~u27dqhyhd6.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
||||
0:{"tree":{"name":"","param":null,"prefetchHints":16,"slots":{"children":{"name":"__PAGE__","param":null,"prefetchHints":0,"slots":null}}},"staleTime":300,"buildId":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
|
Before Width: | Height: | Size: 25 KiB |
@@ -1,11 +0,0 @@
|
||||
self.__BUILD_MANIFEST = {
|
||||
"__rewrites": {
|
||||
"afterFiles": [],
|
||||
"beforeFiles": [],
|
||||
"fallback": []
|
||||
},
|
||||
"sortedPages": [
|
||||
"/_app",
|
||||
"/_error"
|
||||
]
|
||||
};self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()
|
||||
@@ -1 +0,0 @@
|
||||
self.__MIDDLEWARE_MATCHERS = [];self.__MIDDLEWARE_MATCHERS_CB && self.__MIDDLEWARE_MATCHERS_CB()
|
||||
@@ -1 +0,0 @@
|
||||
self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()
|
||||
@@ -1,16 +0,0 @@
|
||||
1:"$Sreact.fragment"
|
||||
2:I[39756,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
3:I[37457,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
4:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"OutletBoundary"]
|
||||
5:"$Sreact.suspense"
|
||||
8:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"ViewportBoundary"]
|
||||
a:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"MetadataBoundary"]
|
||||
c:I[68027,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default",1]
|
||||
:HL["/_next/static/chunks/0~n~ndg8g34g9.css","style"]
|
||||
0:{"P":null,"c":["","_not-found"],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0~n~ndg8g34g9.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/0dbhjjzl8qfwv.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable h-full antialiased","children":["$","body",null,{"className":"min-h-full flex flex-col","children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L4",null,{"children":["$","$5",null,{"name":"Next.MetadataOutlet","children":"$@6"}]}]]}],{},null,false,null]},null,false,"$@7"]},null,false,null],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L8",null,{"children":"$L9"}],["$","div",null,{"hidden":true,"children":["$","$La",null,{"children":["$","$5",null,{"name":"Next.Metadata","children":"$Lb"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$c",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0~n~ndg8g34g9.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
d:[]
|
||||
7:"$Wd"
|
||||
9:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
||||
e:I[27201,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"IconMark"]
|
||||
6:null
|
||||
b:[["$","title","0",{"children":"🎙️ ONNX VC - Real-Time AI Voice Changer"}],["$","meta","1",{"name":"description","content":"ONNX VC - Pengubah suara real-time berbasis AI berlatensi ultra-rendah dengan ONNX Runtime."}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$Le","3",{}]]
|
||||
@@ -1,16 +0,0 @@
|
||||
1:"$Sreact.fragment"
|
||||
2:I[39756,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
3:I[37457,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
4:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"OutletBoundary"]
|
||||
5:"$Sreact.suspense"
|
||||
8:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"ViewportBoundary"]
|
||||
a:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"MetadataBoundary"]
|
||||
c:I[68027,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default",1]
|
||||
:HL["/_next/static/chunks/0~n~ndg8g34g9.css","style"]
|
||||
0:{"P":null,"c":["","_not-found"],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0~n~ndg8g34g9.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/0dbhjjzl8qfwv.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable h-full antialiased","children":["$","body",null,{"className":"min-h-full flex flex-col","children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L4",null,{"children":["$","$5",null,{"name":"Next.MetadataOutlet","children":"$@6"}]}]]}],{},null,false,null]},null,false,"$@7"]},null,false,null],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L8",null,{"children":"$L9"}],["$","div",null,{"hidden":true,"children":["$","$La",null,{"children":["$","$5",null,{"name":"Next.Metadata","children":"$Lb"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$c",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0~n~ndg8g34g9.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
d:[]
|
||||
7:"$Wd"
|
||||
9:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
||||
e:I[27201,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"IconMark"]
|
||||
6:null
|
||||
b:[["$","title","0",{"children":"🎙️ ONNX VC - Real-Time AI Voice Changer"}],["$","meta","1",{"name":"description","content":"ONNX VC - Pengubah suara real-time berbasis AI berlatensi ultra-rendah dengan ONNX Runtime."}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$Le","3",{}]]
|
||||
@@ -1,6 +0,0 @@
|
||||
1:"$Sreact.fragment"
|
||||
2:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"ViewportBoundary"]
|
||||
3:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"MetadataBoundary"]
|
||||
4:"$Sreact.suspense"
|
||||
5:I[27201,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"IconMark"]
|
||||
0:{"rsc":["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"🎙️ ONNX VC - Real-Time AI Voice Changer"}],["$","meta","1",{"name":"description","content":"ONNX VC - Pengubah suara real-time berbasis AI berlatensi ultra-rendah dengan ONNX Runtime."}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L5","3",{}]]}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
@@ -1,5 +0,0 @@
|
||||
1:"$Sreact.fragment"
|
||||
2:I[39756,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
3:I[37457,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
:HL["/_next/static/chunks/0~n~ndg8g34g9.css","style"]
|
||||
0:{"rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0~n~ndg8g34g9.css","precedence":"next"}],["$","script","script-0",{"src":"/_next/static/chunks/0dbhjjzl8qfwv.js","async":true}]],["$","html",null,{"lang":"en","className":"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable h-full antialiased","children":["$","body",null,{"className":"min-h-full flex flex-col","children":["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
@@ -1,5 +0,0 @@
|
||||
1:"$Sreact.fragment"
|
||||
2:I[39756,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
3:I[37457,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
4:[]
|
||||
0:{"rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"isPartial":false,"staleTime":300,"varyParams":"$W4","buildId":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
@@ -1,5 +0,0 @@
|
||||
1:"$Sreact.fragment"
|
||||
2:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"OutletBoundary"]
|
||||
3:"$Sreact.suspense"
|
||||
0:{"rsc":["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],null,["$","$L2",null,{"children":["$","$3",null,{"name":"Next.MetadataOutlet","children":"$@4"}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
4:null
|
||||
@@ -1,2 +0,0 @@
|
||||
:HL["/_next/static/chunks/0~n~ndg8g34g9.css","style"]
|
||||
0:{"tree":{"name":"","param":null,"prefetchHints":16,"slots":{"children":{"name":"/_not-found","param":null,"prefetchHints":0,"slots":{"children":{"name":"__PAGE__","param":null,"prefetchHints":0,"slots":null}}}}},"staleTime":300,"buildId":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
|
Before Width: | Height: | Size: 25 KiB |
@@ -1 +0,0 @@
|
||||
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
||||
|
Before Width: | Height: | Size: 391 B |
@@ -1 +0,0 @@
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1,20 +0,0 @@
|
||||
1:"$Sreact.fragment"
|
||||
2:I[39756,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
3:I[37457,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default"]
|
||||
4:I[47257,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"ClientPageRoot"]
|
||||
5:I[52683,["/_next/static/chunks/0dbhjjzl8qfwv.js","/_next/static/chunks/01yjdu1pd4sew.js"],"default"]
|
||||
8:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"OutletBoundary"]
|
||||
9:"$Sreact.suspense"
|
||||
b:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"ViewportBoundary"]
|
||||
d:I[97367,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"MetadataBoundary"]
|
||||
f:I[68027,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"default",1]
|
||||
:HL["/_next/static/chunks/0~n~ndg8g34g9.css","style"]
|
||||
:HL["/_next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
||||
:HL["/_next/static/media/caa3a2e1cccd8315-s.p.09~u27dqhyhd6.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
||||
0:{"P":null,"c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0~n~ndg8g34g9.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/0dbhjjzl8qfwv.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable h-full antialiased","children":["$","body",null,{"className":"min-h-full flex flex-col","children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L4",null,{"Component":"$5","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@6","$@7"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/01yjdu1pd4sew.js","async":true,"nonce":"$undefined"}]],["$","$L8",null,{"children":["$","$9",null,{"name":"Next.MetadataOutlet","children":"$@a"}]}]]}],{},null,false,null]},null,false,null],["$","$1","h",{"children":[null,["$","$Lb",null,{"children":"$Lc"}],["$","div",null,{"hidden":true,"children":["$","$Ld",null,{"children":["$","$9",null,{"name":"Next.Metadata","children":"$Le"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$f",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0~n~ndg8g34g9.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"ncF6Dp_0OCMhTp1KUVnS4"}
|
||||
6:{}
|
||||
7:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
|
||||
c:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
||||
10:I[27201,["/_next/static/chunks/0dbhjjzl8qfwv.js"],"IconMark"]
|
||||
a:null
|
||||
e:[["$","title","0",{"children":"🎙️ ONNX VC - Real-Time AI Voice Changer"}],["$","meta","1",{"name":"description","content":"ONNX VC - Pengubah suara real-time berbasis AI berlatensi ultra-rendah dengan ONNX Runtime."}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L10","3",{}]]
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "frontend-next",
|
||||
"name": "frontend",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build && node copy-build.js",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint"
|
||||
},
|
||||
|
Before Width: | Height: | Size: 391 B After Width: | Height: | Size: 391 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 385 B After Width: | Height: | Size: 385 B |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
@@ -1 +0,0 @@
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
||||
|
Before Width: | Height: | Size: 128 B |
@@ -1 +0,0 @@
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|
||||
|
Before Width: | Height: | Size: 385 B |