Last active
September 29, 2025 19:16
-
-
Save jhowbhz/a939c984e8b029ed06c100de7944ca8a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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