1

I have to pipe a wave data stream to ffmpeg in Python. I can easily create an output pipe from an input mp3 file like:

       process = (
            ffmpeg
            .input(path)
            .output('pipe:', **output_kwargs)
            .run_async(pipe_stdout=True, pipe_stderr=True))
        buffer, _ = process.communicate()
        # because of we need (n_channels, samples)
        waveform = np.frombuffer(buffer, dtype='<f4').reshape(-1, n_channels)
        if not waveform.dtype == np.dtype(dtype):
            waveform = waveform.astype(dtype)

Here waveform will contain the wave audio file.

Now, I want to pipe the same data, but from an input stream, but for some reason it does not work as expected:

    # data shape is like (9161728, 2) for two channels audio data
    input_kwargs = {'ar': sample_rate, 'ac': data.shape[1]} 
    output_kwargs = {'ar': sample_rate, 'strict': '-2'}
    n_channels = 2
    process = (
        ffmpeg
        .input('pipe:', format='f32le', **input_kwargs)
        .output('pipe:', **output_kwargs)
        .run_async(pipe_stdin=True, quiet=True))
    buffer, err = process.communicate(input=data.astype('<f4').tobytes())

The output buffer is empty here after getting the results from process.communicate, while err is

Unable to find a suitable output format for 'pipe:'\npipe:: Invalid argument\n"
loretoparisi
  • 15,724
  • 11
  • 102
  • 146
  • Have you already looked at [ffmpeg in Python subprocess - Unable to find a suitable output format for 'pipe:'](https://stackoverflow.com/a/32242361/8150685)? – Error - Syntactical Remorse Nov 18 '19 at 13:54
  • Also do you want to implement it yourself using ffmpeg or are you okay [using other solutions](https://stackoverflow.com/questions/10287683/python-convert-wav-to-mp3). – Error - Syntactical Remorse Nov 18 '19 at 13:57
  • Thanks, I'm using `https://github.com/kkroening/ffmpeg-python`, so it should be straightforward, but no in the case of having both `input` and `output` as pipe. – loretoparisi Nov 18 '19 at 13:59

1 Answers1

1

I know it's been a long time.. but for others who might encounter the same problem: if you are using pipe stream to grasp the output, then you must give ffmpeg a proper format so that it knows what kind of format the output should be transformed, simplely add the flag '-f <fmt>' such like '-f mp3' in the **output_kwargs, then it should do.

say if you wanna transform an audio into .mp3, $path is your original audio file path, then modified the output_kwargs as below:

 process = (
        ffmpeg
        .input(path)
        .output('pipe:', **{'loglevel':'error', 'codec:a':libmp3lame, 'f':'mp3'})
        .run_async(pipe_stdout=True, pipe_stderr=True))
    buffer, _ = process.communicate()
    data_byte = io.BytesIO(buffer)
    fout = open(out_path,'wb')
    fout.writelines(data_byte)
    fout.close()

then you have your mp3 file at $out_path

a relevant 'subprocess.popen' command should be like

import subprocess
my_process = subprocess.Popen(['ffmpeg','-i', path, '-codec:a', 'libmp3lame', '-f', 'mp3', 'pipe:1'], stdout=PIPE, stderr=PIPE)
buffer, _ = process.communicate()
etc....
Cyril CHAPON
  • 3,556
  • 4
  • 22
  • 40
cmk
  • 11
  • 2
  • Thanks for taking time to answer a long-time-ago answer; this will surely help Would you mind formatting your code, and providing a fully and directly working example ? – Cyril CHAPON Oct 23 '20 at 08:37
  • @CyrilCHAPON no pro, and sry for the late reply, I didn't check my notification so often, – cmk Oct 26 '20 at 09:30