@enslo/sd-metadata 2.0.0 → 2.0.1
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.ja.md +32 -41
- package/README.md +32 -40
- package/dist/index.js +61 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -11,7 +11,7 @@ AI生成画像に埋め込まれたメタデータを読み書きするための
|
|
|
11
11
|
## 特徴
|
|
12
12
|
|
|
13
13
|
- **マルチフォーマット対応**: PNG (tEXt / iTXt)、JPEG (COM / Exif)、WebP (Exif)
|
|
14
|
-
-
|
|
14
|
+
- **シンプルAPI**: `read()`、`write()`、`embed()`、`stringify()` — 4つの関数で全ユースケースをカバー
|
|
15
15
|
- **TypeScriptネイティブ**: TypeScriptで書かれており、型定義を完全同梱
|
|
16
16
|
- **ゼロ依存**: Node.jsとブラウザで外部依存なしで動作
|
|
17
17
|
- **フォーマット変換**: PNG、JPEG、WebP間でメタデータをシームレスに変換
|
|
@@ -95,10 +95,9 @@ const { read } = require('@enslo/sd-metadata');
|
|
|
95
95
|
### Node.jsでの使用
|
|
96
96
|
|
|
97
97
|
```typescript
|
|
98
|
-
import { read,
|
|
99
|
-
import { readFileSync
|
|
98
|
+
import { read, stringify } from '@enslo/sd-metadata';
|
|
99
|
+
import { readFileSync } from 'fs';
|
|
100
100
|
|
|
101
|
-
// サポートされている任意のフォーマットからメタデータを読み込み
|
|
102
101
|
const imageData = readFileSync('image.png');
|
|
103
102
|
const result = read(imageData);
|
|
104
103
|
|
|
@@ -108,24 +107,30 @@ if (result.status === 'success') {
|
|
|
108
107
|
console.log('Model:', result.metadata.model?.name);
|
|
109
108
|
console.log('Size:', result.metadata.width, 'x', result.metadata.height);
|
|
110
109
|
}
|
|
110
|
+
|
|
111
|
+
// 読みやすいテキストにフォーマット(任意のstatusで動作)
|
|
112
|
+
const text = stringify(result);
|
|
113
|
+
if (text) {
|
|
114
|
+
console.log(text);
|
|
115
|
+
}
|
|
111
116
|
```
|
|
112
117
|
|
|
113
118
|
### ブラウザでの使用
|
|
114
119
|
|
|
115
120
|
```typescript
|
|
116
|
-
import { read } from '@enslo/sd-metadata';
|
|
121
|
+
import { read, softwareLabels } from '@enslo/sd-metadata';
|
|
117
122
|
|
|
118
123
|
// ファイル入力を処理
|
|
119
124
|
const fileInput = document.querySelector('input[type="file"]');
|
|
120
125
|
fileInput.addEventListener('change', async (e) => {
|
|
121
126
|
const file = e.target.files[0];
|
|
122
127
|
if (!file) return;
|
|
123
|
-
|
|
128
|
+
|
|
124
129
|
const arrayBuffer = await file.arrayBuffer();
|
|
125
130
|
const result = read(arrayBuffer);
|
|
126
|
-
|
|
131
|
+
|
|
127
132
|
if (result.status === 'success') {
|
|
128
|
-
document.getElementById('tool').textContent = result.metadata.software;
|
|
133
|
+
document.getElementById('tool').textContent = softwareLabels[result.metadata.software];
|
|
129
134
|
document.getElementById('prompt').textContent = result.metadata.prompt;
|
|
130
135
|
document.getElementById('model').textContent = result.metadata.model?.name || 'N/A';
|
|
131
136
|
}
|
|
@@ -154,7 +159,7 @@ if (result.status === 'success') {
|
|
|
154
159
|
> 本番環境では `@latest` の代わりに特定のバージョンを指定してください:
|
|
155
160
|
>
|
|
156
161
|
> ```text
|
|
157
|
-
> https://cdn.jsdelivr.net/npm/@enslo/sd-metadata@2.0.
|
|
162
|
+
> https://cdn.jsdelivr.net/npm/@enslo/sd-metadata@2.0.1/dist/index.js
|
|
158
163
|
> ```
|
|
159
164
|
|
|
160
165
|
### 応用例
|
|
@@ -185,8 +190,7 @@ if (parseResult.status === 'success') {
|
|
|
185
190
|
}
|
|
186
191
|
```
|
|
187
192
|
|
|
188
|
-
> [
|
|
189
|
-
> このライブラリはメタデータの読み書きのみを扱います。実際の画像フォーマット変換(ピクセルのデコード/エンコード)には、[sharp](https://www.npmjs.com/package/sharp)、[jimp](https://www.npmjs.com/package/jimp)、ブラウザCanvas APIなどの画像処理ライブラリを使用してください。
|
|
193
|
+
> **Tip:** このライブラリはメタデータの読み書きのみを扱います。実際の画像フォーマット変換(ピクセルのデコード/エンコード)には、[sharp](https://www.npmjs.com/package/sharp)、[jimp](https://www.npmjs.com/package/jimp)、ブラウザCanvas APIなどの画像処理ライブラリを使用してください。
|
|
190
194
|
|
|
191
195
|
</details>
|
|
192
196
|
|
|
@@ -309,8 +313,7 @@ const result = embed(imageData, {
|
|
|
309
313
|
});
|
|
310
314
|
```
|
|
311
315
|
|
|
312
|
-
>
|
|
313
|
-
> extras のキーが構造化フィールド(例:`Steps`)と一致する場合、extras の値が元の位置で構造化フィールドを上書きします。新しいキーは末尾に追加されます。
|
|
316
|
+
> **Tip:** extras のキーが構造化フィールド(例:`Steps`)と一致する場合、extras の値が元の位置で構造化フィールドを上書きします。新しいキーは末尾に追加されます。
|
|
314
317
|
|
|
315
318
|
`EmbedMetadata` はすべての `GenerationMetadata` バリアントのサブセットなので、パース結果のメタデータをそのまま渡せます — `characterPrompts` を持つ NovelAI も含めて:
|
|
316
319
|
|
|
@@ -353,10 +356,15 @@ if (text) {
|
|
|
353
356
|
|
|
354
357
|
## APIリファレンス
|
|
355
358
|
|
|
356
|
-
### `read(input: Uint8Array | ArrayBuffer): ParseResult`
|
|
359
|
+
### `read(input: Uint8Array | ArrayBuffer, options?: ReadOptions): ParseResult`
|
|
357
360
|
|
|
358
361
|
画像ファイルからメタデータを読み込み、パースします。
|
|
359
362
|
|
|
363
|
+
**パラメータ:**
|
|
364
|
+
|
|
365
|
+
- `input` - 画像ファイルデータ(PNG、JPEG、またはWebP)
|
|
366
|
+
- `options` - オプションの読み込み設定(詳細は[型ドキュメント](./docs/types.ja.md)を参照)
|
|
367
|
+
|
|
360
368
|
**戻り値:**
|
|
361
369
|
|
|
362
370
|
- `{ status: 'success', metadata, raw }` - パース成功
|
|
@@ -575,45 +583,28 @@ type RawMetadata =
|
|
|
575
583
|
| { format: 'webp'; segments: MetadataSegment[] };
|
|
576
584
|
```
|
|
577
585
|
|
|
578
|
-
> [!TIP]
|
|
579
|
-
> TypeScriptユーザー向け:全ての型はエクスポートされており、インポートして使用できます。
|
|
580
|
-
>
|
|
581
|
-
> ```typescript
|
|
582
|
-
> import type {
|
|
583
|
-
> BaseMetadata,
|
|
584
|
-
> EmbedMetadata,
|
|
585
|
-
> ParseResult,
|
|
586
|
-
> GenerationMetadata,
|
|
587
|
-
> GenerationSoftware,
|
|
588
|
-
> ModelSettings,
|
|
589
|
-
> SamplingSettings
|
|
590
|
-
> } from '@enslo/sd-metadata';
|
|
591
|
-
> ```
|
|
592
|
-
>
|
|
593
|
-
> IDEのIntelliSenseを使用して自動補完とインラインドキュメントを活用してください。
|
|
594
|
-
|
|
595
586
|
`ModelSettings`、`SamplingSettings`、フォーマット固有の型を含む全てのエクスポート型の詳細なドキュメントについては、[型ドキュメント](./docs/types.ja.md)を参照してください。
|
|
596
587
|
|
|
597
588
|
## 開発
|
|
598
589
|
|
|
599
590
|
```bash
|
|
600
591
|
# 依存関係をインストール
|
|
601
|
-
|
|
592
|
+
pnpm install
|
|
602
593
|
|
|
603
594
|
# テストを実行
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
# ウォッチモード
|
|
607
|
-
npm run test:watch
|
|
608
|
-
|
|
609
|
-
# テストカバレッジ
|
|
610
|
-
npm run test:coverage
|
|
595
|
+
pnpm test
|
|
611
596
|
|
|
612
597
|
# ビルド
|
|
613
|
-
|
|
598
|
+
pnpm build
|
|
614
599
|
|
|
615
600
|
# リント
|
|
616
|
-
|
|
601
|
+
pnpm lint
|
|
602
|
+
|
|
603
|
+
# 型チェック
|
|
604
|
+
pnpm typecheck
|
|
605
|
+
|
|
606
|
+
# デモサイト起動
|
|
607
|
+
pnpm demo
|
|
617
608
|
```
|
|
618
609
|
|
|
619
610
|
## ライセンス
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ A TypeScript library to read and write metadata embedded in AI-generated images.
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
13
|
- **Multi-format Support**: PNG (tEXt / iTXt), JPEG (COM / Exif), WebP (Exif)
|
|
14
|
-
- **
|
|
14
|
+
- **Simple API**: `read()`, `write()`, `embed()`, `stringify()` — four functions cover all use cases
|
|
15
15
|
- **TypeScript Native**: Written in TypeScript with full type definitions included
|
|
16
16
|
- **Zero Dependencies**: Works in Node.js and browsers without any external dependencies
|
|
17
17
|
- **Format Conversion**: Seamlessly convert metadata between PNG, JPEG, and WebP
|
|
@@ -95,8 +95,8 @@ const { read } = require('@enslo/sd-metadata');
|
|
|
95
95
|
### Node.js Usage
|
|
96
96
|
|
|
97
97
|
```typescript
|
|
98
|
-
import { read,
|
|
99
|
-
import { readFileSync
|
|
98
|
+
import { read, stringify } from '@enslo/sd-metadata';
|
|
99
|
+
import { readFileSync } from 'fs';
|
|
100
100
|
|
|
101
101
|
const imageData = readFileSync('image.png');
|
|
102
102
|
const result = read(imageData);
|
|
@@ -107,24 +107,30 @@ if (result.status === 'success') {
|
|
|
107
107
|
console.log('Model:', result.metadata.model?.name);
|
|
108
108
|
console.log('Size:', result.metadata.width, 'x', result.metadata.height);
|
|
109
109
|
}
|
|
110
|
+
|
|
111
|
+
// Format as human-readable text (works with any status)
|
|
112
|
+
const text = stringify(result);
|
|
113
|
+
if (text) {
|
|
114
|
+
console.log(text);
|
|
115
|
+
}
|
|
110
116
|
```
|
|
111
117
|
|
|
112
118
|
### Browser Usage
|
|
113
119
|
|
|
114
120
|
```typescript
|
|
115
|
-
import { read } from '@enslo/sd-metadata';
|
|
121
|
+
import { read, softwareLabels } from '@enslo/sd-metadata';
|
|
116
122
|
|
|
117
123
|
// Handle file input
|
|
118
124
|
const fileInput = document.querySelector('input[type="file"]');
|
|
119
125
|
fileInput.addEventListener('change', async (e) => {
|
|
120
126
|
const file = e.target.files[0];
|
|
121
127
|
if (!file) return;
|
|
122
|
-
|
|
128
|
+
|
|
123
129
|
const arrayBuffer = await file.arrayBuffer();
|
|
124
130
|
const result = read(arrayBuffer);
|
|
125
|
-
|
|
131
|
+
|
|
126
132
|
if (result.status === 'success') {
|
|
127
|
-
document.getElementById('tool').textContent = result.metadata.software;
|
|
133
|
+
document.getElementById('tool').textContent = softwareLabels[result.metadata.software];
|
|
128
134
|
document.getElementById('prompt').textContent = result.metadata.prompt;
|
|
129
135
|
document.getElementById('model').textContent = result.metadata.model?.name || 'N/A';
|
|
130
136
|
}
|
|
@@ -153,7 +159,7 @@ if (result.status === 'success') {
|
|
|
153
159
|
> For production use, pin to a specific version instead of `@latest`:
|
|
154
160
|
>
|
|
155
161
|
> ```text
|
|
156
|
-
> https://cdn.jsdelivr.net/npm/@enslo/sd-metadata@2.0.
|
|
162
|
+
> https://cdn.jsdelivr.net/npm/@enslo/sd-metadata@2.0.1/dist/index.js
|
|
157
163
|
> ```
|
|
158
164
|
|
|
159
165
|
### Advanced Examples
|
|
@@ -184,8 +190,7 @@ if (parseResult.status === 'success') {
|
|
|
184
190
|
}
|
|
185
191
|
```
|
|
186
192
|
|
|
187
|
-
> [
|
|
188
|
-
> This library handles metadata read/write only. For actual image format conversion (decoding/encoding pixels), use image processing libraries like [sharp](https://www.npmjs.com/package/sharp), [jimp](https://www.npmjs.com/package/jimp), or browser Canvas API.
|
|
193
|
+
> **Tip:** This library handles metadata read/write only. For actual image format conversion (decoding/encoding pixels), use image processing libraries like [sharp](https://www.npmjs.com/package/sharp), [jimp](https://www.npmjs.com/package/jimp), or browser Canvas API.
|
|
189
194
|
|
|
190
195
|
</details>
|
|
191
196
|
|
|
@@ -305,8 +310,7 @@ const result = embed(imageData, {
|
|
|
305
310
|
});
|
|
306
311
|
```
|
|
307
312
|
|
|
308
|
-
>
|
|
309
|
-
> If an extras key matches a structured field (e.g., `Steps`), the extras value overrides the structured value at its original position. New keys are appended at the end.
|
|
313
|
+
> **Tip:** If an extras key matches a structured field (e.g., `Steps`), the extras value overrides the structured value at its original position. New keys are appended at the end.
|
|
310
314
|
|
|
311
315
|
Since `EmbedMetadata` is a subset of all `GenerationMetadata` variants, you can pass parsed metadata directly — including NovelAI with its `characterPrompts`:
|
|
312
316
|
|
|
@@ -349,10 +353,15 @@ if (text) {
|
|
|
349
353
|
|
|
350
354
|
## API Reference
|
|
351
355
|
|
|
352
|
-
### `read(input: Uint8Array | ArrayBuffer): ParseResult`
|
|
356
|
+
### `read(input: Uint8Array | ArrayBuffer, options?: ReadOptions): ParseResult`
|
|
353
357
|
|
|
354
358
|
Reads and parses metadata from an image file.
|
|
355
359
|
|
|
360
|
+
**Parameters:**
|
|
361
|
+
|
|
362
|
+
- `input` - Image file data (PNG, JPEG, or WebP)
|
|
363
|
+
- `options` - Optional read options (see [Type Documentation](./docs/types.md) for details)
|
|
364
|
+
|
|
356
365
|
**Returns:**
|
|
357
366
|
|
|
358
367
|
- `{ status: 'success', metadata, raw }` - Successfully parsed
|
|
@@ -574,45 +583,28 @@ type RawMetadata =
|
|
|
574
583
|
| { format: 'webp'; segments: MetadataSegment[] };
|
|
575
584
|
```
|
|
576
585
|
|
|
577
|
-
> [!TIP]
|
|
578
|
-
> For TypeScript users: All types are exported and available for import.
|
|
579
|
-
>
|
|
580
|
-
> ```typescript
|
|
581
|
-
> import type {
|
|
582
|
-
> BaseMetadata,
|
|
583
|
-
> EmbedMetadata,
|
|
584
|
-
> ParseResult,
|
|
585
|
-
> GenerationMetadata,
|
|
586
|
-
> GenerationSoftware,
|
|
587
|
-
> ModelSettings,
|
|
588
|
-
> SamplingSettings
|
|
589
|
-
> } from '@enslo/sd-metadata';
|
|
590
|
-
> ```
|
|
591
|
-
>
|
|
592
|
-
> Use your IDE's IntelliSense for auto-completion and inline documentation.
|
|
593
|
-
|
|
594
586
|
For detailed documentation of all exported types including `ModelSettings`, `SamplingSettings`, and format-specific types, see the [Type Documentation](./docs/types.md).
|
|
595
587
|
|
|
596
588
|
## Development
|
|
597
589
|
|
|
598
590
|
```bash
|
|
599
591
|
# Install dependencies
|
|
600
|
-
|
|
592
|
+
pnpm install
|
|
601
593
|
|
|
602
594
|
# Run tests
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
# Watch mode
|
|
606
|
-
npm run test:watch
|
|
607
|
-
|
|
608
|
-
# Test coverage
|
|
609
|
-
npm run test:coverage
|
|
595
|
+
pnpm test
|
|
610
596
|
|
|
611
597
|
# Build
|
|
612
|
-
|
|
598
|
+
pnpm build
|
|
613
599
|
|
|
614
600
|
# Lint
|
|
615
|
-
|
|
601
|
+
pnpm lint
|
|
602
|
+
|
|
603
|
+
# Type check
|
|
604
|
+
pnpm typecheck
|
|
605
|
+
|
|
606
|
+
# Start demo site
|
|
607
|
+
pnpm demo
|
|
616
608
|
```
|
|
617
609
|
|
|
618
610
|
## License
|
package/dist/index.js
CHANGED
|
@@ -936,7 +936,13 @@ function toJsonResult(value) {
|
|
|
936
936
|
}
|
|
937
937
|
|
|
938
938
|
// src/parsers/comfyui-nodes.ts
|
|
939
|
-
var SAMPLER_TYPES = [
|
|
939
|
+
var SAMPLER_TYPES = [
|
|
940
|
+
"KSampler",
|
|
941
|
+
"KSamplerAdvanced",
|
|
942
|
+
"SamplerCustomAdvanced",
|
|
943
|
+
"SamplerCustom",
|
|
944
|
+
"DetailerForEach"
|
|
945
|
+
];
|
|
940
946
|
var LATENT_IMAGE_TYPES = ["EmptyLatentImage"];
|
|
941
947
|
var LATENT_IMAGE_RGTHREE_TYPES = ["SDXL Empty Latent Image (rgthree)"];
|
|
942
948
|
var CHECKPOINT_TYPES = ["CheckpointLoaderSimple", "CheckpointLoader"];
|
|
@@ -1004,13 +1010,29 @@ function extractPromptTexts(nodes, sampler) {
|
|
|
1004
1010
|
return { promptText: "", negativeText: "" };
|
|
1005
1011
|
}
|
|
1006
1012
|
const conditioningSource = resolveConditioningSource(nodes, sampler);
|
|
1007
|
-
const positiveRef = conditioningSource.inputs.positive;
|
|
1008
|
-
const negativeRef = conditioningSource.inputs.negative;
|
|
1009
1013
|
return {
|
|
1010
|
-
promptText:
|
|
1011
|
-
|
|
1014
|
+
promptText: extractTextFromConditioning(
|
|
1015
|
+
nodes,
|
|
1016
|
+
conditioningSource.inputs.positive,
|
|
1017
|
+
"positive"
|
|
1018
|
+
),
|
|
1019
|
+
negativeText: extractTextFromConditioning(
|
|
1020
|
+
nodes,
|
|
1021
|
+
conditioningSource.inputs.negative,
|
|
1022
|
+
"negative"
|
|
1023
|
+
)
|
|
1012
1024
|
};
|
|
1013
1025
|
}
|
|
1026
|
+
function extractTextFromConditioning(nodes, ref, condKey, maxDepth = 10) {
|
|
1027
|
+
if (maxDepth <= 0 || !isNodeReference(ref)) return "";
|
|
1028
|
+
const nodeId = String(ref[0]);
|
|
1029
|
+
const text = extractText(nodes, nodeId);
|
|
1030
|
+
if (text) return text;
|
|
1031
|
+
const node = nodes[nodeId];
|
|
1032
|
+
if (!node) return "";
|
|
1033
|
+
const next = node.inputs[condKey];
|
|
1034
|
+
return extractTextFromConditioning(nodes, next, condKey, maxDepth - 1);
|
|
1035
|
+
}
|
|
1014
1036
|
function extractDimensions(latentImage, latentImageRgthree) {
|
|
1015
1037
|
if (latentImage) {
|
|
1016
1038
|
const width = Number(latentImage.inputs.width) || 0;
|
|
@@ -1033,20 +1055,21 @@ function extractSampling(nodes, sampler) {
|
|
|
1033
1055
|
if (sampler.class_type === "SamplerCustomAdvanced") {
|
|
1034
1056
|
return extractAdvancedSampling(nodes, sampler);
|
|
1035
1057
|
}
|
|
1058
|
+
if (sampler.class_type === "SamplerCustom") {
|
|
1059
|
+
return extractCustomSampling(nodes, sampler);
|
|
1060
|
+
}
|
|
1036
1061
|
let seed = sampler.inputs.seed;
|
|
1037
1062
|
if (isNodeReference(seed)) {
|
|
1038
1063
|
const seedNode = nodes[String(seed[0])];
|
|
1039
1064
|
seed = seedNode?.inputs.seed;
|
|
1040
1065
|
}
|
|
1041
|
-
const rawDenoise = sampler.inputs.denoise;
|
|
1042
|
-
const denoise = typeof rawDenoise === "number" && rawDenoise < 1 ? rawDenoise : void 0;
|
|
1043
1066
|
return {
|
|
1044
1067
|
seed,
|
|
1045
1068
|
steps: sampler.inputs.steps,
|
|
1046
1069
|
cfg: sampler.inputs.cfg,
|
|
1047
1070
|
sampler: sampler.inputs.sampler_name,
|
|
1048
1071
|
scheduler: sampler.inputs.scheduler,
|
|
1049
|
-
denoise
|
|
1072
|
+
denoise: sampler.inputs.denoise
|
|
1050
1073
|
};
|
|
1051
1074
|
}
|
|
1052
1075
|
function extractAdvancedSampling(nodes, sampler) {
|
|
@@ -1054,15 +1077,30 @@ function extractAdvancedSampling(nodes, sampler) {
|
|
|
1054
1077
|
const guiderNode = resolveNode(nodes, sampler.inputs.guider);
|
|
1055
1078
|
const samplerSelectNode = resolveNode(nodes, sampler.inputs.sampler);
|
|
1056
1079
|
const schedulerNode = resolveNode(nodes, sampler.inputs.sigmas);
|
|
1057
|
-
const rawDenoise = schedulerNode?.inputs.denoise;
|
|
1058
|
-
const denoise = typeof rawDenoise === "number" && rawDenoise < 1 ? rawDenoise : void 0;
|
|
1059
1080
|
return {
|
|
1060
1081
|
seed: noiseNode?.inputs.noise_seed,
|
|
1061
1082
|
steps: schedulerNode?.inputs.steps,
|
|
1062
1083
|
cfg: guiderNode?.inputs.cfg,
|
|
1063
1084
|
sampler: samplerSelectNode?.inputs.sampler_name,
|
|
1064
1085
|
scheduler: schedulerNode?.inputs.scheduler,
|
|
1065
|
-
denoise
|
|
1086
|
+
denoise: schedulerNode?.inputs.denoise
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
function extractCustomSampling(nodes, sampler) {
|
|
1090
|
+
const samplerSelectNode = resolveNode(nodes, sampler.inputs.sampler);
|
|
1091
|
+
const schedulerNode = resolveNode(nodes, sampler.inputs.sigmas);
|
|
1092
|
+
let seed = sampler.inputs.noise_seed;
|
|
1093
|
+
if (isNodeReference(seed)) {
|
|
1094
|
+
const seedNode = nodes[String(seed[0])];
|
|
1095
|
+
seed = seedNode?.inputs.seed;
|
|
1096
|
+
}
|
|
1097
|
+
return {
|
|
1098
|
+
seed,
|
|
1099
|
+
steps: schedulerNode?.inputs.steps,
|
|
1100
|
+
cfg: sampler.inputs.cfg,
|
|
1101
|
+
sampler: samplerSelectNode?.inputs.sampler_name,
|
|
1102
|
+
scheduler: schedulerNode?.inputs.scheduler,
|
|
1103
|
+
denoise: schedulerNode?.inputs.denoise
|
|
1066
1104
|
};
|
|
1067
1105
|
}
|
|
1068
1106
|
function extractModel(checkpoint, unetLoader) {
|
|
@@ -1192,6 +1230,14 @@ function parseComfyUI(entries) {
|
|
|
1192
1230
|
...merged
|
|
1193
1231
|
});
|
|
1194
1232
|
}
|
|
1233
|
+
function normalizeDenoise(sampling) {
|
|
1234
|
+
if (!sampling || typeof sampling.denoise !== "number") return sampling;
|
|
1235
|
+
if (sampling.denoise >= 1) {
|
|
1236
|
+
const { denoise: _, ...rest } = sampling;
|
|
1237
|
+
return rest;
|
|
1238
|
+
}
|
|
1239
|
+
return sampling;
|
|
1240
|
+
}
|
|
1195
1241
|
function cleanJsonString(json) {
|
|
1196
1242
|
return json.replace(/\0+$/, "").replace(/:\s*NaN\b/g, ": null");
|
|
1197
1243
|
}
|
|
@@ -1233,10 +1279,12 @@ function extractComfyUIMetadata(nodes) {
|
|
|
1233
1279
|
c.latentImageRgthree
|
|
1234
1280
|
);
|
|
1235
1281
|
const hiresSamplerNode = findHiresSampler(nodes);
|
|
1236
|
-
const hiresSampling =
|
|
1282
|
+
const hiresSampling = normalizeDenoise(
|
|
1283
|
+
hiresSamplerNode ? extractSampling(nodes, hiresSamplerNode) : void 0
|
|
1284
|
+
);
|
|
1237
1285
|
const hiresScale = resolveHiresScale(nodes, c, width);
|
|
1238
1286
|
const upscalerName = c.hiresModelUpscale?.inputs.model_name;
|
|
1239
|
-
const rawSampling = extractSampling(nodes, c.sampler);
|
|
1287
|
+
const rawSampling = normalizeDenoise(extractSampling(nodes, c.sampler));
|
|
1240
1288
|
const clipSkip = extractClipSkip(c.clipSetLastLayer);
|
|
1241
1289
|
return trimObject({
|
|
1242
1290
|
prompt: promptText || void 0,
|