14 KiB
Metadata System Usage Guide
This guide provides detailed instructions and examples for using the Metadata System for ComfyUI. It covers basic and advanced usage, as well as integration with ComfyUI nodes.
Table of Contents
Basic Usage
Initialization
Initialize the MetadataService to start working with the system:
from Metadata_system import MetadataService
# Basic initialization
service = MetadataService()
# With debug mode enabled for troubleshooting
service = MetadataService(debug=True)
# With human-readable text format
service = MetadataService(human_readable_text=True)
# Using as a context manager (ensures proper cleanup)
with MetadataService() as service:
# Your code here
pass
Writing Metadata
Write metadata to one or more storage formats:
# Create metadata dictionary
metadata = {
'basic': {
'title': 'Mountain Landscape',
'description': 'AI generated mountain landscape',
'keywords': ['mountains', 'landscape', 'nature', 'AI'],
'rating': 4
},
'ai_info': {
'generation': {
'model': 'stable-diffusion-v1-5',
'prompt': 'majestic mountains with snow caps',
'negative_prompt': 'ugly, blurry',
'sampler': 'euler_a',
'steps': 30,
'cfg_scale': 7.5,
'seed': 1234567890
}
}
}
# Write to all supported formats
result = service.write_metadata('path/to/image.png', metadata)
# Write to specific formats
result = service.write_metadata('path/to/image.png', metadata,
targets=['embedded', 'xmp'])
# Check results
for target, success in result.items():
print(f"{target}: {'Succeeded' if success else 'Failed'}")
Reading Metadata
Read metadata from storage formats:
# Read from embedded metadata with fallback
metadata = service.read_metadata('path/to/image.png', source='embedded', fallback=True)
# Read from specific source without fallback
xmp_metadata = service.read_metadata('path/to/image.png', source='xmp', fallback=False)
# Access specific sections
if 'basic' in metadata:
print(f"Title: {metadata['basic'].get('title', 'No title')}")
if 'ai_info' in metadata and 'generation' in metadata['ai_info']:
gen = metadata['ai_info']['generation']
print(f"Model: {gen.get('model')}")
print(f"Prompt: {gen.get('prompt')}")
Merging Metadata
Merge new metadata with existing metadata:
# New metadata to merge
new_metadata = {
'basic': {
'keywords': ['new', 'tags', 'to', 'add']
},
'analysis': {
'technical': {
'blur': {
'score': 0.92,
'higher_better': True
}
}
}
}
# Merge with existing metadata
result = service.merge_metadata('path/to/image.png', new_metadata)
# Merge and write to specific targets
result = service.merge_metadata('path/to/image.png', new_metadata,
targets=['embedded', 'txt'])
Metadata Structure
The metadata is organized into sections for different types of information:
Basic Section
Contains essential image information:
basic = {
'title': 'Image Title', # Image title
'description': 'Detailed description', # Description/caption
'keywords': ['keyword1', 'keyword2'], # Tags/keywords
'rating': 4, # Rating (1-5)
'creator': 'Author Name', # Creator/author
'rights': 'Copyright information', # Copyright/license
'create_date': '2025-03-15T12:34:56' # Creation timestamp
}
Analysis Section
Contains analysis results from various tools:
analysis = {
'technical': {
'blur': {
'score': 0.92, # Blur detection score
'higher_better': True # Whether higher is better
},
'noise': {
'score': 0.08, # Noise detection score
'higher_better': False # Whether higher is better
}
},
'aesthetic': {
'composition': 7.8, # Composition score
'color_harmony': 8.2, # Color harmony score
'overall': 7.9 # Overall aesthetic score
},
'pyiqa': {
'niqe': { # No-reference IQA model
'score': 3.45,
'higher_better': False,
'range': [0, 25]
},
'musiq': { # Multi-scale IQA model
'score': 78.2,
'higher_better': True,
'range': [0, 100]
}
},
'classification': {
'style': 'photorealistic', # Detected style
'content_type': 'landscape', # Content type
'has_text': False # Text detection result
}
}
AI Info Section
Contains AI generation information:
ai_info = {
'generation': {
'model': 'stable-diffusion-v1-5', # Base model
'prompt': 'mountain landscape', # Positive prompt
'negative_prompt': 'ugly, blurry', # Negative prompt
'sampler': 'euler_a', # Sampler name
'steps': 30, # Sampling steps
'cfg_scale': 7.5, # CFG scale
'seed': 1234567890, # Generation seed
'width': 512, # Image width
'height': 512, # Image height
'loras': [ # LoRAs used
{
'name': 'example_lora',
'strength': 0.8
}
]
},
'workflow': { # Full workflow data
# ComfyUI workflow data (simplified for brevity)
'nodes': { ... }
}
}
Regions Section
Contains information about specific regions in the image:
regions = {
'faces': [ # Detected faces
{
'type': 'Face',
'name': 'Person 1',
'area': { # Face coordinates
'x': 0.2, # Normalized (0-1)
'y': 0.3,
'w': 0.1,
'h': 0.15
},
'extensions': { # Extended face data
'eiqa': {
'face_analysis': {
'gender': 'female',
'age': 28,
'emotion': 'happy'
}
}
}
}
],
'areas': [ # Other detected areas
{
'type': 'Object',
'name': 'Mountain',
'area': {
'x': 0.1,
'y': 0.2,
'w': 0.8,
'h': 0.5
}
}
],
'summary': { # Summary statistics
'face_count': 1,
'detector_type': 'deepface'
}
}
ComfyUI Node Usage
Metadata Save Image Node
The eric_metadata_save_image node saves images with metadata:
- Connect your image output to the node's
imagesinput - Connect workflow data (optional) to the
workflow_datainput - Set basic parameters:
save_path: Directory to save imagesfilename_prefix: Prefix for generated filenamesfilename_number_padding: Number of digits for sequential numberingfilename_number_start: Starting number for sequential filenames
- Metadata options:
title: Image titledescription: Image descriptionkeywords: Comma-separated keywordssave_metadata_to: Formats to save metadata (embedded,xmp,txt,db)human_readable_text: Use human-readable text format
This node automatically captures workflow data, generation parameters, and technical image information.
Metadata Entry Node
The eric_metadata_entry node allows adding custom metadata:
- Connect to any workflow position
- Fill in metadata fields:
- Basic information (title, description, keywords)
- Analysis scores
- Custom fields
- Connect to other nodes that process metadata
Metadata Query Node
The eric_metadata_query_node filters and retrieves metadata:
- Connect to image input
- Set query parameters:
query_type: Type of query to performfield_path: Path to the metadata field to querycomparison: Comparison operator (equals, greater_than, etc.)value: Value to compare against
- Use outputs:
result: Query resultmetadata: Full metadata dictionaryimage: Passed-through image
Workflow Extractor Node
The eric_workflow_extractor node extracts workflow data from images:
- Connect to image input
- Set extraction parameters:
extraction_mode: How to extract workflow datainclude_basic_metadata: Whether to include basic metadata
- Use outputs:
workflow_data: Extracted workflow JSONmetadata: Full metadata dictionaryimage: Passed-through image
Advanced Features
Human-readable Text Format
The system can create human-readable text files for easy viewing:
# Enable human-readable text format
service = MetadataService(human_readable_text=True)
# Or change format at runtime
service.set_text_format(human_readable=True)
# Write metadata (will use human-readable format for text files)
service.write_metadata('path/to/image.png', metadata)
Example output:
Last update: 2025-03-15T10:23:45.123456
Metadata for image.png
Basic Information:
Title: Mountain Landscape
Description: AI generated mountain landscape
Keywords: mountains, landscape, nature, AI
AI Generation Information:
Prompt: majestic mountains with snow caps
Negative prompt: ugly, blurry
Model: stable-diffusion-v1-5
Sampler: euler_a
Steps: 30
Cfg_scale: 7.5
Seed: 1234567890
Database Queries
Perform advanced queries on the database:
from Metadata_system.handlers.db import DatabaseHandler
db = DatabaseHandler()
# Search for high-quality mountain images
results = db.search_images({
'scores': [
('aesthetic', 'overall', '>', 7.0),
('technical', 'blur.score', '>', 0.8)
],
'keywords': ['mountains'],
'classifications': [('style', 'photorealistic')],
'orientation': 'landscape',
'order_by': 'images.created_date DESC',
'limit': 10
})
# Process results
for image in results:
print(f"Found image: {image['filepath']}")
print(f"Rating: {image.get('rating', 'N/A')}")
Resource Identifiers
Set custom resource identifiers for XMP metadata:
# Set resource identifier for all handlers
service.set_resource_identifier("file:///custom/path/to/resource.jpg")
# Write metadata with custom resource identifier
service.write_metadata('path/to/image.jpg', metadata)
Batch Operations
Perform operations on multiple files:
# Using DatabaseHandler for batch operations
from Metadata_system.handlers.db import DatabaseHandler
db = DatabaseHandler()
# Define file paths
file_paths = [
'path/to/image1.png',
'path/to/image2.jpg',
'path/to/image3.webp'
]
# Read metadata from multiple files
results = db.batch_operation('read', file_paths)
# Update metadata for multiple files
new_metadata = {
'basic': {
'keywords': ['batch', 'processed']
}
}
results = db.batch_operation('write', file_paths, new_metadata)
# Check results
for filepath, success in results.items():
print(f"{filepath}: {'Succeeded' if success else 'Failed'}")
Troubleshooting
Common Issues
Issue: Cannot write embedded metadata to PNG file Solution: Ensure PyExiv2 is installed or use ExifTool as a fallback
# Check if PyExiv2 is available
try:
import pyexiv2
print("PyExiv2 is available")
except ImportError:
print("PyExiv2 is not available, using ExifTool fallback")
Issue: Files not showing metadata in other applications Solution: Verify format compatibility and try XMP sidecars
# Force write to XMP sidecar
service.write_metadata('path/to/image.png', metadata, targets=['xmp'])
Issue: Database errors Solution: Check SQLite installation and file permissions
# Use try-except to handle database errors
try:
from Metadata_system.handlers.db import DatabaseHandler
db = DatabaseHandler()
# Operations with db
except Exception as e:
print(f"Database error: {str(e)}")
# Fall back to file-based storage
service.write_metadata('path/to/image.png', metadata, targets=['embedded', 'xmp', 'txt'])
Debug Mode
Enable debug mode for detailed logging:
# Initialize with debug mode
service = MetadataService(debug=True)
# Operations will now produce detailed logs
service.write_metadata('path/to/image.png', metadata)
Debug logs include:
- Format detection results
- Handler selection details
- Operation traces
- Error messages with stack traces
Access error history from handlers:
# Get embedded handler
embedded_handler = service._get_embedded_handler()
# Print error history
for error in embedded_handler.error_history:
print(f"[{error['timestamp']}] {error['level']}: {error['message']}")
if error['error']:
print(f"Error: {error['error']}")
print("---")