【问题标题】:How to get duration of Audio Stream and continue audio streaming from any point如何获取音频流的持续时间并从任何点继续音频流
【发布时间】:2012-02-16 20:20:17
【问题描述】:

说明:

我有以下音频播放器的代码。我可以通过单击进度条(在 0-to-mediaplayer.getDuration() 之间)从任何持续时间继续播放音频。它非常适合音频播放。

音频流中的问题:

  • 当我从 Internet 服务器(例如 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);
            }
        }
    };
}

时间显示在进度条上方。

时间:“当前持续时间”/“总持续时间”

【问题讨论】:

  • @Arif:我正在创建一个媒体播放器,如果你解决了这个问题,你会把代码发邮件给我吗? abuhamzah09 at gmail dot com
  • LTDAudioPlayer 是什么控件?
  • @AbuHamzah 是 MyAudioPlayer 而不是 LTDAudioPlayer

标签: android audio-streaming android-mediaplayer


【解决方案1】:

第一个大问题是您的初始化顺序: 在实际调用 resetAndStartPlayer 中的 setDataSource 之前调用 getDuration。 MediaPlayer 应该如何知道没有数据源的持续时间?

以下是正确执行此操作的方法:

  1. 在 Activity.onCreate 中调用 MediaPlayer.setDataSource()

  2. 执行 AsyncTask,在其 doInBackground 调用 MediaPlayer.prepare() 中,如果从 http 流式传输,这将需要一段时间,但完成后,播放器应该知道媒体的长度

  3. 在AsyncTask.onPostExecute 调用MediaPlayer.getDuration(),如果流打开成功应该会成功;之后你可以调用 MediaPlayer.start()

重要的事情:

  • getDuration 在调用 prepare 后起作用
  • prepare 可能需要更长的时间,应该在其他线程中调用
  • 你也可以使用 prepareAsync 并避免 AsyncTask,然后你会使用 setOnPreparedListener 回调来调用 getDuration

【讨论】:

  • 感谢您有兴趣解决问题。在 mediaPlayer.onPrepared() 中准备好 mediaPlayer 后,我已将代码修改为 getDuration ... 正如我提到的,问题出在音频流中,它仍然存在。当我流式传输更小的音频时。 GetDuration 返回我 6 小时之类的。但是当我从 sdcard 播放音频时,相同的代码会返回正确的持续时间。
  • 发布远程流的示例 url。
【解决方案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 允许清理音频流。我已经在我的一个项目中实现了它,但这需要一些时间。从其他位置恢复音频流需要一些时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-29
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-27
    • 1970-01-01
    相关资源
    最近更新 更多