Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to record and save as mp3 online streaming audio

I have a streaming url to stream in my application and I also record the same file to listen offline too. I am able to stream the URL with the help of media player and service, but now I am looking for the recording logic of the same file.

How can I record live streaming and save file on the SD card?

like image 759
Krishnakant Dalal Avatar asked Jul 18 '13 19:07

Krishnakant Dalal


People also ask

Can you download streaming audio?

You can use any recording tool to record the streaming audio file first and then choose to save it as MP3 files. Many free audio streaming recorders are available, such as EaseUS RecExperts, which can record or download them on the computer.


2 Answers

I assume you don't want to record the audio stream using your mic, but rather download the original audio file, then what you are looking for is called progressive download, here is a good tutorial to set it up with the MediaController, basically you first start to download the file, and while you are downloading it, you read the buffered file locally with the player as datasource.

From the above link you can use the StreamingMediaPlayer, original android MediaPlayer does not yet support streaming from external URLs so this class provides a pseudo-streaming function by downloading the content incrementally & playing as soon as we get enough audio in our temporary storage.

public class StreamingMediaPlayer {

private static final int INTIAL_KB_BUFFER =  96*10/8;//assume 96kbps*10secs/8bits per byte

private TextView textStreamed;

private ImageButton playButton;

private ProgressBar progressBar;

//  Track for display by progressBar
private long mediaLengthInKb, mediaLengthInSeconds;
private int totalKbRead = 0;

// Create Handler to call View updates on the main UI thread.
private final Handler handler = new Handler();

private MediaPlayer     mediaPlayer;

private File downloadingMediaFile; 

private boolean isInterrupted;

private Context context;

private int counter = 0;

public StreamingMediaPlayer(Context  context,TextView textStreamed, ImageButton playButton, Button  streamButton,ProgressBar    progressBar) 
{
    this.context = context;
    this.textStreamed = textStreamed;
    this.playButton = playButton;
    this.progressBar = progressBar;
}

/**  
 * Progressivly download the media to a temporary location and update the MediaPlayer as new content becomes available.
 */  
public void startStreaming(final String mediaUrl, long  mediaLengthInKb, long   mediaLengthInSeconds) throws IOException {

    this.mediaLengthInKb = mediaLengthInKb;
    this.mediaLengthInSeconds = mediaLengthInSeconds;

    Runnable r = new Runnable() {   
        public void run() {   
            try {   
                downloadAudioIncrement(mediaUrl);
            } catch (IOException e) {
                Log.e(getClass().getName(), "Unable to initialize the MediaPlayer for fileUrl=" + mediaUrl, e);
                return;
            }   
        }   
    };   
    new Thread(r).start();
}

/**  
 * Download the url stream to a temporary location and then call the setDataSource  
 * for that local file
 */  
public void downloadAudioIncrement(String mediaUrl) throws IOException {

    URLConnection cn = new URL(mediaUrl).openConnection();   
    cn.connect();   
    InputStream stream = cn.getInputStream();
    if (stream == null) {
        Log.e(getClass().getName(), "Unable to create InputStream for mediaUrl:" + mediaUrl);
    }

    downloadingMediaFile = new File(context.getCacheDir(),"downloadingMedia_" + (counter++) + ".dat");
    FileOutputStream out = new FileOutputStream(downloadingMediaFile);   
    byte buf[] = new byte[16384];
    int totalBytesRead = 0, incrementalBytesRead = 0;
    do {
        int numread = stream.read(buf);   
        if (numread <= 0)   
            break;   
        out.write(buf, 0, numread);
        totalBytesRead += numread;
        incrementalBytesRead += numread;
        totalKbRead = totalBytesRead/1000;

        testMediaBuffer();
        fireDataLoadUpdate();
    } while (validateNotInterrupted());   

    stream.close();
    if (validateNotInterrupted()) {
        fireDataFullyLoaded();
    }
}  

private boolean validateNotInterrupted() {
    if (isInterrupted) {
        if (mediaPlayer != null) {
            mediaPlayer.pause();
            //mediaPlayer.release();
        }
        return false;
    } else {
        return true;
    }
}


/**
 * Test whether we need to transfer buffered data to the MediaPlayer.
 * Interacting with MediaPlayer on non-main UI thread can causes crashes to so perform this using a Handler.
 */  
private void  testMediaBuffer() {
    Runnable updater = new Runnable() {
        public void run() {
            if (mediaPlayer == null) {
                //  Only create the MediaPlayer once we have the minimum buffered data
                if ( totalKbRead >= INTIAL_KB_BUFFER) {
                    try {
                        startMediaPlayer();
                    } catch (Exception e) {
                        Log.e(getClass().getName(), "Error copying buffered conent.", e);               
                    }
                }
            } else if ( mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000 ){ 
                //  NOTE:  The media player has stopped at the end so transfer any existing buffered data
                //  We test for < 1second of data because the media player can stop when there is still
                //  a few milliseconds of data left to play
                transferBufferToMediaPlayer();
            }
        }
    };
    handler.post(updater);
}

private void startMediaPlayer() {
    try {   
        File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".dat");
        moveFile(downloadingMediaFile,bufferedFile);

        Log.e("Player",bufferedFile.length()+"");
        Log.e("Player",bufferedFile.getAbsolutePath());

        mediaPlayer = new MediaPlayer();
        mediaPlayer.setDataSource(bufferedFile.getAbsolutePath());
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mediaPlayer.prepare();
        fireDataPreloadComplete();

    } catch (IOException e) {
        Log.e(getClass().getName(), "Error initializing the MediaPlaer.", e);
        return;
    }   
}

/**
 * Transfer buffered data to the MediaPlayer.
 * Interacting with MediaPlayer on non-main UI thread can causes crashes to so perform this using a Handler.
 */  
private void transferBufferToMediaPlayer() {
    try {
        // First determine if we need to restart the player after transferring data...e.g. perhaps the user pressed pause
        boolean wasPlaying = mediaPlayer.isPlaying();
        int curPosition = mediaPlayer.getCurrentPosition();
        mediaPlayer.pause();

        File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".dat");
        //FileUtils.copyFile(downloadingMediaFile,bufferedFile);

        mediaPlayer = new MediaPlayer();
        mediaPlayer.setDataSource(bufferedFile.getAbsolutePath());
        //mediaPlayer.setAudioStreamType(AudioSystem.STREAM_MUSIC);
        mediaPlayer.prepare();
        mediaPlayer.seekTo(curPosition);

        //  Restart if at end of prior beuffered content or mediaPlayer was previously playing.  
        //  NOTE:  We test for < 1second of data because the media player can stop when there is still
        //  a few milliseconds of data left to play
        boolean atEndOfFile = mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000;
        if (wasPlaying || atEndOfFile){
            mediaPlayer.start();
        }
    }catch (Exception e) {
        Log.e(getClass().getName(), "Error updating to newly loaded content.", e);                  
    }
}

private void fireDataLoadUpdate() {
    Runnable updater = new Runnable() {
        public void run() {
            textStreamed.setText((CharSequence) (totalKbRead + " Kb read"));
            float loadProgress = ((float)totalKbRead/(float)mediaLengthInKb);
            progressBar.setSecondaryProgress((int)(loadProgress*100));
        }
    };
    handler.post(updater);
}

/**
 * We have preloaded enough content and started the MediaPlayer so update the buttons & progress meters.
 */
private void fireDataPreloadComplete() {
    Runnable updater = new Runnable() {
        public void run() {
            mediaPlayer.start();
            startPlayProgressUpdater();
            playButton.setEnabled(true);
            //streamButton.setEnabled(false);
        }
    };
    handler.post(updater);
}

private void fireDataFullyLoaded() {
    Runnable updater = new Runnable() { 
        public void run() {
            transferBufferToMediaPlayer();
            textStreamed.setText((CharSequence) ("Audio full loaded: " + totalKbRead + " Kb read"));
        }
    };
    handler.post(updater);
}

public MediaPlayer getMediaPlayer() {
    return mediaPlayer;
}

public void startPlayProgressUpdater() {
    float progress = (((float)mediaPlayer.getCurrentPosition()/1000)/(float)mediaLengthInSeconds);
    progressBar.setProgress((int)(progress*100));

    if (mediaPlayer.isPlaying()) {
        Runnable notification = new Runnable() {
            public void run() {
                startPlayProgressUpdater();
            }
        };
        handler.postDelayed(notification,1000);
    }
}    

public void interrupt() {
    playButton.setEnabled(false);
    isInterrupted = true;
    validateNotInterrupted();
}

public void moveFile(File   oldLocation, File   newLocation)
throws IOException {

    if ( oldLocation.exists( )) {
        BufferedInputStream  reader = new BufferedInputStream( new FileInputStream(oldLocation) );
        BufferedOutputStream  writer = new BufferedOutputStream( new FileOutputStream(newLocation, false));
        try {
            byte[]  buff = new byte[8192];
            int numChars;
            while ( (numChars = reader.read(  buff, 0, buff.length ) ) != -1) {
                writer.write( buff, 0, numChars );
            }
        } catch( IOException ex ) {
            throw new IOException("IOException when transferring " + oldLocation.getPath() + " to " + newLocation.getPath());
        } finally {
            try {
                if ( reader != null ){
                    writer.close();
                    reader.close();
                }
            } catch( IOException ex ){
                Log.e(getClass().getName(),"Error closing files when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() ); 
            }
        }
    } else {
        throw new IOException("Old location does not exist when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() );
    }
}

}

Then you can easily use it like:

private void startStreamingAudio() {
    try { 
        final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar);
        if ( audioStreamer != null) {
            audioStreamer.interrupt();
        }
        audioStreamer = new StreamingMediaPlayer(this,textStreamed, playButton, streamButton,progressBar);
        audioStreamer.startStreaming("http://www.pocketjourney.com/downloads/pj/tutorials/audio.mp3",1677, 214);
        //streamButton.setEnabled(false);
    } catch (IOException e) {
        Log.e(getClass().getName(), "Error starting to stream audio.", e);                  
    }
like image 188
Gomino Avatar answered Nov 14 '22 23:11

Gomino


I think your problem is solved there :

https://stackoverflow.com/a/5384161/2545832

Try to do a byte by byte operation. It works by this guy.

Hope it helps !

EDIT :

Sorry didn't see the comment !

like image 23
Laurent Meyer Avatar answered Nov 15 '22 00:11

Laurent Meyer