Metadata-Version: 2.4
Name: ds2svc
Version: 0.1.0
Summary: Restore SVC models disguised as OpenUTAU/DiffSinger voicebanks
Author-email: Kakaru Hayate <kakaru.hayate@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/KakaruHayate/ds2svc
Project-URL: Repository, https://github.com/KakaruHayate/ds2svc.git
Project-URL: Bug Tracker, https://github.com/KakaruHayate/ds2svc/issues
Keywords: svc,rvc,ddsp,voice-conversion,diffsinger,onnx
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE.md
Requires-Dist: onnx>=1.14
Requires-Dist: onnxruntime>=1.16
Requires-Dist: numpy>=1.23
Requires-Dist: pyyaml>=6.0
Provides-Extra: infer
Requires-Dist: torch>=2.0; extra == "infer"
Requires-Dist: torchaudio>=2.0; extra == "infer"
Requires-Dist: transformers>=4.30; extra == "infer"
Requires-Dist: librosa>=0.10; extra == "infer"
Requires-Dist: soundfile; extra == "infer"
Provides-Extra: extract
Requires-Dist: torch>=2.0; extra == "extract"
Requires-Dist: librosa>=0.10; extra == "extract"
Requires-Dist: onnxslim; extra == "extract"
Provides-Extra: webui
Requires-Dist: streamlit>=1.30; extra == "webui"
Requires-Dist: soundfile; extra == "webui"
Provides-Extra: realtime
Requires-Dist: sounddevice; extra == "realtime"
Requires-Dist: FreeSimpleGUI; extra == "realtime"
Requires-Dist: torchfcpe; extra == "realtime"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Dynamic: license-file

# ds2svc

Restore SVC models that have been **disguised as OpenUTAU-compatible DiffSinger
voicebanks**, and run inference on the recovered model.

Some packed "DiffSinger" voicebanks in the wild are not DiffSinger at all — they
are existing SVC models (RVC, DDSP-SVC) repackaged to run on a DiffSinger ONNX
API. This harms the open community's trust and safety. `ds2svc` identifies such
banks, extracts the genuine SVC model back out, and provides inference.

## What it does

1. **Detect** — load a voicebank ZIP, read its yaml manifest, and inspect the
   ONNX **graph internals** (not just config) to decide whether it is a legitimate
   DiffSinger bank or a disguised SVC model.
2. **Extract** *(in progress)* — recover the SVC ONNX with clean inputs
   (`cvec_units` + `f0`).
3. **Infer** *(planned)* — Streamlit WebUI + realtime inference.

Supported disguises:

| Source | Based on | Disguise | Genuine model recovered |
|--------|----------|----------|--------------------------|
| [UTAI](https://github.com/SaigyoYuyuko/Utai) | [RVC](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI) | RVC packed as a "vocoder" | `(units[768], f0) → waveform` |
| [DDSP-SVS](https://github.com/myueqf/DDSP-SVS) | [DDSP-SVC](https://github.com/yxlllc/DDSP-SVC) | DDSP-SVC packed inside the "acoustic" model | `(units[768], f0, volume) → mel → pc-nsf-hifigan` |

## Detection signatures

Detection trusts the **ONNX graph**, not the config (config fields are easy to
fake, and unusual-but-legit banks exist):

- **UTAI / RVC** — the payload graph contains a normalizing flow (`net_g/flow`)
  beside `net_g/enc_p` and an NSF decoder `net_g/dec`: the RVC `SynthesizerTrn`.
- **DDSP-SVS** — the acoustic graph contains a real `STFT` op (legit DiffSinger
  acoustics have none) plus `ddsp_model/unit2ctrl`, `istft_method`, `melext`, and
  a `backend_reflow` ReFlow stage.
- DSP ops alone (`Sin`/`Cos`/`CumSum`/`RandomNormalLike`) are **not** used — they
  also appear in genuine DiffSinger diffusion backbones.

## Usage

```bash
pip install -e .[infer,realtime]
ds2svc detect path/to/bank.zip
ds2svc extract path/to/bank.zip --out artifacts/<id>
ds2svc infer artifacts/<id> --in vocal.wav --out converted.wav --f0 fcpe
ds2svc realtime artifacts/<id>
```

See [MANUAL_DOWNLOADS.md](MANUAL_DOWNLOADS.md) for offline weight installation.

## Status

- [x] Voicebank ZIP reader + manifest resolver (paths resolved relative to yaml)
- [x] ONNX graph probe + detection (RVC / DDSP-SVS / legit)
- [x] **UTAI/RVC extraction** — graph-surgery excision of the empty-index
      `TopK` chain, input rename `mel`→`cvec_units`. Output:
      `(cvec_units[1,T,768], f0[1,T]) → waveform[1,N]` at 44.1 kHz,
      `net_g` (encoder + flow + NSF decoder) preserved byte-for-byte.
- [x] **DDSP-SVS extraction** — bit-lossless weight-port into a rebuilt
      `Unit2Wav` (`CombSubSuperFast` + `RectifiedFlow`/`LYNXNet2`), re-exported
      as a **single** ONNX `(cvec_units[1,T,768], f0[1,T], volume[1,T]) →
      mel[1,T,128]` (ReFlow loop baked in). Pair with `pc-nsf-hifigan` for audio;
      the mel→wav stage can later be merged into this graph for a one-shot
      audio-output model.
- [x] **Inference frontend** — ContentVec (`lengyue233/content-vec-best`),
      f0 (fcpe/rmvpe), volume, pc-nsf-hifigan vocoder, and a unified
      `load_model(ModelDir) → infer(audio, sr, key_shift, f0_method)` that
      auto-selects RVC or DDSP path from ``ds2svc_meta.json``.
- [x] **Realtime GUI** — FreeSimpleGUI + sounddevice stream with sliding
      buffer, SOLA crossfade, correlation-based overlap alignment, f0=fcpe
      default. ``ds2svc realtime <model_dir>``.
- [x] **Streamlit WebUI** — drag-drop vocal WAV → convert → preview + download.
      Auto-caches model, persists output across re-renders.
      ``streamlit run ds2svc/webui/app.py``
- [x] [**Manual download guide**](MANUAL_DOWNLOADS.md) for offline weight
      placement, with per-file URLs and directory layout.

See [PLAN.md](PLAN.md) for the full design.

## Development

Tests reference private voicebanks by anonymized IDs. Copy
`tests/fixtures/local_banks.example.json` → `local_banks.json` (gitignored) and
point the IDs at your local archives, then:

```bash
pytest
```

## License

MIT. This project is for community safety and lawful recovery of open or
self-owned models. Respect the licenses of upstream RVC / DDSP-SVC / DiffSinger.
