Skip to content

Commit

Permalink
Sync flac metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
huchenlei committed Jun 29, 2024
1 parent 241f086 commit b4b686c
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 2 deletions.
14 changes: 13 additions & 1 deletion src/scripts/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ComfyWidgetConstructor, ComfyWidgets, initWidgets } from "./widgets";
import { ComfyUI, $el } from "./ui";
import { api } from "./api";
import { defaultGraph } from "./defaultGraph";
import { getPngMetadata, getWebpMetadata, importA1111, getLatentMetadata } from "./pnginfo";
import { getPngMetadata, getWebpMetadata, getFlacMetadata, importA1111, getLatentMetadata } from "./pnginfo";
import { addDomClippingSetting } from "./domWidget";
import { createImageHost, calculateImageGrid } from "./ui/imagePreview"
import { DraggableList } from "./ui/draggableList";
Expand Down Expand Up @@ -2304,6 +2304,18 @@ export class ComfyApp {
const workflow = pngInfo?.workflow || pngInfo?.Workflow;
const prompt = pngInfo?.prompt || pngInfo?.Prompt;

if (workflow) {
this.loadGraphData(await parseComfyWorkflow(workflow));
} else if (prompt) {
this.loadApiJson(JSON.parse(prompt));
} else {
this.showErrorOnFileLoad(file);
}
} else if (file.type === "audio/flac") {
const pngInfo = await getFlacMetadata(file);
const workflow = pngInfo?.workflow || pngInfo?.Workflow;
const prompt = pngInfo?.prompt || pngInfo?.Prompt;

if (workflow) {
this.loadGraphData(await parseComfyWorkflow(workflow));
} else if (prompt) {
Expand Down
71 changes: 71 additions & 0 deletions src/scripts/pnginfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,77 @@ export function getLatentMetadata(file) {
});
}

function getString(dataView: DataView, offset: number, length: number): string {
let string = '';
for (let i = 0; i < length; i++) {
string += String.fromCharCode(dataView.getUint8(offset + i));
}
return string;
}

// Function to parse the Vorbis Comment block
function parseVorbisComment(dataView: DataView): Record<string, string> {
let offset = 0;
const vendorLength = dataView.getUint32(offset, true);
offset += 4;
const vendorString = getString(dataView, offset, vendorLength);
offset += vendorLength;

const userCommentListLength = dataView.getUint32(offset, true);
offset += 4;
const comments = {};
for (let i = 0; i < userCommentListLength; i++) {
const commentLength = dataView.getUint32(offset, true);
offset += 4;
const comment = getString(dataView, offset, commentLength);
offset += commentLength;

const [key, value] = comment.split('=');

comments[key] = value;
}

return comments;
}

// Function to read a FLAC file and parse Vorbis comments
export function getFlacMetadata(file: Blob): Promise<Record<string, string>> {
return new Promise((r) => {
const reader = new FileReader();
reader.onload = function(event) {
const arrayBuffer = event.target.result as ArrayBuffer;
const dataView = new DataView(arrayBuffer);

// Verify the FLAC signature
const signature = String.fromCharCode(...new Uint8Array(arrayBuffer, 0, 4));
if (signature !== 'fLaC') {
console.error('Not a valid FLAC file');
return;
}

// Parse metadata blocks
let offset = 4;
let vorbisComment = null;
while (offset < dataView.byteLength) {
const isLastBlock = dataView.getUint8(offset) & 0x80;
const blockType = dataView.getUint8(offset) & 0x7F;
const blockSize = dataView.getUint32(offset, false) & 0xFFFFFF;
offset += 4;

if (blockType === 4) { // Vorbis Comment block type
vorbisComment = parseVorbisComment(new DataView(arrayBuffer, offset, blockSize));
}

offset += blockSize;
if (isLastBlock) break;
}

r(vorbisComment);
};
reader.readAsArrayBuffer(file);
});
}

export async function importA1111(graph, parameters) {
const p = parameters.lastIndexOf("\nSteps:");
if (p > -1) {
Expand Down
2 changes: 1 addition & 1 deletion src/scripts/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ export class ComfyUI {
const fileInput = $el("input", {
id: "comfy-file-input",
type: "file",
accept: ".json,image/png,.latent,.safetensors,image/webp",
accept: ".json,image/png,.latent,.safetensors,image/webp,audio/flac",
style: { display: "none" },
parent: document.body,
onchange: () => {
Expand Down

0 comments on commit b4b686c

Please sign in to comment.