2014-09-11 79 views
1

我正在开发一个android应用程序。我想完成下面的功能。 我将使用手机的内置麦克风进行录音,同时我希望通过手机的扬声器或耳机播放录制的音频。 可行吗?如果是的话,请帮助我。Android中的音频录制和流式传输

+0

当您录制时,您是在录制文件还是暂存缓冲区? – 2014-09-11 06:29:05

回答

0

首先在onCreate方法,MediaRecorder类对象和要保存记录数据的文件路径中创建对象。

String outputFile = Environment.getExternalStorageDirectory(). 
    getAbsolutePath() + "/myrecording.3gp"; // Define outputFile outside onCreate method 

    MediaRecorder myAudioRecorder = new MediaRecorder(); // Define this outside onCreate method 

    myAudioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
    myAudioRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
    myAudioRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB); 
    myAudioRecorder.setOutputFile(outputFile); 

这三个函数可以在任何按钮上调用它,以便播放Rec,停止Rec并启动Rec;

public void start(View view){ 
    try { 
    myAudioRecorder.prepare(); 
    myAudioRecorder.start(); 
    } catch (IllegalStateException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } catch (IOException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } 
    start.setEnabled(false); 
    stop.setEnabled(true); 
    Toast.makeText(getApplicationContext(), "Recording started", Toast.LENGTH_LONG).show(); 
    } 

    public void stop(View view){ 

    myAudioRecorder.stop(); 
    myAudioRecorder.release(); 
    myAudioRecorder = null; 
    stop.setEnabled(false); 
    play.setEnabled(true); 
    Toast.makeText(getApplicationContext(), "Audio recorded successfully", 
    Toast.LENGTH_LONG).show(); 
    } 



    public void play(View view) throws IllegalArgumentException, 

    SecurityException, IllegalStateException, IOException{ 
    MediaPlayer m = new MediaPlayer(); 
    m.setDataSource(outputFile); 
    m.prepare(); 
    m.start(); 
    Toast.makeText(getApplicationContext(), "Playing audio", Toast.LENGTH_LONG).show(); 

    } 
0

当我读到开发文档here,Android支持RTSP协议(实时流媒体),还HTTP/HTTPS协议直播流媒体草案。

还有一个例子here。您必须拥有Streaming服务器的基础知识,例如Red5或Wowza。

0

这是一个简单的录音和回放应用程序。
采用Android AudioRecordAudioTrack

设计

录制的音频被写入缓冲区,并从同一个缓冲播放,这一机制在运行一个循环(使用Android的线程)控制按钮。


代码

private String TAG = "AUDIO_RECORD_PLAYBACK"; 
private boolean isRunning = true; 
private Thread m_thread;    /* Thread for running the Loop */ 

private AudioRecord recorder = null; 
private AudioTrack track = null; 

int bufferSize = 320;     /* Buffer for recording data */ 
byte buffer[] = new byte[bufferSize]; 

/* Method to Enable/Disable Buttons */ 
private void enableButton(int id,boolean isEnable){ 
    ((Button)findViewById(id)).setEnabled(isEnable); 
} 

的GUI有两个按钮STARTSTOP
启用按钮:

enableButton(R.id.StartButton,true); 
enableButton(R.id.StopButton,false); 

/* Assign Button Click Handlers */ 
((Button)findViewById(R.id.StartButton)).setOnClickListener(btnClick); 
((Button)findViewById(R.id.StopButton)).setOnClickListener(btnClick); 

映射START和STOP按钮OnClickListener

private View.OnClickListener btnClick = new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     switch(v.getId()){ 
     case R.id.StartButton: 
     { 
      Log.d(TAG, "======== Start Button Pressed =========="); 
      isRunning = true; 
      do_loopback(isRunning); 
      enableButton(R.id.StartButton,false); 
      enableButton(R.id.StopButton,true); 
      break; 
     } 
     case R.id.StopButton: 
     { 
      Log.d(TAG, "======== Stop Button Pressed =========="); 
      isRunning = false; 
      do_loopback(isRunning); 
      enableButton(R.id.StopButton,false); 
      enableButton(R.id.StartButton,true); 
      break; 
     } 
    } 
} 

启动线程:

private void do_loopback(final boolean flag) 
{ 
    m_thread = new Thread(new Runnable() { 
     public void run() { 
      run_loop(flag); 
     } 
    }); 
    m_thread.start(); 
} 

用于初始化AudioRecord和AudioTrack方法:

public AudioTrack findAudioTrack (AudioTrack track) 
{ 
    Log.d(TAG, "===== Initializing AudioTrack API ===="); 
    int m_bufferSize = AudioTrack.getMinBufferSize(8000, 
      AudioFormat.CHANNEL_OUT_MONO, 
      AudioFormat.ENCODING_PCM_16BIT); 

    if (m_bufferSize != AudioTrack.ERROR_BAD_VALUE) 
    { 
     track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, 
       AudioFormat.CHANNEL_OUT_MONO, 
       AudioFormat.ENCODING_PCM_16BIT, m_bufferSize, 
       AudioTrack.MODE_STREAM); 

     if (track.getState() == AudioTrack.STATE_UNINITIALIZED) { 
      Log.e(TAG, "===== AudioTrack Uninitialized ====="); 
      return null; 
     } 
    } 
    return track; 
} 

public AudioRecord findAudioRecord (AudioRecord recorder) 
{ 
    Log.d(TAG, "===== Initializing AudioRecord API =====");  
    int m_bufferSize = AudioRecord.getMinBufferSize(8000, 
      AudioFormat.CHANNEL_IN_MONO, 
      AudioFormat.ENCODING_PCM_16BIT); 

    if (m_bufferSize != AudioRecord.ERROR_BAD_VALUE) 
    { 
     recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, 
       AudioFormat.CHANNEL_IN_MONO, 
       AudioFormat.ENCODING_PCM_16BIT, m_bufferSize); 

     if (recorder.getState() == AudioRecord.STATE_UNINITIALIZED) { 
      Log.e(TAG, "====== AudioRecord UnInitilaised ====== "); 
      return null; 
     } 
    } 
    return recorder; 
} 

的值findAudioRecordfindAudioTrack可以改变基于设备。
请参考this的问题。


代码运行循环:

public void run_loop (boolean isRunning) 
{ 

    /** == If Stop Button is pressed == **/ 
    if (isRunning == false) { 
     Log.d(TAG, "===== Stop Button is pressed ===== "); 

     if (AudioRecord.STATE_INITIALIZED == recorder.getState()){ 
      recorder.stop(); 
      recorder.release(); 
     } 
     if (AudioTrack.STATE_INITIALIZED == track.getState()){ 
      track.stop(); 
      track.release(); 
     } 
     return; 
    } 


    /** ======= Initialize AudioRecord and AudioTrack ======== **/ 
    recorder = findAudioRecord(recorder); 
    if (recorder == null) { 
     Log.e(TAG, "======== findAudioRecord : Returned Error! =========== "); 
     return; 
    } 

    track = findAudioTrack(track); 
    if (track == null) { 
     Log.e(TAG, "======== findAudioTrack : Returned Error! ========== "); 
     return; 
    } 

    if ((AudioRecord.STATE_INITIALIZED == recorder.getState()) && 
      (AudioTrack.STATE_INITIALIZED == track.getState())) 
    { 
     recorder.startRecording(); 
     Log.d(TAG, "========= Recorder Started... ========="); 
     track.play(); 
     Log.d(TAG, "========= Track Started... ========="); 
    } 
    else 
    { 
     Log.d(TAG, "==== Initilazation failed for AudioRecord or AudioTrack ====="); 
     return; 
    } 

    /** ------------------------------------------------------ **/ 

    /* Recording and Playing in chunks of 320 bytes */ 
    bufferSize = 320; 

    while (isRunning == true) 
    { 
     /* Read & Write to the Device */ 
     recorder.read(buffer, 0, bufferSize); 
     track.write(buffer, 0, bufferSize); 

    } 
    Log.i(TAG, "Loopback exit"); 
    return; 
} 

请在AndroidManifest.xml

<uses-permission android:name="android.permission.RECORD_AUDIO" > </uses-permission> 

这上面的程序以下也可以通过使用写入/从文件读取相同的API。
为什么要使用audioRecord而不是mediaRecorder - See here

该代码已经过测试(在Google Nexus 5上)并且工作正常。

注意:请为recorder.readtrack.write添加一些错误检查代码,以防万一您失败。同样适用于findAudioRecordfindAudioTrack