Finding a good balance

This commit is contained in:
2026-05-31 00:50:46 -05:00
parent 5578b84fd8
commit bee1ed65a4
8 changed files with 453 additions and 117 deletions
+3
View File
@@ -0,0 +1,3 @@
[submodule "MioCodec"]
path = MioCodec
url = https://github.com/Aratako/MioCodec
Submodule
+1
Submodule MioCodec added at 7747354437
Binary file not shown.
+413
View File
@@ -0,0 +1,413 @@
import argparse
import math
import queue
import threading
import time
from pathlib import Path
import numpy as np
import sounddevice as sd
import soundfile as sf
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchaudio
from miocodec.model import MioCodecModel
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
import gc
class StreamingISTFT:
def __init__(self, n_fft, hop, device):
self.n_fft = n_fft
self.win = n_fft
self.hop = hop
self.pad = (self.win - hop) // 2
self.window = torch.hann_window(self.win, device=device)
self.win_sq = (self.window**2).view(1, -1, 1)
self.carry = self.win - self.hop
self.tail_y = torch.zeros(1, 0, device=device)
self.tail_e = torch.zeros(1, 0, device=device)
self.started = False
def reset(self):
self.tail_y = self.tail_y[:, :0]
self.tail_e = self.tail_e[:, :0]
self.started = False
def process(self, spec):
T = spec.shape[-1]
ifft = torch.fft.irfft(spec, self.n_fft, dim=1, norm="backward") * self.window.view(1, -1, 1)
region = (T - 1) * self.hop + self.win
y = F.fold(ifft, (1, region), (1, self.win), stride=(1, self.hop))[:, 0, 0, :]
e = F.fold(self.win_sq.expand(1, self.win, T), (1, region), (1, self.win), stride=(1, self.hop))[:, 0, 0, :]
tl = self.tail_y.shape[-1]
if tl:
y[:, :tl] += self.tail_y
e[:, :tl] += self.tail_e
emit = region - self.carry
out = y[:, :emit] / e[:, :emit].clamp(min=1e-8)
self.tail_y = y[:, emit:].clone()
self.tail_e = e[:, emit:].clone()
if not self.started:
out = out[:, self.pad:]
self.started = True
return out.squeeze(0)
class StreamingVC:
def __init__(self, model, device, *, chunk=6, enc_left=48, enc_right=2,
dec_left=32, dec_right=3, ema_alpha=0.9):
self.m = model.to(device).eval()
self.dev = device
c = model.config
ssl_fps = self.m.ssl_feature_extractor.ssl_sample_rate // self.m.ssl_feature_extractor.hop_size
self.token_hz = ssl_fps // c.downsample_factor
self.sr = c.sample_rate
self.tok_samples = self.sr // self.token_hz
ups_total = self.m.wave_upsampler.total_upsample_factor
self.frames_per_tok = c.wave_upsample_factor * ups_total
assert self.frames_per_tok * c.hop_length == self.tok_samples, "token/frame/sample ratios disagree"
self.chunk = chunk
self.enc_left, self.enc_right = enc_left, enc_right
self.dec_left, self.dec_right = dec_left, dec_right
self.local_layers = list(self.m.local_ssl_layers)
self.istft = StreamingISTFT(c.n_fft, c.hop_length, device)
self.global_emb = None
self.src_mean = self.src_std = None
self.tokens = None
self.decoded = 0
self.ema_alpha = ema_alpha
self.prev_local_feats = None
def _raw_local(self, audio):
feats = self.m.ssl_feature_extractor(audio.to(self.dev))
sel = [feats[i - 1] for i in self.local_layers]
return torch.stack(sel, 0).mean(0) if len(sel) > 1 else sel[0]
def apply_ema(self, local_feats):
if self.prev_local_feats is not None and local_feats.shape == self.prev_local_feats.shape:
local_feats = self.ema_alpha * local_feats + (1.0 - self.ema_alpha) * self.prev_local_feats
self.prev_local_feats = local_feats.clone()
return local_feats
@torch.inference_mode()
def set_target(self, ref_audio):
feats = self.m.encode(ref_audio.to(self.dev), return_content=False, return_global=True)
self.global_emb = feats.global_embedding.view(1, -1)
def _encode_features(self, loc):
loc_norm = (loc - self.src_mean) / (self.src_std + 1e-8)
enc = self.m.local_encoder(loc_norm)
enc = self.m.conv_downsample(enc.transpose(1, 2)).transpose(1, 2)
_, idx = self.m.local_quantizer.encode(enc)
return idx
@torch.inference_mode()
def seed(self, seed_audio):
self.reset()
if seed_audio.dim() == 1:
seed_audio = seed_audio.unsqueeze(0)
loc = self._raw_local(seed_audio)
self.src_mean = loc.mean(dim=1, keepdim=True).clone()
self.src_std = loc.std(dim=1, keepdim=True).clone()
idx = self._encode_features(loc)
self.tokens = idx.clone()
self.decoded = idx.shape[1]
def reset(self):
self.istft.reset()
self.tokens = None
self.decoded = 0
self.prev_local_feats = None
@torch.inference_mode()
def _encode(self, window_audio):
loc = self._raw_local(window_audio)
loc = self.apply_ema(loc)
return self._encode_features(loc)
@torch.inference_mode()
def _wave_stages(self, tok_window):
Tw = tok_window.shape[1]
emb = self.m.local_quantizer.decode(tok_window)
x = self.m.wave_prenet(emb)
x = self.m.wave_conv_upsample(x.transpose(1, 2)).transpose(1, 2)
x = F.interpolate(x.transpose(1, 2), size=2 * Tw, mode=self.m.config.wave_interpolation_mode).transpose(1, 2)
x = self.m.wave_prior_net(x.transpose(1, 2)).transpose(1, 2)
x = self.m.wave_decoder(x, condition=self.global_emb.unsqueeze(1))
x = self.m.wave_post_net(x.transpose(1, 2)).transpose(1, 2)
return self.m.wave_upsampler(x.transpose(1, 2))
@torch.inference_mode()
def _decode(self, tok_window, keep_left, keep_n):
x = self._wave_stages(tok_window)
h = self.m.istft_head.out(x).transpose(1, 2)
mag, phase = h.chunk(2, dim=1)
mag = torch.exp(mag).clamp(max=1e2)
spec = torch.complex(mag * torch.cos(phase), mag * torch.sin(phase))
f0 = keep_left * self.frames_per_tok
f1 = (keep_left + keep_n) * self.frames_per_tok
return self.istft.process(spec[..., f0:f1])
def _commit_tokens(self, new_idx):
self.tokens = new_idx if self.tokens is None else torch.cat([self.tokens, new_idx], dim=1)
def _drain(self, final=False):
out = []
committed = self.tokens.shape[1]
while True:
d0 = self.decoded
avail = committed - d0
if avail <= 0 or (not final and avail < self.chunk + self.dec_right):
break
keep_n = min(self.chunk, avail) if final else self.chunk
left = min(self.dec_left, d0)
right = min(self.dec_right, committed - (d0 + keep_n))
win = self.tokens[:, d0 - left: d0 + keep_n + right]
out.append(self._decode(win, left, keep_n))
self.decoded += keep_n
return torch.cat(out) if out else torch.zeros(0, device=self.dev)
def list_devices():
print(f"{'idx':>4} {'name':<50} {'in':>3} {'out':>3} {'sr':>7}")
print("-" * 76)
for i, d in enumerate(sd.query_devices()):
print(f"{i:>4} {d['name']:<50} {d['max_input_channels']:>3} {d['max_output_channels']:>3} {int(d['default_samplerate']):>7}")
def sync_time(fn):
if DEVICE.type == "cuda":
torch.cuda.synchronize()
t0 = time.perf_counter()
out = fn()
if DEVICE.type == "cuda":
torch.cuda.synchronize()
return out, (time.perf_counter() - t0) * 1000
def load_audio(path, target_sr):
a, sr = sf.read(path, dtype="float32", always_2d=True)
a = a.mean(axis=1)
if sr != target_sr:
print(f"Resampling {path.name} from {sr} Hz to {target_sr} Hz...")
tensor = torch.from_numpy(a)
tensor = torchaudio.functional.resample(tensor, orig_freq=sr, new_freq=target_sr)
else:
tensor = torch.from_numpy(a)
p = torch.abs(tensor).max()
return tensor / p if p > 1e-8 else tensor
def main():
gc.collect()
gc.freeze()
gc.disable()
parser = argparse.ArgumentParser()
parser.add_argument("--list-devices", action="store_true")
parser.add_argument("--input", type=int)
parser.add_argument("--output", type=int)
parser.add_argument("--target", type=Path, help="Target voice reference WAV")
parser.add_argument("--seed-audio", type=Path, help="Seed speaker calibration WAV (optional)")
parser.add_argument("--chunk", type=int, default=6)
parser.add_argument("--enc-left", type=int, default=48)
parser.add_argument("--enc-right", type=int, default=2)
parser.add_argument("--dec-left", type=int, default=32)
parser.add_argument("--dec-right", type=int, default=3)
parser.add_argument("--ema-alpha", type=float, default=0.9,
help="EMA smoothing on local SSL features (0=full smoothing, 1=no smoothing)")
parser.add_argument("--rms-floor", type=float, default=0.0035,
help="RMS threshold below which audio chunk is evaluated as silence")
parser.add_argument("--hangover-chunks", type=int, default=5,
help="Number of chunks to hold the gate open after RMS drop")
parser.add_argument("--silence-fade-ms", type=float, default=10.0,
help="Ramp-down duration in ms at silence boundary (0 to disable)")
args = parser.parse_args()
if args.list_devices:
list_devices()
return
if args.input is None or args.output is None:
parser.error("--input and --output required")
model = MioCodecModel.from_pretrained("Aratako/MioCodec-25Hz-44.1kHz-v2")
vc = StreamingVC(
model, DEVICE, chunk=args.chunk, enc_left=args.enc_left, enc_right=args.enc_right,
dec_left=args.dec_left, dec_right=args.dec_right, ema_alpha=args.ema_alpha
)
sr = vc.sr
ts = vc.tok_samples
chunk_samples = vc.chunk * ts
left_pad = vc.enc_left * ts
right_pad = vc.enc_right * ts
budget_ms = (vc.chunk / vc.token_hz) * 1000
fade_samples = int(args.silence_fade_ms * 0.001 * sr)
print(f"Sample Rate: {sr} Hz | Chunk: {args.chunk} tokens ({budget_ms:.1f}ms budget)")
print(f"EMA alpha: {args.ema_alpha} | Silence fade: {args.silence_fade_ms:.0f}ms")
print(f"Loading target speaker profile: {args.target}...")
target_audio = load_audio(args.target, sr)
vc.set_target(target_audio)
in_info = sd.query_devices(args.input)
n_in_ch = min(in_info["max_input_channels"], 2)
if args.seed_audio:
print(f"Loading speaker calibration profile: {args.seed_audio}...")
seed_audio = load_audio(args.seed_audio, sr)
else:
print("\n" + "=" * 60)
print("No seed-audio provided. Recording 3 seconds for normalization calibration.")
print("Please speak into your microphone...")
print("=" * 60)
recorded = sd.rec(int(3.0 * sr), samplerate=sr, channels=n_in_ch, dtype="float32")
sd.wait()
print("Recording complete. Calibrating feature scaling...")
recorded_mono = recorded.mean(axis=1) if recorded.shape[1] > 1 else recorded[:, 0]
seed_audio = torch.from_numpy(recorded_mono)
print("Seeding streaming context from speaker profile...")
vc.seed(seed_audio)
if seed_audio.numel() >= left_pad:
raw_input_accum = seed_audio[-left_pad:].numpy()
else:
raw_input_accum = np.pad(seed_audio.numpy(), (left_pad - seed_audio.numel(), 0))
in_q = queue.Queue(maxsize=8)
out_q = queue.Queue(maxsize=2)
stop_event = threading.Event()
def input_cb(indata, frames, time_info, status):
if in_q.full():
in_q.get_nowait()
mono = indata.mean(axis=1) if indata.shape[1] > 1 else indata[:, 0]
in_q.put_nowait(mono.copy())
def write_thread(out_stream):
while not stop_event.is_set():
try:
pcm = out_q.get(timeout=0.5)
out_stream.write(pcm)
except queue.Empty:
continue
print(f"\n{'chunk':>6} {'q_in':>4} {'q_out':>5} {'enc':>7} {'dec':>7} {'total':>7} {'budget':>7} {'gap':>7}")
print("-" * 76)
chunk_n = 0
t_last = None
hangover_counter = 0
if fade_samples > 0:
ramp_down = np.linspace(1.0, 0.0, fade_samples, dtype=np.float32)
with sd.InputStream(device=args.input, channels=n_in_ch, samplerate=sr,
blocksize=chunk_samples, dtype="float32",
callback=input_cb, latency="low"):
with sd.OutputStream(device=args.output, channels=2, samplerate=sr,
dtype="float32", latency="low") as out_stream:
writer = threading.Thread(target=write_thread, args=(out_stream,), daemon=True)
writer.start()
try:
while True:
raw = in_q.get()
t_now = time.perf_counter()
gap_ms = (t_now - t_last) * 1000 if t_last else 0.0
t_last = t_now
rms = float(np.sqrt(np.mean(raw ** 2)))
if rms >= args.rms_floor:
hangover_counter = args.hangover_chunks
is_silence = False
else:
if hangover_counter > 0:
hangover_counter -= 1
is_silence = False
else:
is_silence = True
raw_input_accum = np.concatenate([raw_input_accum, raw])
required_samples = left_pad + chunk_samples + right_pad
if len(raw_input_accum) >= required_samples:
window_np = raw_input_accum[:required_samples]
raw_input_accum = raw_input_accum[chunk_samples:]
if is_silence:
window_np = window_np.copy()
active_start = left_pad
active_end = left_pad + chunk_samples
if fade_samples > 0:
fade_end = active_start + fade_samples
window_np[active_start:fade_end] *= ramp_down
window_np[fade_end:active_end] = 0.0
else:
window_np[active_start:active_end] = 0.0
window_torch = torch.from_numpy(window_np).unsqueeze(0).to(DEVICE)
with torch.no_grad():
idx, t_enc = sync_time(lambda: vc._encode(window_torch))
chunk_tokens = idx[:, vc.enc_left : vc.enc_left + vc.chunk]
vc._commit_tokens(chunk_tokens)
audio_out, t_dec = sync_time(lambda: vc._drain(final=False))
if audio_out.numel() == 0:
pcm_out = np.zeros((chunk_samples, 2), dtype=np.float32)
else:
pcm = audio_out.cpu().numpy()
pcm = np.clip(pcm, -1.0, 1.0)
pcm_out = np.stack([pcm, pcm], axis=1)
else:
pcm_out = np.zeros((chunk_samples, 2), dtype=np.float32)
t_enc, t_dec = 0.0, 0.0
out_q.put(pcm_out)
total = t_enc + t_dec
chunk_n += 1
if is_silence:
print(
f"{chunk_n:>6} {in_q.qsize():>4} {out_q.qsize():>5} "
f"{'--silence--':>31} rms={rms:.4f}",
flush=True,
)
else:
print(
f"{chunk_n:>6} {in_q.qsize():>4} {out_q.qsize():>5} "
f"{t_enc:>6.1f}ms {t_dec:>6.1f}ms "
f"{total:>6.1f}ms {budget_ms:>6.0f}ms {gap_ms:>6.1f}ms",
flush=True,
)
except KeyboardInterrupt:
pass
finally:
stop_event.set()
writer.join()
print("stopped")
if __name__ == "__main__":
main()
+2 -2
View File
@@ -100,7 +100,7 @@ class StreamingVCONNX:
opts = ort.SessionOptions() opts = ort.SessionOptions()
opts.inter_op_num_threads = 1 opts.inter_op_num_threads = 1
opts.intra_op_num_threads = 0 opts.intra_op_num_threads = 4
opts.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL opts.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL
opts.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL opts.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
@@ -123,7 +123,7 @@ class StreamingVCONNX:
self.tokens = None self.tokens = None
self.decoded = 0 self.decoded = 0
self.prev_local_feats = None self.prev_local_feats = None
self.ema_alpha = 0.4 self.ema_alpha = 0.9
def _ssl(self, win16): def _ssl(self, win16):
w = take(win16, 0, self.ssl_in).reshape(1, -1) w = take(win16, 0, self.ssl_in).reshape(1, -1)
+34
View File
@@ -0,0 +1,34 @@
# optimize_models.py
from onnxruntime.transformers.optimizer import optimize_model
from onnxruntime.transformers.fusion_options import FusionOptions
def optimize_custom(input_path, output_path):
print(f"Optimizing {input_path}...")
# Load default BERT fusion options
options = FusionOptions("bert")
# Disable LayerNorm fusions that break on AdaLN / dynamic biases
options.enable_skip_layer_norm = False
options.enable_layer_norm = False
# Run the optimizer
optimizer = optimize_model(
input=input_path,
model_type="bert",
optimization_options=options
)
optimizer.save_model_to_file(output_path)
print(f"Saved optimized model to {output_path}\n")
if __name__ == "__main__":
optimize_custom("outputs/encode.onnx", "outputs/encode_opt.onnx")
optimize_custom("outputs/decode.onnx", "outputs/decode_opt.onnx")
# ssl.onnx (WavLM) is a standard BERT architecture, so we can leave
# all standard fusions enabled for maximum speed.
print("Optimizing outputs/ssl.onnx...")
ssl_opt = optimize_model("outputs/ssl.onnx", model_type="bert")
ssl_opt.save_model_to_file("outputs/ssl_opt.onnx")
print("Saved optimized model to outputs/ssl_opt.onnx")
-2
View File
@@ -10,10 +10,8 @@ dependencies = [
"onnxruntime>=1.26.0", "onnxruntime>=1.26.0",
"onnxruntime-gpu>=1.26.0", "onnxruntime-gpu>=1.26.0",
"onnxruntime-openvino>=1.24.1", "onnxruntime-openvino>=1.24.1",
"onnxruntime-tools>=1.7.0",
"onnxscript>=0.7.0", "onnxscript>=0.7.0",
"sounddevice>=0.5.5", "sounddevice>=0.5.5",
"sympy>=1.14.0",
"torch>=2.11.0", "torch>=2.11.0",
] ]
Generated
-113
View File
@@ -121,18 +121,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
] ]
[[package]]
name = "coloredlogs"
version = "15.0.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "humanfriendly" },
]
sdist = { url = "https://files.pythonhosted.org/packages/cc/c7/eed8f27100517e8c0e6b923d5f0845d0cb99763da6fdee00478f91db7325/coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0", size = 278520, upload-time = "2021-06-11T10:22:45.202Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", size = 46018, upload-time = "2021-06-11T10:22:42.561Z" },
]
[[package]] [[package]]
name = "cuda-bindings" name = "cuda-bindings"
version = "12.9.7" version = "12.9.7"
@@ -223,10 +211,8 @@ dependencies = [
{ name = "onnxruntime" }, { name = "onnxruntime" },
{ name = "onnxruntime-gpu" }, { name = "onnxruntime-gpu" },
{ name = "onnxruntime-openvino" }, { name = "onnxruntime-openvino" },
{ name = "onnxruntime-tools" },
{ name = "onnxscript" }, { name = "onnxscript" },
{ name = "sounddevice" }, { name = "sounddevice" },
{ name = "sympy" },
{ name = "torch", version = "2.11.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "torch", version = "2.11.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "torch", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform != 'linux' and sys_platform != 'win32'" }, { name = "torch", version = "2.12.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform != 'linux' and sys_platform != 'win32'" },
] ]
@@ -238,10 +224,8 @@ requires-dist = [
{ name = "onnxruntime", specifier = ">=1.26.0" }, { name = "onnxruntime", specifier = ">=1.26.0" },
{ name = "onnxruntime-gpu", specifier = ">=1.26.0" }, { name = "onnxruntime-gpu", specifier = ">=1.26.0" },
{ name = "onnxruntime-openvino", specifier = ">=1.24.1" }, { name = "onnxruntime-openvino", specifier = ">=1.24.1" },
{ name = "onnxruntime-tools", specifier = ">=1.7.0" },
{ name = "onnxscript", specifier = ">=0.7.0" }, { name = "onnxscript", specifier = ">=0.7.0" },
{ name = "sounddevice", specifier = ">=0.5.5" }, { name = "sounddevice", specifier = ">=0.5.5" },
{ name = "sympy", specifier = ">=1.14.0" },
{ name = "torch", specifier = ">=2.11.0" }, { name = "torch", specifier = ">=2.11.0" },
] ]
@@ -370,18 +354,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/02/28/d7cef5e477b855c25d415b8f57e5bc7347c7a90cad3acf1725d0c92ca294/huggingface_hub-1.17.0-py3-none-any.whl", hash = "sha256:3b8156d23118e87f6a587648bfbc04f04a12a757ccb4ed298b35c4ae638bf24c", size = 671546, upload-time = "2026-05-28T15:12:11.441Z" }, { url = "https://files.pythonhosted.org/packages/02/28/d7cef5e477b855c25d415b8f57e5bc7347c7a90cad3acf1725d0c92ca294/huggingface_hub-1.17.0-py3-none-any.whl", hash = "sha256:3b8156d23118e87f6a587648bfbc04f04a12a757ccb4ed298b35c4ae638bf24c", size = 671546, upload-time = "2026-05-28T15:12:11.441Z" },
] ]
[[package]]
name = "humanfriendly"
version = "10.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pyreadline3", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/cc/3f/2c29224acb2e2df4d2046e4c73ee2662023c58ff5b113c4c1adac0886c43/humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc", size = 360702, upload-time = "2021-09-17T21:40:43.31Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", size = 86794, upload-time = "2021-09-17T21:40:39.897Z" },
]
[[package]] [[package]]
name = "idna" name = "idna"
version = "3.17" version = "3.17"
@@ -934,24 +906,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/3e/92/46ae2cd565961a89189900f385bb2f13a9fa731ea4674001d23720fbb1e0/onnxruntime_openvino-1.24.1-cp313-cp313-win_amd64.whl", hash = "sha256:434bf49aa71393c577a456c9d76c98e6d6958a833fa0876793e3d5437b5a511a", size = 13658485, upload-time = "2026-02-26T13:44:53.889Z" }, { url = "https://files.pythonhosted.org/packages/3e/92/46ae2cd565961a89189900f385bb2f13a9fa731ea4674001d23720fbb1e0/onnxruntime_openvino-1.24.1-cp313-cp313-win_amd64.whl", hash = "sha256:434bf49aa71393c577a456c9d76c98e6d6958a833fa0876793e3d5437b5a511a", size = 13658485, upload-time = "2026-02-26T13:44:53.889Z" },
] ]
[[package]]
name = "onnxruntime-tools"
version = "1.7.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "coloredlogs" },
{ name = "numpy" },
{ name = "onnx" },
{ name = "packaging" },
{ name = "psutil" },
{ name = "py-cpuinfo" },
{ name = "py3nvml" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fd/b5/c36283fef3b1d492a39d1b5f3f195965fbf002b168633daad302c51d8f4c/onnxruntime_tools-1.7.0.tar.gz", hash = "sha256:6dbdcee49424e066bcd10357c37d51bc422ae26494e3c2f0c1970d534f967f6d", size = 141435, upload-time = "2021-03-25T21:42:42.571Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6f/b0/db0e73356df0aaa8737e6f13c0dac499b5d904d3fa267c8ebf24515e8001/onnxruntime_tools-1.7.0-py3-none-any.whl", hash = "sha256:1dff888b5c482ac5bc627f12e108445fefcb3d600c43f63633975316fe617ad8", size = 212695, upload-time = "2021-03-25T21:42:40.551Z" },
]
[[package]] [[package]]
name = "onnxscript" name = "onnxscript"
version = "0.7.0" version = "0.7.0"
@@ -993,55 +947,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b8/ef/50433d346c56657a70d27f156c7b349ac59a068b01de4eb796e747eecc43/protobuf-7.35.0-py3-none-any.whl", hash = "sha256:c13f325cf242bad135c350629eeb5d54b24228eb472fb3e2e9ebbd4c5dc20ca0", size = 171659, upload-time = "2026-05-19T23:02:27.842Z" }, { url = "https://files.pythonhosted.org/packages/b8/ef/50433d346c56657a70d27f156c7b349ac59a068b01de4eb796e747eecc43/protobuf-7.35.0-py3-none-any.whl", hash = "sha256:c13f325cf242bad135c350629eeb5d54b24228eb472fb3e2e9ebbd4c5dc20ca0", size = 171659, upload-time = "2026-05-19T23:02:27.842Z" },
] ]
[[package]]
name = "psutil"
version = "7.2.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" },
{ url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" },
{ url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" },
{ url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" },
{ url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" },
{ url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" },
{ url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664, upload-time = "2026-01-28T18:15:09.469Z" },
{ url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087, upload-time = "2026-01-28T18:15:11.724Z" },
{ url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383, upload-time = "2026-01-28T18:15:13.445Z" },
{ url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210, upload-time = "2026-01-28T18:15:16.002Z" },
{ url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228, upload-time = "2026-01-28T18:15:18.385Z" },
{ url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284, upload-time = "2026-01-28T18:15:19.912Z" },
{ url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" },
{ url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" },
{ url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" },
{ url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" },
{ url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" },
{ url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" },
{ url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" },
{ url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" },
]
[[package]]
name = "py-cpuinfo"
version = "9.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/37/a8/d832f7293ebb21690860d2e01d8115e5ff6f2ae8bbdc953f0eb0fa4bd2c7/py-cpuinfo-9.0.0.tar.gz", hash = "sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690", size = 104716, upload-time = "2022-10-25T20:38:06.303Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5", size = 22335, upload-time = "2022-10-25T20:38:27.636Z" },
]
[[package]]
name = "py3nvml"
version = "0.2.7"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "xmltodict" },
]
sdist = { url = "https://files.pythonhosted.org/packages/10/7e/fa282e456b87570d663ce97946b4dcb16850d4495ce4bd625a1a10c8ed56/py3nvml-0.2.7.tar.gz", hash = "sha256:09ee1d04598a6e664e24465f804ce3bfe119a6fdb5362df1c168f8aa929fbd73", size = 58224, upload-time = "2021-11-22T14:30:27.541Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/03/3a/ea6f2419bd20f97f65ee55a9910c722313fe99cacc0bf77afb4b74b446ff/py3nvml-0.2.7-py3-none-any.whl", hash = "sha256:30101170d1f51419c8d21fd8ca6cdc333a552b4f8a945c2fc7d107d77e4220dd", size = 55503, upload-time = "2021-11-22T14:30:25.794Z" },
]
[[package]] [[package]]
name = "pycparser" name = "pycparser"
version = "3.0" version = "3.0"
@@ -1060,15 +965,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
] ]
[[package]]
name = "pyreadline3"
version = "3.5.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b6/6d/f94028646d7bbe6d9d873c47ee7c246f2d29129d253f0d96cb6fcab70733/pyreadline3-3.5.6.tar.gz", hash = "sha256:61e53218b99656091ddb077df9e71f25850e72e030b6183b39c9b7e6e4f4a9bf", size = 100368, upload-time = "2026-05-14T17:55:04.471Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f7/5e/35c856e186b74678c24927847ad9895a51f1bc02a0c6126477a6c6040064/pyreadline3-3.5.6-py3-none-any.whl", hash = "sha256:8449b734232e42a5dcd74048e39b60db2839a4c38cf3ae2bf7707d58b5389c0d", size = 85243, upload-time = "2026-05-14T17:55:03.262Z" },
]
[[package]] [[package]]
name = "pyyaml" name = "pyyaml"
version = "6.0.3" version = "6.0.3"
@@ -1406,12 +1302,3 @@ sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac8
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
] ]
[[package]]
name = "xmltodict"
version = "1.0.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/19/70/80f3b7c10d2630aa66414bf23d210386700aa390547278c789afa994fd7e/xmltodict-1.0.4.tar.gz", hash = "sha256:6d94c9f834dd9e44514162799d344d815a3a4faec913717a9ecbfa5be1bb8e61", size = 26124, upload-time = "2026-02-22T02:21:22.074Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/38/34/98a2f52245f4d47be93b580dae5f9861ef58977d73a79eb47c58f1ad1f3a/xmltodict-1.0.4-py3-none-any.whl", hash = "sha256:a4a00d300b0e1c59fc2bfccb53d7b2e88c32f200df138a0dd2229f842497026a", size = 13580, upload-time = "2026-02-22T02:21:21.039Z" },
]