Как получить продолжительность аудиопотока и продолжить потоковое аудио с любой точки

Описание:

У меня есть следующий код для аудиоплеера. Я могу продолжить воспроизведение аудио с любой продолжительности, щелкнув индикатор выполнения (между 0-to-mediaplayer.getDuration()). Он отлично работает для воспроизведения аудио.

Проблема с потоковой передачей аудио:

  • Когда я передаю аудиофайл с интернет-сервера (скажем, s3-bucket), он начинает передаваться правильно.
  • Но mediaPlayer.getDuration() и mediaPlayer.getCurrentPosition() возвращают неверные значения. В начале потоковой передачи mediaPlayer.getCurrentPosition() возвращает 5 часов.
  • Из-за этого я не могу продолжать потоковую передачу аудио с указанной продолжительности потока (длительность от 0 до потока).

Вопросы:

  1. Как я могу получить продолжительность аудиопотока
  2. Как я могу продолжить потоковое аудио с указанной продолжительности. Например, для файла продолжительностью 10 минут я хочу начать потоковую передачу с 6-й минуты.

Код:

public class MyAudioPlayer extends Activity 
implements OnClickListener{


    MediaPlayer mediaPlayer = null;
    private boolean isPaused=false;
    private boolean isStop = true;

    String filePath = null;
    String productName = null;

    ImageButton btnPlay = null;
    ImageButton btnPause = null;
    ImageButton btnReset = null;
    ImageButton btnStop = null;

    AudioManager audioManager = null;
    SeekBar volControl = null;
    SeekBar progressControl = null;
    TextView progressText = null;
    long durationInMillis = -1;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.ltd_audio_player);

        volControl = (SeekBar)findViewById(R.id.player_volume);
        progressControl = (SeekBar)findViewById(R.id.player_seekbar);
        progressText = (TextView) findViewById(R.id.player_progress_text);

        btnPlay = (ImageButton) findViewById(R.id.ic_player_play); 

        btnPause = (ImageButton) findViewById(R.id.ic_player_pause);  

        btnReset = (ImageButton) findViewById(R.id.ic_player_reset); 

        btnStop = (ImageButton) findViewById(R.id.ic_player_stop);   

        btnPlay.setOnClickListener(this);
        btnPause.setOnClickListener(this);
        btnReset.setOnClickListener(this);
        btnStop.setOnClickListener(this);

        filePath = getIntent().getExtras().getString("localPath");

        this.setPlayer();
        this.resetAndStartPlayer();


    }

    @Override
    protected void onResume() {
        super.onResume();   
        isPaused=false;
        progressText.postDelayed(onEverySecond, 1000);
    }

    @Override
    protected void onPause() {
        super.onPause();

        isPaused=true;
    }
    private void setProgressControl() {
        int maxVolume = mediaPlayer.getDuration();
        int curVolume = mediaPlayer.getCurrentPosition();

        progressControl.setMax(maxVolume);
        progressControl.setProgress(curVolume);
        progressControl.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

            @Override
            public void onProgressChanged(SeekBar seekbar, int progress, boolean fromUser) {
                mediaPlayer.seekTo(progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                // TODO Auto-generated method stub

            }
        });     
    }
    @Override
    public void onClick(View v) {
        switch(v.getId()){
        case R.id.ic_player_play:
            if(isStop==true){
                try {
                    mediaPlayer.prepareAsync();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }else{
                mediaPlayer.start();
                isStop = true;
            }
            break;
        case R.id.ic_player_pause:
            mediaPlayer.pause();
            break;
        case R.id.ic_player_reset:
            mediaPlayer.seekTo(0);
            break;
        case R.id.ic_player_stop:
            isStop = true;
            progressControl.setProgress(0);
            mediaPlayer.stop();
            break;
        }

    }
    private void resetAndStartPlayer(){
        try {
            if(filePath!=null){
                mediaPlayer.setDataSource(filePath);
                mediaPlayer.prepareAsync();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private void setPlayer(){

        getWindow().setFormat(PixelFormat.UNKNOWN);
        mediaPlayer = new MediaPlayer();    

        mediaPlayer.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {

            @Override
            public void onBufferingUpdate(MediaPlayer mp, int percent) {
                progressControl.setSecondaryProgress((progressControl.getMax()/100)*percent);

            }
        });
        mediaPlayer.setOnPreparedListener(new OnPreparedListener() {

            @Override
            public void onPrepared(MediaPlayer mp) {
                mediaPlayer.start();
                isStop=false;
                durationInMillis = mediaPlayer.getDuration();
                MyAudioPlayer.this.setProgressControl();
            }
        });
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    }
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        mediaPlayer.release();
        super.onDestroy();
    }
    protected void setProgressText() {
        durationInMillis = mediaPlayer.getDuration();
        int curVolume = mediaPlayer.getCurrentPosition();
        long HOUR = 60*60*1000;
        if(progressText!=null){
            if(durationInMillis>HOUR){
                progressText.setText(String.format("%1$tH:%1$tM:%1$tS", new Date(curVolume))
                        +" / "+String.format("%1$tH:%1$tM:%1$tS", new Date(durationInMillis)));
            }else{
                progressText.setText(String.format("%1$tM:%1$tS", new Date(curVolume))
                        +" / "+String.format("%1$tM:%1$tS", new Date(durationInMillis)));
            }
        }       
    }
    private Runnable onEverySecond=new Runnable() {
        public void run() {

            if (mediaPlayer!=null) {
                progressControl.setProgress(mediaPlayer.getCurrentPosition());

                MyAudioPlayer.this.setProgressText();
            }

            if (!isPaused) {
                progressText.postDelayed(onEverySecond, 1000);
            }
        }
    };
}

Время отображается над индикатором выполнения.

Время: "Текущая продолжительность"/"Общая продолжительность"

введите здесь описание изображения


person Muhammad Nabeel Arif    schedule 23.01.2012    source источник
comment
@Arif: я работаю над созданием медиаплеера, и если вы решите проблему, вы пришлете мне код по электронной почте? abuhamzah09 в Gmail точка ком   -  person Nick Kahn    schedule 01.03.2012
comment
какой элемент управления LTDAudioPlayer ?   -  person Nick Kahn    schedule 02.03.2012
comment
@AbuHamzah это был MyAudioPlayer вместо LTDAudioPlayer   -  person Muhammad Nabeel Arif    schedule 02.03.2012


Ответы (2)


Надеюсь, что это может решить вашу проблему.

1) Продолжительность и ход аудиопотока

Я просмотрел ваш код, у вас есть серьезная ошибка в вашем коде для расчета времени. Вы создаете новую дату (durationInMillis). Дата добавляет ваш регион, т.е. GMT+XX часов, поэтому вы получаете 5-часов в начале потоковой передачи. Вы должны использовать следующий метод для вычисления currentProgress/duration.

protected void setProgressText() {

    final int HOUR = 60*60*1000;
    final int MINUTE = 60*1000;
    final int SECOND = 1000;

    int durationInMillis = mediaPlayer.getDuration();
    int curVolume = mediaPlayer.getCurrentPosition();

    int durationHour = durationInMillis/HOUR;
    int durationMint = (durationInMillis%HOUR)/MINUTE;
    int durationSec = (durationInMillis%MINUTE)/SECOND;

    int currentHour = curVolume/HOUR;
    int currentMint = (curVolume%HOUR)/MINUTE;
    int currentSec = (curVolume%MINUTE)/SECOND;

    if(durationHour>0){
        System.out.println(" 1 = "+String.format("%02d:%02d:%02d/%02d:%02d:%02d", 
                currentHour,currentMint,currentSec, durationHour,durationMint,durationSec));            
    }else{
        System.out.println(" 1 = "+String.format("%02d:%02d/%02d:%02d", 
                currentMint,currentSec, durationMint,durationSec));
    }
}

2) Очистка для потоковой передачи.

MediaPlayer позволяет очищать аудиопоток. Я реализовал это в одном из своих проектов, но это занимает некоторое время. Для возобновления потоковой передачи звука из другого места требуется некоторое время.

person Talha Hafeez    schedule 27.01.2012

Первая большая проблема — это ваш порядок инициализации: вы вызываете getDuration до того, как на самом деле вызываете setDataSource в resetAndStartPlayer. Как MediaPlayer должен знать продолжительность без источника данных?

Вот как это сделать правильно:

  1. вызов MediaPlayer.setDataSource() в Activity.onCreate

  2. выполнить AsyncTask, в его doInBackground вызовите MediaPlayer.prepare(), это займет некоторое время, если он транслируется с http, но после его завершения проигрыватель должен знать длину мультимедиа

  3. в вызове AsyncTask.onPostExecute MediaPlayer.getDuration(), который должен завершиться успешно, если поток был успешно открыт; после этого вы можете вызвать MediaPlayer.start()

Важные вещи:

  • getDuration работает после того, как была вызвана подготовка
  • подготовка может занять больше времени и должна вызываться в другом потоке
  • вы также можете использовать prepareAsync и избегать AsyncTask, тогда вы должны использовать обратный вызов setOnPreparedListener для вызова getDuration
person Pointer Null    schedule 26.01.2012
comment
Я ценю ваш интерес к решению проблемы. Я изменил код на getDuration после того, как mediaPlayer подготовлен в mediaPlayer.onPrepared()... Как я уже упоминал, проблема была в потоковом аудио, она все еще существует. Когда я транслирую аудио еще меньше. GetDuration возвращает мне 6 часов и что-то в этом роде. Но когда я воспроизвожу звук с SD-карты, тот же код возвращает правильную продолжительность. - person Muhammad Nabeel Arif; 26.01.2012
comment
Опубликуйте пример URL-адреса вашего удаленного потока. - person Pointer Null; 27.01.2012