You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, outputFileName = "extracted_audio.wav") {
// Create a container for the result or error message
const container = document.createElement('div');
container.style.cssText = `
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 30px;
font-family: 'Segoe UI', system-ui, Tahoma, Geneva, Verdana, sans-serif;
background: #ffffff;
border: 1px solid #e0e0e0;
border-radius: 12px;
box-shadow: 0 4px 15px rgba(0,0,0,0.08);
text-align: center;
box-sizing: border-box;
width: 100%;
max-width: 450px;
margin: 20px auto;
`;
try {
// Fetch the file from the image object (assuming it points to an MP4/Media source via Data URI or Blob URL)
const response = await fetch(originalImg.src);
const arrayBuffer = await response.arrayBuffer();
// Use the Web Audio API to decode the media container's audio track natively
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
if (!audioBuffer) {
throw new Error("No decodable audio track found in the source file.");
}
// Function to interleave channel data and wrap it in a proper WAV format Blob
function bufferToWave(abuffer) {
const numOfChan = abuffer.numberOfChannels;
const length = abuffer.length;
const buffer = new ArrayBuffer(44 + length * numOfChan * 2);
const view = new DataView(buffer);
const channels = [];
let i, offset = 0, pos = 0;
function writeString(s) {
for (let k = 0; k < s.length; k++) {
view.setUint8(pos, s.charCodeAt(k));
pos++;
}
}
// Write RIFF chunk descriptor
writeString('RIFF');
view.setUint32(pos, 36 + length * numOfChan * 2, true); pos += 4;
writeString('WAVE');
// Write FMT sub-chunk
writeString('fmt ');
view.setUint32(pos, 16, true); pos += 4; // Sub-chunk code size
view.setUint16(pos, 1, true); pos += 2; // Audio format (PCM)
view.setUint16(pos, numOfChan, true); pos += 2;
view.setUint32(pos, abuffer.sampleRate, true); pos += 4;
view.setUint32(pos, abuffer.sampleRate * 2 * numOfChan, true); pos += 4;
view.setUint16(pos, numOfChan * 2, true); pos += 2; // Block align
view.setUint16(pos, 16, true); pos += 2; // Bits per sample
// Write Data sub-chunk
writeString('data');
view.setUint32(pos, length * numOfChan * 2, true); pos += 4;
// Extract all channel data
for(i = 0; i < abuffer.numberOfChannels; i++) {
channels.push(abuffer.getChannelData(i));
}
// Write interleaved multichannel data streams while converting float 32 to signed int 16 PCM
while(pos < buffer.byteLength) {
for(i = 0; i < numOfChan; i++) {
// Clamp to min/max amplitude
let sample = Math.max(-1, Math.min(1, channels[i][offset]));
// Scale into 16-bit boundaries
sample = sample < 0 ? sample * 0x8000 : sample * 0x7FFF;
view.setInt16(pos, sample, true);
pos += 2;
}
offset++;
}
return new Blob([buffer], { type: "audio/wav" });
}
// Convert and generate URL handle
const wavBlob = bufferToWave(audioBuffer);
const wavUrl = URL.createObjectURL(wavBlob);
container.innerHTML = `
<h3 style="margin-top: 0; margin-bottom: 20px; color: #2c3e50; font-size: 20px;">Extracted Audio</h3>
<audio controls src="${wavUrl}" style="width: 100%; margin-bottom: 20px; outline: none;"></audio>
<a href="${wavUrl}" download="${outputFileName}" style="display: inline-block; padding: 12px 24px; background-color: #3498db; color: #fff; text-decoration: none; border-radius: 8px; font-weight: 600; font-size: 15px; box-shadow: 0 4px 6px rgba(52,152,219,0.2); transition: background-color 0.2s, transform 0.1s; cursor: pointer;">
Download Audio (WAV)
</a>
`;
// Minor visual feedback on hover
const downloadLink = container.querySelector('a');
downloadLink.addEventListener('mouseenter', () => downloadLink.style.backgroundColor = '#2980b9');
downloadLink.addEventListener('mouseleave', () => downloadLink.style.backgroundColor = '#3498db');
} catch (err) {
// Construct Graceful Error View
container.innerHTML = `
<h3 style="color: #e74c3c; margin-top:0; font-size: 20px;">Processing Error</h3>
<p style="font-size: 15px; color: #34495e; line-height: 1.5; margin-bottom: 12px;">
Could not extract audio. Ensure the file processed is a valid video/media source (like MP4) containing an audio track.
</p>
<div style="font-size: 13px; color: #7f8c8d; background: #fdfdfd; padding: 12px; border-radius: 6px; border: 1px solid #efefef; word-wrap: break-word; text-align: left;">
<strong>Details:</strong> ${err.message}
</div>
`;
}
return container;
}
Apply Changes