Python Forum

Full Version: When piping a FFMPEG stream to PyAudio, I get a "click" on every loop
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I am ultimately looking to do analysis on some streaming audio, but for now I am just trying to get it to play audio well as a first step.

I am generating a MP3 RTP steam on another device (sender) on my network. Using FFMPEG, I pipe that into python for playing via pyaudio. (receiver)

It does play on the receiver, but ever 1/2 second or so, you get a "click" noise that appear to occur on every loop of the while (True) loop. I setup PyAdio to use the callback function, as I thought it would help, but it still makes that noise. If I use FFPLAY to play the stream, it works fine.

Any input on how to make the audio play normally via pyadio? I did also try simpleaudio, pygame, and sounddevice with similar results. I tried to experiment by making a "buffer" of data, but couldn't make that work.

FFMPEG_BIN = "ffmpeg" # on Linux
#FFMPEG_BIN = "ffmpeg.exe" # on Windows
import pyaudio
import wave
import sys
import subprocess as sp
import time
import numpy

command = [ FFMPEG_BIN,
        '-i', 'rtp://172.168.1.231:8000/4',
        '-acodec', 'pcm_s32le',
        '-f', 's16le',
        '-ar', '44100', # ouput will have 44100 Hz
        '-ac', '2', # stereo (set to '1' for mono)
        '-']
pipe = sp.Popen(command, stdout=sp.PIPE, bufsize=10**8)

# instantiate PyAudio (1)
p = pyaudio.PyAudio()

# define callback (2)
def callback(in_data, frame_count, time_info, status):
    data = pipe.stdout.read(10000)
    data = numpy.frombuffer(data, dtype="int32")
    data = data.reshape((len(data)//2,2))
    #data = pipe.readbuffer(frame_count)
    return (data, pyaudio.paContinue)

# open stream using callback (3)
stream = p.open(format=pyaudio.paInt32,
                channels=2,
                rate=44100,
                output=True,
                stream_callback=callback)

# start the stream (4)
stream.start_stream()

# wait for stream to finish (5)
while stream.is_active():
    time.sleep(0.1)

# stop stream (6)
stream.stop_stream()
stream.close()


# close PyAudio (7)
p.terminate()