@gobing-ai/knowledge-kit 0.1.4 → 0.1.6
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/.claude-plugin/marketplace.json +1 -1
- package/dist/board/collect/index.css +447 -0
- package/dist/board/collect/index.js +2505 -453
- package/dist/board/daily-voice/index.css +447 -0
- package/dist/board/daily-voice/index.js +415 -8
- package/dist/board/itc/index.css +447 -0
- package/dist/board/itc/index.js +415 -8
- package/dist/index.js +494 -136
- package/package.json +6 -5
- package/plugins/generations/content-gen/dist/index.js +9 -9
- package/plugins/generations/core-facts-gen/dist/index.js +12 -12
- package/plugins/generations/daily-article-gen/dist/index.js +15 -13
- package/plugins/generations/daily-article-gen/src/index.ts +5 -3
- package/plugins/generations/dailynews-gen/dist/index.js +9 -9
- package/plugins/generations/episode-plan-gen/dist/index.js +12 -12
- package/plugins/generations/gemini-tts/dist/index.js +9 -9
- package/plugins/generations/image-gen/dist/index.js +28 -12
- package/plugins/generations/image-gen/src/compose/card.ts +19 -3
- package/plugins/generations/news-report-gen/dist/index.js +12 -12
- package/plugins/generations/voice-gen/dist/index.js +9 -9
- package/plugins/generations/voxcpm-tts/README.md +31 -0
- package/plugins/generations/voxcpm-tts/dist/index.js +9 -9
- package/plugins/generations/voxcpm-tts/scripts/probe-long-render.py +134 -0
- package/plugins/ingestions/aihot-ingest/dist/index.js +12 -12
- package/plugins/ingestions/horizon-ingest/dist/index.js +12 -12
- package/plugins/ingestions/karakeep-local/dist/index.js +13 -13
- package/plugins/ingestions/last30days-ingest/dist/index.js +12 -12
- package/plugins/ingestions/web-search/dist/index.js +10 -10
- package/plugins/kk/decisions/kk-podcast.yaml +44 -0
- package/plugins/kk/decisions/kk-safety.yaml +46 -0
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/scripts/audio-quality.ts +635 -0
- package/plugins/kk/scripts/daily-stages.ts +163 -0
- package/plugins/kk/scripts/kk-workflow-stages.ts +34 -0
- package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +25 -9
- package/plugins/kk/workflows/kk-daily-safety.yaml +37 -10
- package/plugins/kk/workflows/kk-solo-podcast.yaml +65 -1
- package/plugins/publishings/bilibili-pub/dist/index.js +22 -22
- package/plugins/publishings/bilibili-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/cnblogs-pub/dist/index.js +22 -22
- package/plugins/publishings/cnblogs-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/csdn-pub/dist/index.js +22 -22
- package/plugins/publishings/csdn-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/emdash-pub/dist/index.js +9 -9
- package/plugins/publishings/infoq-pub/dist/index.js +22 -22
- package/plugins/publishings/infoq-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/jike-pub/dist/index.js +22 -22
- package/plugins/publishings/jike-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/juejin-pub/dist/index.js +22 -22
- package/plugins/publishings/juejin-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/medium-pub/dist/index.js +9 -9
- package/plugins/publishings/podcast-pub/dist/index.js +9 -9
- package/plugins/publishings/qiita-pub/dist/index.js +9 -9
- package/plugins/publishings/shipinhao-pub/dist/index.js +22 -22
- package/plugins/publishings/shipinhao-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/sspai-pub/dist/index.js +22 -22
- package/plugins/publishings/sspai-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/substack-pub/dist/index.js +22 -22
- package/plugins/publishings/substack-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/surfdash-pub/dist/index.js +39 -12
- package/plugins/publishings/surfdash-pub/src/index.ts +33 -6
- package/plugins/publishings/surfdash-pub/src/patch.ts +4 -0
- package/plugins/publishings/threads-pub/dist/index.js +9 -9
- package/plugins/publishings/wechatmp-pub/dist/index.js +22 -22
- package/plugins/publishings/wechatmp-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/weibo-pub/dist/index.js +22 -22
- package/plugins/publishings/weibo-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/x-pub/dist/index.js +22 -22
- package/plugins/publishings/x-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/xhs-pub/dist/index.js +22 -22
- package/plugins/publishings/xhs-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/xiaoyuzhou-pub/dist/index.js +22 -22
- package/plugins/publishings/xiaoyuzhou-pub/dist/profile-check.js +22 -22
- package/plugins/publishings/zenn-pub/dist/index.js +9 -9
- package/plugins/kk/workflows/feature-verification.yaml +0 -89
|
@@ -4821,7 +4821,7 @@ var init_zod = __esm(() => {
|
|
|
4821
4821
|
init_external();
|
|
4822
4822
|
});
|
|
4823
4823
|
|
|
4824
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4824
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/errors.js
|
|
4825
4825
|
var ErrorCode;
|
|
4826
4826
|
var init_errors3 = __esm(() => {
|
|
4827
4827
|
ErrorCode = {
|
|
@@ -4832,7 +4832,7 @@ var init_errors3 = __esm(() => {
|
|
|
4832
4832
|
};
|
|
4833
4833
|
});
|
|
4834
4834
|
|
|
4835
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4835
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/api-response.js
|
|
4836
4836
|
var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
|
|
4837
4837
|
var init_api_response = __esm(() => {
|
|
4838
4838
|
init_errors3();
|
|
@@ -4855,13 +4855,13 @@ var init_api_response = __esm(() => {
|
|
|
4855
4855
|
CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
|
|
4856
4856
|
});
|
|
4857
4857
|
|
|
4858
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4858
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/cursor.js
|
|
4859
4859
|
var init_cursor = () => {};
|
|
4860
4860
|
|
|
4861
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4861
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
|
|
4862
4862
|
var init_event_severity = () => {};
|
|
4863
4863
|
|
|
4864
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4864
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/output.js
|
|
4865
4865
|
function processStream(name) {
|
|
4866
4866
|
const proc = globalThis.process;
|
|
4867
4867
|
const stream = proc?.[name];
|
|
@@ -4879,7 +4879,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
|
|
|
4879
4879
|
}
|
|
4880
4880
|
var defaultStderrTarget;
|
|
4881
4881
|
|
|
4882
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4882
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/index.js
|
|
4883
4883
|
var init_dist = __esm(() => {
|
|
4884
4884
|
init_api_response();
|
|
4885
4885
|
init_cursor();
|
|
@@ -11877,7 +11877,7 @@ var init_dist2 = __esm(() => {
|
|
|
11877
11877
|
$visitAsync = visit.visitAsync;
|
|
11878
11878
|
});
|
|
11879
11879
|
|
|
11880
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
11880
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/config.js
|
|
11881
11881
|
var configSchema;
|
|
11882
11882
|
var init_config = __esm(() => {
|
|
11883
11883
|
init_dist2();
|
|
@@ -11901,7 +11901,7 @@ var init_config = __esm(() => {
|
|
|
11901
11901
|
});
|
|
11902
11902
|
});
|
|
11903
11903
|
|
|
11904
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
11904
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
|
|
11905
11905
|
import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
|
|
11906
11906
|
import { dirname, resolve as resolvePath } from "path";
|
|
11907
11907
|
function createNodeFileSystem(root, paths) {
|
|
@@ -12167,7 +12167,7 @@ html, body {
|
|
|
12167
12167
|
<div class="illustration-band">
|
|
12168
12168
|
${illustrationSrc ? `<img src="${illustrationSrc}" alt="">` : `<div style="width:100%;height:100%;background:${palette.background};"></div>`}
|
|
12169
12169
|
</div>
|
|
12170
|
-
<div class="text-panel">
|
|
12170
|
+
<div class="text-panel" id="text-panel">
|
|
12171
12171
|
<div class="headline" data-field="headline" id="headline">${escHtml(input.headline)}</div>
|
|
12172
12172
|
<div class="points-container">
|
|
12173
12173
|
${pointsHtml}
|
|
@@ -12179,17 +12179,33 @@ html, body {
|
|
|
12179
12179
|
(function () {
|
|
12180
12180
|
// Step headline font down from start until it fits, never below floor.
|
|
12181
12181
|
var headline = document.getElementById('headline');
|
|
12182
|
+
var panel = document.getElementById('text-panel');
|
|
12182
12183
|
var headlineMinPx = ${headlineMinPx};
|
|
12183
12184
|
var headlineStartPx = ${headlineStartPx};
|
|
12184
12185
|
var safeWidth = ${safeWidth};
|
|
12185
|
-
var panelHeight = ${textPanelHeight - safeArea * 2};
|
|
12186
12186
|
var size = headlineStartPx;
|
|
12187
|
+
// Measure UNWRAPPED: the headline is white-space:normal + word-break:break-all, so a headline
|
|
12188
|
+
// wider than the safe area wraps instead of overflowing \u2014 scrollWidth then equals the container
|
|
12189
|
+
// width and the width check below never fired, leaving the fit loop at its start size. A 10-char
|
|
12190
|
+
// cover headline (96px x 10 = 960px > 936px safe width) wrapped to two lines, pushed the points
|
|
12191
|
+
// block past the safe bottom, and the composer refused every retry because the remediation only
|
|
12192
|
+
// shortens points (2026-10-19 run: points[1], points[2] overflowed, xhs-render failed, the whole
|
|
12193
|
+
// episode stayed unpublished). nowrap makes scrollWidth the real single-line width, so the loop
|
|
12194
|
+
// shrinks the font until the headline fits on one line.
|
|
12195
|
+
headline.style.whiteSpace = 'nowrap';
|
|
12196
|
+
// The vertical budget is SHARED with the points block: measuring only the headline let a 4-bullet
|
|
12197
|
+
// card overflow by ~30px, and the only remediation rewritable in stderr is a points rewrite \u2014 so
|
|
12198
|
+
// the trailing bullet was dropped on every 4-point card (2026-10-19: cards 02/03 shipped 3 of 4
|
|
12199
|
+
// planned points). The panel's own scrollHeight covers headline + margins + gaps + every point.
|
|
12187
12200
|
while (size > headlineMinPx) {
|
|
12188
12201
|
headline.style.fontSize = size + 'px';
|
|
12189
|
-
if (headline.scrollWidth <= safeWidth &&
|
|
12202
|
+
if (headline.scrollWidth <= safeWidth && panel.scrollHeight <= panel.clientHeight) break;
|
|
12190
12203
|
size -= 4;
|
|
12191
12204
|
}
|
|
12192
12205
|
headline.style.fontSize = Math.max(size, headlineMinPx) + 'px';
|
|
12206
|
+
// Restore wrapping: at the floor size a genuinely too-long headline still wraps (and the composer
|
|
12207
|
+
// then refuses loudly) instead of overflowing the card horizontally.
|
|
12208
|
+
headline.style.whiteSpace = 'normal';
|
|
12193
12209
|
})();
|
|
12194
12210
|
</script>
|
|
12195
12211
|
</body>
|
|
@@ -12573,7 +12589,7 @@ var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx)
|
|
|
12573
12589
|
});
|
|
12574
12590
|
}
|
|
12575
12591
|
});
|
|
12576
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
12592
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/index.js
|
|
12577
12593
|
init_file_system_node();
|
|
12578
12594
|
init_config();
|
|
12579
12595
|
|
|
@@ -275,7 +275,7 @@ html, body {
|
|
|
275
275
|
<div class="illustration-band">
|
|
276
276
|
${illustrationSrc ? `<img src="${illustrationSrc}" alt="">` : `<div style="width:100%;height:100%;background:${palette.background};"></div>`}
|
|
277
277
|
</div>
|
|
278
|
-
<div class="text-panel">
|
|
278
|
+
<div class="text-panel" id="text-panel">
|
|
279
279
|
<div class="headline" data-field="headline" id="headline">${escHtml(input.headline)}</div>
|
|
280
280
|
<div class="points-container">
|
|
281
281
|
${pointsHtml}
|
|
@@ -287,17 +287,33 @@ html, body {
|
|
|
287
287
|
(function () {
|
|
288
288
|
// Step headline font down from start until it fits, never below floor.
|
|
289
289
|
var headline = document.getElementById('headline');
|
|
290
|
+
var panel = document.getElementById('text-panel');
|
|
290
291
|
var headlineMinPx = ${headlineMinPx};
|
|
291
292
|
var headlineStartPx = ${headlineStartPx};
|
|
292
293
|
var safeWidth = ${safeWidth};
|
|
293
|
-
var panelHeight = ${textPanelHeight - safeArea * 2};
|
|
294
294
|
var size = headlineStartPx;
|
|
295
|
+
// Measure UNWRAPPED: the headline is white-space:normal + word-break:break-all, so a headline
|
|
296
|
+
// wider than the safe area wraps instead of overflowing — scrollWidth then equals the container
|
|
297
|
+
// width and the width check below never fired, leaving the fit loop at its start size. A 10-char
|
|
298
|
+
// cover headline (96px x 10 = 960px > 936px safe width) wrapped to two lines, pushed the points
|
|
299
|
+
// block past the safe bottom, and the composer refused every retry because the remediation only
|
|
300
|
+
// shortens points (2026-10-19 run: points[1], points[2] overflowed, xhs-render failed, the whole
|
|
301
|
+
// episode stayed unpublished). nowrap makes scrollWidth the real single-line width, so the loop
|
|
302
|
+
// shrinks the font until the headline fits on one line.
|
|
303
|
+
headline.style.whiteSpace = 'nowrap';
|
|
304
|
+
// The vertical budget is SHARED with the points block: measuring only the headline let a 4-bullet
|
|
305
|
+
// card overflow by ~30px, and the only remediation rewritable in stderr is a points rewrite — so
|
|
306
|
+
// the trailing bullet was dropped on every 4-point card (2026-10-19: cards 02/03 shipped 3 of 4
|
|
307
|
+
// planned points). The panel's own scrollHeight covers headline + margins + gaps + every point.
|
|
295
308
|
while (size > headlineMinPx) {
|
|
296
309
|
headline.style.fontSize = size + 'px';
|
|
297
|
-
if (headline.scrollWidth <= safeWidth &&
|
|
310
|
+
if (headline.scrollWidth <= safeWidth && panel.scrollHeight <= panel.clientHeight) break;
|
|
298
311
|
size -= 4;
|
|
299
312
|
}
|
|
300
313
|
headline.style.fontSize = Math.max(size, headlineMinPx) + 'px';
|
|
314
|
+
// Restore wrapping: at the floor size a genuinely too-long headline still wraps (and the composer
|
|
315
|
+
// then refuses loudly) instead of overflowing the card horizontally.
|
|
316
|
+
headline.style.whiteSpace = 'normal';
|
|
301
317
|
})();
|
|
302
318
|
</script>
|
|
303
319
|
</body>
|
|
@@ -4813,7 +4813,7 @@ var init_zod = __esm(() => {
|
|
|
4813
4813
|
init_external();
|
|
4814
4814
|
});
|
|
4815
4815
|
|
|
4816
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4816
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/errors.js
|
|
4817
4817
|
var ErrorCode;
|
|
4818
4818
|
var init_errors3 = __esm(() => {
|
|
4819
4819
|
ErrorCode = {
|
|
@@ -4824,7 +4824,7 @@ var init_errors3 = __esm(() => {
|
|
|
4824
4824
|
};
|
|
4825
4825
|
});
|
|
4826
4826
|
|
|
4827
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4827
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/api-response.js
|
|
4828
4828
|
var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
|
|
4829
4829
|
var init_api_response = __esm(() => {
|
|
4830
4830
|
init_errors3();
|
|
@@ -4847,13 +4847,13 @@ var init_api_response = __esm(() => {
|
|
|
4847
4847
|
CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
|
|
4848
4848
|
});
|
|
4849
4849
|
|
|
4850
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4850
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/cursor.js
|
|
4851
4851
|
var init_cursor = () => {};
|
|
4852
4852
|
|
|
4853
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4853
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
|
|
4854
4854
|
var init_event_severity = () => {};
|
|
4855
4855
|
|
|
4856
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4856
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/output.js
|
|
4857
4857
|
function processStream(name) {
|
|
4858
4858
|
const proc = globalThis.process;
|
|
4859
4859
|
const stream = proc?.[name];
|
|
@@ -4871,7 +4871,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
|
|
|
4871
4871
|
}
|
|
4872
4872
|
var defaultStderrTarget;
|
|
4873
4873
|
|
|
4874
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4874
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/index.js
|
|
4875
4875
|
var init_dist = __esm(() => {
|
|
4876
4876
|
init_api_response();
|
|
4877
4877
|
init_cursor();
|
|
@@ -11869,7 +11869,7 @@ var init_dist2 = __esm(() => {
|
|
|
11869
11869
|
$visitAsync = visit.visitAsync;
|
|
11870
11870
|
});
|
|
11871
11871
|
|
|
11872
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
11872
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/config.js
|
|
11873
11873
|
var configSchema;
|
|
11874
11874
|
var init_config = __esm(() => {
|
|
11875
11875
|
init_dist2();
|
|
@@ -11893,7 +11893,7 @@ var init_config = __esm(() => {
|
|
|
11893
11893
|
});
|
|
11894
11894
|
});
|
|
11895
11895
|
|
|
11896
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
11896
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
|
|
11897
11897
|
import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
|
|
11898
11898
|
import { dirname, resolve as resolvePath } from "path";
|
|
11899
11899
|
function createNodeFileSystem(root, paths) {
|
|
@@ -12248,14 +12248,14 @@ var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx)
|
|
|
12248
12248
|
});
|
|
12249
12249
|
}
|
|
12250
12250
|
});
|
|
12251
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
12251
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/index.js
|
|
12252
12252
|
init_file_system_node();
|
|
12253
12253
|
init_config();
|
|
12254
12254
|
|
|
12255
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
12255
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/fs.js
|
|
12256
12256
|
init_file_system_node();
|
|
12257
12257
|
|
|
12258
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
12258
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/path.js
|
|
12259
12259
|
function normalizeSeparators(path) {
|
|
12260
12260
|
return path.replaceAll("\\", "/");
|
|
12261
12261
|
}
|
|
@@ -12289,7 +12289,7 @@ function dirnamePath(path) {
|
|
|
12289
12289
|
return normalized.slice(0, index);
|
|
12290
12290
|
}
|
|
12291
12291
|
|
|
12292
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
12292
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/fs.js
|
|
12293
12293
|
async function ensureDirForFile(path, fs = createNodeFileSystem()) {
|
|
12294
12294
|
await fs.ensureDir(dirnamePath(path));
|
|
12295
12295
|
}
|
|
@@ -4813,7 +4813,7 @@ var init_zod = __esm(() => {
|
|
|
4813
4813
|
init_external();
|
|
4814
4814
|
});
|
|
4815
4815
|
|
|
4816
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4816
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/errors.js
|
|
4817
4817
|
var ErrorCode;
|
|
4818
4818
|
var init_errors3 = __esm(() => {
|
|
4819
4819
|
ErrorCode = {
|
|
@@ -4824,7 +4824,7 @@ var init_errors3 = __esm(() => {
|
|
|
4824
4824
|
};
|
|
4825
4825
|
});
|
|
4826
4826
|
|
|
4827
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4827
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/api-response.js
|
|
4828
4828
|
var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
|
|
4829
4829
|
var init_api_response = __esm(() => {
|
|
4830
4830
|
init_errors3();
|
|
@@ -4847,13 +4847,13 @@ var init_api_response = __esm(() => {
|
|
|
4847
4847
|
CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
|
|
4848
4848
|
});
|
|
4849
4849
|
|
|
4850
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4850
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/cursor.js
|
|
4851
4851
|
var init_cursor = () => {};
|
|
4852
4852
|
|
|
4853
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4853
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
|
|
4854
4854
|
var init_event_severity = () => {};
|
|
4855
4855
|
|
|
4856
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4856
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/output.js
|
|
4857
4857
|
function processStream(name) {
|
|
4858
4858
|
const proc = globalThis.process;
|
|
4859
4859
|
const stream = proc?.[name];
|
|
@@ -4871,7 +4871,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
|
|
|
4871
4871
|
}
|
|
4872
4872
|
var defaultStderrTarget;
|
|
4873
4873
|
|
|
4874
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
4874
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/index.js
|
|
4875
4875
|
var init_dist = __esm(() => {
|
|
4876
4876
|
init_api_response();
|
|
4877
4877
|
init_cursor();
|
|
@@ -11869,7 +11869,7 @@ var init_dist2 = __esm(() => {
|
|
|
11869
11869
|
$visitAsync = visit.visitAsync;
|
|
11870
11870
|
});
|
|
11871
11871
|
|
|
11872
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
11872
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/config.js
|
|
11873
11873
|
var configSchema;
|
|
11874
11874
|
var init_config = __esm(() => {
|
|
11875
11875
|
init_dist2();
|
|
@@ -11893,7 +11893,7 @@ var init_config = __esm(() => {
|
|
|
11893
11893
|
});
|
|
11894
11894
|
});
|
|
11895
11895
|
|
|
11896
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
11896
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
|
|
11897
11897
|
import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
|
|
11898
11898
|
import { dirname, resolve as resolvePath } from "path";
|
|
11899
11899
|
function createNodeFileSystem(root, paths) {
|
|
@@ -12248,7 +12248,7 @@ var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx)
|
|
|
12248
12248
|
});
|
|
12249
12249
|
}
|
|
12250
12250
|
});
|
|
12251
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
12251
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/index.js
|
|
12252
12252
|
init_file_system_node();
|
|
12253
12253
|
init_config();
|
|
12254
12254
|
|
|
@@ -79,6 +79,24 @@ that evidence belongs to task 0258.
|
|
|
79
79
|
> Grade any render with `scripts/audit-speaker-consistency.py` (needs this plugin's venv):
|
|
80
80
|
> a per-item F0 spread over 45 Hz means the profile is not anchoring a speaker.
|
|
81
81
|
|
|
82
|
+
### Known artifact: a 40 ms echo lattice on long renders (2026-10-20)
|
|
83
|
+
|
|
84
|
+
A `reference`-anchored profile renders short text clean and long text with a 40 ms (≈25 Hz) periodic
|
|
85
|
+
reflection plus a pause floor only 16–22 dB below speech — heard as 「回声感、瓮声瓮气」. Measured on the
|
|
86
|
+
raw model output (no ffmpeg join, no mp3): `kk stage audio-quality` reports `cepstrum 40 ms @ 27–31 dB`
|
|
87
|
+
for renders >30 s, `pause floor −16…−22 dB`, while a 10 s render of the same profile/text measures
|
|
88
|
+
`22 ms @ 19 dB / −22.5 dB` and the same days' `gemini-tts` episodes measure `20–25 ms @ 19–20 dB /
|
|
89
|
+
−34…−37 dB`. `inference_timesteps`, `cfg_value` and `normalize` do not move it (measured 2026-10-20).
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# reproducible in ~2.5 min, no episode needed:
|
|
93
|
+
plugins/generations/voxcpm-tts/.venv/bin/python \
|
|
94
|
+
plugins/generations/voxcpm-tts/scripts/probe-long-render.py --out /tmp/voxcpm-probe
|
|
95
|
+
kk stage audio-quality /tmp/voxcpm-probe/long-baseline.wav
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Treat a driver/profile change as unproven until a LONG render is measured, not a single sentence.
|
|
99
|
+
|
|
82
100
|
## Control policy
|
|
83
101
|
|
|
84
102
|
`normalize` maps directly; an explicit `seed` calls `torch.manual_seed` before synthesis (the
|
|
@@ -90,3 +108,16 @@ one for every segment, derived from its `emotion`, and the anchored clip already
|
|
|
90
108
|
A per-request `engine`,
|
|
91
109
|
`personality=true` or an active `effects_chain` is rejected. Speed stays in shared postprocessing.
|
|
92
110
|
Transcription is omitted, so ASR-dependent QC is reported unavailable (not passing evidence).
|
|
111
|
+
|
|
112
|
+
#### API/library claim sources and confidence
|
|
113
|
+
|
|
114
|
+
The externally changeable claims this file makes about the installed `voxcpm` package, each with the
|
|
115
|
+
artifact it was read from. This block is enforced by `structure/api-library-claim-citation` (the file
|
|
116
|
+
is in that rule's `--require-block` registry), so a HIGH claim without a citation fails the gate.
|
|
117
|
+
|
|
118
|
+
| Claim | Source | Local verification | Confidence |
|
|
119
|
+
| --- | --- | --- | --- |
|
|
120
|
+
| `reference_wav_path` is accepted only by VoxCPM2 checkpoints; any other model id refuses it, so a `reference` profile is VoxCPM2-only while older checkpoints clone through `prompt_wav_path` + `prompt_text` | installed `voxcpm` package | `plugins/generations/voxcpm-tts/.venv/lib/python3.12/site-packages/voxcpm/core.py:239` (`ValueError("reference_wav_path is only supported with VoxCPM2 models")`); reproduced with `scripts/probe-long-render.py --model openbmb/VoxCPM1.5` | HIGH |
|
|
121
|
+
| `generate()`/`_generate()` exposes `cfg_value` (default 2.0), `inference_timesteps` (10), `normalize`, `denoise` and `max_len`, and this plugin passes none of them — the profile and text are the only inputs it sets | installed `voxcpm` package plus this plugin's worker | `…/site-packages/voxcpm/core.py:180`–`:193` (signature and defaults) and `python/worker.py:252`–`:262` (the three `generate(...)` call shapes) | HIGH |
|
|
122
|
+
| `VOXCPM_MODEL` defaults to `openbmb/VoxCPM2`, the model self-reports its output rate, and that rate is what the WAV header carries (no resampling in this plugin) | this plugin's worker | `python/worker.py:181` (`environ.get("VOXCPM_MODEL", "openbmb/VoxCPM2")`), `:207` (`int(model.tts_model.sample_rate)`) and `:264` (`write_pcm16_wav(dest, pcm, sample_rate)`) | HIGH |
|
|
123
|
+
| A `reference` profile pins one speaker (median-pitch swing 22–26 Hz, sd 9–12 Hz) while `instruct` samples a new speaker per request (141 Hz swing), so multi-segment work needs a reference or continuation profile | measured on this machine, 2026-10-15, three texts | `scripts/audit-speaker-consistency.py` grades a render; the 2026-10-15 figures are the ones its docstring records | MEDIUM |
|
|
@@ -13,7 +13,7 @@ var __esm = (fn, res, err) => () => {
|
|
|
13
13
|
};
|
|
14
14
|
var __require = import.meta.require;
|
|
15
15
|
|
|
16
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
16
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/errors.js
|
|
17
17
|
var ErrorCode;
|
|
18
18
|
var init_errors = __esm(() => {
|
|
19
19
|
ErrorCode = {
|
|
@@ -24,7 +24,7 @@ var init_errors = __esm(() => {
|
|
|
24
24
|
};
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
27
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/api-response.js
|
|
28
28
|
var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
|
|
29
29
|
var init_api_response = __esm(() => {
|
|
30
30
|
init_errors();
|
|
@@ -47,13 +47,13 @@ var init_api_response = __esm(() => {
|
|
|
47
47
|
CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
50
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/cursor.js
|
|
51
51
|
var init_cursor = () => {};
|
|
52
52
|
|
|
53
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
53
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
|
|
54
54
|
var init_event_severity = () => {};
|
|
55
55
|
|
|
56
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
56
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/output.js
|
|
57
57
|
function processStream(name) {
|
|
58
58
|
const proc = globalThis.process;
|
|
59
59
|
const stream = proc?.[name];
|
|
@@ -71,7 +71,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
|
|
|
71
71
|
}
|
|
72
72
|
var defaultStderrTarget;
|
|
73
73
|
|
|
74
|
-
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.
|
|
74
|
+
// ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/index.js
|
|
75
75
|
var init_dist = __esm(() => {
|
|
76
76
|
init_api_response();
|
|
77
77
|
init_cursor();
|
|
@@ -11869,7 +11869,7 @@ var init_dist2 = __esm(() => {
|
|
|
11869
11869
|
$visitAsync = visit.visitAsync;
|
|
11870
11870
|
});
|
|
11871
11871
|
|
|
11872
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
11872
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/config.js
|
|
11873
11873
|
var configSchema;
|
|
11874
11874
|
var init_config = __esm(() => {
|
|
11875
11875
|
init_dist2();
|
|
@@ -11893,7 +11893,7 @@ var init_config = __esm(() => {
|
|
|
11893
11893
|
});
|
|
11894
11894
|
});
|
|
11895
11895
|
|
|
11896
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
11896
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
|
|
11897
11897
|
import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
|
|
11898
11898
|
import { dirname, resolve as resolvePath } from "path";
|
|
11899
11899
|
function createNodeFileSystem(root, paths) {
|
|
@@ -12251,7 +12251,7 @@ var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx)
|
|
|
12251
12251
|
});
|
|
12252
12252
|
}
|
|
12253
12253
|
});
|
|
12254
|
-
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.
|
|
12254
|
+
// ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/index.js
|
|
12255
12255
|
init_file_system_node();
|
|
12256
12256
|
init_config();
|
|
12257
12257
|
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Reproduce the long-form voxcpm "echo / hollow" artifact in ~2.5 minutes.
|
|
3
|
+
|
|
4
|
+
Why this exists: the 2026-10-20 operator report ("回声感、瓮声瓮气") is not reproducible on a short
|
|
5
|
+
sentence — a 10 s render comes out clean — but it IS reproducible on a paragraph of ~450 Chinese
|
|
6
|
+
characters, which is the length the daily pipeline actually renders per section. Measured 2026-10-20
|
|
7
|
+
with `kk stage audio-quality` (real-cepstrum echo probe + pause floor):
|
|
8
|
+
|
|
9
|
+
short render (~10 s) cepstrum 22 ms @ 19 dB pause floor -22.5 dB clean
|
|
10
|
+
long render (~72 s) cepstrum 40 ms @ 30 dB pause floor -16.1 dB reproduced
|
|
11
|
+
shipped 2026-10-20 §00 cepstrum 40 ms @ 23 dB pause floor -15.7 dB reproduced
|
|
12
|
+
|
|
13
|
+
So the artifact is duration-dependent, and a knob experiment has to use a LONG text or it measures
|
|
14
|
+
nothing. The same run measured `inference_timesteps=20` (29.6 dB) and `cfg_value=2.5` (31.5 dB) against
|
|
15
|
+
the default's 30 dB: none of the exposed sampler knobs remove the 40 ms periodicity.
|
|
16
|
+
|
|
17
|
+
Usage (needs the plugin venv):
|
|
18
|
+
|
|
19
|
+
plugins/generations/voxcpm-tts/.venv/bin/python \
|
|
20
|
+
plugins/generations/voxcpm-tts/scripts/probe-long-render.py [--out /tmp/voxcpm-probe]
|
|
21
|
+
|
|
22
|
+
kk stage audio-quality /tmp/voxcpm-probe/long-baseline.wav # then read cepstrum + pauseFloor
|
|
23
|
+
|
|
24
|
+
Options: `--text-file <path>` (default: the built-in paragraph below), `--ref <wav>` (default: the
|
|
25
|
+
operator's `robin-news` clip), `--steps N`, `--cfg F`, `--normalize`, `--name <label>`.
|
|
26
|
+
|
|
27
|
+
The verdict vocabulary lives in `plugins/kk/scripts/audio-quality.ts` (`kk stage audio-quality`);
|
|
28
|
+
this script only renders.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
import argparse
|
|
34
|
+
import contextlib
|
|
35
|
+
import os
|
|
36
|
+
import sys
|
|
37
|
+
import time
|
|
38
|
+
import wave
|
|
39
|
+
|
|
40
|
+
DEFAULT_TEXT = (
|
|
41
|
+
"大家好,今天是2026年10月20日,星期二。这里是由Robin为你带来的咸话咸说之每日AI乱炖。"
|
|
42
|
+
"今天聊两件跟动手有关的事,一位自称几乎不懂游戏开发的作者,靠编程智能体把一款手机端的即时战略游戏"
|
|
43
|
+
"一路做到能离线运行;另一件是 Google 开源了让 PyTorch 跑上 TPU 的项目。两条线索都指向同一件事:"
|
|
44
|
+
"工具链的边界在移动,真正决定成败的不是模型榜单,而是谁能把验收口径写清楚。"
|
|
45
|
+
"先说游戏那条,作者的说法很朴素,他不写引擎,只把需求拆成可以验证的小步,让智能体一步一步改,"
|
|
46
|
+
"每一步都跑一次构建,坏了自己回滚。这种做法听起来笨,但它把不确定性压到了单步之内,"
|
|
47
|
+
"出问题的时候能立刻定位到底层接口还是生成逻辑。我更在意的是这套流程对工程团队的启示:"
|
|
48
|
+
"当生成成本降到几乎为零,稀缺的就不是代码,而是判断哪一步值得交给机器、哪一步必须留给人验。"
|
|
49
|
+
)
|
|
50
|
+
DEFAULT_REF = os.path.expanduser("~/.config/kk/voices/robin-news.wav")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def main() -> int:
|
|
54
|
+
parser = argparse.ArgumentParser(description="Render one long-form voxcpm sample for echo triage.")
|
|
55
|
+
parser.add_argument("--text-file", default=None, help="UTF-8 text to render (default: built-in paragraph)")
|
|
56
|
+
parser.add_argument("--ref", default=DEFAULT_REF, help="reference clip (default: %(default)s)")
|
|
57
|
+
parser.add_argument("--out", default="/tmp/voxcpm-probe", help="output directory (default: %(default)s)")
|
|
58
|
+
parser.add_argument("--name", default="long-baseline", help="output file stem (default: %(default)s)")
|
|
59
|
+
parser.add_argument("--steps", type=int, default=10, help="inference_timesteps (default 10, the plugin's)")
|
|
60
|
+
parser.add_argument("--cfg", type=float, default=2.0, help="cfg_value (default 2.0, the plugin's)")
|
|
61
|
+
parser.add_argument("--normalize", action="store_true", help="pass normalize=True")
|
|
62
|
+
parser.add_argument(
|
|
63
|
+
"--mode",
|
|
64
|
+
choices=["reference", "continuation", "instruct"],
|
|
65
|
+
default="reference",
|
|
66
|
+
help="reference cloning (VoxCPM2 only), prompt continuation, or instruct-only (default reference)",
|
|
67
|
+
)
|
|
68
|
+
parser.add_argument("--prompt-text", default=None, help="transcript of --ref, required by --mode continuation")
|
|
69
|
+
parser.add_argument(
|
|
70
|
+
"--denoise",
|
|
71
|
+
action="store_true",
|
|
72
|
+
help="load the ZipEnhancer denoiser and pass denoise=True (the plugin ships load_denoiser=False)",
|
|
73
|
+
)
|
|
74
|
+
parser.add_argument("--model", default="openbmb/VoxCPM2", help="hub id or local snapshot")
|
|
75
|
+
args = parser.parse_args()
|
|
76
|
+
|
|
77
|
+
text = open(args.text_file, encoding="utf-8").read().strip() if args.text_file else DEFAULT_TEXT
|
|
78
|
+
if not text:
|
|
79
|
+
print("probe: empty text", file=sys.stderr)
|
|
80
|
+
return 2
|
|
81
|
+
if not os.path.isfile(args.ref):
|
|
82
|
+
print(f"probe: reference clip not found: {args.ref}", file=sys.stderr)
|
|
83
|
+
return 2
|
|
84
|
+
os.makedirs(args.out, exist_ok=True)
|
|
85
|
+
|
|
86
|
+
# The model prints its own progress on stdout; keep this script's stdout for the summary.
|
|
87
|
+
with contextlib.redirect_stdout(sys.stderr):
|
|
88
|
+
import numpy as np
|
|
89
|
+
import voxcpm
|
|
90
|
+
|
|
91
|
+
model = voxcpm.VoxCPM.from_pretrained(
|
|
92
|
+
args.model, load_denoiser=args.denoise, optimize=False, device=None
|
|
93
|
+
)
|
|
94
|
+
sample_rate = int(model.tts_model.sample_rate)
|
|
95
|
+
|
|
96
|
+
if args.mode == "continuation" and not args.prompt_text:
|
|
97
|
+
print("probe: --mode continuation needs --prompt-text (the transcript of --ref)", file=sys.stderr)
|
|
98
|
+
return 2
|
|
99
|
+
# Only VoxCPM2 accepts `reference_wav_path`; every other checkpoint clones through a prompt pair.
|
|
100
|
+
anchoring = {
|
|
101
|
+
"reference": {"reference_wav_path": args.ref},
|
|
102
|
+
"continuation": {"prompt_wav_path": args.ref, "prompt_text": args.prompt_text or ""},
|
|
103
|
+
"instruct": {},
|
|
104
|
+
}[args.mode]
|
|
105
|
+
|
|
106
|
+
started = time.time()
|
|
107
|
+
with contextlib.redirect_stdout(sys.stderr):
|
|
108
|
+
waveform = model.generate(
|
|
109
|
+
text=text,
|
|
110
|
+
cfg_value=args.cfg,
|
|
111
|
+
inference_timesteps=args.steps,
|
|
112
|
+
normalize=args.normalize,
|
|
113
|
+
denoise=args.denoise,
|
|
114
|
+
**anchoring,
|
|
115
|
+
)
|
|
116
|
+
samples = np.clip(np.asarray(waveform).squeeze(), -1.0, 1.0)
|
|
117
|
+
path = os.path.join(args.out, f"{args.name}.wav")
|
|
118
|
+
with wave.open(path, "wb") as handle:
|
|
119
|
+
handle.setnchannels(1)
|
|
120
|
+
handle.setsampwidth(2)
|
|
121
|
+
handle.setframerate(sample_rate)
|
|
122
|
+
handle.writeframes((samples * 32767).astype(np.int16).tobytes())
|
|
123
|
+
|
|
124
|
+
seconds = len(samples) / sample_rate
|
|
125
|
+
print(
|
|
126
|
+
f"{path} {seconds:.1f}s sr={sample_rate} chars={len(text)} "
|
|
127
|
+
f"mode={args.mode} steps={args.steps} cfg={args.cfg} normalize={args.normalize} denoise={args.denoise} render={time.time() - started:.1f}s"
|
|
128
|
+
)
|
|
129
|
+
print("measure it with: kk stage audio-quality " + path, file=sys.stderr)
|
|
130
|
+
return 0
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
if __name__ == "__main__":
|
|
134
|
+
sys.exit(main())
|