3

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);
    }
}
4

0 に答える 0