Frage

Wer weiß, wenn AVQueuePlayer beginnt die nächste AVPlayerItem Pufferung, wenn der aktuelle Artikel über bis zum Ende spielen ist?

Ich weiß, es gibt nichts in der Dokumentation dieses vorschlagen, ich frage meist, wenn jemand diese Art von Verhalten beobachtet hat oder nicht.

War es hilfreich?

Lösung

Ok, ich habe über dieses Problem sah wieder und einige Code geschrieben AVQueuePlayer zu überprüfen.

jollyCocoa Antwort wies mich in der richtigen Richtung mit dem Vorschlag, die Status-Eigenschaft auf AVPlayerItem zu beobachten. Allerdings ist die Dokumentation nicht, darauf hinzuweisen scheint, dass diese Eigenschaft (und AVPlayerItemStatusReadyToPlay Wert es insbesondere) könnten Pufferung in Beziehung gesetzt werden.

Doch die AVPlayerItem's loadedTimeRanges Eigenschaft scheint Pufferung mehr verwendet.

Doing KVO auf diesem Array war ein bisschen schwieriger - das Array-Objekt selbst nicht verändert, nur tun es Artikel -. So griff ich zum Druck in jeder Sekunde seinen Inhalt aus

Was ich herausgefunden habe, ist, dass ein paar Sekunden in das erste Element der Warteschlange, die loadedTimeRanges für den zweiten Punkt zeigt sich eine neue CMTimeRange mit Startzeit 0 und einige kleine Dauer. Die Dauer kann bis zu 60 oder so Sekunden erhöhen, während der vorherige Punkt Spiel hält.

Kurze Antwort:. AVQueuePlayer wird die nächste AVPlayerItem puffern, während das aktuelle spielen

Andere Tipps

Wie von iOS 5, scheint es, dass AVQueuePlayer nicht mehr vorge Puffer. Es hat pre-Puffer den nächsten Titel in iOS 4.

Ich bin nicht sicher, warum es eine Änderung gegeben oder wenn es sogar überlegen auf Apples Teil oder einfach nur einen Fehler. Auf jeden Fall ist es ein Schmerz, und ich werde einen Bug mit ihnen darüber vorlegen.

Gefunden eine Arbeit um !!! Nach vielen Stunden des Suchens und nicht bestandenen Tests, fand ich eine Lösung, die funktioniert auf iOS 5 und höher.

Dies wird Dateien abspielen ohne Verzögerung dazwischen. Nicht so praktisch, wenn Sie zwischen Dateien wechseln, wird aber sicherlich alles zusammen für Sie. Es ist immer noch möglich, den Überblick zu behalten, wo jede Datei beginnt, wenn AVURLAsset das Hinzufügen, die cmtime Variable halten, so etwas wie:

NSValue *toJumpTo = [NSValue valueWithCMTime:composition.duration];
[array addObject:toJumpTo];

und dann nur das Array durchlaufen, den aktuellen Zeitwert überprüft und verglichen es CMTimeCompare verwendet wird.

Edit: Wurde auf diese Seite sichtbar aus dem Web-Archiv (der Link zur Zeit Punkte zu Spam).

Ich habe mit dem AVQueuePlayer experimentieren Filme von einem Server bereitgestellt wird. Bei diesem speziellen Test stellte ich einen queuePlayer mit AVPlayerItems mit URL auf zwei verschiedene Video-Assets von verschiedenen Arten initialisiert werden. Eine davon ist eine .mp4-Datei (progressive Download), das andere eine .m3u8 http-Streaming-Datei. Es tut ein bisschen flippig wirken, muss ich sagen.

In Abhängigkeit von der Reihenfolge, in der ich die Dateien Warteschlange bekomme ich ganz anderes Verhalten. Wenn ich mit der .mp4-Datei zu starten, geht die AVPlayerLayer leer und still, wenn der nextItem beginnt Spieler (die .m3u8-Datei). Wenn ich die Reihenfolge ändern und mit der m3u8-Datei starten, die AVPlayerLayer geht leer, aber der Ton aus der zweiten Datei spielt in Ordnung.

Ich habe den Eindruck, von dem, was ich bisher gesehen habe, ist, dass die AVQueuePlayer tut nicht starten Sie den nächsten AVPlayerItem Download, bevor die aktuelle AVPlayerItem Spielen fertig hat. Aber ich könnte falsch sein.

Fortsetzung folgt Ich denke, ...

Edit: Ok, also habe ich einige Tests gemacht und es scheint die nächsten Gegenstände beginnt das Herunterladen, bevor die letzte Punkt beendet spielen. Siehe Beitrag unten. Stroke die "NOT" ...

Edit2: Hinzufügen meiner Erklärung hier statt, da der Kommentar mir Optionen ohne Formatierung links. (Best Practice hierfür ist willkommen, wenn dies eine schlechte Art und Weise ist die Antwort Updates zu handhaben)

Wie auch immer, ich wiederholt durch meine Array Zeilen Hinzufügen Beobachtung des Status mit KVO ...

[playerItem addObserver: self forKeyPath:@"status" options: 0 context: NULL];

ich meinen Controller als Beobachter der AVPlayerItem Mitteilung auch gesetzt AVPlayerItemDidPlayToEndTimeNotification :

[[NSNotificationCenter defaultCenter] addObserver: self
                                         selector: @selector(playerItemDidReachEnd:) 
                                             name: AVPlayerItemDidPlayToEndTimeNotification 
                                           object: nil];

Nun konnte ich die Statusänderung des AVPlayerItem einzuloggen, und es stellt sich die nächste AVPlayerItem in der Warteschlange heraus mit einer Statusänderung protokolliert AVPlayerItemStatusReadyToPlay vor dem aktuellen Element Enden abgespielt wird.

Meine Schlussfolgerung ist daher, dass der nächste Punkt in Zeile beginnt vor dem aktuellen Elemente Enden herunterzuladen.

Jedoch! Ich erstelle ein Array mit AVPlayerItems, die ich meine Spieler erstellen. Das Lesen der AVFoundation docs auf AVAssets, habe ich den Eindruck, dass diese herunterladen ihr Vermögen asynchron, aber ich bin immer noch unsicher, wenn diese Downloads werden vom IAPlayerItem initiiert. Ich noch etwas flippiges Verhalten habe, wenn ich die .m3u8-Datei in die Warteschlange hinzufügen, die ich frage, ob diese Vermögenswerte zum Zeitpunkt der Erstellung beginnen Herunterladen (scheinen ein wenig seltsam für mich, obwohl).

Ich habe einfache Demo für Sie und andere, die von URL Pufferung Zeit jedes Video reduzieren wollen.

  

Hinweis: Sie wissen nicht, dies der richtige Weg ist oder nicht, aber es funktioniert perfekt für mich ohne jede Frage. Wenn jemand mehr wissen oder Code verbessern will für besseres Ergebnis dann begrüßt meine Antwort zu ändern.

In dem folgenden Code, Erstes Video nimmt normale Pufferzeit. Nächstes Video automatisch startet, wenn aktuelle Video-Finish ist und Sie können links und rechts Swipe nächstes und vorheriges Video zu bewegen.

Befolgen Sie die folgenden Schritte aus.

1) In der videoPlayerVC.h Datei.

#import <AVFoundation/AVFoundation.h>
#import <AVKit/AVKit.h>

@interface videoPlayerVC : UIViewController
{
    AVPlayerViewController *avPlyrViewController;
    AVPlayerItem *currentAVPlyrItem;

    int currentVideoNO;  // For current video track.
    NSMutableArray *arrOfAVPItems;
    NSMutableArray *arrOfPlyer;
}

2) In der videoPlayerVC.m Datei

Hier können Sie starten Video durch Klick auf den Button zu spielen. Im Folgenden finden Sie Aktionsmethode der Schaltfläche.

-(void)clickOnPlayVideosImage:(UIButton *)sender
{
   // In my App. all video URLs is up to 15 second.
    currentVideoNO = 0;
    NSMutableArray *arrForVideoURL = [[NSMutableArray alloc]initWithObjects:
                                      [NSURL URLWithString:@"http://videos/url1.mov"],
                                      [NSURL URLWithString:@"http://videos/url2.mov"],
                                      [NSURL URLWithString:@"http://videos/url3.mov"],
                                      [NSURL URLWithString:@"http://videos/url3.mov"],
                                      [NSURL URLWithString:@"http://videos/url4.mov"],
                                      [NSURL URLWithString:@"http://videos/url5.mov"], nil];

    AVPlayerItem *thePlayerItemA = [[AVPlayerItem alloc] initWithURL:[arrForVideoURL objectAtIndex:0]];
    AVPlayerItem *thePlayerItemB = [[AVPlayerItem alloc] initWithURL:[arrForVideoURL objectAtIndex:1]];
    AVPlayerItem *thePlayerItemC = [[AVPlayerItem alloc] initWithURL:[arrForVideoURL objectAtIndex:2]];
    AVPlayerItem *thePlayerItemD = [[AVPlayerItem alloc] initWithURL:[arrForVideoURL objectAtIndex:3]];
    AVPlayerItem *thePlayerItemE = [[AVPlayerItem alloc] initWithURL:[arrForVideoURL objectAtIndex:4]];
    AVPlayerItem *thePlayerItemF = [[AVPlayerItem alloc] initWithURL:[arrForVideoURL objectAtIndex:5]];

    if(arrOfAVPItems.count > 0)
       [arrOfAVPItems removeAllObjects];
    arrOfAVPItems = nil;

    if(arrOfPlyer.count > 0)
        [arrOfPlyer removeAllObjects];
    arrOfPlyer = nil;
    arrOfPlyer = [[NSMutableArray alloc] init];

    arrOfAVPItems = [NSMutableArray arrayWithObjects:thePlayerItemA, thePlayerItemB, thePlayerItemC, thePlayerItemD, thePlayerItemE, thePlayerItemF, nil]; // Add All items in the Array

    for(AVPlayerItem *myPlyrItem in arrOfAVPItems)
    {
        AVPlayer *videoPlayerNext = [AVPlayer playerWithPlayerItem:myPlyrItem]; /// Add item in the player
        [videoPlayerNext play]; 
        [videoPlayerNext pause];
        [arrOfPlyer addObject:videoPlayerNext]; /// Make Array of  "AVPlayer" just reduce buffering of each video. 
    }

    avPlyrViewController = [AVPlayerViewController new];
    avPlyrViewController.delegate = self;
    avPlyrViewController.player = (AVPlayer *)arrOfPlyer[0]; // Add first player from the Array.
    avPlyrViewController.showsPlaybackControls = YES;
    avPlyrViewController.allowsPictureInPicturePlayback = YES;
    avPlyrViewController.videoGravity = AVLayerVideoGravityResizeAspect;

    [self presentViewController:avPlyrViewController animated:YES completion:^{
        [self performSelector:@selector(playVideos) withObject:nil afterDelay:1];/// call method after one second for play video.

        UISwipeGestureRecognizer * swipeleft=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeleftToNextVideo:)];
        swipeleft.direction=UISwipeGestureRecognizerDirectionLeft;
        [avPlyrViewController.view addGestureRecognizer:swipeleft]; // Add left swipe for move on next video

        UISwipeGestureRecognizer * swiperight=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeleftToPerviousVideo:)];
        swiperight.direction=UISwipeGestureRecognizerDirectionRight;
        [avPlyrViewController.view addGestureRecognizer:swiperight]; // Add right swipe for move on previous video
    }];
}

Jetzt schreiben playVideos Methodencode.

#pragma mark - AVPlayer Methods -

-(void)playVideos
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:currentAVPlyrItem]; // remove current "AVPlayerItem" from the notification observe.

    if(arrOfAVPItems.count > 0)
    {
        currentAVPlyrItem = (AVPlayerItem *)arrOfAVPItems[currentVideoNO]; // Add "AVPlayerItem" from the array.

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemDidReachEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:currentAVPlyrItem]; // Add notification observer to indication current "AVPlayerItem" is finish.

        // pause and nil previous player if available.
        [avPlyrViewController.player pause];
        avPlyrViewController.player = nil;

        avPlyrViewController.player = (AVPlayer *)arrOfPlyer[currentVideoNO]; // add new player from the array
        [avPlyrViewController.player.currentItem seekToTime:kCMTimeZero]; // set for start video on initial position.
        [avPlyrViewController.player play]; // Play video

    }
}

Notification Beobachter Video, um anzuzeigen, zu beenden.

- (void)playerItemDidReachEnd:(NSNotification *)notification
{
    NSLog(@"IT REACHED THE END");
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:currentAVPlyrItem];  // remove current "AVPlayerItem" from the notification observe.

    [self swipeleftToNextVideo:nil]; // Call method for next video.
}

Methode für das Spiel nächstes Video

-(void)swipeleftToNextVideo:(UISwipeGestureRecognizer*)gestureRecognizer
{
    currentVideoNO++;
    if(currentVideoNO > (arrOfAVPItems.count -1))
        currentVideoNO = 0;

    NSLog(@"current - %d and last - %d", currentVideoNO, (int)(arrOfAVPItems.count -1));

    [self playVideos];
}

Verfahren zur Wiedergabe vorherigen Video.

-(void)swipeleftToPerviousVideo:(UISwipeGestureRecognizer*)gestureRecognizer
{
    currentVideoNO--;
    if(currentVideoNO < 0)
        currentVideoNO = (int)(arrOfAVPItems.count -1);

    NSLog(@"current - %d and last - %d", currentVideoNO, (int)(arrOfAVPItems.count -1));

    [self playVideos];
}

Gehen Sie folgendermaßen vor. Wenn irgendein Zweifel dann kommentieren bitte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top