使用 ffmpeg api 调用将 3gp (amr) 转换为 mp3
我尝试使用 libavformat (ffmpeg) 构建自己的函数,将 3gp 音频文件(用 Android 移动设备录制)转换为 mp3 文件。
我使用 av_read_frame() 从输入文件读取帧并使用 avcodec_decode_audio3() 解码数据
到缓冲区中,并使用该缓冲区通过 avcodec_encode_audio 将数据编码为 mp3。
这似乎为我提供了将 wav 转换为 mp3 和 mp3 转换为 wav (或解码一个 mp3 并编码为另一个 mp3)的正确结果,但不适用于 amr 到 mp3。
我生成的 mp3 文件似乎具有正确的长度,但仅包含噪音。
在另一篇文章中,我读到 amr-decoder 不使用与 mp3 相同的样本格式。
AMR 使用 FLT 和 mp3 S16 或 S32,我必须进行重新采样。
因此,我为已解码的每个帧调用 av_audio_resample_init() 和 audio_resample。
但这并不能完全解决我的问题。现在我可以听到我录制的声音并且听不懂我在说什么,但是质量很低并且仍然有很多噪音。
我不确定我是否正确设置了 av_audio_resample 的参数,特别是最后 4 个参数(我认为不是),或者我是否错过了其他内容。
ReSampleContext* reSampleContext = av_audio_resample_init(1, 1, 44100, 8000, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT, 0, 0, 0, 0.0);
while(1)
{
if(av_read_frame(ic, &avpkt) < 0)
{
break;
}
out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
int count;
count = avcodec_decode_audio3(audio_stream->codec, (short *)decodedBuffer, &out_size, &avpkt);
if(count < 0)
{
break;
}
if((audio_resample(reSampleContext, (short *)resampledBuffer, (short *)decodedBuffer, out_size / 4)) < 0)
{
fprintf(stderr, "Error\n");
exit(1);
}
out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
pktOut.size = avcodec_encode_audio(c, outbuf, out_size, (short *)resampledBuffer);
if(c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE)
{
pktOut.pts = av_rescale_q(c->coded_frame->pts, c->time_base, outStream->time_base);
//av_res
}
pktOut.pts = AV_NOPTS_VALUE;
pktOut.dts = AV_NOPTS_VALUE;
pktOut.flags |= AV_PKT_FLAG_KEY;
pktOut.stream_index = audio_stream->index;
pktOut.data = outbuf;
if(av_write_frame(oc, &pktOut) != 0)
{
fprintf(stderr, "Error while writing audio frame\n");
exit(1);
}
}