Text-to-Speech
VoxCPM
English
voxcpm2
voice-cloning
quantization
fp8
torchao
w8a8
blackwell
english
v1
Instructions to use ajh-code/VoxCPM2-FP8-W8A8 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- VoxCPM
How to use ajh-code/VoxCPM2-FP8-W8A8 with VoxCPM:
import soundfile as sf from voxcpm import VoxCPM model = VoxCPM.from_pretrained("ajh-code/VoxCPM2-FP8-W8A8") wav = model.generate( text="VoxCPM is an innovative end-to-end TTS model from ModelBest, designed to generate highly expressive speech.", prompt_wav_path=None, # optional: path to a prompt speech for voice cloning prompt_text=None, # optional: reference text cfg_value=2.0, # LM guidance on LocDiT, higher for better adherence to the prompt, but maybe worse inference_timesteps=10, # LocDiT inference timesteps, higher for better result, lower for fast speed normalize=True, # enable external TN tool denoise=True, # enable external Denoise tool retry_badcase=True, # enable retrying mode for some bad cases (unstoppable) retry_badcase_max_times=3, # maximum retrying times retry_badcase_ratio_threshold=6.0, # maximum length restriction for bad case detection (simple but effective), it could be adjusted for slow pace speech ) sf.write("output.wav", wav, 16000) print("saved: output.wav") - Notebooks
- Google Colab
- Kaggle
Download validate_release.py from ajh-code/VoxCPM2-FP8-W8A8: direct link, hf CLI and curl.
- Browser
- Download file 5.16 kB
-
https://huggingface.co/ajh-code/VoxCPM2-FP8-W8A8/resolve/main/validate_release.py
- Command line
-
hf download hf://ajh-code/VoxCPM2-FP8-W8A8/validate_release.py
-
curl -L -o validate_release.py https://huggingface.co/ajh-code/VoxCPM2-FP8-W8A8/resolve/main/validate_release.py
5.16 kB
| #!/usr/bin/env python3 | |
| """Validate the self-contained VoxCPM2 FP8 W8A8 V1 release payload.""" | |
| from __future__ import annotations | |
| import hashlib | |
| import json | |
| import struct | |
| from pathlib import Path | |
| from typing import Any | |
| ROOT = Path(__file__).resolve().parent | |
| MANIFEST_PATH = ROOT / "MANIFEST.json" | |
| EXPECTED_FORMAT = "voxcpm2-torchao-fp8-static-v1" | |
| EXPECTED_SOURCE_REVISION = "32279effe8c19989596f05d353d1447f51d9e915" | |
| EXPECTED_MODEL_SHA256 = "fd86c0740d0faa9ba6017b28453851b68f754c3ac9b5d3051f0987e4a77cbd82" | |
| EXPECTED_QUANTIZED_MODULES = 424 | |
| IGNORED_TOP_LEVEL = {".cache", ".venv", "__pycache__"} | |
| def sha256(path: Path) -> str: | |
| digest = hashlib.sha256() | |
| with path.open("rb") as handle: | |
| for block in iter(lambda: handle.read(8 * 1024 * 1024), b""): | |
| digest.update(block) | |
| return digest.hexdigest() | |
| def distributed_files() -> set[str]: | |
| result: set[str] = set() | |
| for path in ROOT.rglob("*"): | |
| relative = path.relative_to(ROOT) | |
| if relative.parts[0] in IGNORED_TOP_LEVEL or not path.is_file(): | |
| continue | |
| if relative.as_posix() != "MANIFEST.json": | |
| result.add(relative.as_posix()) | |
| return result | |
| def safetensors_header(path: Path) -> dict[str, Any]: | |
| with path.open("rb") as handle: | |
| raw_length = handle.read(8) | |
| if len(raw_length) != 8: | |
| raise ValueError("Truncated safetensors length header") | |
| header_length = struct.unpack("<Q", raw_length)[0] | |
| if not 2 <= header_length <= 128 * 1024 * 1024: | |
| raise ValueError(f"Invalid safetensors header length: {header_length}") | |
| raw_header = handle.read(header_length) | |
| if len(raw_header) != header_length: | |
| raise ValueError("Truncated safetensors JSON header") | |
| value = json.loads(raw_header) | |
| if not isinstance(value, dict): | |
| raise ValueError("Safetensors header is not an object") | |
| return value | |
| def main() -> None: | |
| manifest = json.loads(MANIFEST_PATH.read_text(encoding="utf-8")) | |
| records = manifest.get("files") | |
| if manifest.get("schema_version") != 1 or not isinstance(records, dict): | |
| raise ValueError("Invalid release manifest") | |
| actual_files = distributed_files() | |
| if actual_files != set(records): | |
| missing = sorted(set(records) - actual_files) | |
| unexpected = sorted(actual_files - set(records)) | |
| raise ValueError(f"Release file set mismatch; missing={missing}, unexpected={unexpected}") | |
| for relative in sorted(records): | |
| path = ROOT / relative | |
| record = records[relative] | |
| actual_size = path.stat().st_size | |
| if actual_size != record.get("bytes"): | |
| raise ValueError(f"Size mismatch for {relative}") | |
| actual_hash = sha256(path) | |
| if actual_hash != record.get("sha256"): | |
| raise ValueError(f"SHA-256 mismatch for {relative}") | |
| print(f"ok {relative} {actual_size} bytes") | |
| fp8_config = json.loads((ROOT / "fp8_config.json").read_text(encoding="utf-8")) | |
| if fp8_config.get("format") != EXPECTED_FORMAT: | |
| raise ValueError("Unexpected FP8 artifact format") | |
| if fp8_config.get("source", {}).get("revision") != EXPECTED_SOURCE_REVISION: | |
| raise ValueError("Unexpected source revision") | |
| quantization = fp8_config.get("quantization", {}) | |
| selected = quantization.get("quantized_modules", []) | |
| state_names = quantization.get("fp8_state_names", []) | |
| if len(selected) != EXPECTED_QUANTIZED_MODULES or len(state_names) != EXPECTED_QUANTIZED_MODULES: | |
| raise ValueError("Unexpected FP8 module/state count") | |
| model_path = ROOT / fp8_config["artifact"]["model_file"] | |
| if fp8_config["artifact"].get("model_sha256") != EXPECTED_MODEL_SHA256: | |
| raise ValueError("FP8 config contains an unexpected model checksum") | |
| if records[model_path.name]["sha256"] != EXPECTED_MODEL_SHA256: | |
| raise ValueError("Manifest model checksum does not match the release checksum") | |
| header = safetensors_header(model_path) | |
| tensor_keys = set(header) - {"__metadata__"} | |
| for state_name in state_names: | |
| required = { | |
| state_name + ".__fp8_qdata", | |
| state_name + ".__fp8_scale", | |
| state_name + ".__fp8_activation_scale", | |
| } | |
| missing = required - tensor_keys | |
| if missing: | |
| raise ValueError(f"Missing FP8 tensors for {state_name}: {sorted(missing)}") | |
| config = json.loads((ROOT / "config.json").read_text(encoding="utf-8")) | |
| if config.get("architecture") != "voxcpm2" or config.get("audio_vae_config", {}).get("out_sample_rate") != 48000: | |
| raise ValueError("Unexpected VoxCPM2 architecture configuration") | |
| print( | |
| json.dumps( | |
| { | |
| "status": "valid", | |
| "files": len(records), | |
| "bytes": sum(record["bytes"] for record in records.values()), | |
| "model_sha256": EXPECTED_MODEL_SHA256, | |
| "quantized_modules": EXPECTED_QUANTIZED_MODULES, | |
| "source_revision": EXPECTED_SOURCE_REVISION, | |
| }, | |
| indent=2, | |
| sort_keys=True, | |
| ) | |
| ) | |
| if __name__ == "__main__": | |
| main() | |