ios - ver - reproducir mp4 en ipad
Comprobar el estado de reproducción de AVPlayer (8)
¿Hay alguna manera de saber si la reproducción de AVPlayer
ha estancado o ha llegado al final?
En iOS10, ahora hay una propiedad incorporada para esto: timeControlStatus
Por ejemplo, esta función reproduce o hace una pausa en avPlayer en función de su estado y actualiza el botón Reproducir / Pausa de forma adecuada.
@IBAction func btnPlayTap(_ sender: Any) {
if aPlayer.timeControlStatus == .playing {
aPlayer.pause()
btnPlay.setImage(UIImage(named: "control-play"), for: .normal)
} else if aPlayer.timeControlStatus == .paused {
aPlayer.play()
btnPlay.setImage(UIImage(named: "control-pause"), for: .normal)
}
}
En cuanto a su segunda pregunta, para saber si el jugador llegó al final, lo más fácil sería configurar una notificación.
NotificationCenter.default.addObserver(self, selector: #selector(self.didPlayToEnd), name: .AVPlayerItemDidPlayToEndTime, object: nil)
Cuando llega al final, por ejemplo, puede hacer que se rebobine hasta el comienzo del video y restablecer el botón Pausa para Reproducir.
func didPlayToEnd() {
aPlayer.seek(to: CMTimeMakeWithSeconds(0, 1))
btnPlay.setImage(UIImage(named: "control-play"), for: .normal)
}
Estos ejemplos son útiles si está creando sus propios controles, pero si usa un AVPlayerViewController, los controles vienen integrados.
Extensión Swift basada en la respuesta de maz
extension AVPlayer {
var isPlaying: Bool {
return ((rate != 0) && (error == nil))
}
}
La versión Swift de la respuesta de maxkonovalov es esta:
player.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.New, context: nil)
y
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if keyPath == "rate" {
if let rate = change?[NSKeyValueChangeNewKey] as? Float {
if rate == 0.0 {
print("playback stopped")
}
if rate == 1.0 {
print("normal playback")
}
if rate == -1.0 {
print("reverse playback")
}
}
}
}
Gracias maxkonovalov!
Para Swift :
AVPlayer :
let player = AVPlayer(URL: NSURL(string: "http://www.sample.com/movie.mov"))
if (player.rate != 0 && player.error == nil) {
println("playing")
}
Actualización :
player.rate > 0
condición player.rate > 0
cambió a player.rate != 0
porque si el video se reproduce en reversa, puede ser negativo gracias a Julian por señalar.
Nota : Esto podría parecerse a la respuesta de arriba (Maz) pero en Swift ''! Player.error'' me estaba dando un error de compilación, por lo que debe verificar el error usando ''player.error == nil'' en Swift. (Porque la propiedad de error no es del tipo ''Bool'')
AVAudioPlayer:
if let theAudioPlayer = appDelegate.audioPlayer {
if (theAudioPlayer.playing) {
// playing
}
}
AVQueuePlayer:
if let theAudioQueuePlayer = appDelegate.audioPlayerQueue {
if (theAudioQueuePlayer.rate != 0 && theAudioQueuePlayer.error == nil) {
// playing
}
}
Para recibir una notificación para llegar al final de un artículo (a través de Apple ):
[[NSNotificationCenter defaultCenter]
addObserver:<self>
selector:@selector(<#The selector name#>)
name:AVPlayerItemDidPlayToEndTimeNotification
object:<#A player item#>];
Y para seguir jugando puedes:
"rastrear cambios en la posición de la cabeza lectora en un objeto AVPlayer" utilizando addPeriodicTimeObserverForInterval: queue: usingBlock: o addBoundaryTimeObserverForTimes: queue: usingBlock:.
El ejemplo es de Apple:
// Assume a property: @property (retain) id playerObserver;
Float64 durationSeconds = CMTimeGetSeconds([<#An asset#> duration]);
CMTime firstThird = CMTimeMakeWithSeconds(durationSeconds/3.0, 1);
CMTime secondThird = CMTimeMakeWithSeconds(durationSeconds*2.0/3.0, 1);
NSArray *times = [NSArray arrayWithObjects:[NSValue valueWithCMTime:firstThird], [NSValue valueWithCMTime:secondThird], nil];
self.playerObserver = [<#A player#> addBoundaryTimeObserverForTimes:times queue:NULL usingBlock:^{
// Passing NULL for the queue specifies the main queue.
NSString *timeDescription = (NSString *)CMTimeCopyDescription(NULL, [self.player currentTime]);
NSLog(@"Passed a boundary at %@", timeDescription);
[timeDescription release];
}];
Puedes ver que está jugando usando:
AVPlayer *player = ...
if ((player.rate != 0) && (player.error == nil)) {
// player is playing
}
Swift 3 extensión:
extension AVPlayer {
var isPlaying: Bool {
return rate != 0 && error == nil
}
}
Una alternativa más confiable a NSNotification
es agregarse como observador a la propiedad de la rate
del jugador.
[self.player addObserver:self
forKeyPath:@"rate"
options:NSKeyValueObservingOptionNew
context:NULL];
Luego, verifique si el nuevo valor para la tasa observada es cero, lo que significa que la reproducción se ha detenido por alguna razón, como llegar al final o atascarse debido a un buffer vacío.
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary<NSString *,id> *)change
context:(void *)context {
if ([keyPath isEqualToString:@"rate"]) {
float rate = [change[NSKeyValueChangeNewKey] floatValue];
if (rate == 0.0) {
// Playback stopped
} else if (rate == 1.0) {
// Normal playback
} else if (rate == -1.0) {
// Reverse playback
}
}
}
Para la rate == 0.0
caso, para saber qué causó exactamente la detención de la reproducción, puede hacer las siguientes comprobaciones:
if (self.player.error != nil) {
// Playback failed
}
if (CMTimeGetSeconds(self.player.currentTime) >=
CMTimeGetSeconds(self.player.currentItem.duration)) {
// Playback reached end
} else if (!self.player.currentItem.playbackLikelyToKeepUp) {
// Not ready to play, wait until enough data is loaded
}
Y no olvides parar tu reproductor cuando llegue al final:
self.player.actionAtItemEnd = AVPlayerActionAtItemEndPause;
rate
NO es la forma de verificar si un video se está reproduciendo (podría estar bloqueado). De la documentación de la rate
:
Indica la tasa de reproducción deseada; 0.0 significa "en pausa", 1.0 indica un deseo de jugar a la velocidad natural del elemento actual.
Palabras clave "deseo de jugar": una tasa de 1.0
no significa que el video se está reproduciendo.
La solución desde iOS 10.0 es usar AVPlayerTimeControlStatus
que se puede observar en la propiedad AVPlayer
timeControlStatus
.
La solución anterior a iOS 10.0 (9.0, 8.0 etc.) es rodar su propia solución. Una tasa de 0.0
significa que el video está en pausa. Cuando rate != 0.0
significa que el video está reproduciéndose o está atascado.
Puede averiguar la diferencia observando el tiempo del jugador a través de: func addPeriodicTimeObserver(forInterval interval: CMTime, queue: DispatchQueue?, using block: @escaping (CMTime) -> Void) -> Any
El bloque devuelve la hora actual del jugador en CMTime
, por lo que una comparación de lastTime
(la hora que se recibió por última vez del bloque) y currentTime
(el tiempo que el bloque acaba de informar) indicará si el reproductor está reproduciendo o está estancado. Por ejemplo, si lastTime == currentTime
y rate != 0.0
, entonces el jugador se ha estancado.
Como señalaron otros, averiguar AVPlayerItemDidPlayToEndTimeNotification
indica si la reproducción finalizó.