feat: integrate real AudioPlayer, real ImagePicker for Camera/Gallery, and on-the-fly OGG-to-MP3 converter on server

This commit is contained in:
Hamza-Ayed
2026-05-18 17:14:43 +03:00
parent 25bdf1fba1
commit 4ccd90dad3
11 changed files with 368 additions and 41 deletions

View File

@@ -409,6 +409,19 @@ async function handleMessage(ws, raw) {
return respond({ type: 'error', message: 'Failed to download media file from WhatsApp servers after multiple attempts' });
}
// If the media is an Ogg/Opus audio file, convert it to MP3 on-the-fly
if (media.mimetype && (media.mimetype.includes('audio/ogg') || media.mimetype.includes('ogg'))) {
try {
console.log(`[WS] Converting OGG audio file for message ${messageId} to MP3 for iOS compatibility...`);
const mp3Data = await convertOggToMp3(media.data);
media.data = mp3Data;
media.mimetype = 'audio/mp3';
media.filename = 'voice_note.mp3';
} catch (err) {
console.error(`[WS] Ogg to MP3 conversion failed (sending raw Ogg instead):`, err.message);
}
}
return respond({
type: 'media',
messageId: messageId,
@@ -561,3 +574,37 @@ server.listen(PORT, () => {
console.log(`[SERVER] Standalone WhatsApp Bridge running on port ${PORT}`);
initWhatsApp();
});
// ─── OGG to MP3 base64 converter using ffmpeg child process ────────────────
function convertOggToMp3(base64Ogg) {
const { exec } = require('child_process');
const tmp = require('os').tmpdir();
const path = require('path');
const fs = require('fs');
return new Promise((resolve, reject) => {
const timeId = Date.now();
const inputPath = path.join(tmp, `input_${timeId}.ogg`);
const outputPath = path.join(tmp, `output_${timeId}.mp3`);
fs.writeFileSync(inputPath, Buffer.from(base64Ogg, 'base64'));
exec(`ffmpeg -i "${inputPath}" -acodec libmp3lame -aq 2 "${outputPath}"`, (error, stdout, stderr) => {
// Clean up input file
try { fs.unlinkSync(inputPath); } catch(_) {}
if (error) {
console.error('[FFMPEG ERROR]', error);
return reject(error);
}
try {
const mp3Base64 = fs.readFileSync(outputPath).toString('base64');
try { fs.unlinkSync(outputPath); } catch(_) {}
resolve(mp3Base64);
} catch (err) {
reject(err);
}
});
});
}