2013-04-30 129 views
0

我需要生成視頻的音頻流的波形, 當前我正在使用xuggler和java來做一些小事情,但似乎我無法從IAudioSamples獲取我的視頻的輸入流音頻的字節數組。從視頻的音頻流生成波形圖像

現在我正在尋找一個更簡單的方法來做到這一點,因爲xuggler真的變得很難理解,我在網上搜索我發現這一點: http://codeidol.com/java/swing/Audio/Build-an-Audio-Waveform-Display/

應該.wav文件的工作,但當我嘗試在視頻或.mp3上的代碼AudioInputStream返回「無法找到音頻輸入流」

有人可以告訴我一種方法獲取一個視頻的audiostream的byte []數組,以便我可以按照教程創建一個波形? 如果你有建議或其他圖書館可以幫助我我會很高興

回答

1

由於mp3是一種編碼格式,您需要先解碼才能從中獲取光線數據(字節)。

class Mp3FileXuggler { 

private boolean DEBUG = true; 

private String _sInputFileName; 
private IContainer _inputContainer; 
private int _iBitRate; 
private IPacket _packet; 
private int _iAudioStreamId; 
private IStreamCoder _audioCoder; 

private int _iSampleBufferSize; 
private int _iInputSampleRate; 

private static SourceDataLine mLine; 

private int DECODED_AUDIO_SECOND_SIZE = 176375; /** bytes */ 
private int _bytesPerPacket; 

private byte[] _residualBuffer; 

/** 
* Constructor, prepares stream to be readed 
* @param input input File 
* @throws UnsuportedSampleRateException 
*/ 
public Mp3FileXuggler(String sFileName) throws UnsuportedSampleRateException{ 
    this._sInputFileName = sFileName; 
    this._inputContainer = IContainer.make(); 
    this._iSampleBufferSize = 18432; 
    this._residualBuffer = null; 

    /** Open container **/ 
    if (this._inputContainer.open(this._sInputFileName, IContainer.Type.READ, null) < 0) 
     throw new IllegalArgumentException("Could not read the file: " + this._sInputFileName); 

    /** How many streams does the file actually have */ 
    int iNumStreams = this._inputContainer.getNumStreams(); 
    this._iBitRate = this._inputContainer.getBitRate(); 

    if (DEBUG) System.out.println("Bitrate: " + this._iBitRate); 

    /** Iterate the streams to find the first audio stream */ 
    this._iAudioStreamId = -1; 
    this._audioCoder = null; 
    boolean bFound = false; 
    int i = 0; 
    while (i < iNumStreams && bFound == false){ 

     /** Find the stream object */ 
     IStream stream = this._inputContainer.getStream(i); 
     IStreamCoder coder = stream.getStreamCoder(); 

     /** If the stream is audio, stop looking */ 
     if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO){ 
      this._iAudioStreamId = i; 
      this._audioCoder = coder; 
      this._iInputSampleRate = coder.getSampleRate(); 
      bFound = true; 
     } 
     ++i; 
    } 

    /** If none was found */ 
    if (this._iAudioStreamId == -1) 
     throw new RuntimeException("Could not find audio stream in container: " + this._sInputFileName); 

    /** Otherwise, open audiocoder */ 

    if (this._audioCoder.open(null,null) < 0) 
     throw new RuntimeException("could not open audio decoder for container: " + this._sInputFileName); 

    this._packet = IPacket.make(); 

    //openJavaSound(this._audioCoder); 

    /** Dummy read one packet to avoid problems in some audio files */ 
    this._inputContainer.readNextPacket(this._packet); 


    /** Supported sample rates */ 
    switch(this._iInputSampleRate){ 
     case 22050: 
       this._bytesPerPacket = 2304; 
      break; 

     case 44100: 
       this._bytesPerPacket = 4608; 
      break; 


    } 

} 

public byte[] getSamples(){ 
    byte[] rawBytes = null; 


     /** Go to the correct packet */ 
     while (this._inputContainer.readNextPacket(this._packet) >= 0){ 
      //System.out.println(this._packet.getDuration()); 
      /** Once we have a packet, let's see if it belongs to the audio stream */ 

      if (this._packet.getStreamIndex() == this._iAudioStreamId){ 
       IAudioSamples samples = IAudioSamples.make(this._iSampleBufferSize, this._audioCoder.getChannels()); 


       // System.out.println(">> " + samples.toString()); 
       /** Because a packet can contain multiple set of samples (frames of samples). We may need to call 
       * decode audio multiple times at different offsets in the packet's data */ 

       int iCurrentOffset = 0; 
       while(iCurrentOffset < this._packet.getSize()){ 

        int iBytesDecoded = this._audioCoder.decodeAudio(samples, this._packet, iCurrentOffset); 
        iCurrentOffset += iBytesDecoded; 

        if (samples.isComplete()){ 
         rawBytes = samples.getData().getByteArray(0, samples.getSize()); 

         //playJavaSound(samples); 
        } 
       } 
       return rawBytes; 
      } 
      else{ 
       /** Otherwise drop it */ 
       do{}while(false); 
      } 
     } 

    return rawBytes; /** This will return null at this point */ 
} 

}

使用這個類,以便從一個MP3文件中獲得的原始數據,並與他們養活你的頻譜抽屜。