2025-02-11 16:14:27 +00:00

70 lines
2.6 KiB
JavaScript

self.onmessage = async (event) => {
const { videoBuffer, audioBuffer } = event.data;
const SAMPLE_RATE = 44100;
// Extraer energía en rango de frecuencias
const getEnergy = (buffer, freqRange) => {
const offlineCtx = new OfflineAudioContext(1, buffer.length, SAMPLE_RATE);
const source = offlineCtx.createBufferSource();
source.buffer = buffer;
const analyser = offlineCtx.createAnalyser();
analyser.fftSize = 4096;
source.connect(analyser);
analyser.connect(offlineCtx.destination);
source.start();
return offlineCtx.startRendering().then(() => {
const data = new Float32Array(analyser.frequencyBinCount);
analyser.getFloatFrequencyData(data);
const startBin = Math.floor(freqRange[0] * analyser.fftSize / SAMPLE_RATE);
const endBin = Math.floor(freqRange[1] * analyser.fftSize / SAMPLE_RATE);
return data.slice(startBin, endBin);
});
};
// Cross-correlación optimizada
const crossCorrelate = (videoFeatures, audioFeatures) => {
let maxCorr = -Infinity;
let bestOffset = 0;
for (let i = 0; i < videoFeatures.length - audioFeatures.length; i++) {
let corr = 0;
for (let j = 0; j < audioFeatures.length; j++) {
corr += videoFeatures[i + j] * audioFeatures[j];
}
if (corr > maxCorr) {
maxCorr = corr;
bestOffset = i;
}
}
return bestOffset;
};
// Procesar características
try {
const [videoBass, audioBass] = await Promise.all([
getEnergy(videoBuffer, [60, 250]), // Bajos
getEnergy(audioBuffer, [60, 250])
]);
const [videoVoice, audioVoice] = await Promise.all([
getEnergy(videoBuffer, [300, 3400]), // Voces
getEnergy(audioBuffer, [300, 3400])
]);
// Combinar características (peso dinámico)
const isElectronic = audioVoice.reduce((a, b) => a + b) < audioBass.reduce((a, b) => a + b);
const weight = isElectronic ? 0.8 : 0.4;
const videoFeatures = videoBass.map((v, i) => weight * v + (1 - weight) * videoVoice[i]);
const audioFeatures = audioBass.map((v, i) => weight * v + (1 - weight) * audioVoice[i]);
// Calcular offset
const offset = crossCorrelate(videoFeatures, audioFeatures);
self.postMessage({ offset: offset / SAMPLE_RATE });
} catch (error) {
self.postMessage({ error: "Error en el procesamiento" });
}
};