使用 PortAudio 写入 fifo 并使用 ffmpeg 在 OSX 上读取

write with PortAudio into fifo and read with ffmpeg on OSX

我想做什么:

  1. 在 PortAudio 中打开我的麦克风作为音频源(有效)
  2. 将流写入 fifo(有效)
  3. 使用 ffmpeg 读取 fifo(不起作用)

在 PortAudio 中,我使用 Blocking I/O,如下所示: http://portaudio.com/docs/v19-doxydocs/blocking_read_write.html

在循环中,我这样写入 fifo:

int data = write('/tmp/aaa', sampleBlock, bufferSize);

当我将它读取到 PortAudio 写入缓冲区时,它起作用了。

bytes_read = read('/tmp/aaa', readSampleBlock, bufferSize);
err = Pa_WriteStream(stream, readSampleBlock, bufferSize)

当我在控制台上用 ffmpeg 阅读它时:

ffmpeg -y -i /tmp/aaa -f s16le -acodec copy -f nut -ar 48000 -ac 2 -v debug -report -acodec copy out.wav

它只是阻塞循环而已。

谁能帮我弄清楚我需要做什么?

我的代码:

#define SAMPLE_SIZE (1)
#define FRAMES_PER_BUFFER (480)
#define AUDIOFIFO "/tmp/aaa"

char *sampleBlock = NULL;
int status, captured_bytes, fifo, bytes_read;


err = Pa_OpenStream(&stream,
                    &inputParameters,
                    NULL,
                    48000,
                    FRAMES_PER_BUFFER,
                    paClipOff,
                    NULL, /* no callback, use blocking API */
                    NULL ); /* no callback, so no callback userData */
if( err != paNoError ) goto error;

numBytes = FRAMES_PER_BUFFER * numChannels * SAMPLE_SIZE ;
sampleBlock = (char *) malloc( numBytes );
memset( sampleBlock, SAMPLE_SILENCE, numBytes );

if (status = mkfifo(AUDIOFIFO, 0666) < 0) 
{ 
  printf("Error making AUDIOFIFO: %s \n", strerror(errno)); 
}
err = Pa_StartStream( stream );
if( err != paNoError )
{
  goto error;
} 

fifo = open(AUDIOFIFO, O_RDWR, O_NONBLOCK);
if (fifo < 0) printf("Error opening AUDIOFIFO: %s \n", strerror(errno));

for( i=0; i<(60*48000)/FRAMES_PER_BUFFER; ++i )
{   
  if ((err = Pa_ReadStream(stream, sampleBlock, FRAMES_PER_BUFFER)) != paNoError)
  {
    goto xrun;
  }  
  captured_bytes = write(fifo, sampleBlock, FRAMES_PER_BUFFER);
  if (captured_bytes < 0) 
  { 
    printf("Error writing to AUDIOFIFO: %s \n", strerror(errno));
  }

  framesProcessed += bufferSize;
}

AFAIK,ffmpeg 命令行的一般格式是:

ffmpeg <GLOBAL OPTIONS> <INPUT OPTIONS> -i INPUT <OUTPUT OPTIONS> OUTPUT

即您必须在 ffmpeg 打开它之前 描述您的输入流。

所以我认为 -f s16le(至少)必须在 ffmpeg 命令行上的 -i /tmp/aaa 之前:

ffmpeg -y -f s16le -i /tmp/aaa ....