Skip to content

Commit 6a5ffcd

Browse files
committed
Merge branch 'sno-mp3' of github.com:Comfy-Org/ComfyUI-embedded-workflow-editor into sno-mp3
2 parents 9f7cec6 + 92f19cb commit 6a5ffcd

File tree

4 files changed

+56
-68
lines changed

4 files changed

+56
-68
lines changed

app/utils/exif-mp3.test.ts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ test("MP3 metadata extraction", async () => {
77

88
// Extract metadata
99
const metadata = getMp3Metadata(buffer);
10-
10+
1111
// Log the metadata to see what's available
1212
console.log("MP3 metadata:", metadata);
13-
13+
1414
// Basic test to ensure the function runs without errors
1515
expect(metadata).toBeDefined();
1616
});
@@ -19,19 +19,19 @@ test("MP3 metadata write and read", async () => {
1919
// Read test MP3 file
2020
const testFile = Bun.file("tests/mp3/ComfyUI_00047_.mp3");
2121
const buffer = await testFile.arrayBuffer();
22-
22+
2323
// Create test workflow JSON
2424
const testWorkflow = JSON.stringify({
2525
test: "workflow",
26-
nodes: [{ id: 1, name: "Test Node" }]
26+
nodes: [{ id: 1, name: "Test Node" }],
2727
});
28-
28+
2929
// Set metadata - now we can pass the Buffer directly
3030
const modified = setMp3Metadata(buffer, { workflow: testWorkflow });
31-
31+
3232
// Read back the metadata
3333
const readMetadata = getMp3Metadata(modified);
34-
34+
3535
// Verify the workflow was written and read correctly
3636
expect(readMetadata.workflow).toBe(testWorkflow);
3737
});
@@ -40,22 +40,22 @@ test("MP3 metadata update", async () => {
4040
// Read test MP3 file
4141
const testFile = Bun.file("tests/mp3/ComfyUI_00047_.mp3");
4242
const buffer = await testFile.arrayBuffer();
43-
43+
4444
// First, add some metadata - now we can pass the Buffer directly
45-
const modified1 = setMp3Metadata(buffer, {
45+
const modified1 = setMp3Metadata(buffer, {
4646
title: "Test Title",
47-
artist: "ComfyUI"
47+
artist: "ComfyUI",
4848
});
49-
49+
5050
// Then, update the title but keep the artist - no need for conversion
5151
const modified2 = setMp3Metadata(modified1, {
5252
title: "Updated Title",
53-
workflow: "Test Workflow"
53+
workflow: "Test Workflow",
5454
});
55-
55+
5656
// Read back the metadata
5757
const readMetadata = getMp3Metadata(modified2);
58-
58+
5959
// Verify updates
6060
expect(readMetadata.title).toBe("Updated Title");
6161
expect(readMetadata.workflow).toBe("Test Workflow");
@@ -66,29 +66,29 @@ test("MP3 metadata preservation", async () => {
6666
// Read test MP3 file
6767
const testFile = Bun.file("tests/mp3/ComfyUI_00047_.mp3");
6868
const originalBuffer = await testFile.arrayBuffer();
69-
69+
7070
// Get original metadata
7171
const originalMetadata = getMp3Metadata(originalBuffer);
7272
console.log("Original metadata keys:", Object.keys(originalMetadata));
73-
73+
7474
// Sample workflow data
7575
const sampleWorkflow = JSON.stringify({
7676
test: "workflow data",
7777
nodes: { id1: { class_type: "TestNode" } },
7878
});
79-
79+
8080
// Update only the workflow
8181
const modifiedBuffer = setMp3Metadata(originalBuffer, {
8282
workflow: sampleWorkflow,
8383
});
84-
84+
8585
// Get the updated metadata
8686
const updatedMetadata = getMp3Metadata(modifiedBuffer);
87-
87+
8888
// Verify the workflow was updated
8989
expect(updatedMetadata.workflow).toBeDefined();
9090
expect(updatedMetadata.workflow).toEqual(sampleWorkflow);
91-
91+
9292
// Verify other existing metadata is preserved
9393
for (const key of Object.keys(originalMetadata)) {
9494
if (key !== "workflow") {

app/utils/exif-mp3.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
* @returns Object containing extracted metadata with keys as field names and values as strings
1111
*/
1212
export function getMp3Metadata(
13-
input: Uint8Array | ArrayBuffer
13+
input: Uint8Array | ArrayBuffer,
1414
): Record<string, string> {
1515
const buffer = input instanceof Uint8Array ? input : new Uint8Array(input);
1616
const dataView = new DataView(
1717
buffer.buffer,
1818
buffer.byteOffset,
19-
buffer.byteLength
19+
buffer.byteLength,
2020
);
2121
const metadata: Record<string, string> = {};
2222

@@ -48,7 +48,7 @@ export function getMp3Metadata(
4848
*/
4949
export function setMp3Metadata(
5050
buffer: ArrayBuffer | SharedArrayBuffer | Uint8Array,
51-
metadata: Record<string, string>
51+
metadata: Record<string, string>,
5252
): Uint8Array {
5353
// Convert to Uint8Array if not already
5454
const inputData =
@@ -57,16 +57,16 @@ export function setMp3Metadata(
5757
const dataView = new DataView(
5858
inputData.buffer,
5959
inputData.byteOffset,
60-
inputData.byteLength
60+
inputData.byteLength,
6161
);
6262

6363
try {
6464
// Retrieve existing metadata to preserve it
6565
const existingMetadata = getMp3Metadata(inputData);
66-
66+
6767
// Merge existing metadata with new metadata (new takes precedence)
6868
const mergedMetadata = { ...existingMetadata, ...metadata };
69-
69+
7070
// Create or update ID3v2 tags with merged metadata
7171
return updateID3v2Tags(inputData, dataView, mergedMetadata);
7272
} catch (error) {
@@ -89,7 +89,7 @@ function isID3v2(dataView: DataView): boolean {
8989
const id3Header = String.fromCharCode(
9090
dataView.getUint8(0),
9191
dataView.getUint8(1),
92-
dataView.getUint8(2)
92+
dataView.getUint8(2),
9393
);
9494

9595
return id3Header === "ID3";
@@ -110,7 +110,7 @@ function hasID3v1(dataView: DataView): boolean {
110110
const tagMarker = String.fromCharCode(
111111
dataView.getUint8(offset),
112112
dataView.getUint8(offset + 1),
113-
dataView.getUint8(offset + 2)
113+
dataView.getUint8(offset + 2),
114114
);
115115

116116
return tagMarker === "TAG";
@@ -123,7 +123,7 @@ function hasID3v1(dataView: DataView): boolean {
123123
*/
124124
function parseID3v2(
125125
dataView: DataView,
126-
metadata: Record<string, string>
126+
metadata: Record<string, string>,
127127
): void {
128128
// Read ID3v2 header
129129
const version = dataView.getUint8(3);
@@ -143,7 +143,7 @@ function parseID3v2(
143143
dataView.getUint8(offset),
144144
dataView.getUint8(offset + 1),
145145
dataView.getUint8(offset + 2),
146-
dataView.getUint8(offset + 3)
146+
dataView.getUint8(offset + 3),
147147
);
148148

149149
// Frame size is 4 bytes
@@ -193,7 +193,7 @@ function parseID3v2(
193193
}
194194

195195
// Store in metadata - trim any remaining null characters
196-
metadata[description] = value.replace(/\0+$/g, '');
196+
metadata[description] = value.replace(/\0+$/g, "");
197197

198198
offset += valueLength;
199199
}
@@ -220,7 +220,7 @@ function parseID3v2(
220220

221221
// Map common frame IDs to friendly names
222222
const key = mapFrameIDToKey(frameID);
223-
metadata[key] = value.replace(/\0+$/g, '');
223+
metadata[key] = value.replace(/\0+$/g, "");
224224

225225
offset += frameSize - 1;
226226
} else {
@@ -232,7 +232,7 @@ function parseID3v2(
232232
const frameID = String.fromCharCode(
233233
dataView.getUint8(offset),
234234
dataView.getUint8(offset + 1),
235-
dataView.getUint8(offset + 2)
235+
dataView.getUint8(offset + 2),
236236
);
237237

238238
const frameSize =
@@ -255,7 +255,7 @@ function parseID3v2(
255255
*/
256256
function parseID3v1(
257257
dataView: DataView,
258-
metadata: Record<string, string>
258+
metadata: Record<string, string>,
259259
): void {
260260
const offset = dataView.byteLength - 128;
261261

@@ -281,7 +281,7 @@ function parseID3v1(
281281
function updateID3v2Tags(
282282
inputData: Uint8Array,
283283
dataView: DataView,
284-
metadata: Record<string, string>
284+
metadata: Record<string, string>,
285285
): Uint8Array {
286286
// Create a new ID3v2.4 tag
287287
const id3Header = new Uint8Array([
@@ -414,7 +414,7 @@ function createTextFrame(frameId: string, value: string): Uint8Array {
414414
function readString(
415415
dataView: DataView,
416416
offset: number,
417-
length: number
417+
length: number,
418418
): string {
419419
let result = "";
420420
for (let i = 0; i < length; i++) {
@@ -449,7 +449,7 @@ function getSynchsafeInt(dataView: DataView, offset: number): number {
449449
function setSynchsafeInt(
450450
buffer: Uint8Array,
451451
offset: number,
452-
value: number
452+
value: number,
453453
): void {
454454
buffer[offset] = (value >> 21) & 0x7f;
455455
buffer[offset + 1] = (value >> 14) & 0x7f;

bun.lock

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,7 +1197,7 @@
11971197

11981198
"side-channel-weakmap": ["[email protected]", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
11991199

1200-
"signal-exit": ["signal-exit@4.0.2", "", {}, "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q=="],
1200+
"signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
12011201

12021202
"simple-swizzle": ["[email protected]", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="],
12031203

@@ -1477,6 +1477,8 @@
14771477

14781478
"edge-runtime/picocolors": ["[email protected]", "", {}, "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="],
14791479

1480+
"edge-runtime/signal-exit": ["[email protected]", "", {}, "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q=="],
1481+
14801482
"eslint-import-resolver-node/debug": ["[email protected]", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
14811483

14821484
"eslint-module-utils/debug": ["[email protected]", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
@@ -1497,8 +1499,6 @@
14971499

14981500
"glob/minimatch": ["[email protected]", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ=="],
14991501

1500-
"inflight/once": ["[email protected]", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
1501-
15021502
"is-bun-module/semver": ["[email protected]", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
15031503

15041504
"micro/arg": ["[email protected]", "", {}, "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg=="],
@@ -1515,8 +1515,6 @@
15151515

15161516
"prop-types/react-is": ["[email protected]", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
15171517

1518-
"pump/once": ["[email protected]", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
1519-
15201518
"raw-body/http-errors": ["[email protected]", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" } }, "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw=="],
15211519

15221520
"raw-body/iconv-lite": ["[email protected]", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="],
@@ -1579,28 +1577,14 @@
15791577

15801578
"@vercel/gatsby-plugin-vercel-builder/fs-extra/universalify": ["[email protected]", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
15811579

1582-
"@vercel/nft/glob/inherits": ["[email protected]", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
1583-
1584-
"@vercel/nft/glob/once": ["[email protected]", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
1585-
15861580
"@vercel/static-config/ajv/json-schema-traverse": ["[email protected]", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
15871581

1588-
"eslint-import-resolver-node/debug/ms": ["[email protected]", "", {}, "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="],
1589-
1590-
"eslint-module-utils/debug/ms": ["[email protected]", "", {}, "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="],
1591-
1592-
"eslint-plugin-import/debug/ms": ["[email protected]", "", {}, "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="],
1593-
15941582
"glob/minimatch/brace-expansion": ["[email protected]", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
15951583

15961584
"path-match/path-to-regexp/isarray": ["[email protected]", "", {}, "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="],
15971585

15981586
"raw-body/http-errors/inherits": ["[email protected]", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
15991587

1600-
"rimraf/glob/inherits": ["[email protected]", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
1601-
1602-
"rimraf/glob/once": ["[email protected]", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
1603-
16041588
"string-width/strip-ansi/ansi-regex": ["[email protected]", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
16051589

16061590
"sucrase/glob/jackspeak": ["[email protected]", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ=="],

extract-mp3-workflow.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,42 @@ import { getMp3Metadata } from "./app/utils/exif-mp3";
55
async function main() {
66
const testFile = Bun.file("tests/mp3/ComfyUI_00047_.mp3");
77
const buffer = await testFile.arrayBuffer();
8-
8+
99
const metadata = getMp3Metadata(buffer);
10-
10+
1111
console.log("MP3 metadata keys:", Object.keys(metadata));
12-
12+
1313
if (metadata.workflow) {
1414
// Try to parse and format the workflow
1515
try {
1616
const workflowJson = JSON.parse(metadata.workflow);
1717
const formattedWorkflow = JSON.stringify(workflowJson, null, 2);
18-
18+
1919
const outputPath = "tests/mp3/ComfyUI_00047_.mp3.workflow.json";
2020
writeFileSync(outputPath, formattedWorkflow);
2121
console.log(`Workflow extracted and saved to ${outputPath}`);
2222
} catch (error) {
2323
console.error("Error parsing workflow JSON:", error);
24-
24+
2525
// If parsing fails, save the raw workflow
2626
const outputPath = "tests/mp3/ComfyUI_00047_.mp3.workflow.json";
2727
writeFileSync(outputPath, metadata.workflow);
2828
console.log(`Raw workflow saved to ${outputPath}`);
2929
}
3030
} else {
3131
console.log("No workflow found in MP3 metadata");
32-
32+
3333
// If we don't find a workflow, let's create a simple test workflow
34-
const testWorkflow = JSON.stringify({
35-
test: "test-workflow",
36-
format: "mp3",
37-
description: "Test workflow for MP3 format"
38-
}, null, 2);
39-
34+
const testWorkflow = JSON.stringify(
35+
{
36+
test: "test-workflow",
37+
format: "mp3",
38+
description: "Test workflow for MP3 format",
39+
},
40+
null,
41+
2,
42+
);
43+
4044
const outputPath = "tests/mp3/ComfyUI_00047_.mp3.workflow.json";
4145
writeFileSync(outputPath, testWorkflow);
4246
console.log(`Created test workflow and saved to ${outputPath}`);

0 commit comments

Comments
 (0)