@humeai/cli 0.0.10 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/index.js +95 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,6 +61,7 @@ $ hume tts <text>
|
|
|
61
61
|
--trailing-silence #0 Seconds of silence to add at the end (0.0-5.0, default is 0.35)
|
|
62
62
|
--streaming Use streaming mode for TTS generation (default: true)
|
|
63
63
|
--instant-mode Enable ultra-low latency mode for significantly faster generation (requires streaming=true, a voice, and incurs 10% higher cost)
|
|
64
|
+
--curl Generate curl command instead of making the API request
|
|
64
65
|
|
|
65
66
|
━━━ Details ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
66
67
|
|
|
@@ -110,6 +111,9 @@ $ hume tts "Hello world" -v narrator --instant-mode
|
|
|
110
111
|
Setting instant mode in your config (always enable)
|
|
111
112
|
$ hume config set tts.instantMode true
|
|
112
113
|
|
|
114
|
+
Generating curl command instead of making API request
|
|
115
|
+
$ hume tts "Hello world" -v narrator --curl
|
|
116
|
+
|
|
113
117
|
## Voice Management
|
|
114
118
|
|
|
115
119
|
Save a voice from a previous generation
|
package/dist/index.js
CHANGED
|
@@ -50425,6 +50425,33 @@ var getHumeClient = (opts) => {
|
|
|
50425
50425
|
environment: opts.baseUrl ?? "https://api.hume.ai"
|
|
50426
50426
|
});
|
|
50427
50427
|
};
|
|
50428
|
+
var getApiKeyProvenance = (opts, globalConfig, session, env) => {
|
|
50429
|
+
if (opts.apiKey) {
|
|
50430
|
+
return { source: "flag", value: opts.apiKey };
|
|
50431
|
+
}
|
|
50432
|
+
if (env.HUME_API_KEY) {
|
|
50433
|
+
return { source: "env", value: env.HUME_API_KEY };
|
|
50434
|
+
}
|
|
50435
|
+
if (session.apiKey) {
|
|
50436
|
+
return { source: "session", value: session.apiKey };
|
|
50437
|
+
}
|
|
50438
|
+
if (globalConfig.apiKey) {
|
|
50439
|
+
return { source: "global", value: globalConfig.apiKey };
|
|
50440
|
+
}
|
|
50441
|
+
return null;
|
|
50442
|
+
};
|
|
50443
|
+
var formatApiKeyForCurl = (provenance) => {
|
|
50444
|
+
switch (provenance.source) {
|
|
50445
|
+
case "flag":
|
|
50446
|
+
return provenance.value;
|
|
50447
|
+
case "env":
|
|
50448
|
+
return "$HUME_API_KEY";
|
|
50449
|
+
case "global":
|
|
50450
|
+
return "$(hume config show | jq '.apiKey')";
|
|
50451
|
+
case "session":
|
|
50452
|
+
return "$(hume session show | jq '.apiKey')";
|
|
50453
|
+
}
|
|
50454
|
+
};
|
|
50428
50455
|
|
|
50429
50456
|
// src/config.ts
|
|
50430
50457
|
var CONFIG_FILE = "config.json";
|
|
@@ -50443,6 +50470,7 @@ var configValidators = {
|
|
|
50443
50470
|
"tts.trailingSilence": t.cascade(t.isNumber(), t.isInInclusiveRange(0, 5)),
|
|
50444
50471
|
"tts.streaming": t.isBoolean(),
|
|
50445
50472
|
"tts.instantMode": t.isBoolean(),
|
|
50473
|
+
"tts.modelVersion": t.isEnum(["1", "2"]),
|
|
50446
50474
|
json: t.isBoolean(),
|
|
50447
50475
|
pretty: t.isBoolean(),
|
|
50448
50476
|
apiKey: t.isString()
|
|
@@ -50618,7 +50646,7 @@ var resetGlobalConfig = clearConfig("global");
|
|
|
50618
50646
|
// package.json
|
|
50619
50647
|
var package_default = {
|
|
50620
50648
|
name: "@humeai/cli",
|
|
50621
|
-
version: "0.0.
|
|
50649
|
+
version: "0.0.11",
|
|
50622
50650
|
module: "index.ts",
|
|
50623
50651
|
type: "module",
|
|
50624
50652
|
description: "CLI for Hume.ai's OCTAVE expressive TTS API",
|
|
@@ -50796,6 +50824,7 @@ var withStdinAudioPlayer = async (customCommand, f) => {
|
|
|
50796
50824
|
};
|
|
50797
50825
|
|
|
50798
50826
|
// src/tts.ts
|
|
50827
|
+
var import_serialization = __toESM(require_serialization(), 1);
|
|
50799
50828
|
var calculateOutputOpts = (opts) => {
|
|
50800
50829
|
if (opts.numGenerations > 1 && opts.outputFilePath) {
|
|
50801
50830
|
throw new Error("Unexpected: cannot specify both --num-generations and --output-file-path");
|
|
@@ -50873,7 +50902,8 @@ class Tts {
|
|
|
50873
50902
|
speed: null,
|
|
50874
50903
|
trailingSilence: null,
|
|
50875
50904
|
streaming: true,
|
|
50876
|
-
instantMode: false
|
|
50905
|
+
instantMode: false,
|
|
50906
|
+
modelVersion: null
|
|
50877
50907
|
};
|
|
50878
50908
|
async writeFiles(opts, generations) {
|
|
50879
50909
|
if (opts.type === "path") {
|
|
@@ -50985,6 +51015,8 @@ class Tts {
|
|
|
50985
51015
|
const trailingSilence = osgd("trailingSilence").item;
|
|
50986
51016
|
const streaming = osgd("streaming").item;
|
|
50987
51017
|
const instantMode = osgd("instantMode").item;
|
|
51018
|
+
const modelVersion = osgd("modelVersion").item;
|
|
51019
|
+
const requestJson = opts.requestJson ?? null;
|
|
50988
51020
|
const voiceName_ = osgd("voiceName");
|
|
50989
51021
|
const voiceId_ = osgd("voiceId");
|
|
50990
51022
|
let voiceName = voiceName_.item;
|
|
@@ -51015,7 +51047,9 @@ class Tts {
|
|
|
51015
51047
|
speed,
|
|
51016
51048
|
trailingSilence,
|
|
51017
51049
|
streaming,
|
|
51018
|
-
instantMode
|
|
51050
|
+
instantMode,
|
|
51051
|
+
modelVersion,
|
|
51052
|
+
requestJson
|
|
51019
51053
|
};
|
|
51020
51054
|
}
|
|
51021
51055
|
async readStdin() {
|
|
@@ -51035,6 +51069,12 @@ class Tts {
|
|
|
51035
51069
|
async synthesize(rawOpts) {
|
|
51036
51070
|
const { session, globalConfig, env, reporter, hume } = await this.getSettings(rawOpts);
|
|
51037
51071
|
const opts = Tts.resolveOpts(env, globalConfig, session, rawOpts);
|
|
51072
|
+
if (!opts.text && !opts.requestJson) {
|
|
51073
|
+
throw new Error("Either text parameter or --request-json must be provided");
|
|
51074
|
+
}
|
|
51075
|
+
if (opts.text && opts.requestJson) {
|
|
51076
|
+
throw new Error("Cannot specify both text parameter and --request-json. Use one or the other.");
|
|
51077
|
+
}
|
|
51038
51078
|
const outputOpts = calculateOutputOpts(opts);
|
|
51039
51079
|
if (opts.presetVoice) {
|
|
51040
51080
|
reporter.warn("Please use --provider HUME_AI instead of --preset-voice. --preset-voice will be removed in a future version");
|
|
@@ -51045,19 +51085,33 @@ class Tts {
|
|
|
51045
51085
|
}
|
|
51046
51086
|
const utterance = calculateUtterance({
|
|
51047
51087
|
...opts,
|
|
51048
|
-
text,
|
|
51088
|
+
text: text || "",
|
|
51049
51089
|
speed: opts.speed,
|
|
51050
51090
|
trailingSilence: opts.trailingSilence,
|
|
51051
51091
|
provider: opts.provider
|
|
51052
51092
|
});
|
|
51053
|
-
|
|
51054
|
-
|
|
51055
|
-
|
|
51056
|
-
|
|
51057
|
-
|
|
51058
|
-
|
|
51059
|
-
|
|
51060
|
-
|
|
51093
|
+
let tts;
|
|
51094
|
+
if (opts.requestJson) {
|
|
51095
|
+
try {
|
|
51096
|
+
tts = JSON.parse(String(opts.requestJson));
|
|
51097
|
+
debug2("Using hardcoded request body: %O", JSON.stringify(tts, null, 2));
|
|
51098
|
+
} catch (error) {
|
|
51099
|
+
throw new Error(`Invalid JSON in --request-json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
51100
|
+
}
|
|
51101
|
+
} else {
|
|
51102
|
+
const baseTts = {
|
|
51103
|
+
utterances: [utterance],
|
|
51104
|
+
numGenerations: outputOpts.numGenerations,
|
|
51105
|
+
format: { type: opts.format }
|
|
51106
|
+
};
|
|
51107
|
+
if (opts.modelVersion !== null) {
|
|
51108
|
+
tts = { ...baseTts, version: opts.modelVersion };
|
|
51109
|
+
} else {
|
|
51110
|
+
tts = baseTts;
|
|
51111
|
+
}
|
|
51112
|
+
await this.maybeAddContext(opts, tts);
|
|
51113
|
+
}
|
|
51114
|
+
if (opts.instantMode && !opts.requestJson) {
|
|
51061
51115
|
if (!opts.streaming) {
|
|
51062
51116
|
throw new Error("Instant mode requires streaming to be enabled");
|
|
51063
51117
|
}
|
|
@@ -51072,6 +51126,9 @@ class Tts {
|
|
|
51072
51126
|
if (!hume) {
|
|
51073
51127
|
throw new ApiKeyNotSetError;
|
|
51074
51128
|
}
|
|
51129
|
+
if (opts.curl) {
|
|
51130
|
+
return this.generateCurlCommand(opts, env, globalConfig, session, reporter, tts);
|
|
51131
|
+
}
|
|
51075
51132
|
if (opts.streaming) {
|
|
51076
51133
|
return this.synthesizeStreaming(reporter, tts, hume, opts, outputOpts);
|
|
51077
51134
|
}
|
|
@@ -51172,6 +51229,24 @@ class Tts {
|
|
|
51172
51229
|
reporter.json({ result, written_files: writtenFiles });
|
|
51173
51230
|
await this.playAudios(opts.play, writtenFiles, reporter, opts.playCommand ?? null);
|
|
51174
51231
|
}
|
|
51232
|
+
async generateCurlCommand(opts, env, globalConfig, session, reporter, tts) {
|
|
51233
|
+
const apiKeyProvenance = getApiKeyProvenance(opts, globalConfig, session, env);
|
|
51234
|
+
if (!apiKeyProvenance) {
|
|
51235
|
+
throw new ApiKeyNotSetError;
|
|
51236
|
+
}
|
|
51237
|
+
const baseUrl = opts.baseUrl ?? env.HUME_BASE_URL ?? session.baseUrl ?? globalConfig.baseUrl ?? "https://api.hume.ai";
|
|
51238
|
+
const apiKey = formatApiKeyForCurl(apiKeyProvenance);
|
|
51239
|
+
const endpoint = opts.streaming ? "/v0/tts/stream/json" : "/v0/tts";
|
|
51240
|
+
const url = `${baseUrl}${endpoint}`;
|
|
51241
|
+
const serialized = import_serialization.default.tts.PostedTts.jsonOrThrow(tts);
|
|
51242
|
+
const curlCommand = [
|
|
51243
|
+
`curl "${url}"`,
|
|
51244
|
+
` -H "X-Hume-Api-Key: ${apiKey}"`,
|
|
51245
|
+
` --json '${JSON.stringify(serialized)}'`
|
|
51246
|
+
].join(" \\\n");
|
|
51247
|
+
reporter.info("Generated curl command:");
|
|
51248
|
+
console.log(curlCommand);
|
|
51249
|
+
}
|
|
51175
51250
|
}
|
|
51176
51251
|
|
|
51177
51252
|
// src/index.ts
|
|
@@ -51269,6 +51344,7 @@ var usageDescriptions = {
|
|
|
51269
51344
|
"tts.streaming": "Use streaming mode for TTS generation (default: true)",
|
|
51270
51345
|
"tts.instantMode": "Enable ultra-low latency mode for significantly faster generation (requires streaming=true, a voice, and incurs 10% higher cost)",
|
|
51271
51346
|
"tts.modelVersion": "Either '1' for Octave 1 or '2' for Octave 2.",
|
|
51347
|
+
"tts.curl": "Generate curl command instead of making the API request",
|
|
51272
51348
|
apiKey: "Override the default API key",
|
|
51273
51349
|
json: "Output in JSON format",
|
|
51274
51350
|
pretty: "Output in human-readable format"
|
|
@@ -51571,7 +51647,7 @@ class TtsCommand extends Command2 {
|
|
|
51571
51647
|
}), {
|
|
51572
51648
|
usage: `$ hume tts <text>`
|
|
51573
51649
|
});
|
|
51574
|
-
text = exports_options.String({ required:
|
|
51650
|
+
text = exports_options.String({ required: false, name: "text" });
|
|
51575
51651
|
description = exports_options.String("-d,--description", {
|
|
51576
51652
|
description: usageDescriptions["tts.description"]
|
|
51577
51653
|
});
|
|
@@ -51647,6 +51723,12 @@ class TtsCommand extends Command2 {
|
|
|
51647
51723
|
description: usageDescriptions["tts.modelVersion"],
|
|
51648
51724
|
validator: t2.isEnum(["1", "2"])
|
|
51649
51725
|
});
|
|
51726
|
+
requestJson = exports_options.String("--request-json", {
|
|
51727
|
+
description: "Override the request body with a hardcoded JSON string instead of generating it from options"
|
|
51728
|
+
});
|
|
51729
|
+
curl = exports_options.Boolean("--curl", {
|
|
51730
|
+
description: usageDescriptions["tts.curl"]
|
|
51731
|
+
});
|
|
51650
51732
|
async execute() {
|
|
51651
51733
|
const tts = new Tts;
|
|
51652
51734
|
await tts.synthesize(this);
|