pub struct NeuCodecEncoder;Expand description
NeuCodec encoder: converts a 16 kHz audio waveform to speech token IDs.
Note: The full NeuCodec encoder requires Wav2Vec2BertModel (~600 MB) as a semantic feature extractor. Encoder support is not yet implemented in this pure-Rust build.
For reference audio encoding, use the Python neucodec package:
from neucodec import NeuCodec
model = NeuCodec.from_pretrained("neuphonic/neucodec")
codes = model.encode_code(waveform) # → i32 arrayThen save the codes as a .npy file and pass via --ref-codes to the
synthesis examples.
Implementations§
Source§impl NeuCodecEncoder
impl NeuCodecEncoder
Sourcepub fn new() -> Result<Self>
pub fn new() -> Result<Self>
Always returns an error — encoder not yet implemented.
Examples found in repository?
examples/test_pipeline.rs (line 328)
292fn test_burn_backend() {
293 section("6 · Burn Backend");
294
295 // Feature-flag report
296 let wgpu_feature = neutts::codec::wgpu_feature_enabled();
297 item(
298 "wgpu Cargo feature",
299 if wgpu_feature { "\x1b[32menabled\x1b[0m (GPU tried first, NdArray fallback)" }
300 else { "\x1b[2mdisabled\x1b[0m (NdArray CPU always used)" },
301 );
302
303 // Codec constants
304 item("decoder sample rate", &format!("{} Hz", neutts::codec::SAMPLE_RATE));
305 item("encoder sample rate", &format!("{} Hz", neutts::codec::ENCODER_SAMPLE_RATE));
306 item("samples / token (decoder)", &format!("{}", neutts::codec::SAMPLES_PER_TOKEN));
307 item("samples / token (encoder)", &format!("{}", neutts::codec::ENCODER_SAMPLES_PER_TOKEN));
308 item("encoder default input",
309 &format!("{} samples = {} s @ {} Hz",
310 neutts::codec::ENCODER_DEFAULT_INPUT_SAMPLES,
311 neutts::codec::ENCODER_DEFAULT_INPUT_SAMPLES / neutts::codec::ENCODER_SAMPLE_RATE as usize,
312 neutts::codec::ENCODER_SAMPLE_RATE));
313
314 // Runtime decoder probe (only succeeds if ONNX was converted at build time)
315 match neutts::NeuCodecDecoder::new() {
316 Ok(dec) => {
317 ok(&format!("NeuCodecDecoder::new() → backend: \x1b[1m{}\x1b[0m", dec.backend_name()));
318 }
319 Err(_) => {
320 println!(
321 " \x1b[2m~ NeuCodecDecoder::new() → not compiled in \
322 (run `download_models` + `cargo build` to embed weights)\x1b[0m"
323 );
324 }
325 }
326
327 // Runtime encoder probe
328 match neutts::NeuCodecEncoder::new() {
329 Ok(enc) => {
330 ok(&format!("NeuCodecEncoder::new() → backend: \x1b[1m{}\x1b[0m", enc.backend_name()));
331 }
332 Err(_) => {
333 println!(
334 " \x1b[2m~ NeuCodecEncoder::new() → not compiled in \
335 (run `download_models` + `cargo build` to embed weights)\x1b[0m"
336 );
337 }
338 }
339}More examples
examples/encode_reference.rs (line 108)
62fn main() -> anyhow::Result<()> {
63 // ── Parse CLI arguments ───────────────────────────────────────────────────
64 let mut args = std::env::args().skip(1).peekable();
65
66 let mut encoder_bpk: Option<PathBuf> = None; // optional external .bpk weight file
67 let mut audio_path: Option<PathBuf> = None;
68 let mut out_path: Option<PathBuf> = None;
69
70 while let Some(arg) = args.next() {
71 match arg.as_str() {
72 "--encoder" => { if let Some(v) = args.next() { encoder_bpk = Some(PathBuf::from(v)); } }
73 "--audio" | "-i" => { if let Some(v) = args.next() { audio_path = Some(PathBuf::from(v)); } }
74 "--out" | "-o" => { if let Some(v) = args.next() { out_path = Some(PathBuf::from(v)); } }
75 "--help" | "-h" => { print_help(); return Ok(()); }
76 other => {
77 eprintln!("Unknown argument: {other} (use --help for usage)");
78 std::process::exit(1);
79 }
80 }
81 }
82
83 // ── Validate inputs ───────────────────────────────────────────────────────
84 let audio_path = audio_path.ok_or_else(|| {
85 anyhow::anyhow!("No audio file specified. Use --audio <path.wav> (--help for more)")
86 })?;
87
88 if !audio_path.exists() {
89 anyhow::bail!("Audio file not found: {}", audio_path.display());
90 }
91
92 let out_path = out_path.unwrap_or_else(|| audio_path.with_extension("npy"));
93
94 // ── Print configuration ───────────────────────────────────────────────────
95 match &encoder_bpk {
96 Some(p) => println!("Encoder : external BurnPack {}", p.display()),
97 None => println!("Encoder : embedded weights (wgpu → ndarray fallback)"),
98 }
99 println!("Audio : {}", audio_path.display());
100 println!("Output : {}", out_path.display());
101 println!();
102
103 // ── Load encoder ──────────────────────────────────────────────────────────
104 println!("Initialising encoder…");
105 let encoder = match encoder_bpk {
106 Some(ref p) => neutts::NeuCodecEncoder::load(p)
107 .map_err(|e| anyhow::anyhow!("Failed to load encoder from {}: {e}", p.display()))?,
108 None => neutts::NeuCodecEncoder::new()
109 .map_err(|e| anyhow::anyhow!(
110 "{e}\n\n\
111 Run the one-time setup to embed the encoder:\n\
112 \n\
113 \tcargo run --example download_models\n\
114 \tcargo build\n"
115 ))?,
116 };
117 println!(" → backend : {}", encoder.backend_name());
118 println!();
119
120 // ── Encode ────────────────────────────────────────────────────────────────
121 println!("Encoding {}…", audio_path.display());
122 let codes = encoder.encode_wav(&audio_path)?;
123
124 let duration_s = codes.len() as f32 / 50.0;
125 println!(
126 " → {} tokens ({:.2} s of audio at 50 tokens/s)",
127 codes.len(),
128 duration_s,
129 );
130
131 if duration_s < 3.0 {
132 eprintln!(
133 "WARNING: reference is only {duration_s:.1} s — \
134 5–30 s of clean speech gives the best cloning quality."
135 );
136 }
137
138 // ── Save ──────────────────────────────────────────────────────────────────
139 if let Some(parent) = out_path.parent() {
140 if !parent.as_os_str().is_empty() {
141 std::fs::create_dir_all(parent).ok();
142 }
143 }
144
145 neutts::npy::write_npy_i32(&out_path, &codes)?;
146 println!("Saved → {}", out_path.display());
147
148 println!();
149 println!(
150 "Use these codes for synthesis:\n\
151 \n\
152 \tcargo run --example basic --features espeak -- \\\n\
153 \t --text \"Your text here.\" \\\n\
154 \t --ref-codes {} \\\n\
155 \t --ref-text \"Transcript of the reference recording.\"",
156 out_path.display()
157 );
158
159 Ok(())
160}Sourcepub fn load(_path: &Path) -> Result<Self>
pub fn load(_path: &Path) -> Result<Self>
Always returns an error — encoder not yet implemented.
Examples found in repository?
examples/encode_reference.rs (line 106)
62fn main() -> anyhow::Result<()> {
63 // ── Parse CLI arguments ───────────────────────────────────────────────────
64 let mut args = std::env::args().skip(1).peekable();
65
66 let mut encoder_bpk: Option<PathBuf> = None; // optional external .bpk weight file
67 let mut audio_path: Option<PathBuf> = None;
68 let mut out_path: Option<PathBuf> = None;
69
70 while let Some(arg) = args.next() {
71 match arg.as_str() {
72 "--encoder" => { if let Some(v) = args.next() { encoder_bpk = Some(PathBuf::from(v)); } }
73 "--audio" | "-i" => { if let Some(v) = args.next() { audio_path = Some(PathBuf::from(v)); } }
74 "--out" | "-o" => { if let Some(v) = args.next() { out_path = Some(PathBuf::from(v)); } }
75 "--help" | "-h" => { print_help(); return Ok(()); }
76 other => {
77 eprintln!("Unknown argument: {other} (use --help for usage)");
78 std::process::exit(1);
79 }
80 }
81 }
82
83 // ── Validate inputs ───────────────────────────────────────────────────────
84 let audio_path = audio_path.ok_or_else(|| {
85 anyhow::anyhow!("No audio file specified. Use --audio <path.wav> (--help for more)")
86 })?;
87
88 if !audio_path.exists() {
89 anyhow::bail!("Audio file not found: {}", audio_path.display());
90 }
91
92 let out_path = out_path.unwrap_or_else(|| audio_path.with_extension("npy"));
93
94 // ── Print configuration ───────────────────────────────────────────────────
95 match &encoder_bpk {
96 Some(p) => println!("Encoder : external BurnPack {}", p.display()),
97 None => println!("Encoder : embedded weights (wgpu → ndarray fallback)"),
98 }
99 println!("Audio : {}", audio_path.display());
100 println!("Output : {}", out_path.display());
101 println!();
102
103 // ── Load encoder ──────────────────────────────────────────────────────────
104 println!("Initialising encoder…");
105 let encoder = match encoder_bpk {
106 Some(ref p) => neutts::NeuCodecEncoder::load(p)
107 .map_err(|e| anyhow::anyhow!("Failed to load encoder from {}: {e}", p.display()))?,
108 None => neutts::NeuCodecEncoder::new()
109 .map_err(|e| anyhow::anyhow!(
110 "{e}\n\n\
111 Run the one-time setup to embed the encoder:\n\
112 \n\
113 \tcargo run --example download_models\n\
114 \tcargo build\n"
115 ))?,
116 };
117 println!(" → backend : {}", encoder.backend_name());
118 println!();
119
120 // ── Encode ────────────────────────────────────────────────────────────────
121 println!("Encoding {}…", audio_path.display());
122 let codes = encoder.encode_wav(&audio_path)?;
123
124 let duration_s = codes.len() as f32 / 50.0;
125 println!(
126 " → {} tokens ({:.2} s of audio at 50 tokens/s)",
127 codes.len(),
128 duration_s,
129 );
130
131 if duration_s < 3.0 {
132 eprintln!(
133 "WARNING: reference is only {duration_s:.1} s — \
134 5–30 s of clean speech gives the best cloning quality."
135 );
136 }
137
138 // ── Save ──────────────────────────────────────────────────────────────────
139 if let Some(parent) = out_path.parent() {
140 if !parent.as_os_str().is_empty() {
141 std::fs::create_dir_all(parent).ok();
142 }
143 }
144
145 neutts::npy::write_npy_i32(&out_path, &codes)?;
146 println!("Saved → {}", out_path.display());
147
148 println!();
149 println!(
150 "Use these codes for synthesis:\n\
151 \n\
152 \tcargo run --example basic --features espeak -- \\\n\
153 \t --text \"Your text here.\" \\\n\
154 \t --ref-codes {} \\\n\
155 \t --ref-text \"Transcript of the reference recording.\"",
156 out_path.display()
157 );
158
159 Ok(())
160}Sourcepub fn encode_wav(&self, _path: &Path) -> Result<Vec<i32>>
pub fn encode_wav(&self, _path: &Path) -> Result<Vec<i32>>
Encode a WAV file to speech token IDs (not implemented).
Examples found in repository?
examples/encode_reference.rs (line 122)
62fn main() -> anyhow::Result<()> {
63 // ── Parse CLI arguments ───────────────────────────────────────────────────
64 let mut args = std::env::args().skip(1).peekable();
65
66 let mut encoder_bpk: Option<PathBuf> = None; // optional external .bpk weight file
67 let mut audio_path: Option<PathBuf> = None;
68 let mut out_path: Option<PathBuf> = None;
69
70 while let Some(arg) = args.next() {
71 match arg.as_str() {
72 "--encoder" => { if let Some(v) = args.next() { encoder_bpk = Some(PathBuf::from(v)); } }
73 "--audio" | "-i" => { if let Some(v) = args.next() { audio_path = Some(PathBuf::from(v)); } }
74 "--out" | "-o" => { if let Some(v) = args.next() { out_path = Some(PathBuf::from(v)); } }
75 "--help" | "-h" => { print_help(); return Ok(()); }
76 other => {
77 eprintln!("Unknown argument: {other} (use --help for usage)");
78 std::process::exit(1);
79 }
80 }
81 }
82
83 // ── Validate inputs ───────────────────────────────────────────────────────
84 let audio_path = audio_path.ok_or_else(|| {
85 anyhow::anyhow!("No audio file specified. Use --audio <path.wav> (--help for more)")
86 })?;
87
88 if !audio_path.exists() {
89 anyhow::bail!("Audio file not found: {}", audio_path.display());
90 }
91
92 let out_path = out_path.unwrap_or_else(|| audio_path.with_extension("npy"));
93
94 // ── Print configuration ───────────────────────────────────────────────────
95 match &encoder_bpk {
96 Some(p) => println!("Encoder : external BurnPack {}", p.display()),
97 None => println!("Encoder : embedded weights (wgpu → ndarray fallback)"),
98 }
99 println!("Audio : {}", audio_path.display());
100 println!("Output : {}", out_path.display());
101 println!();
102
103 // ── Load encoder ──────────────────────────────────────────────────────────
104 println!("Initialising encoder…");
105 let encoder = match encoder_bpk {
106 Some(ref p) => neutts::NeuCodecEncoder::load(p)
107 .map_err(|e| anyhow::anyhow!("Failed to load encoder from {}: {e}", p.display()))?,
108 None => neutts::NeuCodecEncoder::new()
109 .map_err(|e| anyhow::anyhow!(
110 "{e}\n\n\
111 Run the one-time setup to embed the encoder:\n\
112 \n\
113 \tcargo run --example download_models\n\
114 \tcargo build\n"
115 ))?,
116 };
117 println!(" → backend : {}", encoder.backend_name());
118 println!();
119
120 // ── Encode ────────────────────────────────────────────────────────────────
121 println!("Encoding {}…", audio_path.display());
122 let codes = encoder.encode_wav(&audio_path)?;
123
124 let duration_s = codes.len() as f32 / 50.0;
125 println!(
126 " → {} tokens ({:.2} s of audio at 50 tokens/s)",
127 codes.len(),
128 duration_s,
129 );
130
131 if duration_s < 3.0 {
132 eprintln!(
133 "WARNING: reference is only {duration_s:.1} s — \
134 5–30 s of clean speech gives the best cloning quality."
135 );
136 }
137
138 // ── Save ──────────────────────────────────────────────────────────────────
139 if let Some(parent) = out_path.parent() {
140 if !parent.as_os_str().is_empty() {
141 std::fs::create_dir_all(parent).ok();
142 }
143 }
144
145 neutts::npy::write_npy_i32(&out_path, &codes)?;
146 println!("Saved → {}", out_path.display());
147
148 println!();
149 println!(
150 "Use these codes for synthesis:\n\
151 \n\
152 \tcargo run --example basic --features espeak -- \\\n\
153 \t --text \"Your text here.\" \\\n\
154 \t --ref-codes {} \\\n\
155 \t --ref-text \"Transcript of the reference recording.\"",
156 out_path.display()
157 );
158
159 Ok(())
160}Sourcepub fn backend_name(&self) -> &str
pub fn backend_name(&self) -> &str
Backend name.
Examples found in repository?
examples/test_pipeline.rs (line 330)
292fn test_burn_backend() {
293 section("6 · Burn Backend");
294
295 // Feature-flag report
296 let wgpu_feature = neutts::codec::wgpu_feature_enabled();
297 item(
298 "wgpu Cargo feature",
299 if wgpu_feature { "\x1b[32menabled\x1b[0m (GPU tried first, NdArray fallback)" }
300 else { "\x1b[2mdisabled\x1b[0m (NdArray CPU always used)" },
301 );
302
303 // Codec constants
304 item("decoder sample rate", &format!("{} Hz", neutts::codec::SAMPLE_RATE));
305 item("encoder sample rate", &format!("{} Hz", neutts::codec::ENCODER_SAMPLE_RATE));
306 item("samples / token (decoder)", &format!("{}", neutts::codec::SAMPLES_PER_TOKEN));
307 item("samples / token (encoder)", &format!("{}", neutts::codec::ENCODER_SAMPLES_PER_TOKEN));
308 item("encoder default input",
309 &format!("{} samples = {} s @ {} Hz",
310 neutts::codec::ENCODER_DEFAULT_INPUT_SAMPLES,
311 neutts::codec::ENCODER_DEFAULT_INPUT_SAMPLES / neutts::codec::ENCODER_SAMPLE_RATE as usize,
312 neutts::codec::ENCODER_SAMPLE_RATE));
313
314 // Runtime decoder probe (only succeeds if ONNX was converted at build time)
315 match neutts::NeuCodecDecoder::new() {
316 Ok(dec) => {
317 ok(&format!("NeuCodecDecoder::new() → backend: \x1b[1m{}\x1b[0m", dec.backend_name()));
318 }
319 Err(_) => {
320 println!(
321 " \x1b[2m~ NeuCodecDecoder::new() → not compiled in \
322 (run `download_models` + `cargo build` to embed weights)\x1b[0m"
323 );
324 }
325 }
326
327 // Runtime encoder probe
328 match neutts::NeuCodecEncoder::new() {
329 Ok(enc) => {
330 ok(&format!("NeuCodecEncoder::new() → backend: \x1b[1m{}\x1b[0m", enc.backend_name()));
331 }
332 Err(_) => {
333 println!(
334 " \x1b[2m~ NeuCodecEncoder::new() → not compiled in \
335 (run `download_models` + `cargo build` to embed weights)\x1b[0m"
336 );
337 }
338 }
339}More examples
examples/encode_reference.rs (line 117)
62fn main() -> anyhow::Result<()> {
63 // ── Parse CLI arguments ───────────────────────────────────────────────────
64 let mut args = std::env::args().skip(1).peekable();
65
66 let mut encoder_bpk: Option<PathBuf> = None; // optional external .bpk weight file
67 let mut audio_path: Option<PathBuf> = None;
68 let mut out_path: Option<PathBuf> = None;
69
70 while let Some(arg) = args.next() {
71 match arg.as_str() {
72 "--encoder" => { if let Some(v) = args.next() { encoder_bpk = Some(PathBuf::from(v)); } }
73 "--audio" | "-i" => { if let Some(v) = args.next() { audio_path = Some(PathBuf::from(v)); } }
74 "--out" | "-o" => { if let Some(v) = args.next() { out_path = Some(PathBuf::from(v)); } }
75 "--help" | "-h" => { print_help(); return Ok(()); }
76 other => {
77 eprintln!("Unknown argument: {other} (use --help for usage)");
78 std::process::exit(1);
79 }
80 }
81 }
82
83 // ── Validate inputs ───────────────────────────────────────────────────────
84 let audio_path = audio_path.ok_or_else(|| {
85 anyhow::anyhow!("No audio file specified. Use --audio <path.wav> (--help for more)")
86 })?;
87
88 if !audio_path.exists() {
89 anyhow::bail!("Audio file not found: {}", audio_path.display());
90 }
91
92 let out_path = out_path.unwrap_or_else(|| audio_path.with_extension("npy"));
93
94 // ── Print configuration ───────────────────────────────────────────────────
95 match &encoder_bpk {
96 Some(p) => println!("Encoder : external BurnPack {}", p.display()),
97 None => println!("Encoder : embedded weights (wgpu → ndarray fallback)"),
98 }
99 println!("Audio : {}", audio_path.display());
100 println!("Output : {}", out_path.display());
101 println!();
102
103 // ── Load encoder ──────────────────────────────────────────────────────────
104 println!("Initialising encoder…");
105 let encoder = match encoder_bpk {
106 Some(ref p) => neutts::NeuCodecEncoder::load(p)
107 .map_err(|e| anyhow::anyhow!("Failed to load encoder from {}: {e}", p.display()))?,
108 None => neutts::NeuCodecEncoder::new()
109 .map_err(|e| anyhow::anyhow!(
110 "{e}\n\n\
111 Run the one-time setup to embed the encoder:\n\
112 \n\
113 \tcargo run --example download_models\n\
114 \tcargo build\n"
115 ))?,
116 };
117 println!(" → backend : {}", encoder.backend_name());
118 println!();
119
120 // ── Encode ────────────────────────────────────────────────────────────────
121 println!("Encoding {}…", audio_path.display());
122 let codes = encoder.encode_wav(&audio_path)?;
123
124 let duration_s = codes.len() as f32 / 50.0;
125 println!(
126 " → {} tokens ({:.2} s of audio at 50 tokens/s)",
127 codes.len(),
128 duration_s,
129 );
130
131 if duration_s < 3.0 {
132 eprintln!(
133 "WARNING: reference is only {duration_s:.1} s — \
134 5–30 s of clean speech gives the best cloning quality."
135 );
136 }
137
138 // ── Save ──────────────────────────────────────────────────────────────────
139 if let Some(parent) = out_path.parent() {
140 if !parent.as_os_str().is_empty() {
141 std::fs::create_dir_all(parent).ok();
142 }
143 }
144
145 neutts::npy::write_npy_i32(&out_path, &codes)?;
146 println!("Saved → {}", out_path.display());
147
148 println!();
149 println!(
150 "Use these codes for synthesis:\n\
151 \n\
152 \tcargo run --example basic --features espeak -- \\\n\
153 \t --text \"Your text here.\" \\\n\
154 \t --ref-codes {} \\\n\
155 \t --ref-text \"Transcript of the reference recording.\"",
156 out_path.display()
157 );
158
159 Ok(())
160}Auto Trait Implementations§
impl Freeze for NeuCodecEncoder
impl RefUnwindSafe for NeuCodecEncoder
impl Send for NeuCodecEncoder
impl Sync for NeuCodecEncoder
impl Unpin for NeuCodecEncoder
impl UnsafeUnpin for NeuCodecEncoder
impl UnwindSafe for NeuCodecEncoder
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more