使用xuggler转码音频

时间:2012-12-17 14:34:44

标签: ffmpeg xuggle xuggler

我正在尝试使用标题

转换音频文件
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 code snippet for transcoding audio and video写了它。

音频解码器

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

    }

}

我得到一个输出文件,但它没有播放。我对音频编码和采样的经验很少。提前谢谢。

1 个答案:

答案 0 :(得分:3)

最后,我能够将pcm流转码为mp3流。

代码中有几个问题:

  • 我试图只对一个东西进行转码,即音频和代码片段转码音频以及视频,因此设置流索引存在问题。

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

  • 第二件事是计算ffmpeg guid

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