You can edit the below JavaScript code to customize the image tool.
Apply Changes
/**
* Analyzes an image to find and suggest relevant sound effects.
* This function uses a pre-trained AI model (COCO-SSD via TensorFlow.js)
* to detect common objects in the image. It then maps these objects to a
* list of suggested sound effects. The function will dynamically load the
* required AI libraries from a CDN if they are not already present.
*
* @param {Image} originalImg The input image object to analyze.
* @returns {Promise<HTMLDivElement>} A promise that resolves to an HTML div element
* containing the suggested sound effects, formatted
* as a list with clickable links to a sound library.
*/
async function processImage(originalImg) {
// Helper function to dynamically load a script and return a promise
const loadScript = (url) => {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = url;
script.onload = resolve;
script.onerror = () => reject(new Error(`Failed to load script: ${url}`));
document.head.appendChild(script);
});
};
// Create a container for the results and initial status message
const resultContainer = document.createElement('div');
resultContainer.style.fontFamily = 'Arial, sans-serif';
resultContainer.style.padding = '20px';
resultContainer.style.color = '#333';
resultContainer.innerHTML = '<p>Initializing sound effect finder...</p>';
try {
// Dynamically load TensorFlow.js and the COCO-SSD model if not already loaded.
// This makes the function self-contained.
if (typeof tf === 'undefined') {
await loadScript('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.11.0/dist/tf.min.js');
}
if (typeof cocoSsd === 'undefined') {
resultContainer.innerHTML = '<p>Loading AI model (this may take a moment)...</p>';
await loadScript('https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd@2.2.2/dist/coco-ssd.min.js');
}
resultContainer.innerHTML = '<p>Detecting objects in the image...</p>';
// Load the COCO-SSD model.
const model = await cocoSsd.load();
// Run the model on the input image to get predictions.
const predictions = await model.detect(originalImg);
// A pre-defined map of object classes from the model to sound effect keywords.
const soundMap = {
'person': ['Footsteps', 'Talking Murmur', 'Breathing', 'Crowd Chatter'],
'bicycle': ['Bicycle Bell', 'Chain Rattle', 'Tire on Pavement'],
'car': ['Car Engine Idle', 'Car Horn', 'Tire Screech', 'Door Slam'],
'motorcycle': ['Motorcycle Engine', 'Exhaust Pop'],
'airplane': ['Airplane Jet Engine', 'Propeller Sound'],
'bus': ['Bus Air Brakes', 'Engine Rumble', 'Bus Door Opening'],
'train': ['Train Horn', 'Train on Tracks', 'Steam Hiss'],
'truck': ['Truck Horn', 'Diesel Engine Rumble', 'Air Brakes'],
'boat': ['Boat Horn', 'Water Lapping', 'Sailboat Flapping'],
'bird': ['Bird Chirping', 'Wings Flapping', 'Seagull Call'],
'cat': ['Cat Meow', 'Purring', 'Hissing'],
'dog': ['Dog Bark', 'Dog Panting', 'Growling'],
'horse': ['Horse Neigh', 'Hoofbeats'],
'sheep': ['Sheep Bleating'],
'cow': ['Cow Mooing'],
'backpack': ['Zipper Sound', 'Fabric Rustle'],
'umbrella': ['Rain on Umbrella', 'Opening Umbrella'],
'handbag': ['Zipper', 'Clasp Click'],
'suitcase': ['Rolling Wheels', 'Zipper'],
'frisbee': ['Frisbee Whoosh'],
'sports ball': ['Ball Bounce', 'Kick Sound'],
'baseball bat': ['Bat Hitting Ball (Crack)'],
'skateboard': ['Skateboard on Pavement'],
'surfboard': ['Ocean Waves'],
'tennis racket': ['Tennis Ball Hit'],
'bottle': ['Bottle Clink', 'Liquid Pouring'],
'wine glass': ['Glass Clink', 'Wine Pouring'],
'cup': ['Clinking Ceramic', 'Liquid Pouring'],
'fork': ['Cutlery Clatter'],
'knife': ['Slicing Sound', 'Knife on Plate'],
'spoon': ['Clinking in a Bowl'],
'bowl': ['Clinking Ceramic'],
'banana': ['Peeling Sound'],
'apple': ['Biting Crunch'],
'chair': ['Chair Squeak', 'Chair being Dragged'],
'tv': ['TV Static', 'Dialogue Murmur'],
'laptop': ['Keyboard Typing', 'Fan Whirring'],
'mouse': ['Mouse Click'],
'remote': ['Button Clicks'],
'keyboard': ['Keyboard Typing'],
'cell phone': ['Phone Ringing', 'Vibration', 'Text Alert'],
'microwave': ['Microwave Hum', 'Beep'],
'oven': ['Gas Ignition', 'Oven Fan'],
'toaster': ['Toaster Pop'],
'sink': ['Running Water', 'Faucet Drip'],
'refrigerator': ['Refrigerator Hum'],
'book': ['Page Turning'],
'clock': ['Clock Ticking', 'Alarm Bell'],
'vase': ['Vase Shattering'],
'scissors': ['Scissors Snipping'],
};
resultContainer.innerHTML = ''; // Clear status messages
const title = document.createElement('h2');
title.textContent = 'Suggested Sound Effects';
title.style.marginBottom = '15px';
title.style.borderBottom = '2px solid #eee';
title.style.paddingBottom = '10px';
resultContainer.appendChild(title);
if (predictions.length === 0) {
resultContainer.innerHTML += '<p>No recognizable objects found to suggest sounds for.</p>';
return resultContainer;
}
const foundObjects = new Set(predictions.map(p => p.class));
let suggestionsFound = false;
foundObjects.forEach(objectClass => {
const sounds = soundMap[objectClass];
if (sounds && sounds.length > 0) {
suggestionsFound = true;
const objectContainer = document.createElement('div');
objectContainer.style.marginBottom = '12px';
const objectTitle = document.createElement('h3');
objectTitle.textContent = `For '${objectClass}':`;
objectTitle.style.margin = '0 0 8px 0';
objectTitle.style.textTransform = 'capitalize';
objectTitle.style.fontSize = '1.1em';
const soundList = document.createElement('ul');
soundList.style.margin = '0';
soundList.style.paddingLeft = '20px';
soundList.style.listStyleType = 'disc';
sounds.forEach(sound => {
const listItem = document.createElement('li');
const link = document.createElement('a');
const encodedSound = encodeURIComponent(sound);
// Link to a search on Freesound.org for short, high-quality sounds
link.href = `https://freesound.org/search/?q=${encodedSound}&f=duration%3A%5B0+TO+15%5D&s=score+desc&advanced=0&g=1`;
link.textContent = sound;
link.target = '_blank'; // Open in a new tab
link.title = `Search for "${sound}" on Freesound.org`;
link.style.textDecoration = 'none';
link.style.color = '#0066cc';
link.onmouseover = () => { link.style.textDecoration = 'underline'; };
link.onmouseout = () => { link.style.textDecoration = 'none'; };
listItem.appendChild(link);
soundList.appendChild(listItem);
});
objectContainer.appendChild(objectTitle);
objectContainer.appendChild(soundList);
resultContainer.appendChild(objectContainer);
}
});
if (!suggestionsFound) {
resultContainer.innerHTML += '<p>Found objects, but no specific sound effects in our library for them. Try a different image.</p>';
}
} catch (error) {
console.error("Error processing image:", error);
resultContainer.innerHTML = `<p style="color: #D8000C;">An error occurred while analyzing the image. Please ensure you are connected to the internet and check the browser console for details.</p>`;
}
return resultContainer;
}
Apply Changes