@@ -90,6 +90,7 @@ import useMultiFileAuthStatePrisma from '@utils/use-multi-file-auth-state-prisma
9090import { AuthStateProvider } from '@utils/use-multi-file-auth-state-provider-files' ;
9191import { useMultiFileAuthStateRedisDb } from '@utils/use-multi-file-auth-state-redis-db' ;
9292import axios from 'axios' ;
93+ import audioDecode from 'audio-decode' ;
9394import makeWASocket , {
9495 AnyMessageContent ,
9596 BufferedEventData ,
@@ -3038,6 +3039,42 @@ export class BaileysStartupService extends ChannelStartupService {
30383039 }
30393040 }
30403041
3042+ private async getAudioDuration ( audioBuffer : Buffer ) : Promise < number > {
3043+ try {
3044+ const audioData = await audioDecode ( audioBuffer ) ;
3045+ return Math . ceil ( audioData . duration ) ;
3046+ } catch ( error ) {
3047+ this . logger . warn ( 'Failed to get audio duration, using default 1 second' ) ;
3048+ return 1 ;
3049+ }
3050+ }
3051+
3052+ private async getAudioWaveform ( audioBuffer : Buffer ) : Promise < number [ ] > {
3053+ try {
3054+ const audioData = await audioDecode ( audioBuffer ) ;
3055+ const samples = audioData . channelData [ 0 ] ; // Get first channel
3056+ const waveformLength = 64 ;
3057+ const samplesPerWaveform = Math . floor ( samples . length / waveformLength ) ;
3058+
3059+ const waveform : number [ ] = [ ] ;
3060+ for ( let i = 0 ; i < waveformLength ; i ++ ) {
3061+ const start = i * samplesPerWaveform ;
3062+ const end = start + samplesPerWaveform ;
3063+ let sum = 0 ;
3064+ for ( let j = start ; j < end && j < samples . length ; j ++ ) {
3065+ sum += Math . abs ( samples [ j ] ) ;
3066+ }
3067+ const avg = sum / samplesPerWaveform ;
3068+ waveform . push ( Math . floor ( avg * 100 ) ) ;
3069+ }
3070+
3071+ return waveform ;
3072+ } catch ( error ) {
3073+ this . logger . warn ( 'Failed to generate waveform, using default' ) ;
3074+ return new Array ( 64 ) . fill ( 50 ) ;
3075+ }
3076+ }
3077+
30413078 public async audioWhatsapp ( data : SendAudioDto , file ?: any , isIntegration = false ) {
30423079 const mediaData : SendAudioDto = { ...data } ;
30433080
@@ -3056,9 +3093,12 @@ export class BaileysStartupService extends ChannelStartupService {
30563093 const convert = await this . processAudio ( mediaData . audio ) ;
30573094
30583095 if ( Buffer . isBuffer ( convert ) ) {
3096+ const seconds = await this . getAudioDuration ( convert ) ;
3097+ const waveform = await this . getAudioWaveform ( convert ) ;
3098+
30593099 const result = this . sendMessageWithTyping < AnyMessageContent > (
30603100 data . number ,
3061- { audio : convert , ptt : true , mimetype : 'audio/ogg; codecs=opus' } ,
3101+ { audio : convert , ptt : true , mimetype : 'audio/ogg; codecs=opus' , seconds , waveform } ,
30623102 { presence : 'recording' , delay : data ?. delay } ,
30633103 isIntegration ,
30643104 ) ;
@@ -3069,12 +3109,24 @@ export class BaileysStartupService extends ChannelStartupService {
30693109 }
30703110 }
30713111
3112+ const audioBuffer = isURL ( data . audio ) ? { url : data . audio } : Buffer . from ( data . audio , 'base64' ) ;
3113+ let seconds : number | undefined ;
3114+ let waveform : number [ ] | undefined ;
3115+
3116+ // Only generate waveform for buffers, not URLs
3117+ if ( Buffer . isBuffer ( audioBuffer ) ) {
3118+ seconds = await this . getAudioDuration ( audioBuffer ) ;
3119+ waveform = await this . getAudioWaveform ( audioBuffer ) ;
3120+ }
3121+
30723122 return await this . sendMessageWithTyping < AnyMessageContent > (
30733123 data . number ,
30743124 {
3075- audio : isURL ( data . audio ) ? { url : data . audio } : Buffer . from ( data . audio , 'base64' ) ,
3125+ audio : audioBuffer ,
30763126 ptt : true ,
30773127 mimetype : 'audio/ogg; codecs=opus' ,
3128+ ...( seconds !== undefined && { seconds } ) ,
3129+ ...( waveform !== undefined && { waveform } ) ,
30783130 } ,
30793131 { presence : 'recording' , delay : data ?. delay } ,
30803132 isIntegration ,
0 commit comments