diff --git a/README.md b/README.md new file mode 100644 index 0000000..d2111d4 --- /dev/null +++ b/README.md @@ -0,0 +1,160 @@ +# VoxCPM2 + vLLM-Omni + +PoC para servir o modelo `openbmb/VoxCPM2` com vLLM-Omni, usando GPU NVIDIA e Podman. + +O serviço expõe uma API compatível com OpenAI em `POST /v1/audio/speech` e oferece: + +- Síntese de voz em WAV; +- Streaming de áudio PCM `s16le`, mono, 48 kHz; +- Perfis de voz pré-calculados; +- Criação de novos perfis de voz em um container temporário. + +> Use somente áudios de referência com consentimento explícito e documentado. + +## Pré-requisitos + +No host: + +- Oracle Linux 9 ou outra distribuição Linux compatível; +- GPU NVIDIA compatível (a PoC foi validada em OCI `VM.GPU.A10.1`); +- Driver NVIDIA funcional; +- Podman e NVIDIA Container Toolkit/CDI configurados; +- Acesso à internet no primeiro build e primeiro boot. + +Valide a GPU no host: + +```bash +nvidia-smi -L +``` + +Valide o acesso à GPU pelo Podman: + +```bash +podman run --rm \ + --device nvidia.com/gpu=all \ + --security-opt label=disable \ + ubuntu \ + nvidia-smi -L +``` + +## Build + +```bash +git clone +cd voxcpm-vllm-omni + +mkdir -p runtime/hf-cache runtime/voices + +podman build --pull=newer \ + -t voxcpm-omni:0.28.0-1 \ + -f Containerfile . +``` + +## Executar o servidor + +Para acesso apenas local: + +```bash +podman run -d \ + --name voxcpm-omni \ + --restart=always \ + --device nvidia.com/gpu=all \ + --security-opt label=disable \ + --ipc=host \ + -p 127.0.0.1:8000:8000 \ + -v "$PWD/runtime/hf-cache:/root/.cache/huggingface" \ + -v "$PWD/runtime/voices:/opt/voices:ro" \ + voxcpm-omni:0.28.0-1 +``` + +No primeiro boot, o modelo será baixado para `runtime/hf-cache/`. + +```bash +podman logs -f voxcpm-omni +curl http://127.0.0.1:8000/v1/models +curl http://127.0.0.1:8000/v1/audio/voices +``` + +## Gerar WAV + +```bash +curl -sS -X POST http://127.0.0.1:8000/v1/audio/speech \ + -H "Content-Type: application/json" \ + -d '{ + "model": "openbmb/VoxCPM2", + "input": "Olá. Este é um teste de síntese de voz.", + "voice": "default", + "response_format": "wav" + }' \ + --output teste.wav +``` + +Para usar uma voz pre-processada, substitua `default` pelo nome do perfil, por exemplo `carbonera`. + +## Streaming PCM + +```bash +curl --no-buffer -sS -X POST http://127.0.0.1:8000/v1/audio/speech \ + -H "Content-Type: application/json" \ + -d '{ + "model": "openbmb/VoxCPM2", + "input": "Olá. Este é um teste de streaming.", + "voice": "default", + "stream": true, + "stream_format": "audio", + "response_format": "pcm" + }' \ + --output resposta.pcm +``` + +Formato retornado: PCM `s16le`, mono, 48 kHz. + +## Criar uma voz pre-processada + +Os arquivos de referência não devem ir para o Git. + +Com o serviço parado: + +```bash +podman stop voxcpm-omni + +PROMPT_TEXT="$(tr '\n' ' ' < "$PWD/reference-audio/nome-da-voz.txt")" + +podman run --rm \ + --device nvidia.com/gpu=all \ + --security-opt label=disable \ + --ipc=host \ + -v "$PWD/runtime/hf-cache:/root/.cache/huggingface" \ + -v "$PWD/runtime/voices:/opt/voices" \ + -v "$PWD/reference-audio/nome-da-voz.wav:/opt/input/voz.wav:ro" \ + voxcpm-omni:0.28.0-1 \ + python /opt/vllm-omni/examples/online_serving/text_to_speech/voxcpm2/precompute_custom_voice.py \ + --model openbmb/VoxCPM2 \ + --voice-name nome-da-voz \ + --ref-audio /opt/input/voz.wav \ + --prompt-text "$PROMPT_TEXT" \ + --mode ref_continuation \ + --output-dir /opt/voices \ + --device cuda + +podman start voxcpm-omni +``` + +Confira a nova voz: + +```bash +curl http://127.0.0.1:8000/v1/audio/voices +``` + +## Dados persistentes + +```text +runtime/hf-cache/ Pesos baixados do modelo +runtime/voices/ Perfis .safetensors e manifesto das vozes +``` + +Esses diretórios não são versionados no Git. Para migrar vozes aprovadas entre hosts, copie `runtime/voices/` por um canal seguro. + +## Segurança + +Não exponha a porta 8000 diretamente à internet sem controles adicionais. Para acesso remoto, restrinja firewall e NSG/Security List da OCI ao IP ou à rede autorizada e use um proxy reverso com TLS e autenticação. diff --git a/VOICE_CLONING_NOTICE.md b/VOICE_CLONING_NOTICE.md new file mode 100644 index 0000000..846d794 --- /dev/null +++ b/VOICE_CLONING_NOTICE.md @@ -0,0 +1,59 @@ +# Uso de clonagem de voz e responsabilidade + +> **Minuta para revisão jurídica.** Este aviso complementa a documentação do +> projeto; não substitui contratos, termos de uso, políticas de privacidade ou +> parecer jurídico aplicáveis ao operador do serviço. + +## Licença do código + +O código deste repositório é disponibilizado publicamente sob a Licença Apache +2.0, incluindo uso, alteração, distribuição e exploração comercial, nos termos +do arquivo [LICENSE](LICENSE). Componentes de terceiros, modelos, pesos e +dependências podem possuir licenças e condições próprias, que devem ser +observadas pelo usuário. + +## Responsabilidade por vozes, conteúdo e uso do serviço + +Quem implanta, administra, integra, fornece ou utiliza este serviço +("Operador") é exclusivamente responsável por: + +1. obter, registrar e manter todas as autorizações, consentimentos, licenças e + demais direitos necessários para gravar, enviar, processar, clonar, + sintetizar, reproduzir, distribuir ou explorar comercialmente qualquer voz, + áudio, texto, identidade ou outro conteúdo utilizado no serviço; +2. confirmar que a clonagem ou síntese não viola direitos de personalidade, + direitos autorais, direitos conexos, marcas, privacidade, proteção de dados, + obrigações contratuais ou qualquer lei, regulamento ou ordem aplicável; +3. informar adequadamente os titulares das vozes e os usuários finais sobre o + tratamento de dados e sobre o uso de voz sintética, quando exigido; +4. responder integralmente pela autoria, legitimidade, segurança, divulgação, + distribuição e utilização dos áudios e conteúdos gerados; e +5. manter controles técnicos e operacionais para impedir uso não autorizado, + enganoso, fraudulento ou que permita se passar por terceiro sem autorização. + +É proibido usar este projeto para clonar, imitar ou representar a voz de uma +pessoa sem a autorização válida do respectivo titular ou outro fundamento +jurídico aplicável. O Operador deverá fornecer, quando solicitado pela +autoridade competente ou pelo titular, evidências das autorizações e da base +legal adotada. + +## Ausência de responsabilidade da Oracle + +Na máxima extensão permitida pela legislação aplicável, a Oracle Corporation e +suas afiliadas não são autoras, provedoras, controladoras, operadoras, +coparticipantes, representantes ou garantidoras das vozes, áudios, perfis de +voz, conteúdos, resultados ou serviços criados, hospedados ou disponibilizados +pelo Operador a partir deste projeto. + +O Operador assume, de forma exclusiva, toda a responsabilidade por reclamações, +perdas, danos, sanções, custos e despesas decorrentes ou relacionados à coleta, +clonagem, síntese, geração, armazenamento, transmissão, publicação, +comercialização ou demais usos de vozes e conteúdos no serviço. Nada neste +repositório constitui autorização, endosso, garantia, parceria, agência, +sociedade ou coparticipação da Oracle com o Operador ou com os serviços por ele +oferecidos. + +Esta seção deve ser validada e, se necessário, substituída pelo texto aprovado +pelo departamento jurídico da Oracle antes de qualquer divulgação externa ou +uso contratual. Nenhuma pessoa pode vincular a Oracle ou suas afiliadas sem +autorização expressa e por escrito. diff --git a/config/voxcpm2-a10.yaml b/config/voxcpm2-a10.yaml new file mode 100644 index 0000000..ae773a8 --- /dev/null +++ b/config/voxcpm2-a10.yaml @@ -0,0 +1,54 @@ +# VoxCPM2 deploy: single-stage AR pipeline with per-request state batching. +# Runs on large (H20 141GB) and small (24GB L4) cards alike: the KV cache is +# pinned to a right-sized budget instead of ballooning to fill the card. +# +# VoxCPM2-local runtime knobs are passed through hf_overrides. +async_chunk: false +dtype: bfloat16 + +stages: + - stage_id: 0 + custom_voice_dir: /home/opc/voxcpm-vllm-poc/runtime/voices + max_num_seqs: 2 + #max_num_seqs: 8 + gpu_memory_utilization: 0.9 + # Right-size the KV cache instead of letting it fill gpu_memory_utilization. + # max_num_seqs(8) * max_model_len(4096) ~= 32k tokens; 6 GiB leaves headroom + # for longer live requests while keeping VoxCPM2 TTS decode batches small + # enough to avoid the high ITL observed with large admission caps. + # The remaining VRAM stays free for the VoxCPM2 diffusion side-path + # (LocDiT / AudioVAE / code2wav + batch CUDA-graph pools), which allocates + # outside vLLM's KV accounting during inference. Keeps peak ~13 GiB on any + # card and avoids per-rebase OOM tuning on small CI GPUs. + # Assumes prefix caching off and typical live decode concurrency <= ~8; + # raise this cap if either grows or enable_prefix_caching is turned on. + kv_cache_memory_bytes: 6442450944 # 6 GiB + enforce_eager: true + trust_remote_code: true + enable_prefix_caching: false + async_scheduling: true + max_num_batched_tokens: 4096 + max_model_len: 4096 + devices: "0" + engine_extras: + hf_overrides: + voxcpm2_runtime_config: + audio_emit_every: 1 + vae_decode_every: 3 + enable_batched_cfm: true + enable_batched_vae_decode: true + coalesce_audio_d2h: true + enable_loc_dit_fused_qkv: true + enable_loc_dit_fused_mlp: true + enable_loc_dit_zero_dt_cache: true + enable_loc_dit_skip_qkv_contig: true + enable_loc_dit_reduce_overhead_no_cg: true + enable_unified_decode_graph: true + unified_decode_graph_max_batch_size: 8 + default_sampling_params: + temperature: 0.0 + top_p: 1.0 + top_k: -1 + max_tokens: 4096 + seed: 42 + repetition_penalty: 1.0