2012-12-17 72 views
2

我想要的音频文件转换与头音频转码使用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; 

这里是编码方法,其中i发送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"); 
        } 
       } 
      } 
     } 

    } 

} 

我得到一个输出文件但它不起作用。我对音频编码和采样的经验很少。提前致谢。

回答

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

这将是巨大的,如果你可以分享最后的工作代码。 –