使用ffmpeg创建一个44字节的标头

时间:2015-07-12 18:34:48

标签: c++ audio ffmpeg wav

我使用ffmpeg库创建了一个程序,将音频文件转换为wav文件。除了唯一的问题是它不会创建一个44字节的标头。将文件输入Kaldi语音识别时,会产生错误:

ERROR (online2-wav-nnet2-latgen-faster:Read4ByteTag():wave-reader.cc:74) WaveData: expected 4-byte chunk-name, got read errror

我通过shntool运行文件,它报告一个78字节的标题。无论如何我可以使用ffmpeg库获得标准的44字节头文件吗?

1 个答案:

答案 0 :(得分:1)

FFmpeg将有关编码器的一些元数据插入到头文件中。这是修复之前标题的hexdump:

00000000 52 49 46 46 06 90 00 00 57 41 56 45 66 6d 74 20 |RIFF....WAVEfmt | 00000010 10 00 00 00 01 00 01 00 40 1f 00 00 80 3e 00 00 |........@....>..| 00000020 02 00 10 00 4c 49 53 54 1a 00 00 00 49 4e 46 4f |....LIST....INFO| 00000030 49 53 46 54 0e 00 00 00 4c 61 76 66 35 36 2e 33 |ISFT....Lavf56.3| 00000040 36 2e 31 30 30 00 64 61 74 61 c0 8f 00 00 00 00 |6.100.data......|

如您所见,Lavf56.36.100是标题中的编码器。以下是我用来摆脱它的代码部分。

std::cout<<"------------------BEFORE-----------------------"<<std::endl;
std::cout<< av_dict_count ( (*ofmt_ctx)->metadata) <<std::endl;
std::cout<<"-------------------------------------------"<<std::endl; 
if(av_dict_set(&(*ofmt_ctx)->metadata,"ISFT",NULL, AV_DICT_IGNORE_SUFFIX)){
 std::cerr<<"Nope it, didn't work :("<<std::endl;
}

ret = avformat_write_header(*ofmt_ctx,&(*ofmt_ctx)->metadata );
if (ret < 0) {
  std::cout<<"-------------------------------------------"<<std::endl;
  av_log(NULL, AV_LOG_ERROR, "Error occurred when writing header to file\n");
  return ret;
}
std::cout<<"------------------AFTER-----------------------"<<std::endl;
std::cout<< av_dict_count ( (*ofmt_ctx)->metadata) <<std::endl;
std::cout<<"-------------------------------------------"<<std::endl;

以后是hexdump: 00000000 52 49 46 46 e4 8f 00 00 57 41 56 45 66 6d 74 20 |RIFF....WAVEfmt | 00000010 10 00 00 00 01 00 01 00 40 1f 00 00 80 3e 00 00 |........@....>..| 00000020 02 00 10 00 64 61 74 61 c0 8f 00 00 00 00 00 00 |....data........| 00000030 00 00 00 00 00 00 00 00 ff ff 00 00 00 00 00 00 |................|

shntool现在报告44个字节

(注意:ofmt_ctx是我在这个函数中的**,因此为什么将元数据字典引用为&(*ofmt_ctx)->metadata