Подтвердить что ты не робот

Android: MediaPlayer безразличный или бесшовный Воспроизведение видео

Я могу воспроизводить видео очень хорошо, реализуя OnCompletionListener, чтобы установить источник данных в другой файл. Проблем нет. Я вызываю reset() и готовлю() просто отлично.

То, что я не смог выяснить, заключается в том, как избавиться от мерцания экрана на 1-2 секунды между изменением источника данных и запуском нового видео. Зазор показывает черный экран, и я не нашел способа обойти его.

Я попытался установить фон родительского представления на изображение, но ему удается обойти это. Даже если SurfaceView прозрачен (по умолчанию он по умолчанию.) Я также пытался одновременно воспроизводить несколько видеофайлов и переключать отображение медиапланера, когда он заканчивается, а другой должен начинаться.

Последнее, что я пробовал, - это иметь второе представление в фоновом режиме, которое я показываю временно, пока видео "готовит" и удаляет его, когда видео готово к запуску. Это также было не очень легко.

Есть ли способ избавиться от этого пробела. Запуск видео в цикле прекрасно работает и делает именно то, что я хочу, за исключением того, что он просматривает одно и то же видео, вместо того, чтобы играть в другое, которое я выбираю.

main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:background="@drawable/background"
    android:layout_height="fill_parent">
    <SurfaceView
        android:id="@+id/surface"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_gravity="center">
    </SurfaceView>
</FrameLayout>

Player.java

public class Player extends Activity implements
        OnCompletionListener, MediaPlayer.OnPreparedListener, SurfaceHolder.Callback {
        private MediaPlayer player;
    private SurfaceView surface;
    private SurfaceHolder holder;

    public void onCreate(Bundle b) {
        super.onCreate(b);
        setContentView(R.layout.main);
        surface = (SurfaceView)findViewById(R.id.surface);
        holder = surface.getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);    
    }

    public void onCompletion(MediaPlayer arg0) {
        File clip = new File(Environment.getExternalStorageDirectory(),"file2.mp4");
        playVideo(clip.getAbsolutePath());
    }
    public void onPrepared(MediaPlayer mediaplayer) {
        holder.setFixedSize(player.getVideoWidth(), player.getVideoHeight());
        player.start();
    }

    private void playVideo(String url) {
        try {
            File clip = new File(Environment.getExternalStorageDirectory(),"file1.mp4");

            if (player == null) {
                player = new MediaPlayer();
                player.setScreenOnWhilePlaying(true);
            }
            else {
                player.stop();
                player.reset();
            }
            player.setDataSource(url);
            player.setDisplay(holder);
            player.setOnPreparedListener(this);
            player.prepare();
            player.setOnCompletionListener(this);
        }
        catch (Throwable t) {
            Log.e("ERROR", "Exception Error", t);
        }
    }
4b9b3361

Ответ 1

У меня тоже такая же проблема, как описано ниже ссылкой

Видеообзор исчезает в течение секунды при изменении видео

Но эта проблема не возникнет, если вы попытаетесь использовать Android 4.0+ (ICS). Я начал переносить VideoView.java и MediaPlayer.java с 4.0 на мое приложение, но это кажется сложным и не повезло до сих пор. В основном это кажется ошибкой в ​​собственном коде старых версий.

Ответ 2

после слишком много потраченного времени, пытаясь понять, как играть в последовательные видео без "пробела", я склоняюсь к невозможности. если, конечно, вы не можете выкопать до родного уровня и реализовать своего собственного игрока, мультимедийный плеер Android просто не поддерживает плавное воспроизведение с момента.

Ответ 3

Я не делал этого с воспроизведением видео на MediaPlayer, но я сделал что-то подобное с аудиофайлами, когда поток прерывается, потому что пользователь переключился с 3G на Wi-Fi.

Я думаю, что задержка, которую вы видите, пока медиаплеер буферизует входной файл. Может быть, вы можете определить обоих игроков в начале? Вы должны определить источник данных и подготовить обоих игроков, но только запустить один из них.

Затем в вашем onCompletionListener вы можете перевернуть их вместо сброса существующего и установки нового источника данных.

  player.release();
  player = flipPlayer;
  flipPlayer = null;
  player.start();

Очевидно, вам нужно либо использовать другой onPreparedListener для flipPlayer, либо взять player.start() из onPrepare. (Поскольку вы называете это синхронно, я бы не подумал, что это проблема).

Ответ 4

Я не думаю, что это возможно.

Причина: Mortplayer также был доступен для Windows Mobile, и одна из его сильных сторон заключалась в том, что он поддерживал беспроблемную игру. Однако это не в Android-версии приложения, и сам разработчик пишет, что SDK не разрешает его на xda: http://forum.xda-developers.com/showpost.php?p=5364530&postcount=5

HTH, Даниэле

Ответ 5

Пробовал ли вы готовый (открытый/подготовленный) 2 VideoView, один из которых был видимым, другим невидимым и остановился, и задница вскоре вы получите обратный вызов OnCompletionListener, сделайте 2-й вид видимым, запустите его и скройте 1-й. В то же время, когда играет 2-й, вы можете вызвать open/prepare на 1st VideoView, чтобы открыть/подготовить другой файл.

Ответ 6

@user1263019 - вы могли переносить Android 4.0 MediaPlayer в свое приложение? Я сталкиваюсь с той же проблемой, и я ищу хорошее решение. У моего случая есть изображение поверх SurfaceView, которое должно быть скрыто, чтобы показать воспроизведение видео, но есть разрыв между вызовом start() и фактическим началом видео. Единственным решением до сих пор является запуск Thread, который проверяет, есть ли getCurrentPosition() > 0.

По теме - я думаю, что невозможно безщелезное воспроизведение, хотя Winamp претендует на такие способности. Грязный взлом состоит в том, чтобы подготовить второго игрока за несколько секунд до конца воспроизведения первого игрока, а затем вызвать start() второго игрока на 100-200 мс до окончания воспроизведения.

Ответ 7

В вашей реализации exoplayer (или медиаплеере) используйте обработчик для повторной отправки runnable во время воспроизведения, который получает текущее время отслеживания и передает его на обратный вызов:

public interface MediaAction {
  public void onTrackingChanged(long currentPosition);
}

public class ExoPlayerImplementation implements Exoplayer {

  ..

  private MediaAction mediaActionCallback;
  public void setMediaActionCallback(MediaAction ma) {
    mediaActionCallback = ma;
  }
  public void releaseMediaAction() { mediaActionCallback = null; } 

  private Handler trackingCallback = new Handler(Looper.getMainLooper());

  Runnable trackingTask;
  private Runnable getTrackingTask() {
    Runnable r = new Runnable {
      @Override public void run() {
         long currentPosition = getCurrentPosition();
         if (mediaActionCallback != null) {
           mediaActionCallback.onTrackingChanged(currentPosition);
         }
         // 60hz is 16 ms frame delay...
         trackingCallback.postDelayed(getTrackingTask(), 15);
       }
    };
    trackingTask = r;
    return r;
  }

  public void play() {
    // exoplayer start code
    trackingCallback.post(getTrackingTask());
  } 

  public void pause/stop() {
    trackingCallback.removeCallbacks(trackingTask);
  }

  ..

}

И теперь вы можете отслеживать, когда текущая позиция фактически изменилась, - если она изменилась, вы можете отобразить вид вывода видео или просмотреть/удалить предварительный просмотр (т.е. использовать MediaExtractor для захвата исходных кадров, наложения в виде предварительного просмотра в ImageView затем скрывается, когда текущая позиция увеличивается). Вы можете сделать этот код более полным, объединив его с слушателем состояния: тогда вы знаете, буферизуете ли вы (проверяете положение буферизации по сравнению с текущей позицией), фактически играете, приостанавливаете или останавливаете с помощью соответствующих обратных вызовов (в MediaAction). Вы можете применить этот метод к классам MediaPlayer и ExoPlayer (поскольку это всего лишь интерфейс и обработчик).

Надеюсь, что это поможет!