ConectaPrimoAI commited on
Commit
16f9505
·
verified ·
1 Parent(s): 3cd6712

Upload folder using huggingface_hub

Browse files
__pycache__/armazenamento.cpython-311.pyc CHANGED
Binary files a/__pycache__/armazenamento.cpython-311.pyc and b/__pycache__/armazenamento.cpython-311.pyc differ
 
__pycache__/nucleo.cpython-311.pyc CHANGED
Binary files a/__pycache__/nucleo.cpython-311.pyc and b/__pycache__/nucleo.cpython-311.pyc differ
 
modelos/__pycache__/__init__.cpython-311.pyc CHANGED
Binary files a/modelos/__pycache__/__init__.cpython-311.pyc and b/modelos/__pycache__/__init__.cpython-311.pyc differ
 
modelos/__pycache__/ace_step.cpython-311.pyc CHANGED
Binary files a/modelos/__pycache__/ace_step.cpython-311.pyc and b/modelos/__pycache__/ace_step.cpython-311.pyc differ
 
modelos/__pycache__/base.cpython-311.pyc CHANGED
Binary files a/modelos/__pycache__/base.cpython-311.pyc and b/modelos/__pycache__/base.cpython-311.pyc differ
 
modelos/__pycache__/qwen3_tts.cpython-311.pyc CHANGED
Binary files a/modelos/__pycache__/qwen3_tts.cpython-311.pyc and b/modelos/__pycache__/qwen3_tts.cpython-311.pyc differ
 
modelos/__pycache__/wan22.cpython-311.pyc CHANGED
Binary files a/modelos/__pycache__/wan22.cpython-311.pyc and b/modelos/__pycache__/wan22.cpython-311.pyc differ
 
modelos/__pycache__/z_image.cpython-311.pyc CHANGED
Binary files a/modelos/__pycache__/z_image.cpython-311.pyc and b/modelos/__pycache__/z_image.cpython-311.pyc differ
 
modelos/qwen3_tts.py CHANGED
@@ -1,19 +1,22 @@
1
  # -*- coding: utf-8 -*-
2
  """
3
- NARRAÇÃO — Qwen3-TTS (variantes 0.6B / 1.7B), rodando na GPU do worker.
4
 
5
  O contrato de fora é o de sempre: texto entra, WAV sai. `voice` escolhe um
6
  timbre nomeado; `voice_reference` (um WAV curto em base64) liga o VOICE
7
- CLONING quando o modelo o suporta — o campo já existe no contrato para a
8
- tela não precisar de rota nova no dia em que for oferecido.
9
-
10
- HONESTIDADE DE CARGA: a chamada exata de geração (nomes de método e de
11
- parâmetro) tem de ser conferida contra o model card da versão baixada — o
12
- projeto Qwen troca detalhes entre releases, e este ambiente de desenvolvimento
13
- não alcança os pesos para provar a chamada. O que está aqui segue a API
14
- publicada do projeto; o MODELS.md marca este arquivo como "validar no primeiro
15
- deploy com GPU". Errar isso quebra ALTO (exceção no primeiro uso), não baixo —
16
- que é o jeito certo de errar.
 
 
 
17
  """
18
  from __future__ import annotations
19
 
@@ -32,20 +35,39 @@ VRAM_MINIMA_GB = 4
32
  _modelo_obj = None
33
  _modelo_carregado = ""
34
 
 
 
 
 
 
35
  # Timbres nomeados → os "speakers" do modelo. A tela mostra nomes nossos
36
  # (regra da casa: nome de provedor não chega à tela); a tradução mora aqui.
37
- _VOZES = {"default": "Vivian", "feminina": "Vivian", "masculina": "Ethan"}
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
 
40
  def _modelo() -> str:
41
- return os.getenv("TTS_MODEL", "Qwen/Qwen3-TTS-1.7B").strip()
42
 
43
 
44
  def baixar(progresso: base.Progresso) -> None:
45
  # A mesma revisão do carregar: baixar uma e carregar outra seria baixar
46
- # à toa e baixar DE NOVO dentro da GPU.
 
47
  base.baixar_repo(_modelo(), progresso,
48
  revision=os.getenv("TTS_MODEL_REV") or None)
 
49
 
50
 
51
  def carregar(progresso: base.Progresso) -> None:
@@ -57,22 +79,12 @@ def carregar(progresso: base.Progresso) -> None:
57
  return
58
  progresso(None, "Carregando o modelo de voz…")
59
  import torch
60
- from transformers import AutoModel, AutoProcessor
61
- # trust_remote_code: o Qwen3-TTS traz o código de inferência junto dos
62
- # pesos. É código de terceiro rodando NO WORKER — que não tem segredo
63
- # nenhum do app (ver GPU_WORKER.md); ainda assim, fixe a revisão em
64
- # produção (TTS_MODEL_REV) para o código não trocar sob os seus pés.
65
- rev = os.getenv("TTS_MODEL_REV") or None
66
- _modelo_obj = {
67
- "proc": AutoProcessor.from_pretrained(_modelo(), revision=rev,
68
- trust_remote_code=True,
69
- token=os.getenv("HF_TOKEN") or None),
70
- "model": AutoModel.from_pretrained(_modelo(), revision=rev,
71
- torch_dtype=torch.bfloat16,
72
- trust_remote_code=True,
73
- token=os.getenv("HF_TOKEN") or None
74
- ).to(base.dispositivo()).eval(),
75
- }
76
  _modelo_carregado = _modelo()
77
 
78
 
@@ -84,31 +96,24 @@ def gerar(params: Dict, progresso: base.Progresso) -> base.Saida:
84
  if not texto:
85
  raise ValueError("nada para narrar")
86
  voz = _VOZES.get((params.get("voice") or "default").lower(),
87
- params.get("voice") or "Vivian")
88
- idioma = params.get("language") or "pt-BR"
89
 
90
  progresso(None, "Gerando a narração…")
91
- modelo, proc = _modelo_obj["model"], _modelo_obj["proc"]
92
 
93
- referencia = None
94
- if params.get("voice_reference"):
95
- # Voice cloning: o WAV de referência chega em base64 pelo backend.
 
96
  referencia = io.BytesIO(b64.b64decode(
97
  params["voice_reference"].split(",")[-1]))
 
 
 
 
 
98
 
99
- import torch
100
- with torch.no_grad():
101
- if referencia is not None and hasattr(modelo, "clone"):
102
- onda, taxa = modelo.clone(text=texto, reference=referencia,
103
- language=idioma)
104
- else:
105
- entradas = proc(text=texto, speaker=voz, language=idioma,
106
- return_tensors="pt").to(base.dispositivo())
107
- saida = modelo.generate(**entradas)
108
- onda = saida.audio if hasattr(saida, "audio") else saida[0]
109
- taxa = getattr(saida, "sampling_rate", 24000)
110
-
111
- return _wav_de(onda, taxa), "audio/wav"
112
 
113
 
114
  def descarregar() -> None:
 
1
  # -*- coding: utf-8 -*-
2
  """
3
+ NARRAÇÃO — Qwen3-TTS 12Hz (CustomVoice), pelo pacote oficial `qwen-tts`.
4
 
5
  O contrato de fora é o de sempre: texto entra, WAV sai. `voice` escolhe um
6
  timbre nomeado; `voice_reference` (um WAV curto em base64) liga o VOICE
7
+ CLONING quando o checkpoint o suporta (é o Base que clona; o CustomVoice tem
8
+ os 9 timbres prontos) — o campo já existe no contrato para a tela não
9
+ precisar de rota nova no dia em que for oferecido.
10
+
11
+ DUAS COISAS MEDIDAS NA PRIMEIRA VALIDAÇÃO REAL, e que não se desfazem:
12
+
13
+ - `Qwen/Qwen3-TTS-1.7B` NÃO EXISTE no Hub (404 na primeira geração real).
14
+ Os pesos publicados são os `Qwen3-TTS-12Hz-*`; o padrão daqui é o
15
+ `12Hz-1.7B-CustomVoice`, que é o que dá timbres nomeados ao Estúdio.
16
+ - A chamada NÃO é AutoProcessor/AutoModel + trust_remote_code: o projeto
17
+ publica o pacote `qwen-tts` (PyPI) com `Qwen3TTSModel.from_pretrained` e
18
+ `generate_custom_voice(text, language, speaker, instruct)`. O card do
19
+ modelo é explícito; adivinhar a forma via AutoModel quebraria alto.
20
  """
21
  from __future__ import annotations
22
 
 
35
  _modelo_obj = None
36
  _modelo_carregado = ""
37
 
38
+ # O decodificador de áudio dos 12Hz — baixado junto, porque o qwen-tts o
39
+ # busca por nome na primeira geração e o download tem de acontecer FORA da
40
+ # chamada de GPU (ver base.baixar_repo).
41
+ _TOKENIZER_12HZ = "Qwen/Qwen3-TTS-Tokenizer-12Hz"
42
+
43
  # Timbres nomeados → os "speakers" do modelo. A tela mostra nomes nossos
44
  # (regra da casa: nome de provedor não chega à tela); a tradução mora aqui.
45
+ # Os 9 do CustomVoice: Vivian, Serena, Uncle_Fu, Dylan, Eric, Ryan, Aiden,
46
+ # Ono_Anna, Sohee — nenhum é nativo de português, mas todos falam as 10
47
+ # línguas do modelo (o card diz; Serena é a voz quente feminina, Ryan a
48
+ # masculina clara).
49
+ _VOZES = {"default": "Serena", "feminina": "Serena", "masculina": "Ryan"}
50
+
51
+ # O idioma do pedido chega como código BCP-47; o generate_custom_voice quer
52
+ # o NOME em inglês ("Portuguese"), ou "Auto" para adaptativo.
53
+ _IDIOMAS = {"pt": "Portuguese", "pt-br": "Portuguese", "pt-pt": "Portuguese",
54
+ "en": "English", "en-us": "English", "es": "Spanish",
55
+ "fr": "French", "de": "German", "it": "Italian",
56
+ "ja": "Japanese", "ko": "Korean", "ru": "Russian",
57
+ "zh": "Chinese", "zh-cn": "Chinese"}
58
 
59
 
60
  def _modelo() -> str:
61
+ return os.getenv("TTS_MODEL", "Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice").strip()
62
 
63
 
64
  def baixar(progresso: base.Progresso) -> None:
65
  # A mesma revisão do carregar: baixar uma e carregar outra seria baixar
66
+ # à toa e baixar DE NOVO dentro da GPU. O tokenizer 12Hz vai junto —
67
+ # sem ele aquecido, a primeira geração o baixaria DENTRO da GPU.
68
  base.baixar_repo(_modelo(), progresso,
69
  revision=os.getenv("TTS_MODEL_REV") or None)
70
+ base.baixar_repo(_TOKENIZER_12HZ, progresso)
71
 
72
 
73
  def carregar(progresso: base.Progresso) -> None:
 
79
  return
80
  progresso(None, "Carregando o modelo de voz…")
81
  import torch
82
+ from qwen_tts import Qwen3TTSModel
83
+ # Sem attn_implementation="flash_attention_2": o flash-attn não está na
84
+ # imagem (compilar ele num build de Space leva mais que o build inteiro)
85
+ # e o padrão do transformers funciona — mais lento, mas existe.
86
+ _modelo_obj = Qwen3TTSModel.from_pretrained(
87
+ _modelo(), device_map=base.dispositivo(), dtype=torch.bfloat16)
 
 
 
 
 
 
 
 
 
 
88
  _modelo_carregado = _modelo()
89
 
90
 
 
96
  if not texto:
97
  raise ValueError("nada para narrar")
98
  voz = _VOZES.get((params.get("voice") or "default").lower(),
99
+ params.get("voice") or "Serena")
100
+ idioma = _IDIOMAS.get((params.get("language") or "pt-BR").lower(), "Auto")
101
 
102
  progresso(None, "Gerando a narração…")
 
103
 
104
+ if params.get("voice_reference") and hasattr(_modelo_obj,
105
+ "generate_voice_clone"):
106
+ # Voice cloning (checkpoint Base): o WAV de referência chega em
107
+ # base64 pelo backend.
108
  referencia = io.BytesIO(b64.b64decode(
109
  params["voice_reference"].split(",")[-1]))
110
+ ondas, taxa = _modelo_obj.generate_voice_clone(
111
+ text=texto, language=idioma, reference_audio=referencia)
112
+ else:
113
+ ondas, taxa = _modelo_obj.generate_custom_voice(
114
+ text=texto, language=idioma, speaker=voz)
115
 
116
+ return _wav_de(ondas[0], taxa), "audio/wav"
 
 
 
 
 
 
 
 
 
 
 
 
117
 
118
 
119
  def descarregar() -> None:
requirements.txt CHANGED
@@ -16,6 +16,11 @@ diffusers>=0.34
16
  transformers>=4.51
17
  accelerate>=1.2
18
  safetensors>=0.5
 
 
 
 
 
19
  Pillow==11.1.0
20
  imageio==2.36.1
21
  imageio-ffmpeg==0.6.0
 
16
  transformers>=4.51
17
  accelerate>=1.2
18
  safetensors>=0.5
19
+ # A voz vem pelo pacote OFICIAL do projeto (Qwen3TTSModel + os checkpoints
20
+ # 12Hz) — a primeira validação real provou que AutoModel não serve: o id
21
+ # antigo nem existia no Hub. Ele pina transformers==4.57.3, que satisfaz o
22
+ # >=4.51 do Z-Image — os dois convivem.
23
+ qwen-tts>=0.1.1
24
  Pillow==11.1.0
25
  imageio==2.36.1
26
  imageio-ffmpeg==0.6.0