cli: --ref-text takes a file path instead of inline string content
This commit is contained in:
+1
-3
@@ -2,13 +2,11 @@
|
|||||||
|
|
||||||
set PATH=%~dp0..\build\Release;%PATH%
|
set PATH=%~dp0..\build\Release;%PATH%
|
||||||
|
|
||||||
set /p REFTEXT=<freeman.txt
|
|
||||||
|
|
||||||
qwen-tts.exe ^
|
qwen-tts.exe ^
|
||||||
--model ..\models\qwen-talker-1.7b-base-Q8_0.gguf ^
|
--model ..\models\qwen-talker-1.7b-base-Q8_0.gguf ^
|
||||||
--codec ..\models\qwen-tokenizer-12hz-Q8_0.gguf ^
|
--codec ..\models\qwen-tokenizer-12hz-Q8_0.gguf ^
|
||||||
--ref-audio freeman.wav ^
|
--ref-audio freeman.wav ^
|
||||||
--ref-text "%REFTEXT%" ^
|
--ref-text freeman.txt ^
|
||||||
--lang English ^
|
--lang English ^
|
||||||
-o clone.wav < prompt.txt
|
-o clone.wav < prompt.txt
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -6,6 +6,6 @@ set -eu
|
|||||||
--model ../models/qwen-talker-1.7b-base-Q8_0.gguf \
|
--model ../models/qwen-talker-1.7b-base-Q8_0.gguf \
|
||||||
--codec ../models/qwen-tokenizer-12hz-Q8_0.gguf \
|
--codec ../models/qwen-tokenizer-12hz-Q8_0.gguf \
|
||||||
--ref-audio freeman.wav \
|
--ref-audio freeman.wav \
|
||||||
--ref-text "$(cat freeman.txt)" \
|
--ref-text freeman.txt \
|
||||||
--lang English \
|
--lang English \
|
||||||
-o clone.wav < prompt.txt
|
-o clone.wav < prompt.txt
|
||||||
|
|||||||
+55
-7
@@ -43,9 +43,10 @@ static void print_usage(const char * prog) {
|
|||||||
" --ref-audio <wav> Reference WAV path for voice clone (Base only). Mutually\n"
|
" --ref-audio <wav> Reference WAV path for voice clone (Base only). Mutually\n"
|
||||||
" exclusive with --speaker. Mode A (x_vector_only) extracts\n"
|
" exclusive with --speaker. Mode A (x_vector_only) extracts\n"
|
||||||
" a speaker embedding via the ECAPA-TDNN encoder.\n"
|
" a speaker embedding via the ECAPA-TDNN encoder.\n"
|
||||||
" --ref-text <s> Reference transcript for voice clone ICL mode (Base only,\n"
|
" --ref-text <path> Path to a UTF-8 text file containing the reference\n"
|
||||||
" requires --ref-audio). Switches the prompt to ICL mode B\n"
|
" transcript for voice clone ICL mode (Base only, requires\n"
|
||||||
" where the talker conditions on the reference codec codes.\n"
|
" --ref-audio). Switches the prompt to ICL mode B where the\n"
|
||||||
|
" talker conditions on the reference codec codes.\n"
|
||||||
" --max-new <n> Max new audio frames (default: 2048)\n"
|
" --max-new <n> Max new audio frames (default: 2048)\n"
|
||||||
" --format <fmt> WAV output format: wav16, wav24, wav32 (default: wav16)\n\n"
|
" --format <fmt> WAV output format: wav16, wav24, wav32 (default: wav16)\n\n"
|
||||||
"Sampling options:\n"
|
"Sampling options:\n"
|
||||||
@@ -71,7 +72,7 @@ struct Args {
|
|||||||
const char * instruct;
|
const char * instruct;
|
||||||
const char * speaker;
|
const char * speaker;
|
||||||
const char * ref_audio;
|
const char * ref_audio;
|
||||||
const char * ref_text;
|
const char * ref_text_path;
|
||||||
const char * dump_dir;
|
const char * dump_dir;
|
||||||
const char * out_wav;
|
const char * out_wav;
|
||||||
const char * format;
|
const char * format;
|
||||||
@@ -100,6 +101,34 @@ static std::string read_stdin_text() {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read a small text file into a string. Trims trailing newlines.
|
||||||
|
static bool read_text_file(const char * path, std::string & out) {
|
||||||
|
FILE * f = fopen(path, "rb");
|
||||||
|
if (!f) {
|
||||||
|
fprintf(stderr, "[CLI] FATAL: cannot open '%s'\n", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long sz = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
if (sz < 0) {
|
||||||
|
fclose(f);
|
||||||
|
fprintf(stderr, "[CLI] FATAL: ftell failed on '%s'\n", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out.resize((size_t) sz);
|
||||||
|
if (sz > 0 && fread(&out[0], 1, (size_t) sz, f) != (size_t) sz) {
|
||||||
|
fclose(f);
|
||||||
|
fprintf(stderr, "[CLI] FATAL: fread failed on '%s'\n", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
while (!out.empty() && (out.back() == '\n' || out.back() == '\r')) {
|
||||||
|
out.pop_back();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool parse_args(int argc, char ** argv, Args & a) {
|
static bool parse_args(int argc, char ** argv, Args & a) {
|
||||||
a = {};
|
a = {};
|
||||||
a.lang = "english";
|
a.lang = "english";
|
||||||
@@ -135,7 +164,7 @@ static bool parse_args(int argc, char ** argv, Args & a) {
|
|||||||
} else if (std::strcmp(arg, "--ref-audio") == 0 && i + 1 < argc) {
|
} else if (std::strcmp(arg, "--ref-audio") == 0 && i + 1 < argc) {
|
||||||
a.ref_audio = argv[++i];
|
a.ref_audio = argv[++i];
|
||||||
} else if (std::strcmp(arg, "--ref-text") == 0 && i + 1 < argc) {
|
} else if (std::strcmp(arg, "--ref-text") == 0 && i + 1 < argc) {
|
||||||
a.ref_text = argv[++i];
|
a.ref_text_path = argv[++i];
|
||||||
} else if (std::strcmp(arg, "--format") == 0 && i + 1 < argc) {
|
} else if (std::strcmp(arg, "--format") == 0 && i + 1 < argc) {
|
||||||
a.format = argv[++i];
|
a.format = argv[++i];
|
||||||
} else if (std::strcmp(arg, "--dump") == 0 && i + 1 < argc) {
|
} else if (std::strcmp(arg, "--dump") == 0 && i + 1 < argc) {
|
||||||
@@ -227,13 +256,32 @@ static int run(const Args & a) {
|
|||||||
backend_release(bp.backend, bp.cpu_backend);
|
backend_release(bp.backend, bp.cpu_backend);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (a.ref_text && !a.ref_audio) {
|
if (a.ref_text_path && !a.ref_audio) {
|
||||||
fprintf(stderr, "[CLI] ERROR: --ref-text requires --ref-audio\n");
|
fprintf(stderr, "[CLI] ERROR: --ref-text requires --ref-audio\n");
|
||||||
pipeline_tts_free(&pt);
|
pipeline_tts_free(&pt);
|
||||||
backend_release(bp.backend, bp.cpu_backend);
|
backend_release(bp.backend, bp.cpu_backend);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load the reference transcript from the file passed via --ref-text.
|
||||||
|
// Empty content is rejected since the ICL prompt needs it non empty.
|
||||||
|
std::string ref_text_buf;
|
||||||
|
const char * ref_text = NULL;
|
||||||
|
if (a.ref_text_path) {
|
||||||
|
if (!read_text_file(a.ref_text_path, ref_text_buf)) {
|
||||||
|
pipeline_tts_free(&pt);
|
||||||
|
backend_release(bp.backend, bp.cpu_backend);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (ref_text_buf.empty()) {
|
||||||
|
fprintf(stderr, "[CLI] ERROR: --ref-text file '%s' is empty\n", a.ref_text_path);
|
||||||
|
pipeline_tts_free(&pt);
|
||||||
|
backend_release(bp.backend, bp.cpu_backend);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ref_text = ref_text_buf.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve output WAV format string : wav16 / wav24 / wav32. Default
|
// Resolve output WAV format string : wav16 / wav24 / wav32. Default
|
||||||
// wav16 mirrors the omnivoice.cpp default.
|
// wav16 mirrors the omnivoice.cpp default.
|
||||||
WavFormat wav_fmt;
|
WavFormat wav_fmt;
|
||||||
@@ -286,7 +334,7 @@ static int run(const Args & a) {
|
|||||||
p.instruct = a.instruct;
|
p.instruct = a.instruct;
|
||||||
p.speaker = a.speaker;
|
p.speaker = a.speaker;
|
||||||
p.ref_audio = a.ref_audio;
|
p.ref_audio = a.ref_audio;
|
||||||
p.ref_text = a.ref_text;
|
p.ref_text = ref_text;
|
||||||
p.seed = seed;
|
p.seed = seed;
|
||||||
p.max_new_tokens = a.max_new_tokens;
|
p.max_new_tokens = a.max_new_tokens;
|
||||||
p.do_sample = a.do_sample;
|
p.do_sample = a.do_sample;
|
||||||
|
|||||||
Reference in New Issue
Block a user