Skip to content

Instantly share code, notes, and snippets.

@jhowbhz
Last active September 29, 2025 19:16
Show Gist options
  • Save jhowbhz/a939c984e8b029ed06c100de7944ca8a to your computer and use it in GitHub Desktop.
Save jhowbhz/a939c984e8b029ed06c100de7944ca8a to your computer and use it in GitHub Desktop.
const ffmpegPath = require('ffmpeg-static');
const ffmpeg = require('fluent-ffmpeg');
const fs = require('fs/promises');
const path = require('path');
const os = require('os');
const tmp = require('tmp');
ffmpeg.setFfmpegPath(ffmpegPath);
static async downloadToTmp(url) {
const res = await fetch(url);
if (!res.ok) throw new Error(`Falha ao baixar: ${res.status} ${res.statusText}`);
const tmpFile = tmp.fileSync({ postfix: path.extname(new URL(url).pathname) });
const arrayBuf = await res.arrayBuffer();
await fs.writeFile(tmpFile.name, Buffer.from(arrayBuf));
return { path: tmpFile.name, dispose: () => tmpFile.removeCallback() };
}
static async convertToOpusOgg(inPath, outPath) {
return new Promise((resolve, reject) => {
ffmpeg(inPath)
.noVideo()
.audioChannels(1)
.audioFrequency(16000)
.audioFilters([
'loudnorm=I=-16:TP=-1.5:LRA=11',
'highpass=f=80',
'lowpass=f=7000',
])
.audioCodec('libopus')
.outputOptions([
'-application', 'voip',
'-b:a', '24k',
'-vbr', 'on',
'-compression_level', '10',
'-frame_duration', '60',
'-avoid_negative_ts', 'make_zero'
])
.format('ogg')
.on('error', reject)
.on('end', () => resolve(outPath))
.save(outPath);
});
}
static async sendAudio(req, res) {
const { session, number: phone, time_recording, path: inputPath } = req.body;
if (!inputPath) {
return res.status(400).send({
status: 400,
error: "Path não informado",
message: "Informe o link do arquivo, ele deve estar na internet"
});
}
try {
const client = await this._getClient(session);
await client.startRecording(phone, time_recording || config.time_typing);
const isURL = Sessions.isURL(inputPath);
let localIn, disposer = () => {};
if (isURL) {
const dl = await this.downloadToTmp(inputPath);
localIn = dl.path; disposer = dl.dispose;
} else {
localIn = inputPath;
}
const tmpOut = tmp.fileSync({ postfix: '.ogg' });
const outPath = tmpOut.name;
await this.convertToOpusOgg(localIn, outPath);
const base64 = await Sessions.fileToBase64(outPath);
const fileName = path.basename(outPath, '.ogg');
const response = await client.sendPttFromBase64(phone, base64);
disposer();
tmpOut.removeCallback();
return res.status(200).json({
result: 200,
type: 'ptt',
session,
file: fileName,
data: response
});
} catch (error) {
return this._handleError(res, error, 'sendAudio');
}
}
// update package.json
// "dependencies": {
// "fluent-ffmpeg": "^2.1.2", // wrapper para controlar ffmpeg pelo Node
// "ffmpeg-static": "^5.2.0", // binário ffmpeg portátil, sem precisar instalar no SO
// "tmp": "^0.2.3", // manipular arquivos temporários
// "fs-extra": "^11.2.0" // leitura/escrita de arquivos com helpers adicionais
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment