2

ヘッダー付きのオーディオファイルを変換しようとしています

Opening audio decoder: [pcm] Uncompressed PCM audio decoder
AUDIO: 44100 Hz, 2 ch, s16le, 1411.2 kbit/100.00% (ratio: 176400->176400)
Selected audio codec: [pcm] afm: pcm (Uncompressed PCM)

このファイルをmp3形式にトランスコードしたいと思います。次のコードスニペットがありますが、うまく機能していません。オーディオとビデオをトランスコードするためにXUGGLERコードスニペットを使用して記述しました。

オーディオデコーダーは

    audioDecoder = IStreamCoder.make(IStreamCoder.Direction.DECODING, ICodec.findDecodingCodec(ICodec.ID.CODEC_ID_PCM_S16LE));
    audioDecoder.setSampleRate(44100);
    audioDecoder.setBitRate(176400);
    audioDecoder.setChannels(2);
    audioDecoder.setTimeBase(IRational.make(1,1000));
    if (audioDecoder.open(IMetaData.make(), IMetaData.make()) < 0)
        return false;
    return true; 

オーディオエンコーダは

    outContainer = IContainer.make();
    outContainerFormat = IContainerFormat.make();
    outContainerFormat.setOutputFormat("mp3", urlOut, null);
    int retVal = outContainer.open(urlOut, IContainer.Type.WRITE, outContainerFormat);
    if (retVal < 0) {
        System.out.println("Could not open output container");
        return false;
    }
    outAudioCoder = IStreamCoder.make(IStreamCoder.Direction.ENCODING, ICodec.findEncodingCodec(ICodec.ID.CODEC_ID_MP3));
    outAudioStream = outContainer.addNewStream(outAudioCoder);
    outAudioCoder.setSampleRate(new Integer(44100));
    outAudioCoder.setChannels(2);
    retVal = outAudioCoder.open(IMetaData.make(), IMetaData.make());
    if (retVal < 0) {
        System.out.println("Could not open audio coder");
        return false;
    }
    retVal = outContainer.writeHeader();
    if (retVal < 0) {
        System.out.println("Could not write output FLV header: ");
        return false;
    }
    return true;

そしてここに私がトランスコードするために32バイトのパケットを送るエンコード方法があります

public void encode(byte[] audioFrame){
    //duration of 1 video frame
    long lastVideoPts = 0;

    IPacket packet_out = IPacket.make();
    int lastPos = 0;
    int lastPos_out = 0;

    IAudioSamples audioSamples = IAudioSamples.make(48000, audioDecoder.getChannels());
    IAudioSamples audioSamples_resampled = IAudioSamples.make(48000, audioDecoder.getChannels());

    //we always have 32 bytes/sample
    int pos = 0;
    int audioFrameLength = audioFrame.length;
    int audioFrameCnt = 1;
    iBuffer = IBuffer.make(null, audioFrame, 0, audioFrameLength);
    IPacket packet = IPacket.make(iBuffer);
    //packet.setKeyPacket(true);
    packet.setTimeBase(IRational.make(1,1000));
    packet.setDuration(20);
    packet.setDts(audioFrameCnt*20);
    packet.setPts(audioFrameCnt*20);
    packet.setStreamIndex(1);
    packet.setPosition(lastPos);
    lastPos+=audioFrameLength;
    int pksz = packet.getSize();
    packet.setComplete(true, pksz);
    /*
    * A packet can actually contain multiple samples
    */
    int offset = 0;
    int retVal;
    while(offset < packet.getSize())
    {
        int bytesDecoded = audioDecoder.decodeAudio(audioSamples, packet, offset);
        if (bytesDecoded < 0)
            throw new RuntimeException("got error decoding audio ");
        offset += bytesDecoded;
        if (audioSamples.isComplete())
        {
            int samplesConsumed = 0;
            while (samplesConsumed < audioSamples.getNumSamples()) {
                retVal = outAudioCoder.encodeAudio(packet_out, audioSamples, samplesConsumed);
                if (retVal <= 0)
                    throw new RuntimeException("Could not encode audio");
                samplesConsumed += retVal;
                if (packet_out.isComplete()) {
                    packet_out.setPosition(lastPos_out);
                    packet_out.setStreamIndex(1);
                    lastPos_out+=packet_out.getSize();
                    retVal = outContainer.writePacket(packet_out);
                    if(retVal < 0){
                        throw new RuntimeException("Could not write data packet");
                    }
                }
            }
        }

    }

}

出力ファイルを取得しましたが、再生されません。オーディオのエンコードとサンプリングの経験はほとんどありません。前もって感謝します。

4

1 に答える 1

3

最後に、pcmストリームをmp3ストリームにライブトランスコードすることができます。

コードにはいくつかの問題がありました:

  • オーディオをトランスコードしようとしていたのですが、コードスニペットはビデオだけでなくオーディオもトランスコードしていたため、ストリームインデックスの設定に問題がありました。

    packet_out.setStreamIndex(1); packet_out.setStreamIndex(0)

  • 2番目は計算ffmpegguidでした

    channel * bits * sampling rate = bit rate
    

    このことは私の最後に誤算されました。

  • オーディオサンプルのサンプル数は、サンプリングレートによって異なります。それは私のコードでは間違っていました。

注:これはかなり古いコードです

 byte[] data = new byte[418];

public void encode(byte[] audioFrame) {
    IPacket packet_out = IPacket.make();
    int lastPos_out = 0;


    IAudioSamples audioSamples = IAudioSamples.make(11025, audioDecoder.getChannels());
    //IAudioSamples audioSamples_resampled = IAudioSamples.make(48000, audioDecoder.getChannels());

    //we always have 32 bytes/sample
    int pos = 0;
    int audioFrameLength = audioFrame.length;
    int audioFrameCnt = 1;
    iBuffer = IBuffer.make(null, audioFrame, 0, audioFrameLength);
    IPacket packet = IPacket.make(iBuffer);
    //packet.setKeyPacket(true);
    packet.setTimeBase(IRational.make(1, 1000));
    packet.setStreamIndex(0);
    int pksz = packet.getSize();
    packet.setComplete(true, pksz);
   /*
    * A packet can actually contain multiple samples
    */
    int offset = 0;
    int retVal;
    while (offset < packet.getSize()) {
        int bytesDecoded = audioDecoder.decodeAudio(audioSamples, packet, offset);
        if (bytesDecoded < 0)
            throw new RuntimeException("got error decoding audio ");
        offset += bytesDecoded;
        if (audioSamples.isComplete()) {
            /*audioResampler.resample(audioSamples_resampled, audioSamples, audioSamples.getNumSamples());
            audioSamples_resampled.setPts(Global.NO_PTS);*/
            int samplesConsumed = 0;
            while (samplesConsumed < audioSamples.getNumSamples()) {
                retVal = outAudioCoder.encodeAudio(packet_out, audioSamples, samplesConsumed);
                if (retVal <= 0)
                    throw new RuntimeException("Could not encode audio");
                samplesConsumed += retVal;
                if (packet_out.isComplete()) {
                    packet_out.setPosition(lastPos_out);
                    packet_out.setStreamIndex(0);
                    lastPos_out += packet_out.getSize();
                    System.out.println("size" + packet_out.getSize());
                    packet_out.getByteBuffer().get(data,0,packet_out.getSize());
                    try {
                        fo.write(data);
                    } catch (IOException e) {
                        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                    }
                    packet_out.reset();
                    //retVal = outContainer.writePacket(packet_out);
                    if (retVal < 0) {
                        throw new RuntimeException("Could not write data packet");
                    }
                }
            }
        }
    }
}
于 2012-12-18T10:07:53.727 に答える